From 89fd557ff9de287113300b4da13d9a20c359a9c4 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Wed, 4 Jan 2012 10:06:14 +0000
Subject: [PATCH] LMS-2735 client API and facade clean up. Unit tests for new
 functionality.

SVN: 24089
---
 .../server/DssServiceRpcScreening.java        | 163 ++++++++++--------
 .../server/DssServiceRpcScreeningLogger.java  |  22 +--
 .../ImageRepresentationFormatFinder.java      |  56 ++++++
 .../server/logic/SimpleImageSetMetaData.java  |  73 --------
 .../server/logic/ZoomLevelFinder.java         |  68 --------
 .../api/v1/IDssServiceRpcScreening.java       |  56 +++---
 .../v1/IScreeningOpenbisServiceFacade.java    |  44 +++--
 .../api/v1/ScreeningOpenbisServiceFacade.java |  46 ++---
 ... => AbstractFormatSelectionCriterion.java} |  27 +--
 .../api/v1/dto/ColorDepthCriterion.java       |  10 +-
 .../shared/api/v1/dto/FileTypeCriterion.java  |  10 +-
 ...presentationFormatSelectionCriterion.java} |  13 +-
 .../shared/api/v1/dto/IImageSetMetaData.java  |  55 ------
 .../api/v1/dto/ImageMetaDataIdCriterion.java  |  42 -----
 .../api/v1/dto/ImageRepresentationFormat.java |  26 ++-
 .../shared/api/v1/dto/OriginalCriterion.java  |  12 +-
 .../shared/api/v1/dto/SizeCriterion.java      | 119 +++++++------
 .../basic/dto/ImageDatasetParameters.java     |  13 --
 .../shared/imaging/HCSDatasetLoader.java      |  25 ---
 .../server/DssServiceRpcScreeningTest.java    | 152 +++++++++++++---
 .../shared/api/v1/dto/SizeCriterionTest.java  |  91 ++++++++++
 21 files changed, 597 insertions(+), 526 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ImageRepresentationFormatFinder.java
 delete mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/SimpleImageSetMetaData.java
 delete mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ZoomLevelFinder.java
 rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/{AbstractImageSelectionCriterion.java => AbstractFormatSelectionCriterion.java} (52%)
 rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/{IImageSetSelectionCriterion.java => IImageRepresentationFormatSelectionCriterion.java} (64%)
 delete mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetMetaData.java
 delete mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageMetaDataIdCriterion.java
 create mode 100644 screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterionTest.java

diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
index 72dc83707a7..fae3a3acc04 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
@@ -58,14 +58,14 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IShareIdManager;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size;
-import ch.systemsx.cisd.openbis.dss.screening.server.logic.SimpleImageSetMetaData;
-import ch.systemsx.cisd.openbis.dss.screening.server.logic.ZoomLevelFinder;
+import ch.systemsx.cisd.openbis.dss.screening.server.logic.ImageRepresentationFormatFinder;
 import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening;
 import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.LoadImageConfiguration;
 import ch.systemsx.cisd.openbis.dss.shared.DssScreeningUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.CodeNormalizer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.AbstractFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.DatasetImageRepresentationFormats;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureInformation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector;
@@ -76,8 +76,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageChannel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
@@ -88,7 +87,6 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageRef
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.FeatureValue;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageSetMetaData;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.InternalImageChannel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.InternalImageTransformationInfo;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
@@ -245,25 +243,6 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc<IDssServiceRpc
         }
     }
 
-    public List<Set<IImageSetMetaData>> listImageSetsMetadata(String sessionToken,
-            List<? extends IImageDatasetIdentifier> imageDatasets)
-    {
-        List<Set<IImageSetMetaData>> sets = new ArrayList<Set<IImageSetMetaData>>();
-        for (IImageDatasetIdentifier dataSet : imageDatasets)
-        {
-            String datasetCode = dataSet.getDatasetCode();
-            IImagingDatasetLoader loader = createImageLoader(datasetCode);
-            List<ImageSetMetaData> zoomLevels = loader.getImageParameters().getZoomLevels();
-            Set<IImageSetMetaData> set = new HashSet<IImageSetMetaData>();
-            for (ImageSetMetaData zoomLevel : zoomLevels)
-            {
-                set.add(new SimpleImageSetMetaData(zoomLevel));
-            }
-            sets.add(set);
-        }
-        return sets;
-    }
-
     private ImageDatasetMetadata extractImageMetadata(IImageDatasetIdentifier dataset,
             IHierarchicalContent content)
     {
@@ -537,41 +516,69 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc<IDssServiceRpc
                 configuration.isOpenBisImageTransformationApplied(), imageLoadersMap);
     }
     
+    public InputStream loadImages(String sessionToken, List<PlateImageReference> imageReferences,
+            final ImageRepresentationFormat format)
+    {
+        for (PlateImageReference plateImageReference : imageReferences)
+        {
+            if (plateImageReference.getDatasetCode().equals(format.getDataSetCode()) == false)
+            {
+                throw new UserFailureException(
+                        "At least for one plate image reference the image representation format "
+                                + "is unknown: Plate image reference: " + plateImageReference
+                                + ", format: " + format);
+            }
+        }
+        IImageRepresentationFormatSelectionCriterion criterion =
+                new AbstractFormatSelectionCriterion()
+                    {
+                        private static final long serialVersionUID = 1L;
+
+                        @Override
+                        protected boolean accept(ImageRepresentationFormat availableFormat)
+                        {
+                            return format.getId() == availableFormat.getId();
+                        }
+                    };
+        return loadImages(sessionToken, imageReferences, criterion);
+    }
 
     public InputStream loadImages(String sessionToken, List<PlateImageReference> imageReferences,
-            IImageSetSelectionCriterion... criteria)
+            IImageRepresentationFormatSelectionCriterion... criteria)
     {
-        ZoomLevelFinder finder = new ZoomLevelFinder(criteria);
         final Map<String, IImagingDatasetLoader> imageLoadersMap =
                 getImageDatasetsMap(sessionToken, imageReferences);
-        Map<String, ImageSetMetaData> dataSetToZoomLevelMap = new HashMap<String, ImageSetMetaData>();
-        for (Entry<String, IImagingDatasetLoader> entry : imageLoadersMap.entrySet())
+        Map<String, ImgImageDatasetDTO> imageDataSetMap =
+                createDataSetCodeToImageDataSetMap(imageReferences);
+        ImageRepresentationFormatFinder finder = new ImageRepresentationFormatFinder(criteria);
+        Map<String, ImageRepresentationFormat> dataSetToImageReferenceFormatMap =
+                new HashMap<String, ImageRepresentationFormat>();
+        for (Entry<String, ImgImageDatasetDTO> entry : imageDataSetMap.entrySet())
         {
             String dataSetCode = entry.getKey();
-            IImagingDatasetLoader loader = entry.getValue();
-            ImageDatasetParameters imageParameters = loader.getImageParameters();
-            List<ImageSetMetaData> filteredZoomLevels =
-                    finder.find(imageParameters.getZoomLevels());
-            if (filteredZoomLevels.isEmpty())
+            List<ImageRepresentationFormat> filteredFormats =
+                    finder.find(getImageRepresentationFormats(entry.getValue()));
+            if (filteredFormats.isEmpty())
             {
-                throw new UserFailureException("No image set fitting criteria found for data set "
-                        + dataSetCode + ".");
+                throw new UserFailureException(
+                        "No image representation format fitting criteria found for data set "
+                                + dataSetCode + ".");
             }
-            if (filteredZoomLevels.size() > 1)
+            if (filteredFormats.size() > 1)
             {
-                throw new UserFailureException("To many image sets fitting criteria for data set "
-                        + dataSetCode + ": " + filteredZoomLevels);
+                throw new UserFailureException(
+                        "To many image representation formats fitting criteria for data set "
+                                + dataSetCode + ": " + filteredFormats);
             }
-            dataSetToZoomLevelMap.put(dataSetCode, filteredZoomLevels.get(0));
+            dataSetToImageReferenceFormatMap.put(dataSetCode, filteredFormats.get(0));
         }
-        List<IHierarchicalContentNode> imageContents =
-                new ArrayList<IHierarchicalContentNode>();
+        List<IHierarchicalContentNode> imageContents = new ArrayList<IHierarchicalContentNode>();
         for (PlateImageReference imageReference : imageReferences)
         {
             String datasetCode = imageReference.getDatasetCode();
             IImagingDatasetLoader loader = imageLoadersMap.get(datasetCode);
-            ImageSetMetaData zoomLevel = dataSetToZoomLevelMap.get(datasetCode);
-            Size size = new Size(zoomLevel.getWidth(), zoomLevel.getHeight());
+            ImageRepresentationFormat format = dataSetToImageReferenceFormatMap.get(datasetCode);
+            Size size = new Size(format.getWidth(), format.getHeight());
             addImageContentTo(imageContents, loader, imageReference, size, null, false, false);
         }
         return new ConcatenatedContentInputStream(true, imageContents);
@@ -791,59 +798,71 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc<IDssServiceRpc
     public List<DatasetImageRepresentationFormats> listAvailableImageRepresentationFormats(
             String sessionToken, List<? extends IDatasetIdentifier> imageDatasets)
     {
-        IImagingReadonlyQueryDAO queryInterface = getDAO();
         ArrayList<DatasetImageRepresentationFormats> result =
                 new ArrayList<DatasetImageRepresentationFormats>(imageDatasets.size());
 
-        // Get the database identifiers for the data sets
-        String[] permIds = new String[imageDatasets.size()];
-        for (int i = 0; i < imageDatasets.size(); ++i)
-        {
-            permIds[i] = imageDatasets.get(i).getPermId();
-        }
-        List<ImgImageDatasetDTO> primImageDatasets =
-                queryInterface.listImageDatasetsByPermId(permIds);
-
-        // Convert this to a hash map for faster indexing
-        HashMap<String, ImgImageDatasetDTO> imageDataSetMap =
-                new HashMap<String, ImgImageDatasetDTO>();
-        for (ImgImageDatasetDTO primImageDataSet : primImageDatasets)
-        {
-            imageDataSetMap.put(primImageDataSet.getPermId(), primImageDataSet);
-        }
+        Map<String, ImgImageDatasetDTO> imageDataSetMap =
+                createDataSetCodeToImageDataSetMap(imageDatasets);
 
         // Not an efficient way to execute this query, but it reuses the queries at our disposal
         for (IDatasetIdentifier imageDataset : imageDatasets)
         {
-            ImgImageDatasetDTO primImageDataSet = imageDataSetMap.get(imageDataset.getPermId());
+            String dataSetCode = imageDataset.getPermId();
+            ImgImageDatasetDTO primImageDataSet = imageDataSetMap.get(dataSetCode);
             if (null == primImageDataSet)
             {
                 List<ImageRepresentationFormat> emptyList = Collections.emptyList();
                 DatasetImageRepresentationFormats datasetResult =
                         new DatasetImageRepresentationFormats(imageDataset, emptyList);
                 result.add(datasetResult);
-                continue;
+            } else
+            {
+                List<ImageRepresentationFormat> formats =
+                        getImageRepresentationFormats(primImageDataSet);
+                DatasetImageRepresentationFormats datasetResult =
+                        new DatasetImageRepresentationFormats(imageDataset, formats);
+                result.add(datasetResult);
             }
-            List<ImgImageZoomLevelDTO> zoomLevels =
-                    queryInterface.listImageZoomLevels(primImageDataSet.getId());
-            List<ImageRepresentationFormat> formats =
-                    convertZoomLevelsToRepresentationFormats(zoomLevels);
-            DatasetImageRepresentationFormats datasetResult =
-                    new DatasetImageRepresentationFormats(imageDataset, formats);
-            result.add(datasetResult);
         }
         return result;
     }
 
+    private List<ImageRepresentationFormat> getImageRepresentationFormats(ImgImageDatasetDTO imageDataSet)
+    {
+        List<ImgImageZoomLevelDTO> zoomLevels = getDAO().listImageZoomLevels(imageDataSet.getId());
+        return convertZoomLevelsToRepresentationFormats(imageDataSet.getPermId(), zoomLevels);
+    }
+
+    private Map<String, ImgImageDatasetDTO> createDataSetCodeToImageDataSetMap(
+            List<? extends IDatasetIdentifier> imageDatasets)
+    {
+        Set<String> permIds = new HashSet<String>();
+        for (IDatasetIdentifier identifier : imageDatasets)
+        {
+            permIds.add(identifier.getPermId());
+        }
+        List<ImgImageDatasetDTO> primImageDatasets =
+                getDAO().listImageDatasetsByPermId(permIds.toArray(new String[permIds.size()]));
+
+        // Convert this to a hash map for faster indexing
+        HashMap<String, ImgImageDatasetDTO> imageDataSetMap =
+                new HashMap<String, ImgImageDatasetDTO>();
+        for (ImgImageDatasetDTO primImageDataSet : primImageDatasets)
+        {
+            imageDataSetMap.put(primImageDataSet.getPermId(), primImageDataSet);
+        }
+        return imageDataSetMap;
+    }
+
     private List<ImageRepresentationFormat> convertZoomLevelsToRepresentationFormats(
-            List<ImgImageZoomLevelDTO> zoomLevels)
+            String dataSetCode, List<ImgImageZoomLevelDTO> zoomLevels)
     {
         ArrayList<ImageRepresentationFormat> results = new ArrayList<ImageRepresentationFormat>();
         for (ImgImageZoomLevelDTO zoomLevel : zoomLevels)
         {
             ImageRepresentationFormat result =
-                    new ImageRepresentationFormat(zoomLevel.getIsOriginal(), zoomLevel.getWidth(),
-                            zoomLevel.getHeight(), zoomLevel.getColorDepth(),
+                    new ImageRepresentationFormat(dataSetCode, zoomLevel.getId(), zoomLevel.getIsOriginal(),
+                            zoomLevel.getWidth(), zoomLevel.getHeight(), zoomLevel.getColorDepth(),
                             zoomLevel.getFileType());
             results.add(result);
         }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningLogger.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningLogger.java
index 0573ed63ad5..3022f6bafbe 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningLogger.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningLogger.java
@@ -19,7 +19,6 @@ package ch.systemsx.cisd.openbis.dss.screening.server;
 import java.io.InputStream;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Set;
 
 import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.common.spring.IInvocationLoggerContext;
@@ -35,9 +34,9 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MicroscopyImageReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference;
@@ -202,13 +201,6 @@ public class DssServiceRpcScreeningLogger extends AbstractServerLogger implement
         return null;
     }
 
-    public List<Set<IImageSetMetaData>> listImageSetsMetadata(String sessionToken,
-            List<? extends IImageDatasetIdentifier> imageDatasets)
-    {
-        logAccess(sessionToken, "load_image_sets_metadata", "DATA_SETS(%s)", imageDatasets);
-        return null;
-    }
-
     public void checkDatasetsAuthorizationForIDatasetIdentifier(String sessionToken,
             List<? extends IDatasetIdentifier> featureDatasets)
     {
@@ -248,7 +240,15 @@ public class DssServiceRpcScreeningLogger extends AbstractServerLogger implement
     }
 
     public InputStream loadImages(String sessionToken, List<PlateImageReference> imageReferences,
-            IImageSetSelectionCriterion... criteria)
+            ImageRepresentationFormat format)
+    {
+        logAccess(sessionToken, "load_images", "IMAGE_REFERENCES(%s) FORMAT(%s)", imageReferences,
+                format);
+        return null;
+    }
+
+    public InputStream loadImages(String sessionToken, List<PlateImageReference> imageReferences,
+            IImageRepresentationFormatSelectionCriterion... criteria)
     {
         logAccess(sessionToken, "load_images", "IMAGE_REFERENCES(%s) CRITERIA(%s)",
                 imageReferences, Arrays.asList(criteria));
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ImageRepresentationFormatFinder.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ImageRepresentationFormatFinder.java
new file mode 100644
index 00000000000..9605ee80536
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ImageRepresentationFormatFinder.java
@@ -0,0 +1,56 @@
+/*
+ * 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.screening.server.logic;
+
+import java.util.List;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
+
+/**
+ * Find {@link ImageRepresentationFormat} instances which fulfill some criteria.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class ImageRepresentationFormatFinder
+{
+    private final IImageRepresentationFormatSelectionCriterion[] criteria;
+
+    public ImageRepresentationFormatFinder(IImageRepresentationFormatSelectionCriterion... criteria)
+    {
+        if (criteria == null || criteria.length == 0)
+        {
+            throw new UserFailureException("No criterion specified.");
+        }
+        this.criteria = criteria;
+    }
+        
+    public List<ImageRepresentationFormat> find(List<ImageRepresentationFormat> formats)
+    {
+        List<ImageRepresentationFormat> filteredFormats = formats;
+        for (IImageRepresentationFormatSelectionCriterion criterion : criteria)
+        {
+            filteredFormats = criterion.getMatching(filteredFormats);
+            if (filteredFormats.size() == 1)
+            {
+                break;
+            }
+        }
+        return filteredFormats;
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/SimpleImageSetMetaData.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/SimpleImageSetMetaData.java
deleted file mode 100644
index faf8a8b4184..00000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/SimpleImageSetMetaData.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.screening.server.logic;
-
-import java.io.Serializable;
-
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Geometry;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageSetMetaData;
-
-/**
- * Implementation of {@link IImageSetMetaData} which wraps a {@link ImageSetMetaData}.
- *
- * @author Franz-Josef Elmer
- */
-public class SimpleImageSetMetaData implements IImageSetMetaData, Serializable
-{
-    private static final long serialVersionUID = 1L;
-    
-    private final Geometry size;
-    private final ImageSetMetaData metaData;
-
-    public SimpleImageSetMetaData(ImageSetMetaData zoomLevel)
-    {
-        this.metaData = zoomLevel;
-        size = Geometry.createFromCartesianDimensions(zoomLevel.getWidth(), zoomLevel.getHeight());
-    }
-
-    public ImageSetMetaData getMetaData()
-    {
-        return metaData;
-    }
-
-    public long getId()
-    {
-        return metaData.getId();
-    }
-
-    public boolean isOriginal()
-    {
-        return metaData.isOriginal();
-    }
-
-    public Geometry getSize()
-    {
-        return size;
-    }
-
-    public Integer getColorDepth()
-    {
-        return metaData.getColorDepth();
-    }
-
-    public String getFileType()
-    {
-        return metaData.getFileType();
-    }
-
-}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ZoomLevelFinder.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ZoomLevelFinder.java
deleted file mode 100644
index 0aed5879119..00000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/logic/ZoomLevelFinder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.screening.server.logic;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageZoomLevelDTO;
-
-/**
- * Find {@link ImgImageZoomLevelDTO} instances which fulfill some criteria.
- *
- * @author Franz-Josef Elmer
- */
-public class ZoomLevelFinder
-{
-    private final IImageSetSelectionCriterion[] criteria;
-
-    public ZoomLevelFinder(IImageSetSelectionCriterion... criteria)
-    {
-        this.criteria = criteria;
-    }
-        
-    public List<ImageSetMetaData> find(List<ImageSetMetaData> zoomLevels)
-    {
-        List<ImageSetMetaData> filteredLevels = zoomLevels;
-        for (IImageSetSelectionCriterion criterion : criteria)
-        {
-            if (filteredLevels.size() == 1)
-            {
-                break;
-            }
-            List<IImageSetMetaData> adaptedFilteredLevels = new ArrayList<IImageSetMetaData>();
-            for (ImageSetMetaData level : filteredLevels)
-            {
-                adaptedFilteredLevels.add(new SimpleImageSetMetaData(level));
-            }
-            adaptedFilteredLevels = criterion.getMatching(adaptedFilteredLevels);
-            filteredLevels = new ArrayList<ImageSetMetaData>();
-            for (IImageSetMetaData adaptedFilteredLevel : adaptedFilteredLevels)
-            {
-                if (adaptedFilteredLevel instanceof SimpleImageSetMetaData)
-                {
-                    filteredLevels.add(((SimpleImageSetMetaData) adaptedFilteredLevel)
-                            .getMetaData());
-                }
-            }
-        }
-        return filteredLevels;
-    }
-}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java
index 4f887d5b66a..b1c0ab7d94d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.dss.screening.shared.api.v1;
 
 import java.io.InputStream;
 import java.util.List;
-import java.util.Set;
 
 import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.common.api.IRpcService;
@@ -38,9 +37,9 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MicroscopyImageReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference;
@@ -267,21 +266,42 @@ public interface IDssServiceRpcScreening extends IRpcService
     
     /**
      * Provides images for the specified list of image references (specified by data set code, well
-     * position, channel and tile) and image selection criteria. These criteria are applied to the
-     * {@link IImageSetMetaData} sets of each data set. Beside of the set of original images a data
-     * set can have other image sets like thumbnails of various sizes. The provided array of
-     * {@link IImageSetSelectionCriterion} are applied one after another onto the set of
-     * {@link IImageSetMetaData} until its size is reduced to one.
+     * position, channel and tile) and specified image representation format. The
+     * {@link ImageRepresentationFormat} argument should be an object returned by
+     * {@link #listAvailableImageRepresentationFormats(String, List)}. This method assumes that all
+     * image references belong to the same data set which has image representations of specified
+     * format.
      * 
-     * @throws UserFailureException if for one data set the filtered {@link IImageSetMetaData} set
-     *             has size zero or greater than one.
+     * @throws UserFailureException if the specified format refers to an image representations
+     *             unknown by at least one plate image reference.
+     * @since 1.10
      */
     @MinimalMinorVersion(10)
     @DataSetAccessGuard
     public InputStream loadImages(String sessionToken,
             @AuthorizationGuard(guardClass = DatasetIdentifierPredicate.class)
-            List<PlateImageReference> imageReferences, IImageSetSelectionCriterion... criteria);
+            List<PlateImageReference> imageReferences, ImageRepresentationFormat format);
     
+    /**
+     * Provides images for the specified list of image references (specified by data set code, well
+     * position, channel and tile) and image selection criteria. These criteria are applied to the
+     * {@link ImageRepresentationFormat} sets of each data set. Beside of the set of original images
+     * a data set can have other image representations like thumbnails of various sizes. The
+     * provided array of {@link IImageRepresentationFormatSelectionCriterion} are applied one after
+     * another onto the set of {@link ImageRepresentationFormat} until its size is reduced to one.
+     * 
+     * @throws UserFailureException if no criterion has been specified (i.e. <code>criteria</code>
+     *             is an empty array) or if for at least one data set the filtered
+     *             {@link ImageRepresentationFormat} set has size zero or greater than one.
+     * @since 1.10
+     */
+    @MinimalMinorVersion(10)
+    @DataSetAccessGuard
+    public InputStream loadImages(String sessionToken,
+            @AuthorizationGuard(guardClass = DatasetIdentifierPredicate.class)
+            List<PlateImageReference> imageReferences,
+            IImageRepresentationFormatSelectionCriterion... criteria);
+
     /**
      * Provide thumbnail images for specified microscopy data set. If no thumbnails are stored on
      * the server, this method will return an empty stream. Images of all tiles are delivered.
@@ -384,21 +404,11 @@ public interface IDssServiceRpcScreening extends IRpcService
             List<? extends IImageDatasetIdentifier> imageDatasets);
     
     /**
-     * Returns for each of the specified image data sets the meta data of available image sets.
-     * 
-     * @since 1.10
-     */
-    @MinimalMinorVersion(10)
-    @DataSetAccessGuard
-    public List<Set<IImageSetMetaData>> listImageSetsMetadata(String sessionToken,
-            @AuthorizationGuard(guardClass = DatasetIdentifierPredicate.class)
-            List<? extends IImageDatasetIdentifier> imageDatasets);
-
-    /**
-     * Return image representation formats available for the specified image datasets.
+     * Return image representation formats available for the specified image data sets.
      * 
      * @param imageDatasets The image data sets for which the representation formats are requested.
      * @return A list with one entry for each in <b>imageDatasets</b>. 
+     * @since 1.10
      */
     @MinimalMinorVersion(10)
     @DataSetAccessGuard
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
index 98aa555ea67..e5d8f0c887a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
@@ -20,7 +20,6 @@ import java.io.File;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.common.api.retry.Retry;
@@ -44,10 +43,10 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MaterialTypeIdentifier;
@@ -770,20 +769,36 @@ public interface IScreeningOpenbisServiceFacade
 
     /**
      * Provides images for the specified list of image references (specified by data set code, well
-     * position, channel and tile) and image selection criteria. These criteria are applied to the
-     * {@link IImageSetMetaData} sets of each data set. Beside of the set of original images a data
-     * set can have other image sets like thumbnails of various sizes. The provided array of
-     * {@link IImageSetSelectionCriterion} are applied one after another onto the set of
-     * {@link IImageSetMetaData} until its size is reduced to one.
+     * position, channel and tile) and specified image representation format. The
+     * {@link ImageRepresentationFormat} argument should be an object returned by
+     * {@link #listAvailableImageRepresentationFormats(List)}. This method assumes that all image
+     * references belong to the same data set which has image representations of specified format.
      * 
      * @param plateImageHandler Handler for the delivered images.
-     * @throws UserFailureException if for one data set the filtered {@link IImageSetMetaData} set
-     *             has size zero or greater than one.
+     * @throws UserFailureException if the specified format refers to an image representations
+     *             unknown by at least one plate image reference.
      */
     public void loadImages(List<PlateImageReference> imageReferences,
-            IPlateImageHandler plateImageHandler, IImageSetSelectionCriterion... criteria)
+            IPlateImageHandler plateImageHandler, ImageRepresentationFormat format)
             throws IOException;
 
+    /**
+     * Provides images for the specified list of image references (specified by data set code, well
+     * position, channel and tile) and image selection criteria. These criteria are applied to the
+     * {@link ImageRepresentationFormat} sets of each data set. Beside of the set of original images
+     * a data set can have other image representations like thumbnails of various sizes. The
+     * provided array of {@link IImageRepresentationFormatSelectionCriterion} are applied one after
+     * another onto the set of {@link ImageRepresentationFormat} until its size is reduced to one.
+     * 
+     * @param plateImageHandler Handler for the delivered images.
+     * @throws UserFailureException if no criterion has been specified (i.e. <code>criteria</code>
+     *             is an empty array) or if for at least one data set the filtered
+     *             {@link ImageRepresentationFormat} set has size zero or greater than one.
+     */
+    public void loadImages(List<PlateImageReference> imageReferences,
+            IPlateImageHandler plateImageHandler,
+            IImageRepresentationFormatSelectionCriterion... criteria) throws IOException;
+
     /**
      * Loads the PNG-encoded image for the specified <var>imageReference</var>.
      * <p>
@@ -852,13 +867,6 @@ public interface IScreeningOpenbisServiceFacade
     public List<ImageDatasetMetadata> listImageMetadata(
             List<? extends IImageDatasetIdentifier> imageDatasets);
 
-    /**
-     * Returns for each of the specified image data sets the meta data of available image sets.
-     */
-    @Retry
-    public List<Set<IImageSetMetaData>> listImageSetsMetadata(
-            List<? extends IImageDatasetIdentifier> imageDatasets);
-
     /**
      * For a given list of <var>plates</var>, return the mapping of plate wells to materials
      * contained in each well.
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
index dc796a8cd0d..6e78202370a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
@@ -70,10 +70,10 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Geometry;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetMetaData;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageSetSelectionCriterion;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageRepresentationFormatSelectionCriterion;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageRepresentationFormat;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.MaterialTypeIdentifier;
@@ -1609,24 +1609,6 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         return result;
     }
 
-    public List<Set<IImageSetMetaData>> listImageSetsMetadata(
-            List<? extends IImageDatasetIdentifier> imageDatasets)
-    {
-        final List<Set<IImageSetMetaData>> list = new ArrayList<Set<IImageSetMetaData>>();
-        metaDataMultiplexer.process(imageDatasets, new IReferenceHandler<IImageDatasetIdentifier>()
-            {
-                public void handle(DssServiceRpcScreeningHolder dssService,
-                        List<IImageDatasetIdentifier> references)
-                {
-                    checkDSSMinimalMinorVersion(dssService, "listImageSetsMetadata", List.class);
-                    List<Set<IImageSetMetaData>> sets =
-                            dssService.getService().listImageSetsMetadata(sessionToken, references);
-                    list.addAll(sets);
-                }
-            });
-        return list;
-    }
-
     public List<PlateWellMaterialMapping> listPlateMaterialMapping(
             List<? extends PlateIdentifier> plates,
             MaterialTypeIdentifier materialTypeIdentifierOrNull)
@@ -1833,9 +1815,29 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
                     });
     }
 
+    public void loadImages(final List<PlateImageReference> imageReferences,
+            final IPlateImageHandler plateImageHandler, final ImageRepresentationFormat format)
+            throws IOException
+    {
+        plateImageReferencesMultiplexer.process(imageReferences,
+                new IReferenceHandler<PlateImageReference>()
+                    {
+                        public void handle(DssServiceRpcScreeningHolder dssService,
+                                List<PlateImageReference> references)
+                        {
+                            checkDSSMinimalMinorVersion(dssService, "loadImages", List.class,
+                                    ImageRepresentationFormat.class);
+                            final InputStream stream =
+                                    dssService.getService().loadImages(sessionToken, references,
+                                            format);
+                            processImagesStreamUnchecked(plateImageHandler, references, stream);
+                        }
+                    });
+    }
+
     public void loadImages(List<PlateImageReference> imageReferences,
             final IPlateImageHandler plateImageHandler,
-            final IImageSetSelectionCriterion... criteria) throws IOException
+            final IImageRepresentationFormatSelectionCriterion... criteria) throws IOException
     {
         plateImageReferencesMultiplexer.process(imageReferences,
                 new IReferenceHandler<PlateImageReference>()
@@ -1844,7 +1846,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
                                 List<PlateImageReference> references)
                         {
                             checkDSSMinimalMinorVersion(dssService, "loadImages", List.class,
-                                    IImageSetSelectionCriterion[].class);
+                                    IImageRepresentationFormatSelectionCriterion[].class);
                             final InputStream stream =
                                     dssService.getService().loadImages(sessionToken, references,
                                             criteria);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractImageSelectionCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractFormatSelectionCriterion.java
similarity index 52%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractImageSelectionCriterion.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractFormatSelectionCriterion.java
index 5396f41386c..b4c3fce8253 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractImageSelectionCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/AbstractFormatSelectionCriterion.java
@@ -20,32 +20,35 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Abstract super class of {@link IImageSetSelectionCriterion} which accepting matching
- * {@link IImageSetMetaData} instance individually. 
- *
+ * Abstract super class of {@link IImageRepresentationFormatSelectionCriterion} which accepting
+ * matching {@link ImageRepresentationFormat} instance individually.
+ * 
  * @author Franz-Josef Elmer
  */
-public abstract class AbstractImageSelectionCriterion implements IImageSetSelectionCriterion
+public abstract class AbstractFormatSelectionCriterion implements
+        IImageRepresentationFormatSelectionCriterion
 {
     private static final long serialVersionUID = 1L;
 
-    public List<IImageSetMetaData> getMatching(List<IImageSetMetaData> imageMetaData)
+    public List<ImageRepresentationFormat> getMatching(
+            List<ImageRepresentationFormat> imageRepresentationFormats)
     {
-        List<IImageSetMetaData> filteredMetaData = new ArrayList<IImageSetMetaData>();
-        for (IImageSetMetaData metaData : imageMetaData)
+        List<ImageRepresentationFormat> filteredMetaData =
+                new ArrayList<ImageRepresentationFormat>();
+        for (ImageRepresentationFormat format : imageRepresentationFormats)
         {
-            if (accept(metaData))
+            if (accept(format))
             {
-                filteredMetaData.add(metaData);
+                filteredMetaData.add(format);
             }
         }
         return filteredMetaData;
     }
-    
+
     /**
-     * Returns <code>true</code> if the specified {@link IImageSetMetaData} instance is
+     * Returns <code>true</code> if the specified {@link ImageRepresentationFormat} instance is
      * accepted by this criterion.
      */
-    protected abstract boolean accept(IImageSetMetaData imageMetaData);
+    protected abstract boolean accept(ImageRepresentationFormat format);
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ColorDepthCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ColorDepthCriterion.java
index 2f5d6332677..0ae6932fe6d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ColorDepthCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ColorDepthCriterion.java
@@ -25,12 +25,14 @@ import java.util.Set;
  *
  * @author Franz-Josef Elmer
  */
-public class ColorDepthCriterion extends AbstractImageSelectionCriterion
+public class ColorDepthCriterion extends AbstractFormatSelectionCriterion
 {
+    private static final long serialVersionUID = 1L;
+    
     private final Set<Integer> colorDepth;
 
     /**
-     * Creates an instance which allows all images with specified color depths.
+     * Creates an instance which allows all image representation formats with specified color depths.
      */
     public ColorDepthCriterion(Integer... colorDepths)
     {
@@ -38,9 +40,9 @@ public class ColorDepthCriterion extends AbstractImageSelectionCriterion
     }
 
     @Override
-    protected boolean accept(IImageSetMetaData imageMetaData)
+    protected boolean accept(ImageRepresentationFormat format)
     {
-        return colorDepth.contains(imageMetaData.getColorDepth());
+        return colorDepth.contains(format.getColorDepth());
     }
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FileTypeCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FileTypeCriterion.java
index 7ca3e4a72fb..9d001d303ef 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FileTypeCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FileTypeCriterion.java
@@ -25,12 +25,14 @@ import java.util.Set;
  *
  * @author Franz-Josef Elmer
  */
-public class FileTypeCriterion extends AbstractImageSelectionCriterion
+public class FileTypeCriterion extends AbstractFormatSelectionCriterion
 {
+    private static final long serialVersionUID = 1L;
+    
     private final Set<String> fileTypes;
 
     /**
-     * Creates an instance which accepts all images of specified file types.
+     * Creates an instance which accepts all image representation formats of specified file types.
      */
     public FileTypeCriterion(String... fileTypes)
     {
@@ -38,9 +40,9 @@ public class FileTypeCriterion extends AbstractImageSelectionCriterion
     }
 
     @Override
-    protected boolean accept(IImageSetMetaData imageMetaData)
+    protected boolean accept(ImageRepresentationFormat format)
     {
-        return fileTypes.contains(imageMetaData.getFileType());
+        return fileTypes.contains(format.getFileType());
     }
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetSelectionCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageRepresentationFormatSelectionCriterion.java
similarity index 64%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetSelectionCriterion.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageRepresentationFormatSelectionCriterion.java
index c4e73f568f9..3895733af55 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetSelectionCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageRepresentationFormatSelectionCriterion.java
@@ -20,15 +20,16 @@ import java.io.Serializable;
 import java.util.List;
 
 /**
- * Interface of an image selection criterion based on {@link IImageSetMetaData}.
- *
+ * Interface of an image selection criterion based on {@link ImageRepresentationFormat}.
+ * 
  * @author Franz-Josef Elmer
  */
-public interface IImageSetSelectionCriterion extends Serializable
+public interface IImageRepresentationFormatSelectionCriterion extends Serializable
 {
     /**
-     * Returns all {@link IImageSetMetaData} objects from the specified list which fulfill this
-     * criterion.
+     * Returns all {@link ImageRepresentationFormat} objects from the specified list which fulfill
+     * this criterion.
      */
-    public List<IImageSetMetaData> getMatching(List<IImageSetMetaData> imageMetaData);
+    public List<ImageRepresentationFormat> getMatching(
+            List<ImageRepresentationFormat> imageRepresentationFormats);
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetMetaData.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetMetaData.java
deleted file mode 100644
index f049eb105da..00000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/IImageSetMetaData.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.plugin.screening.shared.api.v1.dto;
-
-/**
- * Interface for meta data of image sets.
- *
- * @author Franz-Josef Elmer
- */
-public interface IImageSetMetaData
-{
-    /**
-     * Returns the unique id of this image set meta data.
-     */
-    public long getId();
-    
-    /**
-     * Returns <code>true</code> if this image set contains the original images.
-     */
-    public boolean isOriginal();
-    
-    /**
-     * Returns the size of all images in the set.
-     */
-    public Geometry getSize();
-    
-    /**
-     * Returns the color depth (if known) of all images in the set.
-     * 
-     * @return <code>null</code> if color depth is unknown.
-     */
-    public Integer getColorDepth();
-    
-    /**
-     * Returns the file type (if known) of all images in the set.
-     * 
-     * @return <code>null</code> if file type is unknown.
-     */
-    public String getFileType();
-    
-}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageMetaDataIdCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageMetaDataIdCriterion.java
deleted file mode 100644
index 970cd1fb3eb..00000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageMetaDataIdCriterion.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.plugin.screening.shared.api.v1.dto;
-
-/**
- * Criterion based on the ID of an {@link IImageSetMetaData} object.
- *
- * @author Franz-Josef Elmer
- */
-public class ImageMetaDataIdCriterion extends AbstractImageSelectionCriterion
-{
-    private final long imageMetaDataId;
-
-    /**
-     * Creates an instance based on the specified ID.
-     */
-    public ImageMetaDataIdCriterion(long imageMetaDataId)
-    {
-        this.imageMetaDataId = imageMetaDataId;
-    }
-
-    @Override
-    protected boolean accept(IImageSetMetaData imageMetaData)
-    {
-        return imageMetaDataId == imageMetaData.getId();
-    }
-
-}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageRepresentationFormat.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageRepresentationFormat.java
index ef49a97f580..704919eb47d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageRepresentationFormat.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/ImageRepresentationFormat.java
@@ -33,6 +33,10 @@ public class ImageRepresentationFormat implements Serializable
 {
     private static final long serialVersionUID = 1L;
 
+    private final String dataSetCode;
+    
+    private final long id;
+    
     private boolean original;
 
     private Integer width;
@@ -46,16 +50,20 @@ public class ImageRepresentationFormat implements Serializable
     /**
      * Constructor.
      * 
+     * @param dataSetCode 
+     * @param id 
      * @param original
      * @param width
      * @param height
      * @param colorDepth
      * @param fileType
      */
-    public ImageRepresentationFormat(boolean original, Integer width, Integer height,
+    public ImageRepresentationFormat(String dataSetCode, long id, boolean original, Integer width, Integer height,
             Integer colorDepth, String fileType)
     {
         super();
+        this.dataSetCode = dataSetCode;
+        this.id = id;
         this.original = original;
         this.width = width;
         this.height = height;
@@ -63,6 +71,22 @@ public class ImageRepresentationFormat implements Serializable
         this.fileType = fileType;
     }
 
+    /**
+     * Returns the data set code to which this image representation format belongs.
+     */
+    public String getDataSetCode()
+    {
+        return dataSetCode;
+    }
+
+    /**
+     * Return the ID of this image representation format. 
+     */
+    public long getId()
+    {
+        return id;
+    }
+
     /**
      * @return True if the format is the original format of the underlying image.
      */
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/OriginalCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/OriginalCriterion.java
index af8314eba28..42cc82755e9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/OriginalCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/OriginalCriterion.java
@@ -17,18 +17,20 @@
 package ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto;
 
 /**
- * Criterion which filters image meta data concerning whether they are original or not.
+ * Criterion which filters image representation formats concerning whether they are original or not.
  *
  * @author Franz-Josef Elmer
  */
-public class OriginalCriterion extends AbstractImageSelectionCriterion
+public class OriginalCriterion extends AbstractFormatSelectionCriterion
 {
+    private static final long serialVersionUID = 1L;
+    
     private final boolean original;
 
     /**
      * Creates an instance based on the specified flag. If the flag is <code>true</code>
      * all original images fulfill this criterion. If the flag is <code>false</code> all
-     * images which are not original (e.g. thumbnails) fullfil this criterion.
+     * images which are not original (e.g. thumbnails) fulfill this criterion.
      */
     public OriginalCriterion(boolean original)
     {
@@ -36,9 +38,9 @@ public class OriginalCriterion extends AbstractImageSelectionCriterion
     }
 
     @Override
-    protected boolean accept(IImageSetMetaData imageMetaData)
+    protected boolean accept(ImageRepresentationFormat format)
     {
-        return imageMetaData.isOriginal() == original;
+        return format.isOriginal() == original;
     }
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterion.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterion.java
index c8cbcedc26e..3324974d4e4 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterion.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterion.java
@@ -26,128 +26,143 @@ import java.util.List;
  * 
  * @author Franz-Josef Elmer
  */
-public class SizeCriterion implements IImageSetSelectionCriterion
+public class SizeCriterion implements IImageRepresentationFormatSelectionCriterion
 {
     private static final long serialVersionUID = 1L;
 
     public static enum Type
     {
         /**
-         * Picks that image set where the image size is the largest one which just fits into
-         * a bounding box specified by width and height.
+         * Picks that format where the image size is the largest one which just fits into a
+         * bounding box specified by width and height.
          */
         LARGEST_IN_BOUNDING_BOX()
         {
             @Override
-            void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                    List<IImageSetMetaData> filteredImageMetaData)
+            void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                    List<ImageRepresentationFormat> filteredFormats)
             {
-                List<IImageSetMetaData> smallerMetaData = new ArrayList<IImageSetMetaData>();
-                INSIDE_BOUNDING_BOX.filter(width, height, imageMetaData, smallerMetaData);
-                if (smallerMetaData.isEmpty() == false)
+                List<ImageRepresentationFormat> smallerFormats =
+                        new ArrayList<ImageRepresentationFormat>();
+                INSIDE_BOUNDING_BOX.filter(width, height, formats, smallerFormats);
+                if (smallerFormats.isEmpty() == false)
                 {
-                    Collections.sort(smallerMetaData, SIZE_COMPARATOR);
-                    filteredImageMetaData.add(smallerMetaData.get(smallerMetaData.size() - 1));
+                    Collections.sort(smallerFormats, SIZE_COMPARATOR);
+                    filteredFormats.add(smallerFormats.get(smallerFormats.size() - 1));
                 }
             }
         },
         /**
-         * Picks all image sets where the image size is inside a bounding box specified by width and
+         * Picks all formats where the image size is inside a bounding box specified by width and
          * height.
          */
         INSIDE_BOUNDING_BOX
         {
             @Override
-            void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                    List<IImageSetMetaData> filteredImageMetaData)
+            void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                    List<ImageRepresentationFormat> filteredFormats)
             {
-                for (IImageSetMetaData metaData : imageMetaData)
+                for (ImageRepresentationFormat format : formats)
                 {
-                    Geometry size = metaData.getSize();
-                    if (size.getWidth() <= width && size.getHeight() <= height)
+                    if (getWidth(format) <= width && getHeight(format) <= height)
                     {
-                        filteredImageMetaData.add(metaData);
+                        filteredFormats.add(format);
                     }
                 }
             }
         },
         /**
-         * Picks that image set where the image size is the smallest one covering a bounding box
+         * Picks that format where the image size is the smallest one covering a bounding box
          * specified by width and height.
          */
         SMALLEST_COVERING_BOUNDING_BOX
         {
             @Override
-            void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                    List<IImageSetMetaData> filteredImageMetaData)
+            void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                    List<ImageRepresentationFormat> filteredFormats)
             {
-                List<IImageSetMetaData> largerMetaData = new ArrayList<IImageSetMetaData>();
-                COVERING_BOUNDING_BOX.filter(width, height, imageMetaData, largerMetaData);
-                if (largerMetaData.isEmpty() == false)
+                List<ImageRepresentationFormat> largerFormats =
+                        new ArrayList<ImageRepresentationFormat>();
+                COVERING_BOUNDING_BOX.filter(width, height, formats, largerFormats);
+                if (largerFormats.isEmpty() == false)
                 {
-                    Collections.sort(largerMetaData, SIZE_COMPARATOR);
-                    filteredImageMetaData.add(largerMetaData.get(0));
+                    Collections.sort(largerFormats, SIZE_COMPARATOR);
+                    filteredFormats.add(largerFormats.get(0));
                 }
             }
         },
         /**
-         * Picks all image sets where the image size covers a bounding box specified by width and
+         * Picks all formats where the image size covers a bounding box specified by width and
          * height.
          */
         COVERING_BOUNDING_BOX
         {
             @Override
-            void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                    List<IImageSetMetaData> filteredImageMetaData)
+            void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                    List<ImageRepresentationFormat> filteredFormats)
             {
-                for (IImageSetMetaData metaData : imageMetaData)
+                for (ImageRepresentationFormat format : formats)
                 {
-                    Geometry size = metaData.getSize();
-                    if (size.getWidth() >= width && size.getHeight() >= height)
+                    if (getWidth(format) >= width && getHeight(format) >= height)
                     {
-                        filteredImageMetaData.add(metaData);
+                        filteredFormats.add(format);
                     }
                 }
             }
         },
         /**
-         * Picks all image sets where the image size is exactly as specified by width and height.
+         * Picks all formats where the image size is exactly as specified by width and height.
          */
         EXACTLY
         {
             @Override
-            void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                    List<IImageSetMetaData> filteredImageMetaData)
+            void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                    List<ImageRepresentationFormat> filteredFormats)
             {
-                for (IImageSetMetaData metaData : imageMetaData)
+                for (ImageRepresentationFormat format : formats)
                 {
-                    Geometry size = metaData.getSize();
-                    if (size.getWidth() == width && size.getHeight() == height)
+                    if (getWidth(format) == width && getHeight(format) == height)
                     {
-                        filteredImageMetaData.add(metaData);
+                        filteredFormats.add(format);
                     }
                 }
             }
         };
 
-        abstract void filter(int width, int height, List<IImageSetMetaData> imageMetaData,
-                List<IImageSetMetaData> filteredImageMetaData);
+        abstract void filter(int width, int height, List<ImageRepresentationFormat> formats,
+                List<ImageRepresentationFormat> filteredFormats);
     }
 
-    private static final Comparator<IImageSetMetaData> SIZE_COMPARATOR =
-            new Comparator<IImageSetMetaData>()
+    private static final Comparator<ImageRepresentationFormat> SIZE_COMPARATOR =
+            new Comparator<ImageRepresentationFormat>()
                 {
-                    public int compare(IImageSetMetaData i1, IImageSetMetaData i2)
+                    public int compare(ImageRepresentationFormat i1, ImageRepresentationFormat i2)
                     {
-                        return area(i1.getSize()) - area(i2.getSize());
+                        return area(i1) - area(i2);
                     }
 
-                    private int area(Geometry geometry)
+                    private int area(ImageRepresentationFormat format)
                     {
-                        return geometry.getWidth() * geometry.getHeight();
+                        return mapNull(format.getWidth()) * mapNull(format.getHeight());
                     }
+
                 };
 
+    private static int getWidth(ImageRepresentationFormat format)
+    {
+        return mapNull(format.getWidth());
+    }
+
+    private static int getHeight(ImageRepresentationFormat format)
+    {
+        return mapNull(format.getHeight());
+    }
+
+    private static int mapNull(Integer number)
+    {
+        return number == null ? 0 : number.intValue();
+    }
+
     private final int width;
 
     private final int height;
@@ -168,11 +183,13 @@ public class SizeCriterion implements IImageSetSelectionCriterion
         this.type = type;
     }
 
-    public List<IImageSetMetaData> getMatching(List<IImageSetMetaData> imageMetaData)
+    public List<ImageRepresentationFormat> getMatching(
+            List<ImageRepresentationFormat> imageRepresentationFormats)
     {
-        List<IImageSetMetaData> filteredMetaData = new ArrayList<IImageSetMetaData>();
-        type.filter(width, height, imageMetaData, filteredMetaData);
-        return filteredMetaData;
+        List<ImageRepresentationFormat> filteredFormats =
+                new ArrayList<ImageRepresentationFormat>();
+        type.filter(width, height, imageRepresentationFormats, filteredFormats);
+        return filteredFormats;
     }
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
index 4d5b577bcf3..e185875d656 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageZoomLevelDTO;
 
 /**
  * Describes the images in the dataset: tiles geometry, channels, dataset code and plate geometry if
@@ -51,8 +50,6 @@ public class ImageDatasetParameters implements Serializable
 
     private String mergedChannelTransformerFactorySignatureOrNull;
     
-    private List<ImageSetMetaData> zoomLevels;
-
     public Integer tryGetRowsNum()
     {
         return rowsNumOrNull;
@@ -197,14 +194,4 @@ public class ImageDatasetParameters implements Serializable
                 mergedChannelTransformerFactorySignatureOrNull;
     }
 
-    public List<ImageSetMetaData> getZoomLevels()
-    {
-        return zoomLevels;
-    }
-
-    public void setZoomLevels(List<ImageSetMetaData> zoomLevels)
-    {
-        this.zoomLevels = zoomLevels;
-    }
-
 }
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 17b351c5e7d..05acbdd419c 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
@@ -30,7 +30,6 @@ 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.ImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageSetMetaData;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.InternalImageChannel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.InternalImageTransformationInfo;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
@@ -41,7 +40,6 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgCo
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgExperimentDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageDatasetDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageTransformationDTO;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageZoomLevelDTO;
 
 /**
  * Helper class for easy handling of HCS image dataset standard structure with no code for handling
@@ -209,32 +207,9 @@ public class HCSDatasetLoader implements IImageDatasetLoader
         params.setIsMultidimensional(dataset.getIsMultidimensional());
         params.setMergedChannelTransformerFactorySignature(mergedChannelTransformerFactorySignatureOrNull);
         params.setInternalChannels(convertChannels());
-        params.setZoomLevels(translate(query.listImageZoomLevels(dataset.getId())));
         return params;
     }
     
-    private List<ImageSetMetaData> translate(List<ImgImageZoomLevelDTO> zoomLevels)
-    {
-        List<ImageSetMetaData> result = new ArrayList<ImageSetMetaData>();
-        for (ImgImageZoomLevelDTO zoomLevel : zoomLevels)
-        {
-            ImageSetMetaData metaData = new ImageSetMetaData();
-            metaData.setId(zoomLevel.getId());
-            metaData.setOriginal(zoomLevel.getIsOriginal());
-            metaData.setWidth(mapNullTo0(zoomLevel.getWidth()));
-            metaData.setHeight(mapNullTo0(zoomLevel.getHeight()));
-            metaData.setColorDepth(zoomLevel.getColorDepth());
-            metaData.setFileType(zoomLevel.getFileType());
-            result.add(metaData);
-        }
-        return result;
-    }
-    
-    private int mapNullTo0(Integer n)
-    {
-        return n == null ? 0 : n;
-    }
-    
     private List<InternalImageChannel> convertChannels()
     {
         List<InternalImageChannel> convertedChannels = new ArrayList<InternalImageChannel>();
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 82d53dd2270..de6851a0702 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
@@ -70,9 +70,12 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtilTest;
 import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.DataSetBuilder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.DatasetIdentifier;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.DatasetImageRepresentationFormats;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureInformation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDataset;
@@ -80,6 +83,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.OriginalCriterion;
 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.ImageDatasetParameters;
@@ -98,6 +102,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgFe
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgFeatureVocabularyTermDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageDatasetDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageTransformationDTO;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageZoomLevelDTO;
 
 /**
  * Test cases for the {@link DssServiceRpcScreening}.
@@ -122,12 +127,14 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
 
     private static final String DATASET_CODE = "ds1";
 
+    private static final String DATASET_CODE2 = "ds2";
+    
     private static final String CHANNEL_CODE = "GFP";
 
     private static final String EXPERIMENT_PERM_ID = "exp-123";
 
     private static final long EXPERIMENT_ID = 333;
-
+    
     private static final String URL1 = "url1";
 
     private static final String SESSION_TOKEN = "session";
@@ -175,7 +182,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
         contentProvider = context.mock(IHierarchicalContentProvider.class);
         transformerFactory = new ImageTransformerFactory();
         featureVectorDatasetIdentifier1 = create(DATASET_CODE);
-        featureVectorDatasetIdentifier2 = create("ds2");
+        featureVectorDatasetIdentifier2 = create(DATASET_CODE2);
         final ImageDatasetParameters imageParameters = new ImageDatasetParameters();
         imageParameters.setRowsNum(7);
         imageParameters.setColsNum(4);
@@ -262,7 +269,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testListAvailableFeatureNames()
     {
         prepareAssetDataSetsAreAccessible();
-        prepareLockDataSet("ds1", "ds2");
+        prepareLockDataSet("ds1", DATASET_CODE2);
 
         long[] dataSetIDs = new long[]
             { 1, 2 };
@@ -286,7 +293,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testListAvailableFeatures()
     {
         prepareAssetDataSetsAreAccessible();
-        prepareLockDataSet("ds1", "ds2");
+        prepareLockDataSet("ds1", DATASET_CODE2);
 
         long[] dataSetIDs = new long[]
             { 1, 2 };
@@ -323,9 +330,9 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testLoadFeatures()
     {
         prepareAssetDataSetsAreAccessible();
-        prepareLockDataSet("ds1", "ds2");
+        prepareLockDataSet("ds1", DATASET_CODE2);
         FeatureVectorDatasetReference r1 = createFeatureVectorDatasetReference(DATASET_CODE);
-        FeatureVectorDatasetReference r2 = createFeatureVectorDatasetReference("ds2");
+        FeatureVectorDatasetReference r2 = createFeatureVectorDatasetReference(DATASET_CODE2);
         String[][] featureCodesPerDataset = new String[][]
             {
                 { "F1", "F2" } };
@@ -429,15 +436,117 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
                 "UNKNOWN"));
     }
 
+    @Test
+    public void testListAvailableImageRepresentationFormats()
+    {
+        prepareLockDataSet(DATASET_CODE, DATASET_CODE2);
+        prepareAssetDataSetsAreAccessible(DATASET_CODE, DATASET_CODE2);
+        context.checking(new Expectations()
+            {
+                {
+                    one(dao).listImageDatasetsByPermId(new String[]
+                        { DATASET_CODE, DATASET_CODE2 });
+                    ImgImageDatasetDTO ds1 =
+                            new ImgImageDatasetDTO(DATASET_CODE, null, null, null, false, null,
+                                    null);
+                    ds1.setId(42);
+                    will(returnValue(Arrays.asList(ds1)));
+
+                    one(dao).listImageZoomLevels(42L);
+                    ImgImageZoomLevelDTO level1 =
+                            new ImgImageZoomLevelDTO("i1", true, "r1", 10, 20, 8, "png", 102);
+                    ImgImageZoomLevelDTO level2 =
+                            new ImgImageZoomLevelDTO("i2", false, "r2", 11, 21, 16, "blub", 103);
+                    will(returnValue(Arrays.asList(level1, level2)));
+                }
+            });
+
+        DatasetIdentifier id1 = new DatasetIdentifier(DATASET_CODE, URL1);
+        DatasetIdentifier id2 = new DatasetIdentifier(DATASET_CODE2, URL1);
+        List<DatasetIdentifier> dataSetIdentifiers = Arrays.asList(id1, id2);
+        List<DatasetImageRepresentationFormats> formats =
+                screeningService.listAvailableImageRepresentationFormats(SESSION_TOKEN,
+                        dataSetIdentifiers);
+
+        assertEquals("[DatasetImageRepresentationFormats[ds1,["
+                + "ImageRepresentationFormat[true,10,20,8,png], "
+                + "ImageRepresentationFormat[false,11,21,16,blub]]], "
+                + "DatasetImageRepresentationFormats[ds2,[]]]", formats.toString());
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testLoadImagesByCriteria() throws IOException
+    {
+        prepareLockDataSet(DATASET_CODE, DATASET_CODE);
+        prepareAssetDataSetsAreAccessible(DATASET_CODE, DATASET_CODE);
+        DatasetIdentifier id1 = new DatasetIdentifier(DATASET_CODE, URL1);
+        prepareGetExperimentPermIDs(id1);
+        PlateImageReference plateRef1 = new PlateImageReference(1, 1, 0, CHANNEL_CODE, id1);
+        PlateImageReference plateRef2 = new PlateImageReference(1, 2, 1, CHANNEL_CODE, id1);
+        context.checking(new Expectations()
+            {
+                {
+                    one(dao).listImageDatasetsByPermId(new String[]
+                        { DATASET_CODE });
+                    ImgImageDatasetDTO ds1 =
+                            new ImgImageDatasetDTO(DATASET_CODE, null, null, null, false, null,
+                                    null);
+                    ds1.setId(42);
+                    will(returnValue(Arrays.asList(ds1)));
+
+                    one(dao).listImageZoomLevels(42L);
+                    ImgImageZoomLevelDTO level1 =
+                            new ImgImageZoomLevelDTO("i1", true, "r1", 10, 20, null, null, 102);
+                    ImgImageZoomLevelDTO level2 =
+                            new ImgImageZoomLevelDTO("i2", false, "r2", 11, 21, null, null, 103);
+                    will(returnValue(Arrays.asList(level1, level2)));
+                    
+                    RequestedImageSize thumbnailSize =
+                            new RequestedImageSize(new Size(10, 20), false);
+                    one(imageLoader).tryGetImage(
+                            CHANNEL_CODE,
+                            ImageChannelStackReference.createHCSFromLocations(new Location(1, 1),
+                                    new Location(1, 1)), thumbnailSize);
+                    will(returnValue(new AbsoluteImageReference(image("img1.jpg"), "img1", null,
+                            null, thumbnailSize, createBlueColor(),
+                            new ImageTransfomationFactories(), null)));
+
+                    one(imageLoader).tryGetImage(
+                            CHANNEL_CODE,
+                            ImageChannelStackReference.createHCSFromLocations(new Location(2, 1),
+                                    new Location(2, 1)), thumbnailSize);
+                    will(returnValue(new AbsoluteImageReference(image("img1.png"), "img1", null,
+                            null, thumbnailSize, createBlueColor(),
+                            new ImageTransfomationFactories(), null)));
+                    
+                }
+            });
+
+
+        InputStream stream = screeningService.loadImages(SESSION_TOKEN,
+                Arrays.asList(plateRef1, plateRef2),
+                new OriginalCriterion(true));
+        
+        ConcatenatedFileOutputStreamWriter imagesWriter =
+                new ConcatenatedFileOutputStreamWriter(stream);
+        BufferedImage image1 = extractNextImage(imagesWriter);
+        assertEquals("4x4", image1.getWidth() + "x" + image1.getHeight());
+        BufferedImage image2 = extractNextImage(imagesWriter);
+        assertEquals("4x4", image2.getWidth() + "x" + image2.getHeight());
+        stream.close();
+        context.assertIsSatisfied();
+    }
+    
     @Test
     public void testGetImageTransformerFactoryForChannel()
     {
         final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1");
-        final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1");
+        final DatasetIdentifier ds2 = new DatasetIdentifier(DATASET_CODE2, "url1");
         final String channel = "dapi";
         prepareAssetDataSetsAreAccessible();
         prepareGetExperimentPermIDs(ds1, ds2);
-        prepareLockDataSet("ds1", "ds2");
+        prepareLockDataSet("ds1", DATASET_CODE2);
         context.checking(new Expectations()
             {
                 {
@@ -471,10 +580,10 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testGetImageTransformerFactoryForExperiment()
     {
         final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1");
-        final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1");
+        final DatasetIdentifier ds2 = new DatasetIdentifier(DATASET_CODE2, "url1");
         prepareAssetDataSetsAreAccessible();
         prepareGetExperimentPermIDs(ds1, ds2);
-        prepareLockDataSet("ds1", "ds2");
+        prepareLockDataSet("ds1", DATASET_CODE2);
         context.checking(new Expectations()
             {
                 {
@@ -500,9 +609,9 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testSaveImageTransformerFactoryForDatasetChannelFailedDueToInvalidAuthorization()
     {
         final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1");
-        final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1");
+        final DatasetIdentifier ds2 = new DatasetIdentifier(DATASET_CODE2, "url1");
         final String channel = "dapi";
-        prepareLockDataSet(DATASET_CODE, "ds2");
+        prepareLockDataSet(DATASET_CODE, DATASET_CODE2);
         context.checking(new Expectations()
             {
                 {
@@ -529,9 +638,9 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
     public void testSaveImageTransformerFactoryForDatasetChannel()
     {
         final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1");
-        final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1");
+        final DatasetIdentifier ds2 = new DatasetIdentifier(DATASET_CODE2, "url1");
         final String channel = "dapi";
-        prepareLockDataSet(DATASET_CODE, "ds2");
+        prepareLockDataSet(DATASET_CODE, DATASET_CODE2);
         prepareAssetDataSetsAreAccessible();
         context.checking(new Expectations()
             {
@@ -545,7 +654,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
                     one(dao).tryGetImageDatasetByPermId(DATASET_CODE);
                     will(returnValue(dataset));
 
-                    one(dao).tryGetImageDatasetByPermId("ds2");
+                    one(dao).tryGetImageDatasetByPermId(DATASET_CODE2);
                     will(returnValue(dataset));
 
                     allowing(dao).hasDatasetChannels(DATASET_CODE);
@@ -633,15 +742,16 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
         context.checking(new Expectations()
             {
                 {
-                    DataSet dataSet = new DataSet();
-                    Experiment experiment = new Experiment();
-                    experiment.setPermId(EXPERIMENT_PERM_ID);
-                    experiment.setId(EXPERIMENT_ID);
-                    dataSet.setExperiment(experiment);
+                    Experiment experiment =
+                            new ExperimentBuilder().id(EXPERIMENT_ID).permID(EXPERIMENT_PERM_ID)
+                                    .getExperiment();
                     for (DatasetIdentifier datasetIdentifier : dataSetIdentifiers)
                     {
                         one(service).tryGetDataSet(SESSION_TOKEN,
                                 datasetIdentifier.getDatasetCode());
+                        DataSet dataSet =
+                                new DataSetBuilder().code(datasetIdentifier.getDatasetCode())
+                                        .experiment(experiment).type("HCS_IMAGE").getDataSet();
                         will(returnValue(dataSet));
                     }
                 }
@@ -853,7 +963,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
 
     private void prepareAssetDataSetsAreAccessible()
     {
-        prepareAssetDataSetsAreAccessible("ds1", "ds2");
+        prepareAssetDataSetsAreAccessible("ds1", DATASET_CODE2);
     }
 
     private void prepareAssetDataSetsAreAccessible(final String... dsCodes)
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterionTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterionTest.java
new file mode 100644
index 00000000000..130a228f5e9
--- /dev/null
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/SizeCriterionTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 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.plugin.screening.shared.api.v1.dto;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+public class SizeCriterionTest extends AssertJUnit
+{
+    @Test
+    public void testMatchingExactly()
+    {
+        SizeCriterion criterion = new SizeCriterion(10, 20, SizeCriterion.Type.EXACTLY);
+        List<ImageRepresentationFormat> result =
+                criterion
+                        .getMatching(Arrays.asList(format(10, 20), format(10, 21), format(11, 20)));
+        assertEquals("[ImageRepresentationFormat[true,10,20,8,png]]", result.toString());
+    }
+
+    @Test
+    public void testMatchingCoveringBoundingBox()
+    {
+        SizeCriterion criterion =
+                new SizeCriterion(10, 20, SizeCriterion.Type.COVERING_BOUNDING_BOX);
+        List<ImageRepresentationFormat> result =
+                criterion.getMatching(Arrays.asList(format(10, 20), format(10, 21), format(11, 20),
+                        format(9, 20), format(10, 19)));
+        assertEquals("[ImageRepresentationFormat[true,10,20,8,png], "
+                + "ImageRepresentationFormat[true,10,21,8,png], "
+                + "ImageRepresentationFormat[true,11,20,8,png]]", result.toString());
+    }
+
+    @Test
+    public void testMatchingSamllestCoveringBoundingBox()
+    {
+        SizeCriterion criterion =
+                new SizeCriterion(10, 20, SizeCriterion.Type.SMALLEST_COVERING_BOUNDING_BOX);
+        List<ImageRepresentationFormat> result =
+                criterion.getMatching(Arrays.asList(format(20, 20), format(9, 21), format(21, 20)));
+        assertEquals("[ImageRepresentationFormat[true,20,20,8,png]]", result.toString());
+    }
+
+    @Test
+    public void testMatchingInsideBoundingBox()
+    {
+        SizeCriterion criterion =
+                new SizeCriterion(10, 20, SizeCriterion.Type.INSIDE_BOUNDING_BOX);
+        List<ImageRepresentationFormat> result =
+                criterion.getMatching(Arrays.asList(format(10, 20), format(10, 21), format(11, 20),
+                        format(9, 20), format(10, 19)));
+        assertEquals("[ImageRepresentationFormat[true,10,20,8,png], "
+                + "ImageRepresentationFormat[true,9,20,8,png], "
+                + "ImageRepresentationFormat[true,10,19,8,png]]", result.toString());
+    }
+    
+    @Test
+    public void testMatchingLargestInBoundingBox()
+    {
+        SizeCriterion criterion =
+                new SizeCriterion(10, 20, SizeCriterion.Type.LARGEST_IN_BOUNDING_BOX);
+        List<ImageRepresentationFormat> result =
+                criterion.getMatching(Arrays.asList(format(10, 21), format(1, 2),
+                        format(9, 20), format(10, 19)));
+        assertEquals("[ImageRepresentationFormat[true,10,19,8,png]]", result.toString());
+    }
+
+    private ImageRepresentationFormat format(Integer width, Integer height)
+    {
+        return new ImageRepresentationFormat("ds1", 1, true, width, height, 8, "png");
+    }
+}
-- 
GitLab