From 15aabc4a5e966fd40e5cd38b8f03c1ef748664bf Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Mon, 2 Nov 2015 11:30:34 +0000 Subject: [PATCH] SSDM-2710: Extending MaximumIntensityProjectionGenerationAlgorithm by allowing to use thumbnails as image sources if available. SVN: 34957 --- .../dss/etl/Hdf5ThumbnailGenerator.java | 2 +- .../dto/api/IImageGenerationAlgorithm.java | 8 +- .../api/impl/EmptyImageCreationAlgorithm.java | 4 +- ...ntensityProjectionGenerationAlgorithm.java | 92 ++++++++++++++++++- ...ImagingDataSetRegistrationTransaction.java | 2 +- ...sityProjectionGenerationAlgorithmTest.java | 4 +- 6 files changed, 99 insertions(+), 13 deletions(-) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/Hdf5ThumbnailGenerator.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/Hdf5ThumbnailGenerator.java index 9ba79c9b523..0ea50170d90 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/Hdf5ThumbnailGenerator.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/Hdf5ThumbnailGenerator.java @@ -300,7 +300,7 @@ public class Hdf5ThumbnailGenerator implements IHDF5WriterClient return Status.OK; } - private String createThumbnailPath(ImageFileInfo plateImage, String channelCode) + public static String createThumbnailPath(ImageFileInfo plateImage, String channelCode) { StringBuilder newImagePath = new StringBuilder(); if (plateImage.hasWellLocation()) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/IImageGenerationAlgorithm.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/IImageGenerationAlgorithm.java index 2a00f8b6d65..3dad3085540 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/IImageGenerationAlgorithm.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/IImageGenerationAlgorithm.java @@ -3,6 +3,7 @@ package ch.systemsx.cisd.openbis.dss.etl.dto.api; import java.awt.image.BufferedImage; import java.util.List; +import ch.systemsx.cisd.etlserver.registrator.api.v2.IDataSet; import ch.systemsx.cisd.openbis.dss.etl.IImageProvider; import ch.systemsx.cisd.openbis.dss.etl.dto.api.impl.ImageDataSetInformation; @@ -16,7 +17,8 @@ public interface IImageGenerationAlgorithm /** * Creates thumbnails for the specified data set info. */ - public List<BufferedImage> generateImages(ImageDataSetInformation information, IImageProvider imageProvider); + public List<BufferedImage> generateImages(ImageDataSetInformation information, + List<IDataSet> thumbnailDatasets, IImageProvider imageProvider); /** * Returns the code of the data set to be registered containing these representative thumbnails. @@ -25,8 +27,8 @@ public interface IImageGenerationAlgorithm /** * Returns the thumbnail file name for the specified index. The index specifies the corresponding - * image returned by {@link #generateImages(ImageDataSetInformation, IImageProvider)}. - * Note, all file names generated by this method have to different. + * image returned by {@link #generateImages(ImageDataSetInformation, List, IImageProvider)}. + * Note, all file names generated by this method have to be different. */ public String getImageFileName(int index); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/EmptyImageCreationAlgorithm.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/EmptyImageCreationAlgorithm.java index 2e2bd6fbcb6..ac7f0e41309 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/EmptyImageCreationAlgorithm.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/EmptyImageCreationAlgorithm.java @@ -5,6 +5,7 @@ import java.io.Serializable; import java.util.Collections; import java.util.List; +import ch.systemsx.cisd.etlserver.registrator.api.v2.IDataSet; import ch.systemsx.cisd.openbis.dss.etl.IImageProvider; import ch.systemsx.cisd.openbis.dss.etl.dto.api.IImageGenerationAlgorithm; import ch.systemsx.cisd.openbis.generic.shared.IServer; @@ -21,7 +22,8 @@ public class EmptyImageCreationAlgorithm implements IImageGenerationAlgorithm, S } @Override - public List<BufferedImage> generateImages(ImageDataSetInformation information, IImageProvider imageProvider) + public List<BufferedImage> generateImages(ImageDataSetInformation information, + List<IDataSet> thumbnailDatasets, IImageProvider imageProvider) { return Collections.emptyList(); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithm.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithm.java index e3f11abeb47..daa1dc24683 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithm.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithm.java @@ -11,7 +11,13 @@ import java.util.List; import java.util.Map; import ch.rinn.restrictions.Private; +import ch.systemsx.cisd.etlserver.registrator.api.v2.IDataSet; +import ch.systemsx.cisd.etlserver.registrator.api.v2.impl.DataSet; import ch.systemsx.cisd.openbis.common.io.FileBasedContentNode; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.DefaultFileBasedHierarchicalContentFactory; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode; +import ch.systemsx.cisd.openbis.dss.etl.Hdf5ThumbnailGenerator; import ch.systemsx.cisd.openbis.dss.etl.IImageProvider; import ch.systemsx.cisd.openbis.dss.etl.dto.ImageLibraryInfo; import ch.systemsx.cisd.openbis.dss.etl.dto.api.Channel; @@ -19,6 +25,7 @@ import ch.systemsx.cisd.openbis.dss.etl.dto.api.ChannelColorComponent; import ch.systemsx.cisd.openbis.dss.etl.dto.api.IImageGenerationAlgorithm; import ch.systemsx.cisd.openbis.dss.etl.dto.api.ImageFileInfo; import ch.systemsx.cisd.openbis.dss.generic.server.images.ImageChannelsUtils; +import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size; import ch.systemsx.cisd.openbis.generic.shared.IServer; import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent; @@ -56,6 +63,8 @@ public class MaximumIntensityProjectionGenerationAlgorithm implements IImageGene private int width; private int height; + + private boolean useThumbnails; /** * Creates an instance for the specified data set type. The generated image will have the same size as @@ -94,6 +103,15 @@ public class MaximumIntensityProjectionGenerationAlgorithm implements IImageGene this.height = height; this.filename = filename; } + + /** + * Uses thumbnails (if present) instead of original images. + */ + public MaximumIntensityProjectionGenerationAlgorithm useThumbnails() + { + useThumbnails = true; + return this; + } @Override public String getDataSetTypeCode() @@ -102,13 +120,15 @@ public class MaximumIntensityProjectionGenerationAlgorithm implements IImageGene } @Override - public List<BufferedImage> generateImages(ImageDataSetInformation information, IImageProvider imageProvider) + public List<BufferedImage> generateImages(ImageDataSetInformation information, + List<IDataSet> thumbnailDatasets, IImageProvider imageProvider) { ImageDataSetStructure structure = information.getImageDataSetStructure(); ImageLibraryInfo library = structure.getImageStorageConfiguraton().tryGetImageLibrary(); List<ImageFileInfo> images = structure.getImages(); Map<String, ChannelAndColorComponent> channelsByCode = getChannelsByCode(structure); File incomingDirectory = information.getIncomingDirectory(); + File thumbnailDataSet = tryFindMatchingThumbnailDataSet(information, thumbnailDatasets); int maxIntensity = 0; for (ImageFileInfo imageFileInfo : images) { @@ -116,10 +136,10 @@ public class MaximumIntensityProjectionGenerationAlgorithm implements IImageGene { continue; } - String imagePath = imageFileInfo.getImageRelativePath(); - ChannelAndColorComponent channelAndColorComponent = channelsByCode.get(imageFileInfo.getChannelCode()); - String identifier = imageFileInfo.tryGetUniqueStringIdentifier(); - BufferedImage image = loadImage(imageProvider, incomingDirectory, imagePath, identifier, library); + String channelCode = imageFileInfo.getChannelCode(); + ChannelAndColorComponent channelAndColorComponent = channelsByCode.get(channelCode); + BufferedImage image = loadImage(imageProvider, library, images, incomingDirectory, + thumbnailDataSet, imageFileInfo, channelCode); image = ImageChannelsUtils.rescaleIfNot8Bit(image, 0f, channelAndColorComponent.channel.tryGetChannelColor()); image = ImageChannelsUtils.extractChannel(image, channelAndColorComponent.colorComponent); image = ImageChannelsUtils.transformGrayToColor(image, channelAndColorComponent.channel.tryGetChannelColor()); @@ -150,6 +170,68 @@ public class MaximumIntensityProjectionGenerationAlgorithm implements IImageGene } } + private BufferedImage loadImage(IImageProvider imageProvider, ImageLibraryInfo library, + List<ImageFileInfo> images, File incomingDirectory, + File thumbnailDataSet, ImageFileInfo imageFileInfo, String channelCode) + { + String imagePath = imageFileInfo.getImageRelativePath(); + String identifier = imageFileInfo.tryGetUniqueStringIdentifier(); + BufferedImage image = null; + if (thumbnailDataSet != null && useThumbnails) + { + IHierarchicalContent content = new DefaultFileBasedHierarchicalContentFactory() + .asHierarchicalContent(thumbnailDataSet, null); + String thumbnailPath = Hdf5ThumbnailGenerator.createThumbnailPath(imageFileInfo, channelCode); + IHierarchicalContentNode rootNode = content.getRootNode(); + String containerPath = rootNode.getChildNodes().get(0).getRelativePath(); + IHierarchicalContentNode node = content.tryGetNode(containerPath + "/" + thumbnailPath + ".png"); + if (node != null) + { + image = imageProvider.getImage(node, images.get(0).tryGetUniqueStringIdentifier(), null); + } + } + if (image == null) + { + image = loadImage(imageProvider, incomingDirectory, imagePath, identifier, library); + } + return image; + } + + private File tryFindMatchingThumbnailDataSet(ImageDataSetInformation information, List<IDataSet> thumbnailDatasets) + { + ThumbnailsInfo thumbnailsInfos = information.getThumbnailsInfos(); + if (thumbnailsInfos != null) + { + for (String permId : thumbnailsInfos.getThumbnailPhysicalDatasetsPermIds()) + { + Size dimension = thumbnailsInfos.tryGetDimension(permId); + if (dimension != null && (dimension.getWidth() == width || dimension.getHeight() == height)) + { + IDataSet thumbnailDataSet = tryFindDataSetByPermId(thumbnailDatasets, permId); + if (thumbnailDataSet instanceof DataSet) + { + return ((DataSet<?>) thumbnailDataSet).getDataSetStagingFolder(); + } + } + } + } + return null; + } + + + + private IDataSet tryFindDataSetByPermId(List<IDataSet> dataSets, String permId) + { + for (IDataSet dataSet : dataSets) + { + if (dataSet.getDataSetCode().equals(permId)) + { + return dataSet; + } + } + return null; + } + @Private BufferedImage loadImage(IImageProvider imageProvider, File incomingDirectory, String imagePath, String identifier, ImageLibraryInfo library) { diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/v2/ImagingDataSetRegistrationTransaction.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/v2/ImagingDataSetRegistrationTransaction.java index d626cd91230..40751157131 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/v2/ImagingDataSetRegistrationTransaction.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/v2/ImagingDataSetRegistrationTransaction.java @@ -384,7 +384,7 @@ public class ImagingDataSetRegistrationTransaction extends DataSetRegistrationTr { return; } - List<BufferedImage> images = algorithm.generateImages(imageDataSetInformation, imageCache); + List<BufferedImage> images = algorithm.generateImages(imageDataSetInformation, thumbnailDatasets, imageCache); if (images.size() > 0) { IDataSet representative = createNewDataSet(algorithm.getDataSetTypeCode()); diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithmTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithmTest.java index 572c124b62f..4eec12b4793 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithmTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/impl/MaximumIntensityProjectionGenerationAlgorithmTest.java @@ -186,7 +186,7 @@ public class MaximumIntensityProjectionGenerationAlgorithmTest extends AbstractF Channel channel2 = new Channel("CI2", "i2", new ChannelColorRGB(0, 120, 180)); structure.setChannels(Arrays.asList(channel1, channel2)); - List<BufferedImage> generatedImages = generationAlgorithm.generateImages(information, DUMMY_IMAGE_PROVIDER); + List<BufferedImage> generatedImages = generationAlgorithm.generateImages(information, null, DUMMY_IMAGE_PROVIDER); assertEquals("[incoming/images/i1.png: i1 [lib (reader: reader)], " + "incoming/images/i2.png: i2 [lib (reader: reader)]]", generationAlgorithm.recorder.toString()); @@ -208,7 +208,7 @@ public class MaximumIntensityProjectionGenerationAlgorithmTest extends AbstractF Channel channel2 = new Channel("CI3", "i3", new ChannelColorRGB(0, 120, 180)); structure.setChannels(Arrays.asList(channel1, channel2)); - List<BufferedImage> generatedImages = generationAlgorithm.generateImages(information, DUMMY_IMAGE_PROVIDER); + List<BufferedImage> generatedImages = generationAlgorithm.generateImages(information, null, DUMMY_IMAGE_PROVIDER); assertEquals("[incoming/images/i2.png: i2 [lib (reader: reader)], " + "incoming/images/i3.png: i3 [lib (reader: reader)]]", generationAlgorithm.recorder.toString()); -- GitLab