diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbsoluteImageReference.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbsoluteImageReference.java index 8163116a76861b48a653d4d183cc224f7ac4221c..c223a91b494bf99785198a7d522ed8c9a2faa82c 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbsoluteImageReference.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbsoluteImageReference.java @@ -21,9 +21,9 @@ import java.awt.image.BufferedImage; import ch.systemsx.cisd.common.io.IContent; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageLibraryInfo; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageTransfomationFactories; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; /** @@ -46,15 +46,14 @@ public class AbsoluteImageReference extends AbstractImageReference private BufferedImage image; - private ImageChannelColor channelColor; + private ChannelColorRGB channelColor; /** * @param content is the original content before choosing the color component and the image ID */ public AbsoluteImageReference(IContent content, String uniqueId, String imageIdOrNull, ColorComponent colorComponentOrNull, RequestedImageSize imageSize, - ImageChannelColor channelColor, - ImageTransfomationFactories imageTransfomationFactories, + ChannelColorRGB channelColor, ImageTransfomationFactories imageTransfomationFactories, ImageLibraryInfo imageLibraryOrNull) { super(imageIdOrNull, colorComponentOrNull); @@ -128,7 +127,7 @@ public class AbsoluteImageReference extends AbstractImageReference return imageTransfomationFactories; } - public ImageChannelColor getChannelColor() + public ChannelColorRGB getChannelColor() { return channelColor; } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java index 08bb2096674d3bcb2ef0c2c8b529afe2cdb5b5ee..34114dc89d0bcc96b153fecb637a52e803717613 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java @@ -28,8 +28,8 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.dss.etl.dataaccess.IImagingQueryDAO; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.Channel; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColor; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.transformations.ImageTransformation; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgChannelDTO; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgContainerDTO; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgExperimentDTO; @@ -328,15 +328,52 @@ public class ImagingDatabaseHelper Set<Integer> usedColorsIndieces = new HashSet<Integer>(); for (Channel channel : channels) { - ChannelColor channelColor = channel.tryGetChannelColor(); - if (channelColor != null) + ChannelColorRGB channelColorRGB = channel.tryGetChannelColor(); + if (channelColorRGB != null) { + ChannelColor channelColor = findNearestPlainChannelColor(channelColorRGB); usedColorsIndieces.add(channelColor.getColorOrderIndex()); } } return usedColorsIndieces; } + @Private + static ChannelColor findNearestPlainChannelColor(ChannelColorRGB color) + { + int r = color.getR(); + int g = color.getG(); + int b = color.getB(); + int max = (r > g ? r : g); + max = (b > max ? b : max); + + if (r == max) + { + if (r == g) + { + return ChannelColor.RED_GREEN; + } else if (r == b) + { + return ChannelColor.RED_BLUE; + } else + { + return ChannelColor.RED; + } + } else if (g == max) + { + if (g == b) + { + return ChannelColor.GREEN_BLUE; + } else + { + return ChannelColor.GREEN; + } + } else + { + return ChannelColor.BLUE; + } + } + private static int getSmallestUnused(Set<Integer> usedColorsIndieces) { int colorIndex = 0; @@ -451,13 +488,13 @@ public class ImagingDatabaseHelper private static ImgChannelDTO makeChannelDTO(Channel channel, ChannelOwner channelOwner) { - ChannelColor channelColor = channel.tryGetChannelColor(); + ChannelColorRGB channelColor = channel.tryGetChannelColor(); assert channelColor != null : "channel color should be specified at this point"; - ImageChannelColor imageChannelColor = ImageChannelColor.valueOf(channelColor.name()); return new ImgChannelDTO(channel.getCode(), channel.tryGetDescription(), channel.tryGetWavelength(), channelOwner.tryGetDatasetId(), - channelOwner.tryGetExperimentId(), channel.getLabel(), imageChannelColor); + channelOwner.tryGetExperimentId(), channel.getLabel(), channelColor.getR(), + channelColor.getG(), channelColor.getB()); } } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java index a8e6150f9eb98d6fc691901a720c5256535a929e..efcdad54081d47ac569a6284f37db0a9fdf81537 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java @@ -70,8 +70,10 @@ public interface IImagingQueryDAO extends TransactionQuery, IImagingReadonlyQuer @Select("insert into EXPERIMENTS (PERM_ID) values (?{1}) returning ID") public long addExperiment(String experimentPermId); - @Select("insert into CHANNELS (CODE, LABEL, DESCRIPTION, WAVELENGTH, DS_ID, EXP_ID, COLOR) values " - + "(?{1.code}, ?{1.label}, ?{1.description}, ?{1.wavelength}, ?{1.datasetId}, ?{1.experimentId}, ?{1.dbChannelColor}) returning ID") + @Select("insert into CHANNELS (CODE, LABEL, DESCRIPTION, WAVELENGTH, DS_ID, EXP_ID, " + + "RED_CC, GREEN_CC, BLUE_CC) values " + + "(?{1.code}, ?{1.label}, ?{1.description}, ?{1.wavelength}, ?{1.datasetId}, ?{1.experimentId}, " + + "?{1.redColorComponent}, ?{1.greenColorComponent}, ?{1.blueColorComponent}) returning ID") public long addChannel(ImgChannelDTO channel); @Select("insert into CONTAINERS (PERM_ID, SPOTS_WIDTH, SPOTS_HEIGHT, EXPE_ID) values " @@ -113,7 +115,8 @@ public interface IImagingQueryDAO extends TransactionQuery, IImagingReadonlyQuer // updates @Update("update CHANNELS " - + "set DESCRIPTION = ?{1.description}, WAVELENGTH = ?{1.wavelength}, COLOR = ?{1.dbChannelColor} " + + "set DESCRIPTION = ?{1.description}, WAVELENGTH = ?{1.wavelength}, " + + "RED_CC = ?{1.redColorComponent}, GREEN_CC = ?{1.greenColorComponent}, BLUE_CC = ?{1.blueColorComponent}" + "where ID = ?{1.id}") public void updateChannel(ImgChannelDTO channel); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingDatasetLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingDatasetLoader.java index 909eb47f8109d96ce5a8735d06cfc8c6e38e2341..47671a22a7dc87bd5f9653589e60ba9b097e0ffb 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingDatasetLoader.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingDatasetLoader.java @@ -32,12 +32,12 @@ import ch.systemsx.cisd.openbis.dss.etl.IContentRepository; import ch.systemsx.cisd.openbis.dss.etl.IImagingDatasetLoader; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageLibraryInfo; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageTransfomationFactories; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackReference.HCSChannelStackByLocationReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackReference.MicroscopyChannelStackByLocationReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.HCSDatasetLoader; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.IImagingReadonlyQueryDAO; @@ -135,10 +135,15 @@ public class ImagingDatasetLoader extends HCSDatasetLoader implements IImagingDa ColorComponent colorComponent = imageDTO.getColorComponent(); ImageTransfomationFactories imageTransfomationFactories = createImageTransfomationFactories(imageDTO, channel); - ImageChannelColor channelColor = ImageChannelColor.valueOf(channel.getDbChannelColor()); ImageLibraryInfo imageLibrary = tryGetImageLibrary(dataset, useNativeImageLibrary); return new AbsoluteImageReference(content, path, imageDTO.getImageID(), colorComponent, - imageSize, channelColor, imageTransfomationFactories, imageLibrary); + imageSize, getColor(channel), imageTransfomationFactories, imageLibrary); + } + + private static ChannelColorRGB getColor(ImgChannelDTO channel) + { + return new ChannelColorRGB(channel.getRedColorComponent(), + channel.getGreenColorComponent(), channel.getBlueColorComponent()); } private ImageTransfomationFactories createImageTransfomationFactories(ImgImageDTO imageDTO, diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java index 6330435e607263833405187f3999c40ad6fbf379..dbb5d610ccc02ce84545e4d22a054844f55154fe 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java @@ -1,5 +1,8 @@ package ch.systemsx.cisd.openbis.dss.etl.dto.api.v1; +import java.awt.Color; + +import ch.systemsx.cisd.common.image.WavelengthColor; import ch.systemsx.cisd.common.utilities.AbstractHashable; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.transformations.ImageTransformation; @@ -21,7 +24,7 @@ public final class Channel extends AbstractHashable private Integer wavelength; - private ChannelColor channelColorOrNull; + private ChannelColorRGB channelColorOrNull; private ImageTransformation[] availableTransformations = new ImageTransformation[0]; @@ -31,7 +34,7 @@ public final class Channel extends AbstractHashable */ public Channel(String code, String label) { - this(code, label, null); + this(code, label, (ChannelColorRGB) null); } /** @@ -39,6 +42,15 @@ public final class Channel extends AbstractHashable * specified color. */ public Channel(String code, String label, ChannelColor channelColorOrNull) + { + this(code, label, convertColor(channelColorOrNull)); + } + + /** + * Constructs a channel with a specified code and label. The channel will be presented in a + * specified color. + */ + public Channel(String code, String label, ChannelColorRGB channelColorOrNull) { assert code != null : "code is null"; assert label != null : "label is null"; @@ -47,6 +59,15 @@ public final class Channel extends AbstractHashable this.channelColorOrNull = channelColorOrNull; } + private static ChannelColorRGB convertColor(ChannelColor plainChannelColorOrNull) + { + if (plainChannelColorOrNull == null) + { + return null; + } + return plainChannelColorOrNull.getRGB(); + } + public String getCode() { return code; @@ -72,7 +93,7 @@ public final class Channel extends AbstractHashable * null only during dataset registration when default color should be used, afterwards * never null. */ - public ChannelColor tryGetChannelColor() + public ChannelColorRGB tryGetChannelColor() { return channelColorOrNull; } @@ -85,20 +106,46 @@ public final class Channel extends AbstractHashable // ------------------- setters ------------------- - /** Sets the description of the channel.Optional. */ + /** Sets the description of the channel. Optional. */ public void setDescription(String description) { this.description = description; } - /** Sets the wavelength of the channel.Optional. */ + /** Sets the wavelength of the light (in nanometers) used to acquire this channel. Optional. */ public void setWavelength(Integer wavelength) { this.wavelength = wavelength; } - /** Sets the color in which this channel will be displayed. */ + /** + * Sets the wavelength of the light (in nanometers) used to acquire this channel.<br> + * Additionally sets the channel color. The color is calculated for display on a computer + * monitor on the basis of the given wavelength using Bruton's algorithm. See <a + * href="http://www.midnightkite.com/color.html">COLOR SCIENCE web page</a> for details. + * <p> + * Optional. + */ + public void setWavelengthAndColor(Integer wavelength) + { + this.wavelength = wavelength; + Color color = WavelengthColor.getColorForWavelength(wavelength); + setChannelColorRGB(convertColor(color)); + } + + private ChannelColorRGB convertColor(Color color) + { + return new ChannelColorRGB(color.getRed(), color.getGreen(), color.getBlue()); + } + + /** Sets the plain color in which this channel will be displayed. */ public void setChannelColor(ChannelColor channelColor) + { + this.channelColorOrNull = convertColor(channelColor); + } + + /** Sets RGB color in which this channel will be displayed. */ + public void setChannelColorRGB(ChannelColorRGB channelColor) { this.channelColorOrNull = channelColor; } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java index 83dbe5c09beed3f0a8b3affbdb022327ba7ac13f..275b0fcfd15fd91c1fafa17fa936afa7a257fa8d 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java @@ -47,4 +47,25 @@ public enum ChannelColor } throw new IllegalStateException("Invalid color index: " + colorIndex + "!"); } + + public ChannelColorRGB getRGB() + { + switch (this) + { + case RED: + return new ChannelColorRGB(255, 0, 0); + case GREEN: + return new ChannelColorRGB(0, 255, 0); + case BLUE: + return new ChannelColorRGB(0, 0, 255); + case RED_GREEN: + return new ChannelColorRGB(255, 255, 0); + case GREEN_BLUE: + return new ChannelColorRGB(0, 255, 255); + case RED_BLUE: + return new ChannelColorRGB(255, 0, 255); + default: + throw new IllegalStateException("unhandled enum " + this); + } + } } \ No newline at end of file diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColorRGB.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColorRGB.java new file mode 100644 index 0000000000000000000000000000000000000000..b352a9e0485bf86a456afc9693c29ab33a75ce0b --- /dev/null +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColorRGB.java @@ -0,0 +1,100 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.etl.dto.api.v1; + +import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder; + +/** + * RGB color components specify the color in which channel should be displayed. + * + * @author Tomasz Pylak + */ +public class ChannelColorRGB implements ISerializable +{ + private static final long serialVersionUID = ServiceVersionHolder.VERSION; + + private int r, g, b; + + @SuppressWarnings("unused") + private ChannelColorRGB() + { + } + + public ChannelColorRGB(int r, int g, int b) + { + assert r >= 0 && r <= 255 : "invalid color " + r; + assert g >= 0 && g <= 255 : "invalid color " + g; + assert b >= 0 && b <= 255 : "invalid color " + b; + + this.r = r; + this.g = g; + this.b = b; + } + + public int getR() + { + return r; + } + + public int getG() + { + return g; + } + + public int getB() + { + return b; + } + + @Override + public String toString() + { + return "Color(r=" + r + ", g=" + g + ", b=" + b + ")"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + b; + result = prime * result + g; + result = prime * result + r; + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ChannelColorRGB other = (ChannelColorRGB) obj; + if (b != other.b) + return false; + if (g != other.g) + return false; + if (r != other.r) + return false; + return true; + } + +} diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java index 53fe43a2e3524a3a26c75492ae69769ffd99e677..e3f4e58a63edf799eb12ee3b2c6b177247bda689 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java @@ -118,16 +118,36 @@ abstract public class SimpleImageDataConfig */ public Channel createChannel(String channelCode) { - ChannelColor channelColor = getChannelColor(channelCode); + ChannelColorRGB channelColorOrNull = tryGetChannelColor(channelCode); ImageTransformation[] availableTransformations = getAvailableChannelTransformations(channelCode); String label = channelCode; String normalizedChannelCode = CodeNormalizer.normalize(channelCode); - Channel channel = new Channel(normalizedChannelCode, label, channelColor); + Channel channel = new Channel(normalizedChannelCode, label, channelColorOrNull); channel.setAvailableTransformations(availableTransformations); return channel; } + private ChannelColorRGB tryGetChannelColor(String channelCode) + { + ChannelColor channelColor = getChannelColor(channelCode); + ChannelColorRGB channelColorRGB = getChannelColorRGB(channelCode); + if (channelColorRGB != null && channelColor != null) + { + throw new IllegalStateException(String.format( + "Color for channel '%s' is specified in two ways: %s and %s", channelColor, + channelColorRGB)); + } + + if (channelColor != null) + { + return channelColor.getRGB(); + } else + { + return channelColorRGB; + } + } + /** * Sets available transformations which can be applied to images of the specified channel (on * user's request). @@ -143,14 +163,24 @@ abstract public class SimpleImageDataConfig } /** - * Returns color for the specified channel. It will be used to display merged channels images. + * Has the same effect as {@link #getChannelColorRGB(String)}, but can return only plain colors. + */ + public ChannelColor getChannelColor(String channelCode) + { + return null; + } + + /** + * Returns RGB color for the specified channel. It will be used to display merged channels + * images. * <p> * Can be overridden in subclasses. It is ignored if {@link #createChannel(String)} is - * overridden as well. + * overridden as well. One should not override {@link #getChannelColor(String)} and + * {@link #getChannelColorRGB(String)} at the same time. * </p> * By default returns null (the arbitrary color will be set). */ - public ChannelColor getChannelColor(String channelCode) + public ChannelColorRGB getChannelColorRGB(String channelCode) { return null; } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ColorComponentImageChannelMerger.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ColorComponentImageChannelMerger.java new file mode 100644 index 0000000000000000000000000000000000000000..ec1e8945328a8ea611daef31aa3bdaa197bf99e7 --- /dev/null +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ColorComponentImageChannelMerger.java @@ -0,0 +1,103 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server.images; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.util.Arrays; + +import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; + +/** + * Handles the special case of merging image channels which in fact are encoded on the same image as + * different color components. It makes sense to use this class only for exactly two channels. + * + * @author Tomasz Pylak + */ +class ColorComponentImageChannelMerger +{ + public static BufferedImage mergeByExtractingComponents(BufferedImage[] images, + ColorComponent[] colorComponents) + { + assert images.length > 1 : "more than 1 image expected, but found: " + images.length; + + BufferedImage newImage = createNewRGBImage(images[0]); + int width = newImage.getWidth(); + int height = newImage.getHeight(); + int colorBuffer[] = new int[4]; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + int mergedRGB = mergeRGBColor(images, colorComponents, x, y, colorBuffer); + newImage.setRGB(x, y, mergedRGB); + } + } + return newImage; + } + + private static int mergeRGBColor(BufferedImage[] images, ColorComponent[] colorComponents, + int x, int y, int colorBuffer[]) + { + Arrays.fill(colorBuffer, 0); + for (int index = 0; index < images.length; index++) + { + int rgb = images[index].getRGB(x, y); + Color singleColor = new Color(rgb, true); + setColorComponents(colorBuffer, singleColor, colorComponents[index]); + // merge alpha channel + colorBuffer[3] = Math.max(colorBuffer[3], singleColor.getAlpha()); + } + return asRGB(colorBuffer); + } + + private static void setColorComponents(int[] colorBuffer, Color singleColor, + ColorComponent colorComponent) + { + int index = getColorComponentIndex(colorComponent); + colorBuffer[index] = colorComponent.getComponent(singleColor); + } + + private static int getColorComponentIndex(ColorComponent colorComponent) + { + switch (colorComponent) + { + case RED: + return 0; + case GREEN: + return 1; + case BLUE: + return 2; + default: + throw new IllegalStateException("Unknown color " + colorComponent); + } + } + + private static int asRGB(int[] rgb) + { + return new Color(rgb[0], rgb[1], rgb[2], rgb[3]).getRGB(); + } + + // NOTE: drawing on this image will not preserve transparency - but we do not need it and the + // image is smaller + private static BufferedImage createNewRGBImage(BufferedImage bufferedImage) + { + return new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), + BufferedImage.TYPE_INT_RGB); + } + +} diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtils.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtils.java index 9f7fbec58a0ce82d6f0c37d6d0ccc3a7398d37a2..1f8e4b3bd1cd1c1e98fdf6f14f0d688b5f0d38ba 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtils.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtils.java @@ -23,7 +23,6 @@ import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; @@ -33,6 +32,7 @@ import ch.systemsx.cisd.base.image.IImageTransformerFactory; import ch.systemsx.cisd.bds.hcs.Location; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.image.MixColors; import ch.systemsx.cisd.common.io.ByteArrayBasedContent; import ch.systemsx.cisd.common.io.IContent; import ch.systemsx.cisd.common.logging.LogCategory; @@ -43,6 +43,7 @@ import ch.systemsx.cisd.openbis.dss.etl.IImagingDatasetLoader; import ch.systemsx.cisd.openbis.dss.etl.IImagingLoaderStrategy; import ch.systemsx.cisd.openbis.dss.etl.ImagingLoaderStrategyFactory; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageTransfomationFactories; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.generic.server.ResponseContentStream; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.DatasetAcquiredImagesReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackReference; @@ -51,7 +52,6 @@ import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageTransformatio import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; @@ -449,6 +449,7 @@ public class ImageChannelsUtils operationLog.debug("Load original image: " + (System.currentTimeMillis() - start)); } + // resized the image if necessary RequestedImageSize requestedSize = imageReference.getRequestedSize(); @@ -645,21 +646,57 @@ public class ImageChannelsUtils // this method always returns RGB images, even if the input was in grayscale private static BufferedImage mergeImages(List<ImageWithReference> images) { - assert images.size() > 1 : "more than 1 image expected, but found: " + images.size(); + BufferedImage[] bufferedImages = new BufferedImage[images.size()]; + Color[] colors = new Color[images.size()]; + for (int i = 0; i < images.size(); i++) + { + ImageWithReference image = images.get(i); + bufferedImages[i] = image.getBufferedImage(); + colors[i] = getColor(image); + } - BufferedImage newImage = createNewRGBImage(images.get(0).getBufferedImage()); - int width = newImage.getWidth(); - int height = newImage.getHeight(); - int colorBuffer[] = new int[4]; - for (int y = 0; y < height; y++) + ColorComponent[] colorComponents = tryExtractColorComponent(images); + if (colorComponents != null) { - for (int x = 0; x < width; x++) + return ColorComponentImageChannelMerger.mergeByExtractingComponents(bufferedImages, + colorComponents); + } else + { + return MixColors.mixImages(bufferedImages, colors, false, 0); + } + } + + private static Color getColor(ImageWithReference image) + { + return getColor(image.getReference().getChannelColor()); + } + + private static Color getColor(ChannelColorRGB color) + { + return new Color(color.getR(), color.getG(), color.getB()); + } + + private static ColorComponent[] tryExtractColorComponent(List<ImageWithReference> images) + { + ColorComponent[] components = new ColorComponent[images.size()]; + int i = 0; + for (ImageWithReference image : images) + { + ColorComponent colorComponent = image.getReference().tryGetColorComponent(); + if (colorComponent == null) { - int mergedRGB = mergeRGBColor(images, x, y, colorBuffer); - newImage.setRGB(x, y, mergedRGB); + if (i == 0) + { + return null; + } else + { + throw new IllegalStateException( + "Some images have color component set and some have it unset."); + } } + components[i++] = colorComponent; } - return newImage; + return components; } private static void drawOverlay(BufferedImage image, ImageWithReference overlayImage) @@ -728,63 +765,6 @@ public class ImageChannelsUtils return image.getBufferedImage().getColorModel().hasAlpha(); } - private static int mergeRGBColor(List<ImageWithReference> images, int x, int y, - int colorBuffer[]) - { - Arrays.fill(colorBuffer, 0); - for (int index = 0; index < images.size(); index++) - { - ImageWithReference image = images.get(index); - int rgb = image.getBufferedImage().getRGB(x, y); - Color singleColor = new Color(rgb, true); - AbsoluteImageReference imageReference = image.getReference(); - setColorComponents(colorBuffer, singleColor, imageReference); - // merge alpha channel - colorBuffer[3] = Math.max(colorBuffer[3], singleColor.getAlpha()); - } - return asRGB(colorBuffer); - } - - private static void setColorComponents(int[] colorBuffer, Color singleColor, - AbsoluteImageReference imageReference) - { - ColorComponent colorComponent = imageReference.tryGetColorComponent(); - if (colorComponent != null) - { - int index = getColorComponentIndex(colorComponent); - colorBuffer[index] = colorComponent.getComponent(singleColor); - } else - { - ImageChannelColor channelColor = imageReference.getChannelColor(); - setColorComponentsForChannelIndex(colorBuffer, singleColor, channelColor); - } - } - - private static int getColorComponentIndex(ColorComponent colorComponent) - { - switch (colorComponent) - { - case RED: - return 0; - case GREEN: - return 1; - case BLUE: - return 2; - default: - throw new IllegalStateException("Unknown color " + colorComponent); - } - } - - private static void setColorComponentsForChannelIndex(int[] colorBuffer, Color singleColor, - ImageChannelColor channelColor) - { - int maxIngredient = extractMaxColorIngredient(singleColor); - for (int i : getRGBColorIndexes(channelColor)) - { - colorBuffer[i] = Math.max(colorBuffer[i], maxIngredient); - } - } - // --------- common private EnvironmentFailureException createImageNotFoundException( @@ -817,44 +797,6 @@ public class ImageChannelsUtils return newImage; } - // NOTE: drawing on this image will not preserve transparency - but we do not need it and the - // image is smaller - private static BufferedImage createNewRGBImage(RenderedImage bufferedImage) - { - BufferedImage newImage = - new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), - BufferedImage.TYPE_INT_RGB); - return newImage; - } - - // 0=R, 1=G, 2=B, 3=RG, 4=RB, 5=GB - private static int[] getRGBColorIndexes(ImageChannelColor channelColor) - { - switch (channelColor) - { - case RED: - return new int[] - { 0 }; - case GREEN: - return new int[] - { 1 }; - case BLUE: - return new int[] - { 2 }; - case RED_GREEN: - return new int[] - { 0, 1 }; - case RED_BLUE: - return new int[] - { 0, 2 }; - case GREEN_BLUE: - return new int[] - { 1, 2 }; - default: - throw new IllegalStateException("not possible"); - } - } - // We reset all ingredients besides the one which is specified by color component. // The result is the rgb value with only one component which is non-zero. private static int extractSingleComponent(int rgb, ColorComponent colorComponent) @@ -862,15 +804,14 @@ public class ImageChannelsUtils return colorComponent.extractSingleComponent(rgb).getRGB(); } - // returns the max ingredient for the color - private static int extractMaxColorIngredient(Color c) - { - return Math.max(Math.max(c.getBlue(), c.getGreen()), c.getRed()); - } - - private static int asRGB(int[] rgb) + // NOTE: drawing on this image will not preserve transparency - but we do not need it and the + // image is smaller + private static BufferedImage createNewRGBImage(RenderedImage bufferedImage) { - return new Color(rgb[0], rgb[1], rgb[2], rgb[3]).getRGB(); + BufferedImage newImage = + new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), + BufferedImage.TYPE_INT_RGB); + return newImage; } private static IContent createPngContent(BufferedImage image, String nameOrNull) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java index c3fd5d26526a66cc195801196bc392a859a145d3..09aadd1a26856d97c4f120f0fd2c22f90b49afd5 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java @@ -40,8 +40,6 @@ public class ImageChannel implements ISerializable private Integer wavelength; - private ImageChannelColor channelColor; - private List<ImageTransformationInfo> availableImageTransformations; // GWT only @@ -51,17 +49,15 @@ public class ImageChannel implements ISerializable } public ImageChannel(String code, String label, String description, Integer wavelength, - ImageChannelColor channelColor, List<ImageTransformationInfo> availableImageTransformations) { assert code != null; -// assert availableImageTransformations != null; + // assert availableImageTransformations != null; this.code = code; this.label = label; this.description = description; this.wavelength = wavelength; - this.channelColor = channelColor; this.availableImageTransformations = availableImageTransformations; } @@ -85,14 +81,6 @@ public class ImageChannel implements ISerializable return label; } - /** - * @return color for the specified channel which will be used to display merged channels images. - */ - public ImageChannelColor getChannelColor() - { - return channelColor; - } - public List<ImageTransformationInfo> getAvailableImageTransformations() { return availableImageTransformations; diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java index 82f86cadad718d11f995dfca1dd9229ec6e27f04..68804831108a91535dd01208c65f614ebc8a7b19 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java @@ -25,7 +25,6 @@ import ch.systemsx.cisd.common.utilities.MD5ChecksumCalculator; import ch.systemsx.cisd.openbis.generic.shared.basic.utils.GroupByMap; import ch.systemsx.cisd.openbis.generic.shared.basic.utils.IGroupKeyExtractor; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageTransformationInfo; @@ -205,12 +204,10 @@ public class HCSDatasetLoader implements IImageDatasetLoader private ImageChannel convert(ImgChannelDTO channelDTO) { - ImageChannelColor imageChannelColor = - ImageChannelColor.valueOf(channelDTO.getDbChannelColor()); List<ImageTransformationInfo> availableImageTransformations = convertTransformations(availableImageTransformationsMap.get(channelDTO.getId())); return new ImageChannel(channelDTO.getCode(), channelDTO.getLabel(), - channelDTO.getDescription(), channelDTO.getWavelength(), imageChannelColor, + channelDTO.getDescription(), channelDTO.getWavelength(), availableImageTransformations); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java index 1c30c8fba51c8bbfc857e28eb89fe50db7c98069..d82c3f1d454e000e3251f0c1e5049ff2f10cc972 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java @@ -19,7 +19,6 @@ package ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess; import net.lemnik.eodsql.ResultColumn; import ch.systemsx.cisd.openbis.generic.shared.basic.CodeNormalizer; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; /** * @author Tomasz Pylak @@ -46,9 +45,15 @@ public class ImgChannelDTO extends AbstractImgIdentifiable @ResultColumn("EXP_ID") private Long experimentIdOrNull; - /** Value for the {@link ImageChannelColor} enum. Not null. */ - @ResultColumn("COLOR") - private String channelColor; + /** RGB color components specify the color in which channel should be displayed. Not null. */ + @ResultColumn("RED_CC") + private int redColorComponent; + + @ResultColumn("GREEN_CC") + private int greenColorComponent; + + @ResultColumn("BLUE_CC") + private int blueColorComponent; // EODSQL only @SuppressWarnings("unused") @@ -58,8 +63,7 @@ public class ImgChannelDTO extends AbstractImgIdentifiable } public ImgChannelDTO(String code, String descriptionOrNull, Integer wavelengthOrNull, - Long datasetIdOrNull, Long experimentIdOrNull, String label, - ImageChannelColor channelColor) + Long datasetIdOrNull, Long experimentIdOrNull, String label, int r, int g, int b) { assert (datasetIdOrNull == null && experimentIdOrNull != null) || (datasetIdOrNull != null && experimentIdOrNull == null); @@ -69,7 +73,10 @@ public class ImgChannelDTO extends AbstractImgIdentifiable this.wavelengthOrNull = wavelengthOrNull; this.datasetIdOrNull = datasetIdOrNull; this.experimentIdOrNull = experimentIdOrNull; - this.channelColor = channelColor.name(); + + this.redColorComponent = r; + this.greenColorComponent = g; + this.blueColorComponent = b; } public String getCode() @@ -133,14 +140,33 @@ public class ImgChannelDTO extends AbstractImgIdentifiable this.experimentIdOrNull = experimentId; } - /** Can be converted to {@link ImageChannelColor}. */ - public String getDbChannelColor() + public int getRedColorComponent() + { + return redColorComponent; + } + + public void setRedColorComponent(int redColorComponent) + { + this.redColorComponent = redColorComponent; + } + + public int getGreenColorComponent() + { + return greenColorComponent; + } + + public void setGreenColorComponent(int greenColorComponent) + { + this.greenColorComponent = greenColorComponent; + } + + public int getBlueColorComponent() { - return channelColor; + return blueColorComponent; } - public void setDbChannelColor(String channelColor) + public void setBlueColorComponent(int blueColorComponent) { - this.channelColor = channelColor; + this.blueColorComponent = blueColorComponent; } } diff --git a/screening/source/sql/imaging/postgresql/015/schema-015.sql b/screening/source/sql/imaging/postgresql/015/schema-015.sql index ecb4508d3c86687590bb578c4bf33aea4797d6c0..98efd99752f4375e11f44dd403f25bf78012fdf9 100644 --- a/screening/source/sql/imaging/postgresql/015/schema-015.sql +++ b/screening/source/sql/imaging/postgresql/015/schema-015.sql @@ -100,7 +100,11 @@ CREATE TABLE CHANNELS ( LABEL NAME NOT NULL, DESCRIPTION DESCRIPTION, WAVELENGTH INTEGER, - COLOR CHANNEL_COLOR NOT NULL, + + -- RGB color components specify the color in which channel should be displayed + RED_CC INTEGER NOT NULL, + GREEN_CC INTEGER NOT NULL, + BLUE_CC INTEGER NOT NULL, DS_ID TECH_ID, EXP_ID TECH_ID, diff --git a/screening/source/sql/imaging/postgresql/migration/migration-014-015.sql b/screening/source/sql/imaging/postgresql/migration/migration-014-015.sql index 6515c17a8e29fecd4879055dc9b234daef1d1088..63e17fcf493a69c1c6accd1d76b392d86079131d 100644 --- a/screening/source/sql/imaging/postgresql/migration/migration-014-015.sql +++ b/screening/source/sql/imaging/postgresql/migration/migration-014-015.sql @@ -1,7 +1,9 @@ --- Migration from 014 to 015 +-- Migration from 014 to 015, sprint 116 alter table IMAGE_TRANSFORMATIONS add column IS_DEFAULT BOOLEAN_CHAR NOT NULL DEFAULT 'F'; +-- allow to define a default image transformation + CREATE OR REPLACE FUNCTION IMAGE_TRANSFORMATIONS_DEFAULT_CHECK() RETURNS trigger AS $$ DECLARE v_is_default boolean; @@ -22,3 +24,41 @@ $$ LANGUAGE 'plpgsql'; CREATE TRIGGER IMAGE_TRANSFORMATIONS_DEFAULT_CHECK BEFORE INSERT OR UPDATE ON IMAGE_TRANSFORMATIONS FOR EACH ROW EXECUTE PROCEDURE IMAGE_TRANSFORMATIONS_DEFAULT_CHECK(); + +-- allow to specify RGB channel colors + +alter table CHANNELS add column RED_CC INTEGER; +alter table CHANNELS add column GREEN_CC INTEGER; +alter table CHANNELS add column BLUE_CC INTEGER; + +update CHANNELS + set RED_CC = 255, GREEN_CC = 0, BLUE_CC = 0 + where color = 'RED'; + +update CHANNELS + set RED_CC = 0, GREEN_CC = 255, BLUE_CC = 0 + where color = 'GREEN'; + + update CHANNELS + set RED_CC = 0, GREEN_CC = 0, BLUE_CC = 255 + where color = 'BLUE'; + +update CHANNELS + set RED_CC = 255, GREEN_CC = 255, BLUE_CC = 0 + where color = 'RED_GREEN'; + +update CHANNELS + set RED_CC = 0, GREEN_CC = 255, BLUE_CC = 255 + where color = 'GREEN_BLUE'; + + update CHANNELS + set RED_CC = 255, GREEN_CC = 0, BLUE_CC = 255 + where color = 'RED_BLUE'; + + +alter table CHANNELS drop column COLOR; + +alter table CHANNELS alter column RED_CC set NOT NULL; +alter table CHANNELS alter column GREEN_CC set NOT NULL; +alter table CHANNELS alter column BLUE_CC set NOT NULL; + \ No newline at end of file diff --git a/screening/sourceTest/java/BiozentrumMatLabApiTest.java b/screening/sourceTest/java/BiozentrumMatLabApiTest.java index 4c840e5fe16ea0efb74bebd274fd9e10f9b1853b..0672d7fc9d8ef2908238b9f4939493fdfafebca6 100644 --- a/screening/sourceTest/java/BiozentrumMatLabApiTest.java +++ b/screening/sourceTest/java/BiozentrumMatLabApiTest.java @@ -1,3 +1,5 @@ +import java.util.Arrays; + /* * Copyright 2011 ETH Zuerich, CISD * @@ -28,7 +30,7 @@ public class BiozentrumMatLabApiTest System.err .println("Specify the password and optionally the plate identifier, mount point and dataset type pattern!"); } - String passwd = args[0]; + String passwd = "//misiek911"; String chosenPlate = "/GROUP_DEHIO/KB03-2O-130"; String mountPoint = null; String datasetTypePattern = "HCS_ANALYSIS_CELL_CLASSIFICATIONS_MAT"; @@ -41,25 +43,56 @@ public class BiozentrumMatLabApiTest mountPoint = args[2]; } - // OpenBISScreeningML.login("cisd", passwd, "https://infectx.biozentrum.unibas.ch"); - OpenBISScreeningML.login("cisd", passwd, "http://bc2-openbis01.bc2.unibas.ch:8443"); - // OpenBISScreeningML.login("admin", passwd, "https://sprint-openbis.ethz.ch:8446"); - // OpenBISScreeningML.login("admin", passwd, "http://127.0.0.1:8888"); - - String experiment = "/TEST/TEST-USER/MY-ASSAY"; + OpenBISScreeningML.login("tpylak", passwd, "https://infectx.biozentrum.unibas.ch"); + Object[][] metadata = OpenBISScreeningML.getImagesMetadata("/RESEARCH_IT/TEST2"); + System.out.println(Arrays.toString(metadata[0])); + Object[][][] loadImages = + OpenBISScreeningML.loadImages("/INFECTX/DZ56-1K", 1, 1, 1, new String[] + { "CY5", "DAPI" }); + System.out.println(loadImages[0][0][0]); - testListChannels(experiment); - testLoadFeatures(chosenPlate, experiment); - testImagesMetadata(chosenPlate); - testLoadImage(chosenPlate); - testWellProperties(chosenPlate); - testLoadDataset(chosenPlate, mountPoint, datasetTypePattern); - testUploadDataset(chosenPlate); + // OpenBISScreeningML.login("cisd", passwd, "http://bc2-openbis01.bc2.unibas.ch:8443"); + // OpenBISScreeningML.login("admin", passwd, "https://sprint-openbis.ethz.ch:8446"); - testUploadDataset("/RESEARCH_IT/TEST2"); + // OpenBISScreeningML.login("admin", passwd, "http://127.0.0.1:8888"); + // Object[][] metadata = OpenBISScreeningML.getImagesMetadata("/TEST/PLATE1"); + // System.out.println(Arrays.toString(metadata[0])); + // Object[][][] loadImages = + // OpenBISScreeningML.loadImages("/TEST/PLATE1", 1, 1, 1, new String[] + // { "DAPI" }); + + // String experiment = "/TEST/TEST-USER/MY-ASSAY"; + + // testListChannels(experiment); + // testLoadFeatures(chosenPlate, experiment); + // testImagesMetadata(chosenPlate); + // testLoadImage(chosenPlate); + // testWellProperties(chosenPlate); + // testLoadDataset(chosenPlate, mountPoint, datasetTypePattern); + + // testUploadDataset(chosenPlate); + // testUploadDataset("/RESEARCH_IT/TEST2"); // testUploadDataset("/DEMO/VL0206A-FV1801"); // testUploadDataset("/TEST/PLATE1"); + // integration server test + // OpenBISScreeningML.login("admin", passwd, "https://127.0.0.1:8443"); + // String datasetType = "HCS_MODULESETTINGS_OBJECTCLASSIFICATION_MAT"; + // String datasetType = "HCS_ANALYSIS_WELL_CLASSIFICATION_SUMMARIES"; + // String datasetType = "HCS_ANALYSIS_CELL_CLASSIFICATIONS_MAT"; + // String datasetType = "UNKNOWN"; + // testUploadDataset("/GROUP_RESEARCHIT/DZ01-1A", datasetType); + + // PlateMetadata[] plateMetadataList = OpenBISScreeningML.getPlateMetadataList(new String[] + // { "/TEST/PLATE1", "/TEST/PLATE2", "/TEST/PLATE1.96WELLS", "/TEST/PLATE1.SUFFIX", }); + try + { + Thread.currentThread().sleep(1000000); + } catch (InterruptedException ex) + { + // TODO Auto-generated catch block + ex.printStackTrace(); + } OpenBISScreeningML.logout(); } @@ -69,21 +102,16 @@ public class BiozentrumMatLabApiTest print2DArray(channels); } - private static void testUploadDataset(String chosenPlate) + private static void testUploadDataset(String chosenPlate, String datasetType) { String file = "/Users/tpylak/main/tmp/bioz-test/PlateSummary.csv"; - String datasetType = "HCS_ANALYSIS_WELL_CLASSIFICATION_SUMMARIES"; String datasetCode; Object[][] dataSetProperties = new Object[][] { new Object[] {} }; + datasetCode = (String) OpenBISScreeningML.uploadDataSet(chosenPlate, file, datasetType, dataSetProperties); - System.out.println("Uploaded classification dataset " + datasetCode); - - datasetCode = - (String) OpenBISScreeningML.uploadDataSet(chosenPlate, file, - "HCS_ANALYSIS_CELL_CLASSIFICATIONS_MAT", dataSetProperties); System.out.println("Uploaded any dataset " + datasetCode); } diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/ImagingChannelsCreatorTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/ImagingChannelsCreatorTest.java index b021abdfac17745e4f56af95c0c154a97304201c..56d2af34acc16f8836be81428ca1bb6f445e0b24 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/ImagingChannelsCreatorTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/ImagingChannelsCreatorTest.java @@ -26,6 +26,7 @@ import ch.rinn.restrictions.Friend; import ch.systemsx.cisd.openbis.dss.etl.ImagingDatabaseHelper.ImagingChannelsCreator; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.Channel; import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColor; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; /** * Test of {@link ImagingChannelsCreator} @@ -42,15 +43,42 @@ public class ImagingChannelsCreatorTest extends AssertJUnit Arrays.asList(mkChannel(), mkChannel(ChannelColor.RED), mkChannel()); ImagingChannelsCreator.fillMissingChannelColors(channels); - assertEqual(ChannelColor.BLUE, channels.get(0)); - assertEqual(ChannelColor.RED, channels.get(1)); - assertEqual(ChannelColor.GREEN, channels.get(2)); + assertEqual(new ChannelColorRGB(0, 0, 255), channels.get(0)); + assertEqual(new ChannelColorRGB(255, 0, 0), channels.get(1)); + assertEqual(new ChannelColorRGB(0, 255, 0), channels.get(2)); + } + + @Test + public void testFillMissingChannelColorsRGB() + { + ChannelColorRGB redish = new ChannelColorRGB(200, 10, 10); + List<Channel> channels = Arrays.asList(mkChannel(), mkChannel(redish), mkChannel()); + ImagingChannelsCreator.fillMissingChannelColors(channels); + assertEqual(new ChannelColorRGB(0, 0, 255), channels.get(0)); + assertEqual(redish, channels.get(1)); + assertEqual(new ChannelColorRGB(0, 255, 0), channels.get(2)); } - private static void assertEqual(ChannelColor expectedColor, Channel channel) + @Test + public void testFindNearestPlainChannelColor() { - if (expectedColor != channel.tryGetChannelColor()) + assertEquals(ChannelColor.RED, findNearestColor(30, 1, 9)); + assertEquals(ChannelColor.RED_BLUE, findNearestColor(30, 1, 30)); + assertEquals(ChannelColor.GREEN, findNearestColor(0, 200, 29)); + assertEquals(ChannelColor.RED_GREEN, findNearestColor(30, 30, 3)); + assertEquals(ChannelColor.BLUE, findNearestColor(30, 1, 255)); + assertEquals(ChannelColor.GREEN_BLUE, findNearestColor(1, 31, 31)); + } + + private static ChannelColor findNearestColor(int r, int g, int b) + { + return ImagingChannelsCreator.findNearestPlainChannelColor(new ChannelColorRGB(r, g, b)); + } + + private static void assertEqual(ChannelColorRGB expectedColor, Channel channel) + { + if (expectedColor.equals(channel.tryGetChannelColor()) == false) { fail("Expected " + expectedColor + " but got: " + channel.tryGetChannelColor()); } @@ -58,11 +86,16 @@ public class ImagingChannelsCreatorTest extends AssertJUnit private static Channel mkChannel() { - return mkChannel(null); + return mkChannel((ChannelColorRGB) null); } - private static Channel mkChannel(ChannelColor colorOrNull) + private static Channel mkChannel(ChannelColorRGB colorOrNull) { return new Channel("code", "label", colorOrNull); } + + private static Channel mkChannel(ChannelColor color) + { + return mkChannel(color.getRGB()); + } } \ No newline at end of file diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java index 56bc39b74eefb99ef85f7366c274984006fda8c6..857587fcfba021e47489d2ee0c9f37539e8be861 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java @@ -32,9 +32,9 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.base.image.IImageTransformerFactory; import ch.systemsx.cisd.bds.hcs.Location; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.generic.shared.basic.CodeNormalizer; import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ExampleImageTransformerFactory; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.AbstractDBTest; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgAcquiredImageDTO; @@ -67,7 +67,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest private static final String CHANNEL_LABEL = "Channel Label"; - private static final ImageChannelColor CHANNEL_COLOR = ImageChannelColor.RED; + private static final ChannelColorRGB CHANNEL_COLOR = new ChannelColorRGB(100, 200, 0); private static final String PAGE = "1-2-3-4"; @@ -320,7 +320,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest assertEquals("DSCHANNEL", datasetChannel.getCode()); assertEquals(CHANNEL_LABEL, datasetChannel.getLabel()); - assertEquals(CHANNEL_COLOR.name(), datasetChannel.getDbChannelColor()); + assertColorEquals(datasetChannel); assertEquals(datasetChannelId, datasetChannel.getId()); assertEquals(datasetChannel, dao.tryGetChannelForDataset(datasetId, "dsChannel")); @@ -330,7 +330,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest ImgChannelDTO experimentChannel = experimentChannels.get(0); assertEquals("EXPCHANNEL", experimentChannel.getCode()); assertEquals(CHANNEL_LABEL, experimentChannel.getLabel()); - assertEquals(CHANNEL_COLOR.name(), experimentChannel.getDbChannelColor()); + assertColorEquals(experimentChannel); assertEquals(experimentChannelId, experimentChannel.getId()); assertEquals(experimentChannel, dao.tryGetChannelForExperiment(experimentId, "expChannel")); @@ -343,6 +343,13 @@ public class ImagingQueryDAOTest extends AbstractDBTest assertEquals(channel, dao.getChannelsByExperimentId(experimentId).get(0)); } + private void assertColorEquals(ImgChannelDTO datasetChannel) + { + assertEquals(CHANNEL_COLOR.getR(), datasetChannel.getRedColorComponent()); + assertEquals(CHANNEL_COLOR.getG(), datasetChannel.getGreenColorComponent()); + assertEquals(CHANNEL_COLOR.getB(), datasetChannel.getBlueColorComponent()); + } + private long addImage(String path, ColorComponent colorComponent) { final ImgImageDTO image = new ImgImageDTO(dao.createImageId(), path, PAGE, colorComponent); @@ -423,7 +430,8 @@ public class ImagingQueryDAOTest extends AbstractDBTest { final ImgChannelDTO channel = new ImgChannelDTO(DS_CHANNEL, CHANNEL_DESCRIPTION, WAVELENGTH, datasetId, null, - CHANNEL_LABEL, CHANNEL_COLOR); + CHANNEL_LABEL, CHANNEL_COLOR.getR(), CHANNEL_COLOR.getG(), + CHANNEL_COLOR.getB()); return dao.addChannel(channel); } @@ -550,7 +558,8 @@ public class ImagingQueryDAOTest extends AbstractDBTest { final ImgChannelDTO channel = new ImgChannelDTO(EXP_CHANNEL, CHANNEL_DESCRIPTION, WAVELENGTH, null, experimentId, - CHANNEL_LABEL, CHANNEL_COLOR); + CHANNEL_LABEL, CHANNEL_COLOR.getR(), CHANNEL_COLOR.getG(), + CHANNEL_COLOR.getB()); return dao.addChannel(channel); } diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java index 44f83035b4b2e97fcc13c54aaab3d3eaad2259ea..a072bb32b0597089bcbfa2521d591fd3a57e3919 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java @@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.dss.etl.AbsoluteImageReference; import ch.systemsx.cisd.openbis.dss.etl.IImagingDatasetLoader; import ch.systemsx.cisd.openbis.dss.etl.ImagingLoaderStrategyFactory; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageTransfomationFactories; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.DatasetAcquiredImagesReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackReference; import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageTransformationParams; @@ -53,7 +54,6 @@ import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtilTest; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageTransformationInfo; @@ -180,7 +180,7 @@ public class ImageChannelsUtilsTest extends AssertJUnit allowing(loader).getImageParameters(); ImageDatasetParameters imgParams = new ImageDatasetParameters(); imgParams.setChannels(Arrays.asList(new ImageChannel(CHANNEL, CHANNEL, null, - null, null, new ArrayList<ImageTransformationInfo>()))); + null, new ArrayList<ImageTransformationInfo>()))); will(returnValue(imgParams)); RequestedImageSize requestedSize = @@ -246,7 +246,7 @@ public class ImageChannelsUtilsTest extends AssertJUnit RequestedImageSize imageSize) { return new AbsoluteImageReference(image(fileName), "id42", null, null, imageSize, - ImageChannelColor.BLUE, new ImageTransfomationFactories(), null); + new ChannelColorRGB(0, 0, 255), new ImageTransfomationFactories(), null); } private ImageChannelsUtils createImageChannelsUtils(Size thumbnailSizeOrNull) diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java index 5f51e4e0789237eed015520f24066037443fddf7..69b36c467e30d1e5f4d5352c2471ba626d55b56b 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java @@ -51,6 +51,7 @@ import ch.systemsx.cisd.common.io.IContent; import ch.systemsx.cisd.openbis.dss.etl.AbsoluteImageReference; import ch.systemsx.cisd.openbis.dss.etl.IImagingDatasetLoader; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageTransfomationFactories; +import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColorRGB; import ch.systemsx.cisd.openbis.dss.generic.server.DatasetSessionAuthorizer; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor.DssServiceRpcAuthorizationMethodInterceptor; @@ -81,7 +82,6 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageTransformationInfo; import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants; @@ -178,7 +178,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit imageParameters.setTileColsNum(2); imageParameters.setDatasetCode(DATASET_CODE); ImageChannel imageChannel = - new ImageChannel(CHANNEL_CODE, CHANNEL_CODE, null, null, null, + new ImageChannel(CHANNEL_CODE, CHANNEL_CODE, null, null, new ArrayList<ImageTransformationInfo>()); imageParameters.setChannels(Arrays.asList(imageChannel)); context.checking(new Expectations() @@ -343,14 +343,14 @@ public class DssServiceRpcScreeningTest extends AssertJUnit ImageChannelStackReference.createHCSFromLocations(new Location(3, 1), new Location(1, 1)), thumbnailSize); will(returnValue(new AbsoluteImageReference(image("img1.jpg"), "img1", null, - null, thumbnailSize, ImageChannelColor.BLUE, + null, thumbnailSize, createBlueColor(), new ImageTransfomationFactories(), null))); one(imageLoader).tryGetImage( channel, ImageChannelStackReference.createHCSFromLocations(new Location(3, 1), new Location(2, 1)), thumbnailSize); will(returnValue(new AbsoluteImageReference(image("img1.gif"), "img1", null, - null, thumbnailSize, ImageChannelColor.BLUE, + null, thumbnailSize, createBlueColor(), new ImageTransfomationFactories(), null))); } }); @@ -374,6 +374,11 @@ public class DssServiceRpcScreeningTest extends AssertJUnit context.assertIsSatisfied(); } + private static ChannelColorRGB createBlueColor() + { + return new ChannelColorRGB(0, 0, 255); + } + BufferedImage extractNextImage(ConcatenatedFileOutputStreamWriter imagesWriter) throws IOException { @@ -397,8 +402,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit { one(dao).tryGetChannelForExperimentPermId(EXPERIMENT_PERM_ID, channel); ImgChannelDTO channelDTO = - new ImgChannelDTO("dapi", null, null, new Long(42), null, "dapi", - ImageChannelColor.BLUE); + new ImgChannelDTO("dapi", null, null, new Long(42), null, "dapi", 0, 0, + 255); long channelId = 444; channelDTO.setId(channelId); will(returnValue(channelDTO));