diff --git a/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java b/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java
index db723ba93bc7156afa8b5bf664e32c3393eb1821..5f8cd1ad4b38b5b28df65cef781e3a5b9932c1c7 100644
--- a/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java
+++ b/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java
@@ -42,6 +42,7 @@ public class ConversionUtils
      * 
      * @throws IllegalArgumentException if the location is not a valid one.
      */
+    // TODO 2009-12-16, Tomasz Pylak: x means rows, y means column, it's counterintuitive 
     public static Point parseSpreadsheetLocation(String spreadsheetLocation)
     {
         if (spreadsheetLocation == null || spreadsheetLocation.length() == 0)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialViewer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialViewer.java
index 0c2ff545e62f0708812b865efdb6f095e0143d67..98e20eedb33225d1ed2483ff74cf259cfa1ecf00 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialViewer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialViewer.java
@@ -16,25 +16,16 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.material;
 
-import java.util.Set;
-
 import com.extjs.gxt.ui.client.Style.Scroll;
-import com.extjs.gxt.ui.client.util.Margins;
-import com.extjs.gxt.ui.client.widget.LayoutContainer;
-import com.extjs.gxt.ui.client.widget.layout.RowData;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractViewer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
 
 /**
@@ -42,101 +33,49 @@ import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientS
  * 
  * @author Piotr Buczek
  */
-abstract public class GenericMaterialViewer extends AbstractViewer<Material> implements
-        IDatabaseModificationObserver
+public class GenericMaterialViewer extends AbstractViewer<Material>
 {
     private static final String PREFIX = "generic-material-viewer_";
 
     public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
 
-    abstract protected void getMaterialInfo(final AsyncCallback<Material> materialInfoCallback);
-
-    private final IViewContext<?> viewContext;
-
-    protected final TechId materialId;
-
     public static DatabaseModificationAwareComponent create(
             final IViewContext<IGenericClientServiceAsync> viewContext, final TechId materialId)
     {
-        GenericMaterialViewer viewer = new GenericMaterialViewer(viewContext, materialId)
-            {
-                @Override
-                protected void getMaterialInfo(AsyncCallback<Material> materialInfoCallback)
-                {
-                    viewContext.getService().getMaterialInfo(materialId, materialInfoCallback);
-                }
-            };
-        viewer.reloadData();
-        return new DatabaseModificationAwareComponent(viewer, viewer);
+
+        final GenericMaterialViewer viewer = new GenericMaterialViewer(viewContext, materialId);
+        MaterialPropertiesComponent propsComp =
+                new MaterialPropertiesComponent(viewContext, materialId, -1, -1)
+                    {
+                        @Override
+                        protected void getMaterialInfo(
+                                final AsyncCallback<Material> materialInfoCallback)
+                        {
+                            AbstractAsyncCallback<Material> callback =
+                                    new AbstractAsyncCallback<Material>(viewContext)
+                                        {
+                                            @Override
+                                            protected void process(Material result)
+                                            {
+                                                viewer.updateOriginalData(result);
+                                                materialInfoCallback.onSuccess(result);
+                                            }
+                                        };
+                            viewContext.getService().getMaterialInfo(materialId, callback);
+                        }
+                    };
+        viewer.add(propsComp);
+        return new DatabaseModificationAwareComponent(viewer, propsComp);
     }
 
     protected GenericMaterialViewer(final IViewContext<?> viewContext, final TechId materialId)
     {
         super(viewContext, createId(materialId));
-        this.materialId = materialId;
-        this.viewContext = viewContext;
+        setScrollMode(Scroll.AUTO);
     }
 
     public static String createId(final TechId materialId)
     {
         return ID_PREFIX + materialId;
     }
-
-    private static void addSection(final LayoutContainer lc, final Widget w)
-    {
-        lc.add(w, new RowData(-1, -1, new Margins(5)));
-    }
-
-    /**
-     * Load the material information.
-     */
-    protected void reloadData()
-    {
-        getMaterialInfo(new MaterialInfoCallback(viewContext, this));
-    }
-
-    private static final class MaterialInfoCallback extends AbstractAsyncCallback<Material>
-    {
-        private final GenericMaterialViewer genericMaterialViewer;
-
-        private MaterialInfoCallback(final IViewContext<?> viewContext,
-                final GenericMaterialViewer viewer)
-        {
-            super(viewContext);
-            this.genericMaterialViewer = viewer;
-        }
-
-        /**
-         * Sets the {@link Material} for this <var>generic</var> material viewer.
-         * <p>
-         * This method triggers the whole <i>GUI</i> construction.
-         * </p>
-         */
-        @Override
-        protected final void process(final Material result)
-        {
-            genericMaterialViewer.updateOriginalData(result);
-            genericMaterialViewer.removeAll();
-            genericMaterialViewer.setScrollMode(Scroll.AUTO);
-            addSection(genericMaterialViewer, new MaterialPropertiesSection(result, viewContext));
-            genericMaterialViewer.layout();
-        }
-
-    }
-
-    public DatabaseModificationKind[] getRelevantModifications()
-    {
-        return new DatabaseModificationKind[]
-            { DatabaseModificationKind.edit(ObjectKind.MATERIAL),
-                    DatabaseModificationKind.createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
-                    DatabaseModificationKind.edit(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
-                    DatabaseModificationKind.createOrDelete(ObjectKind.VOCABULARY_TERM),
-                    DatabaseModificationKind.edit(ObjectKind.VOCABULARY_TERM) };
-    }
-
-    public void update(Set<DatabaseModificationKind> observedModifications)
-    {
-        reloadData(); // reloads everything
-    }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertiesComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertiesComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..487c6d510f3ae3a9697e197d2c4aa925a3ba703c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertiesComponent.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2009 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.generic.client.web.client.application.material;
+
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.util.Margins;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.layout.RowData;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+
+/**
+ * @author Tomasz Pylak
+ */
+abstract public class MaterialPropertiesComponent extends LayoutContainer implements
+        IDatabaseModificationObserver
+{
+    abstract protected void getMaterialInfo(final AsyncCallback<Material> materialInfoCallback);
+
+    private final IViewContext<?> viewContext;
+
+    protected final TechId materialId;
+
+    private final int width;
+
+    private final int height;
+
+    protected MaterialPropertiesComponent(final IViewContext<?> viewContext,
+            final TechId materialId, int width, int height)
+    {
+        this.materialId = materialId;
+        this.viewContext = viewContext;
+        this.width = width;
+        this.height = height;
+        reloadData();
+    }
+
+    private void addSection(final LayoutContainer lc, final Widget w)
+    {
+        lc.add(w, new RowData(width, height, new Margins(5)));
+    }
+
+    /**
+     * Load the material information.
+     */
+    protected void reloadData()
+    {
+        getMaterialInfo(new MaterialInfoCallback(viewContext, this));
+    }
+
+    private final class MaterialInfoCallback extends AbstractAsyncCallback<Material>
+    {
+        private final MaterialPropertiesComponent viewer;
+
+        private MaterialInfoCallback(final IViewContext<?> viewContext,
+                final MaterialPropertiesComponent viewer)
+        {
+            super(viewContext);
+            this.viewer = viewer;
+        }
+
+        /**
+         * Sets the {@link Material} for this <var>generic</var> material viewer.
+         * <p>
+         * This method triggers the whole <i>GUI</i> construction.
+         * </p>
+         */
+        @Override
+        protected final void process(final Material result)
+        {
+            viewer.removeAll();
+            addSection(viewer, new MaterialPropertiesSection(result, viewContext));
+            viewer.layout();
+        }
+
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.edit(ObjectKind.MATERIAL),
+                    DatabaseModificationKind.createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                    DatabaseModificationKind.edit(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                    DatabaseModificationKind.createOrDelete(ObjectKind.VOCABULARY_TERM),
+                    DatabaseModificationKind.edit(ObjectKind.VOCABULARY_TERM) };
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        reloadData(); // reloads everything
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningImageReportingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningImageReportingPlugin.java
index fa1af0a3785215e6e08509fb7f38af829fb4878d..b3632ddc041dea55167db1e31ee7078dde1ad5d3 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningImageReportingPlugin.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningImageReportingPlugin.java
@@ -40,7 +40,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IntegerTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.StringTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImage;
 
 /**
  * Reporting plugin which shows all images in wells of a plate dataset.
@@ -50,6 +49,22 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImage;
 public class ScreeningImageReportingPlugin extends AbstractDatastorePlugin implements
         IReportingPluginTask
 {
+    // -------- column headers used to describe images for a plate ------
+
+    private static final String IMAGE = "Thumbnail";
+
+    private static final String CHANNEL = "Channel";
+
+    private static final String TILE = "Tile";
+
+    private static final String COLUMN = "Column";
+
+    private static final String ROW = "Row";
+
+    private static final String DATASET_CODE = "Dataset Code";
+
+    // ----------
+
     private static final long serialVersionUID = 1L;
 
     public ScreeningImageReportingPlugin(Properties properties, File storeRoot)
@@ -75,12 +90,12 @@ public class ScreeningImageReportingPlugin extends AbstractDatastorePlugin imple
     private void addReportHeaders(SimpleTableModelBuilder builder)
     {
         // Note: we rely on that column order at the openBIS server side!
-        builder.addHeader(PlateImage.DATASET_CODE);
-        builder.addHeader(PlateImage.ROW);
-        builder.addHeader(PlateImage.COLUMN);
-        builder.addHeader(PlateImage.TILE);
-        builder.addHeader(PlateImage.CHANNEL);
-        builder.addHeader(PlateImage.IMAGE);
+        builder.addHeader(DATASET_CODE);
+        builder.addHeader(ROW);
+        builder.addHeader(COLUMN);
+        builder.addHeader(TILE);
+        builder.addHeader(CHANNEL);
+        builder.addHeader(IMAGE);
     }
 
     private void addReportRows(SimpleTableModelBuilder builder, DatasetDescription dataset,
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningPlateImageParamsReportingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningPlateImageParamsReportingPlugin.java
index 27b3c39914ea453eef2397b17e6831521e8c3e70..a66f64f85dd36f4552c8064b63346fa40495af51 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningPlateImageParamsReportingPlugin.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ScreeningPlateImageParamsReportingPlugin.java
@@ -31,9 +31,9 @@ import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IReportingPlugi
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.SimpleTableModelBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IntegerTableCell;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.StringTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
 
 /**
  * Reporting plugin which shows parameters of the images acquired for a plate dataset.
@@ -43,6 +43,22 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImagePara
 public class ScreeningPlateImageParamsReportingPlugin extends AbstractDatastorePlugin implements
         IReportingPluginTask
 {
+    // -------- column headers used in a DSS service to describe images for a plate ------
+
+    private static final String DATASET = "Dataset";
+
+    private static final String ROWS = "Rows";
+
+    private static final String COLUMNS = "Columns";
+
+    private static final String TILE_ROWS_NUM = "Tile rows";
+
+    private static final String TILE_COLS_NUM = "Tile columns";
+
+    private static final String CHANNELS_NUM = "Number of channels";
+
+    // ----------
+
     private static final long serialVersionUID = 1L;
 
     public ScreeningPlateImageParamsReportingPlugin(Properties properties, File storeRoot)
@@ -68,11 +84,12 @@ public class ScreeningPlateImageParamsReportingPlugin extends AbstractDatastoreP
     private void addReportHeaders(SimpleTableModelBuilder builder)
     {
         // Note: we rely on that column order at the openBIS server side!
-        builder.addHeader(PlateImageParameters.ROWS);
-        builder.addHeader(PlateImageParameters.COLUMNS);
-        builder.addHeader(PlateImageParameters.TILE_ROWS_NUM);
-        builder.addHeader(PlateImageParameters.TILE_COLS_NUM);
-        builder.addHeader(PlateImageParameters.CHANNELS_NUM);
+        builder.addHeader(DATASET);
+        builder.addHeader(ROWS);
+        builder.addHeader(COLUMNS);
+        builder.addHeader(TILE_ROWS_NUM);
+        builder.addHeader(TILE_COLS_NUM);
+        builder.addHeader(CHANNELS_NUM);
     }
 
     private void addReportRows(SimpleTableModelBuilder builder, DatasetDescription dataset,
@@ -82,12 +99,18 @@ public class ScreeningPlateImageParamsReportingPlugin extends AbstractDatastoreP
         Geometry wellGeometry = imageAccessor.getWellGeometry();
         int channels = imageAccessor.getChannelCount();
         List<ISerializableComparable> row =
-                Arrays.<ISerializableComparable> asList(asNum(plateGeometry.getRows()),
-                        asNum(plateGeometry.getColumns()), asNum(wellGeometry.getRows()),
-                        asNum(wellGeometry.getColumns()), asNum(channels));
+                Arrays.<ISerializableComparable> asList(asText(dataset.getDatasetCode()),
+                        asNum(plateGeometry.getRows()), asNum(plateGeometry.getColumns()),
+                        asNum(wellGeometry.getRows()), asNum(wellGeometry.getColumns()),
+                        asNum(channels));
         builder.addRow(row);
     }
 
+    private static ISerializableComparable asText(String text)
+    {
+        return new StringTableCell(text);
+    }
+
     private static ISerializableComparable asNum(int num)
     {
         return new IntegerTableCell(num);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/geneviewer/ScreeningGeneViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/geneviewer/ScreeningGeneViewer.java
index 72c9a9c365907e5a276927a349807c8ba7f4ed4a..0609b1ce7dd37ed4925501646555540c9fc7b7be 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/geneviewer/ScreeningGeneViewer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/geneviewer/ScreeningGeneViewer.java
@@ -16,41 +16,174 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.geneviewer;
 
+import static ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.utils.GuiUtils.withLabel;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Style.Scroll;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.Text;
+import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
+import com.extjs.gxt.ui.client.widget.layout.RowLayout;
+import com.extjs.gxt.ui.client.widget.layout.TableData;
+import com.extjs.gxt.ui.client.widget.layout.TableLayout;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Widget;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractViewer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.ExperimentChooserField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.IChosenEntityListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.ExperimentChooserField.ExperimentChooserFieldAdaptor;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listener.OpenEntityDetailsTabClickListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityReference;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
-import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.material.GenericMaterialViewer;
+import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.material.MaterialPropertiesComponent;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.plateviewer.WellContentDialog;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.plateviewer.WellImages;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.utils.GuiUtils;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 
 /**
  * @author Tomasz Pylak
  */
-public class ScreeningGeneViewer extends GenericMaterialViewer
+public class ScreeningGeneViewer extends AbstractViewer<Material>
 {
+    private static final String PREFIX = GenericConstants.ID_PREFIX + "ScreeningGeneViewer_";
+
     public static DatabaseModificationAwareComponent create(
             final IViewContext<IScreeningClientServiceAsync> viewContext, final TechId materialId)
     {
         ScreeningGeneViewer viewer = new ScreeningGeneViewer(viewContext, materialId);
-        viewer.reloadData();
-        return new DatabaseModificationAwareComponent(viewer, viewer);
+
+        return new DatabaseModificationAwareComponent(viewer, viewer.propertiesSection);
     }
 
     private final IViewContext<IScreeningClientServiceAsync> viewContext;
 
-    protected ScreeningGeneViewer(IViewContext<IScreeningClientServiceAsync> viewContext,
-            TechId materialId)
+    private final MaterialPropertiesComponent propertiesSection;
+
+    protected ScreeningGeneViewer(final IViewContext<IScreeningClientServiceAsync> viewContext,
+            final TechId materialId)
     {
-        super(viewContext, materialId);
+        super(viewContext, createId(materialId));
+        this.propertiesSection = new MaterialPropertiesComponent(viewContext, materialId, -1, 1)
+            {
+                @Override
+                protected void getMaterialInfo(AsyncCallback<Material> materialInfoCallback)
+                {
+                    viewContext.getService().getMaterialInfo(materialId, materialInfoCallback);
+                }
+            };
         this.viewContext = viewContext;
+        setLayout(new BorderLayout());
+        add(propertiesSection, createLeftBorderLayoutData());
+        add(createLocationsPanel(materialId), createRightBorderLayoutData());
+    }
+
+    private Widget createLocationsPanel(final TechId materialId)
+    {
+        final LayoutContainer container = new LayoutContainer();
+
+        ExperimentChooserFieldAdaptor experimentChooser =
+                ExperimentChooserField.create("", true, null, viewContext.getCommonViewContext());
+        ExperimentChooserField chooserField = experimentChooser.getChooserField();
+        chooserField.addChosenEntityListener(new IChosenEntityListener<Experiment>()
+            {
+                public void entityChosen(Experiment entity)
+                {
+                    if (entity != null)
+                    {
+                        loadGeneLocationsPanel(materialId, entity, container);
+                    }
+                }
+            });
+        chooserField.setEditable(false);
+        container.add(GuiUtils.withLabel(experimentChooser.getField(), "Experiment:"));
+        container.add(new Text(
+                "Choose an experiment to find wells where this gene has been suppressed."));
+        return container;
     }
 
-    @Override
-    protected void getMaterialInfo(AsyncCallback<Material> materialInfoCallback)
+    private void loadGeneLocationsPanel(TechId materialId, Experiment entity,
+            final LayoutContainer container)
     {
-        viewContext.getService().getMaterialInfo(materialId, materialInfoCallback);
+        GuiUtils
+                .replaceLastItem(container, new Text(viewContext.getMessage(Dict.LOAD_IN_PROGRESS)));
+        viewContext.getService().getPlateLocations(materialId,
+                new ExperimentIdentifier(entity.getIdentifier()),
+                new AbstractAsyncCallback<List<WellLocation>>(viewContext)
+                    {
+                        @Override
+                        protected void process(List<WellLocation> wellLocations)
+                        {
+                            Widget geneLocationsPanel = createGeneLocationPanel(wellLocations);
+                            GuiUtils.replaceLastItem(container, geneLocationsPanel);
+                        }
+                    });
     }
 
+    private Widget createGeneLocationPanel(List<WellLocation> wellLocations)
+    {
+        LayoutContainer container = new LayoutContainer();
+        container.setScrollMode(Scroll.AUTO);
+        container.setLayout(new TableLayout(3));
+        TableData cellLayout = new TableData();
+        cellLayout.setPadding(20);
+        for (WellLocation loc : wellLocations)
+        {
+            container.add(createLocationDescription(loc), cellLayout);
+        }
+        return container;
+    }
+
+    private LayoutContainer createLocationDescription(WellLocation loc)
+    {
+        LayoutContainer container = new LayoutContainer();
+        container.setLayout(new RowLayout());
+        int margin = 4;
+
+        Widget plateLink = createEntityLink(loc.getPlate());
+        container.add(withLabel(plateLink, "Plate: ", margin));
+
+        Widget wellLink = createEntityLink(loc.getWell());
+        container.add(withLabel(wellLink, "Well: ", margin));
+
+        Widget contentLink = createEntityLink(loc.getMaterialContent());
+        container.add(withLabel(contentLink, "Content: ", margin));
+
+        if (loc.tryGetImages() != null)
+        {
+            container.add(createImageViewer(loc.tryGetImages()));
+        }
+        return container;
+    }
+
+    private Widget createImageViewer(TileImages images)
+    {
+        WellImages wellImages = new WellImages(images);
+        return WellContentDialog.createImageViewer(wellImages, viewContext, 100, 60);
+    }
+
+    private Widget createEntityLink(EntityReference entity)
+    {
+        final ClickHandler listener = new OpenEntityDetailsTabClickListener(entity, viewContext);
+        return LinkRenderer.getLinkWidget(entity.getCode(), listener);
+    }
+
+    public static final String createId(final TechId materialId)
+    {
+        return PREFIX + materialId;
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateContentGrid.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateContentGrid.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac8f706932e0643851187689dde67dda8ae17a6d
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateContentGrid.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2009 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.client.web.client.application.plateviewer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractSimpleBrowserGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author Tomasz Pylak
+ */
+public class PlateContentGrid extends AbstractSimpleBrowserGrid<WellData>
+{
+
+    protected PlateContentGrid(IViewContext<ICommonClientServiceAsync> viewContext,
+            String browserId, String gridId, IDisplayTypeIDGenerator displayTypeIDGenerator)
+    {
+        super(viewContext, browserId, gridId, true, displayTypeIDGenerator);
+        // TODO Auto-generated constructor stub
+    }
+
+    @Override
+    protected IColumnDefinitionKind<WellData>[] getStaticColumnsDefinition()
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected List<IColumnDefinition<WellData>> getInitialFilters()
+    {
+        return new ArrayList<IColumnDefinition<WellData>>();
+    }
+
+    @Override
+    protected void listEntities(DefaultResultSetConfig<String, WellData> resultSetConfig,
+            AbstractAsyncCallback<ResultSet<WellData>> callback)
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    protected void prepareExportEntities(TableExportCriteria<WellData> exportCriteria,
+            AbstractAsyncCallback<String> callback)
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[] {};
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateLayoutSection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateLayoutSection.java
index 9e157cab35392d11f20d170a1c4175dd66688b40..a5604c8eef2e061c571dbd4fb4085767639eccf9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateLayoutSection.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/PlateLayoutSection.java
@@ -52,8 +52,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningCons
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImage;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
@@ -293,7 +293,7 @@ public class PlateLayoutSection extends SingleSectionPanel
             {
                 public void handleEvent(BaseEvent ce)
                 {
-                    WellContentDialog.show(wellData, plateContent, viewContext);
+                    WellContentDialog.showContentDialog(wellData, viewContext);
                 }
             });
         widget.sinkEvents(Events.OnMouseDown.getEventCode());
@@ -371,7 +371,7 @@ public class PlateLayoutSection extends SingleSectionPanel
     {
         WellData[][] matrix =
                 new WellData[plateContent.getRowsNum() + 1][plateContent.getColsNum() + 1];
-        PlateImages plateImages = plateContent.tryGetImages();
+        TileImages plateImages = plateContent.tryGetImages();
         if (plateImages != null)
         {
             addImagePaths(plateContent, matrix, plateImages.getImages());
@@ -391,7 +391,7 @@ public class PlateLayoutSection extends SingleSectionPanel
             WellData wellData = matrix[row][col];
             if (wellData == null)
             {
-                wellData = new WellData(plateContent);
+                wellData = WellData.create(plateContent);
                 matrix[row][col] = wellData;
             }
             wellData.setMetadata(well);
@@ -399,16 +399,16 @@ public class PlateLayoutSection extends SingleSectionPanel
     }
 
     private static void addImagePaths(PlateContent plateContent, WellData[][] matrix,
-            List<PlateImage> imagesList)
+            List<TileImage> imagesList)
     {
-        for (PlateImage image : imagesList)
+        for (TileImage image : imagesList)
         {
             int row = image.getRow();
             int col = image.getColumn();
             WellData wellData = matrix[row][col];
             if (wellData == null)
             {
-                wellData = new WellData(plateContent);
+                wellData = WellData.create(plateContent);
                 matrix[row][col] = wellData;
             }
             wellData.addImage(image);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellContentDialog.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellContentDialog.java
index cbbac1e036fe6c1bf2e8b8d107864e8d4cd79f25..27bc15be66cc6794627cb1e1ab9668218d8e7e7c 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellContentDialog.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellContentDialog.java
@@ -45,9 +45,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listene
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.utils.GuiUtils;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
@@ -57,40 +55,54 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
  */
 public class WellContentDialog
 {
-    private static final int TILE_IMG_WIDTH = 200;
-
-    private static final int TILE_IMG_HEIGHT = 120;
-
-    private final WellData wellData;
-
-    private final PlateContent plateContent;
+    private final WellMetadata metadataOrNull;
 
     private final IViewContext<?> viewContext;
 
-    public static void show(final WellData wellData, final PlateContent plateContent,
-            final IViewContext<?> viewContext)
+    public static void showContentDialog(final WellData wellData, final IViewContext<?> viewContext)
     {
         final LayoutContainer container = new LayoutContainer();
         container.setLayout(new RowLayout());
 
-        final WellContentDialog viewer = new WellContentDialog(wellData, plateContent, viewContext);
-        LayoutContainer descriptionContainer = viewer.createContentDescription();
+        final WellContentDialog contentDialog =
+                new WellContentDialog(wellData.tryGetMetadata(), viewContext);
+        LayoutContainer descriptionContainer = contentDialog.createContentDescription();
         container.add(descriptionContainer);
 
         int dialogWidth;
         int dialogHeight;
-        PlateImages images = plateContent.tryGetImages();
+
+        final WellImages images = wellData.tryGetImages();
         if (images != null)
         {
-            PlateImageParameters imageParameters = images.getImageParameters();
-            final int tileRowsNum = imageParameters.getTileRowsNum();
-            final int tileColsNum = imageParameters.getTileColsNum();
-            int channelsNum = imageParameters.getChannelsNum();
+            int imgW = 200;
+            int imgH = 120;
+            LayoutContainer imageViewer = createImageViewer(images, viewContext, imgW, imgH);
+            container.add(imageViewer);
+
+            dialogWidth = imgW * images.getTileColsNum();
+            dialogHeight = imgH * images.getTileRowsNum() + 160;
+        } else
+        {
+            dialogWidth = 250;
+            dialogHeight = 160;
+        }
+        String title = "Well Content: " + wellData.getWellSubcode();
+        showWellContentDialog(container, dialogWidth, dialogHeight, title);
+    }
 
-            final List<String> channelNames = createChannelsDescriptions(channelsNum);
+    public static LayoutContainer createImageViewer(final WellImages images,
+            final IViewContext<?> viewContext, final int imageWidth, final int imageHeight)
+    {
+        final LayoutContainer container = new LayoutContainer();
+        container.setLayout(new RowLayout());
+
+        int channelsNum = images.getChannelsNum();
+
+        final List<String> channelNames = createChannelsDescriptions(channelsNum);
+        if (channelsNum > 1)
+        {
             ComboBox<SimpleComboValue<String>> channelChooser = createChannelChooser(channelNames);
-            descriptionContainer.add(new Text("Channel:"));
-            descriptionContainer.add(channelChooser);
             channelChooser
                     .addSelectionChangedListener(new SelectionChangedListener<SimpleComboValue<String>>()
                         {
@@ -101,25 +113,17 @@ public class WellContentDialog
                                 String value = se.getSelectedItem().getValue();
                                 int channel = channelNames.indexOf(value) + 1;
                                 LayoutContainer wellsGrid =
-                                        viewer.createWellsGrid(tileRowsNum, tileColsNum, channel);
-                                int lastItemIx = container.getItemCount() - 1;
-                                container.remove(container.getWidget(lastItemIx));
-                                container.insert(wellsGrid, lastItemIx);
-                                container.layout();
+                                        createWellsGrid(images, channel, viewContext, imageWidth,
+                                                imageHeight);
+                                GuiUtils.replaceLastItem(container, wellsGrid);
                             }
                         });
-            LayoutContainer wellsGrid = viewer.createWellsGrid(tileRowsNum, tileColsNum, 1);
-            container.add(wellsGrid);
-
-            dialogWidth = TILE_IMG_WIDTH * tileColsNum;
-            dialogHeight = TILE_IMG_HEIGHT * tileRowsNum + 160;
-        } else
-        {
-            dialogWidth = 250;
-            dialogHeight = 160;
+            container.add(GuiUtils.withLabel(channelChooser, "Channel:"));
         }
-        String title = "Well Content: " + wellData.getWellSubcode();
-        showWellContentDialog(container, dialogWidth, dialogHeight, title);
+        LayoutContainer wellsGrid =
+                createWellsGrid(images, 1, viewContext, imageWidth, imageHeight);
+        container.add(wellsGrid);
+        return container;
     }
 
     private static ComboBox<SimpleComboValue<String>> createChannelChooser(List<String> channelNames)
@@ -158,19 +162,18 @@ public class WellContentDialog
         container.setLayout(tableLayout);
         TableData cellLayout = new TableData();
         cellLayout.setMargin(2);
-        WellMetadata metadata = wellData.tryGetMetadata();
-        if (metadata != null)
+        if (metadataOrNull != null)
         {
             container.add(new Text("Well: "), cellLayout);
-            container.add(createEntityLink(metadata.getWellSample()));
+            container.add(createEntityLink(metadataOrNull.getWellSample()));
 
-            Material content = metadata.tryGetContent();
+            Material content = metadataOrNull.tryGetContent();
             if (content != null)
             {
                 container.add(new Text("Content: "), cellLayout);
                 container.add(createEntityLink(content));
 
-                Material gene = metadata.tryGetGene();
+                Material gene = metadataOrNull.tryGetGene();
                 if (gene != null)
                 {
                     container.add(new Text("Inhibited gene: "), cellLayout);
@@ -199,35 +202,32 @@ public class WellContentDialog
         return LinkRenderer.getLinkWidget(entity.getCode(), listener);
     }
 
-    private WellContentDialog(WellData wellData, PlateContent plateContent,
-            IViewContext<?> viewContext)
+    private WellContentDialog(WellMetadata metadataOrNull, IViewContext<?> viewContext)
     {
-        this.wellData = wellData;
-        this.plateContent = plateContent;
+        this.metadataOrNull = metadataOrNull;
         this.viewContext = viewContext;
     }
 
-    private LayoutContainer createWellsGrid(int tileRowsNum, int tileColsNum, int channel)
+    private static LayoutContainer createWellsGrid(WellImages images, int channel,
+            IViewContext<?> viewContext, int imageWidth, int imageHeight)
     {
-        LayoutContainer container = new LayoutContainer(new TableLayout(tileColsNum));
-        for (int i = 1; i <= tileRowsNum * tileColsNum; i++)
+        LayoutContainer container = new LayoutContainer(new TableLayout(images.getTileColsNum()));
+        for (int i = 1; i <= images.getTileRowsNum() * images.getTileColsNum(); i++)
         {
             Component tileContent;
-            String imagePath = wellData.tryGetImagePath(channel, i);
+            String imagePath = images.tryGetImagePath(channel, i);
             if (imagePath != null)
             {
-                // if we have a path, then download URL should be also available
-                String downloadUrl = plateContent.tryGetImages().getDownloadUrl();
                 String sessionId = getSessionId(viewContext);
                 String imageURL =
-                        SimpleDatastoreImageRenderer.createDatastoreImageUrl(imagePath,
-                                TILE_IMG_WIDTH, TILE_IMG_HEIGHT, downloadUrl, sessionId);
+                        SimpleDatastoreImageRenderer.createDatastoreImageUrl(imagePath, imageWidth,
+                                imageHeight, images.getDownloadUrl(), sessionId);
                 tileContent = new Html(imageURL);
                 PlateStyleSetter.setPointerCursor(tileContent);
             } else
             {
                 tileContent = new Text("No image.");
-                tileContent.setPixelSize(TILE_IMG_WIDTH, TILE_IMG_HEIGHT);
+                tileContent.setPixelSize(imageWidth, imageHeight);
             }
             container.add(tileContent);
         }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellData.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellData.java
index fb7f283d41645df122965fa951091925847f7046..7171ab97ff0e9b3e6d68de201d033b192938c90c 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellData.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellData.java
@@ -17,9 +17,8 @@
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.plateviewer;
 
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImage;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
@@ -29,35 +28,26 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
  */
 class WellData
 {
-    private String[/* channel */][/* tile number */] imagePaths;
-
     private WellMetadata metadata;
 
-    public WellData(PlateContent plateContent)
+    private WellImages imagesOrNull;
+
+    public static WellData create(PlateContent plateContent)
     {
-        PlateImages images = plateContent.tryGetImages();
+        TileImages images = plateContent.tryGetImages();
         if (images != null)
         {
-            this.imagePaths = initImagePathArray(images.getImageParameters());
+            return new WellData(
+                    new WellImages(images.getImageParameters(), images.getDownloadUrl()));
         } else
         {
-            this.imagePaths = null;
+            return new WellData(null);
         }
     }
 
-    private String[][] initImagePathArray(PlateImageParameters params)
-    {
-        int tilesNum = params.getTileRowsNum() * params.getTileColsNum();
-        return new String[params.getChannelsNum()][tilesNum];
-    }
-
-    public void addImage(PlateImage image)
+    private WellData(WellImages imagesOrNull)
     {
-        int channelIx = image.getChannel() - 1;
-        int tileIx = image.getTile() - 1;
-        assert imagePaths != null && imagePaths[channelIx][tileIx] == null : "duplicated image for channelIx = "
-                + channelIx + ", tileIx = " + tileIx;
-        imagePaths[channelIx][tileIx] = image.getImagePath();
+        this.imagesOrNull = imagesOrNull;
     }
 
     public void setMetadata(WellMetadata well)
@@ -65,11 +55,6 @@ class WellData
         this.metadata = well;
     }
 
-    public String tryGetImagePath(int channel, int tile)
-    {
-        return imagePaths != null ? imagePaths[channel - 1][tile - 1] : null;
-    }
-
     public WellMetadata tryGetMetadata()
     {
         return metadata;
@@ -96,4 +81,20 @@ class WellData
             return "?";
         }
     }
+
+    public WellImages tryGetImages()
+    {
+        return imagesOrNull;
+    }
+
+    public void addImage(TileImage image)
+    {
+        assert imagesOrNull != null;
+        imagesOrNull.addImage(image);
+    }
+
+    public String tryGetImagePath(int channel, int tile)
+    {
+        return imagesOrNull == null ? null : imagesOrNull.tryGetImagePath(channel, tile);
+    }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellImages.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellImages.java
new file mode 100644
index 0000000000000000000000000000000000000000..82150ac035079c3b700a07f18c2bf88d98c40f0d
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/plateviewer/WellImages.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009 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.client.web.client.application.plateviewer;
+
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
+
+/**
+ * Images of one well.
+ * 
+ * @author Tomasz Pylak
+ */
+public class WellImages
+{
+    private String[/* channel */][/* tile number */] imagePaths;
+
+    private final int tileRowsNum;
+
+    private final int tileColsNum;
+
+    private final int channelsNum;
+
+    private final String downloadUrl;
+
+    public WellImages(PlateImageParameters imageParams, String downloadUrl)
+    {
+        int tilesNum = imageParams.getTileRowsNum() * imageParams.getTileColsNum();
+        this.tileRowsNum = imageParams.getTileRowsNum();
+        this.tileColsNum = imageParams.getTileColsNum();
+        this.channelsNum = imageParams.getChannelsNum();
+        this.downloadUrl = downloadUrl;
+        this.imagePaths = new String[imageParams.getChannelsNum()][tilesNum];
+    }
+
+    public WellImages(TileImages images)
+    {
+        this(images.getImageParameters(), images.getDownloadUrl());
+        for (TileImage image : images.getImages())
+        {
+            addImage(image);
+        }
+    }
+
+    public void addImage(TileImage image)
+    {
+        int channelIx = image.getChannel() - 1;
+        int tileIx = image.getTile() - 1;
+        assert imagePaths != null && imagePaths[channelIx][tileIx] == null : "duplicated image for channelIx = "
+                + channelIx + ", tileIx = " + tileIx;
+        imagePaths[channelIx][tileIx] = image.getImagePath();
+    }
+
+    public String tryGetImagePath(int channel, int tile)
+    {
+        return imagePaths[channel - 1][tile - 1];
+    }
+
+    public int getTileRowsNum()
+    {
+        return tileRowsNum;
+    }
+
+    public int getTileColsNum()
+    {
+        return tileColsNum;
+    }
+
+    public int getChannelsNum()
+    {
+        return channelsNum;
+    }
+
+    public String getDownloadUrl()
+    {
+        return downloadUrl;
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/utils/GuiUtils.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/utils/GuiUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..3dfd740bd8fc694ddc0475b6447ac87e750c3451
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/utils/GuiUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 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.client.web.client.application.utils;
+
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.Text;
+import com.extjs.gxt.ui.client.widget.layout.TableData;
+import com.extjs.gxt.ui.client.widget.layout.TableLayout;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * @author Tomasz Pylak
+ */
+public class GuiUtils
+{
+    public static void replaceLastItem(LayoutContainer container, Widget newLastWidget)
+    {
+        int lastItemIx = container.getItemCount() - 1;
+        container.remove(container.getWidget(lastItemIx));
+        container.insert(newLastWidget, lastItemIx);
+        container.layout();
+    }
+
+    public static Widget withLabel(Widget component, String label)
+    {
+        return withLabel(component, label, 0);
+    }
+
+    public static Widget withLabel(Widget component, String label, int margin)
+    {
+        LayoutContainer c = new LayoutContainer();
+        c.setLayout(new TableLayout(2));
+        TableData cellLayout = new TableData();
+        cellLayout.setMargin(4);
+        Text labelWidget = new Text(label);
+        labelWidget.setWidth(Math.max(label.length() * 9, 80));
+        c.add(labelWidget, cellLayout);
+        c.add(component);
+        return c;
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServerLogger.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServerLogger.java
index 7de63eda5a50310f347ec14af3a1f06735425742..688a08e08ab1743d94bfa6cc997a5da218992e4f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServerLogger.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServerLogger.java
@@ -69,7 +69,7 @@ final class ScreeningServerLogger extends AbstractServerLogger implements IScree
             ExperimentIdentifier experimentIdentifier)
     {
         logTracking(sessionToken, "getPlateLocations",
-                "geneMaterialId(%d) experimentIdentifier(%s)", geneMaterialId.getId(),
+                "geneMaterialId(%s) experimentIdentifier(%s)", geneMaterialId.getId(),
                 experimentIdentifier);
         return null;
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
index 3d78f4e09ee09e8397f371882f33fccc2a63a49c..621422325fc1663cec566ea1e4a8bd3af24ad241 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
@@ -45,13 +45,13 @@ public interface IScreeningQuery extends BaseQuery
             + "     sample_properties well_props, materials well_material, material_properties well_material_props, "
             + "     sample_types pl_type, sample_types well_type, material_types well_material_type "
             + "where                                                                               "
-            + "-- find 'well' belonging to the plate which belongs to this experiment              "
+            // find 'well' belonging to the plate which belongs to this experiment
             + "exp.id = ?{2} and pl.expe_id = exp.id and well.samp_id_part_of = pl.id and             "
-            + "-- find 'well_material' assigned to the well                                        "
+            // find 'well_material' assigned to the well
             + "well_props.samp_id = well.id and well_material.id = well_props.mate_prop_id and     "
-            + "-- well content material property must point to the specified gene id               "
+            // well content material property must point to the specified gene id
             + "well_material_props.mate_id = well_material.id and well_material_props.mate_prop_id = ?{1} and "
-            + "-- additional joins to entity type tables                                           "
+            // additional joins to entity type tables
             + "pl_type.id = pl.saty_id and well_type.id = well.saty_id and                         "
             + "well_material_type.id = well_material.maty_id ")
     public DataIterator<WellLocation> getPlateLocations(long geneMaterialId, long experimentId);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/DatasetLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/DatasetLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..23e6e68c1ce8e4436a6138718fae7a8a9f5b0339
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/DatasetLoader.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009 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.server.logic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ImageTableCell;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IntegerTableCell;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningConstants;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+
+/**
+ * Loads content of datasets by contacting DSS.
+ * 
+ * @author Tomasz Pylak
+ */
+public class DatasetLoader
+{
+    public static List<TileImage> loadImages(List<String> datasets, String datastoreCode,
+            IExternalDataTable externalDataTable)
+    {
+        TableModel plateReport =
+                externalDataTable.createReportFromDatasets(
+                        ScreeningConstants.PLATE_VIEWER_REPORT_KEY, datastoreCode, datasets);
+        return asImageList(plateReport);
+    }
+
+    public static List<PlateImageParameters> loadImageParameters(List<String> datasets,
+            String datastoreCode, IExternalDataTable externalDataTable)
+    {
+        TableModel imageParamsReport =
+                externalDataTable.createReportFromDatasets(
+                        ScreeningConstants.PLATE_IMAGE_PARAMS_REPORT_KEY, datastoreCode, datasets);
+        return asImageParams(imageParamsReport);
+    }
+
+    private static List<PlateImageParameters> asImageParams(TableModel imageParamsReport)
+    {
+        List<PlateImageParameters> paramsList = new ArrayList<PlateImageParameters>();
+        for (TableModelRow tableModelRow : imageParamsReport.getRows())
+        {
+            paramsList.add(asImageParams(tableModelRow));
+        }
+        return paramsList;
+    }
+
+    private static PlateImageParameters asImageParams(TableModelRow tableModelRow)
+    {
+        PlateImageParameters params = new PlateImageParameters();
+        List<ISerializableComparable> values = tableModelRow.getValues();
+        params.setDatasetCode(asText(values.get(0)));
+        params.setRowsNum(asNum(values.get(1)));
+        params.setColsNum(asNum(values.get(2)));
+        params.setTileRowsNum(asNum(values.get(3)));
+        params.setTileColsNum(asNum(values.get(4)));
+        params.setChannelsNum(asNum(values.get(5)));
+        return params;
+    }
+
+    /**
+     * @param plateImages report of a screening plugun with images for the whole plate
+     */
+    private static final List<TileImage> asImageList(TableModel plateReport)
+    {
+        List<TableModelRow> rows = plateReport.getRows();
+        List<TileImage> images = new ArrayList<TileImage>();
+        for (TableModelRow row : rows)
+        {
+            images.add(createImage(row));
+        }
+        return images;
+    }
+
+    // creates a DTO for an image from an unstructured report row
+    private static TileImage createImage(TableModelRow row)
+    {
+        List<ISerializableComparable> values = row.getValues();
+        TileImage image = new TileImage();
+        image.setDatasetCode(asText(values.get(0)));
+        image.setRow(asNum(values.get(1)));
+        image.setColumn(asNum(values.get(2)));
+        image.setTile(asNum(values.get(3)));
+        image.setChannel(asNum(values.get(4)));
+        image.setImagePath(asImagePath(values.get(5)));
+        return image;
+    }
+
+    private static String asText(ISerializableComparable serializableComparable)
+    {
+        return serializableComparable.toString();
+    }
+
+    private static String asImagePath(ISerializableComparable serializableComparable)
+    {
+        return ((ImageTableCell) serializableComparable).getPath();
+    }
+
+    private static int asNum(ISerializableComparable serializableComparable)
+    {
+        return (int) ((IntegerTableCell) serializableComparable).getNumber();
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/GenePlateLocationsLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/GenePlateLocationsLoader.java
index ac33219be8c88b658aa5a000791a176b37d410d4..790c6b4d12e1c669d4bdb69dae787d72b4d6927a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/GenePlateLocationsLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/GenePlateLocationsLoader.java
@@ -18,22 +18,41 @@ package ch.systemsx.cisd.openbis.plugin.screening.server.logic;
 
 import java.sql.Connection;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import net.lemnik.eodsql.DataIterator;
 import net.lemnik.eodsql.QueryTool;
 
+import org.apache.commons.lang.builder.ToStringBuilder;
+
 import ch.rinn.restrictions.Friend;
+import ch.systemsx.cisd.common.geometry.ConversionUtils;
+import ch.systemsx.cisd.common.geometry.Point;
+import ch.systemsx.cisd.common.utilities.AbstractHashable;
+import ch.systemsx.cisd.common.utilities.ModifiedShortPrefixToStringStyle;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.common.DatabaseContextUtils;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityReference;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningConstants;
 import ch.systemsx.cisd.openbis.plugin.screening.server.IScreeningBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.IScreeningQuery;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 
 /**
@@ -57,16 +76,286 @@ public class GenePlateLocationsLoader
 
     private final IDAOFactory daoFactory;
 
+    private final IExternalDataTable externalDataTable;
+
     private GenePlateLocationsLoader(Session session,
             IScreeningBusinessObjectFactory businessObjectFactory, IDAOFactory daoFactory)
     {
         this.session = session;
         this.businessObjectFactory = businessObjectFactory;
         this.daoFactory = daoFactory;
+        this.externalDataTable = businessObjectFactory.createExternalDataTable(session);
+
     }
 
     private List<WellLocation> getPlateLocations(TechId geneMaterialId,
             ExperimentIdentifier experimentIdentifier)
+    {
+        List<WellLocation> locations = loadLocations(geneMaterialId, experimentIdentifier);
+        List<ExternalDataPE> imageDatasets = loadImageDatasets(locations, externalDataTable);
+        ImagesWithParams images = tryLoadImagesReport(imageDatasets);
+        if (images != null)
+        {
+            enrichWithImages(locations, imageDatasets, images);
+        }
+        return locations;
+    }
+
+    private static void enrichWithImages(List<WellLocation> locations,
+            List<ExternalDataPE> imageDatasets, ImagesWithParams images)
+    {
+        Map<WellPointer, List<TileImage>> imageMap = asMap(images.getImages());
+        Map<Long/* plate id */, String/* datasetCode */> plateToDatasetMap =
+                createPlateToDatasetMap(imageDatasets);
+        Map<String, ExternalDataPE> datasetMap = asSampleMap(imageDatasets);
+
+        for (WellLocation loc : locations)
+        {
+            WellPointer pointer = tryCreateWellPointer(plateToDatasetMap, loc);
+            if (pointer != null)
+            {
+                List<TileImage> tiles = imageMap.get(pointer);
+                if (tiles != null)
+                {
+                    ExternalDataPE dataset = datasetMap.get(pointer.getDatasetCode());
+                    PlateImageParameters imageParameters =
+                            images.getParamsMap().get(dataset.getCode());
+                    TileImages wellImages =
+                            TileImages.create(createReference(dataset), tiles, imageParameters);
+                    loc.setImages(wellImages);
+                }
+            }
+        }
+    }
+
+    private static DatasetReference createReference(ExternalDataPE dataset)
+    {
+        DataStorePE dataStore = dataset.getDataStore();
+        return new DatasetReference(dataset.getCode(), dataStore.getCode(), dataStore
+                .getDownloadUrl());
+    }
+
+    private static WellPointer tryCreateWellPointer(Map<Long, String> plateToDatasetMap,
+            WellLocation location)
+    {
+        String datasetCode = plateToDatasetMap.get(location.getPlate().getId());
+        if (datasetCode != null)
+        {
+            EntityReference well = location.getWell();
+            String wellCode = well.getCode();
+            Point wellLoc = ConversionUtils.parseSpreadsheetLocation(wellCode);
+            return new WellPointer(datasetCode, wellLoc.getX() + 1, wellLoc.getY() + 1);
+        } else
+        {
+            return null;
+        }
+    }
+
+    private static Map<Long, String> createPlateToDatasetMap(List<ExternalDataPE> datasets)
+    {
+        Map<Long, String> map = new HashMap<Long, String>();
+        for (ExternalDataPE dataset : datasets)
+        {
+            map.put(dataset.tryGetSample().getId(), dataset.getCode());
+        }
+        return map;
+    }
+
+    private static Map<WellPointer, List<TileImage>> asMap(List<TileImage> images)
+    {
+        Map<WellPointer, List<TileImage>> map = new HashMap<WellPointer, List<TileImage>>();
+        for (TileImage image : images)
+        {
+            WellPointer pointer = WellPointer.create(image);
+            List<TileImage> list = map.get(pointer);
+            if (list == null)
+            {
+                list = new ArrayList<TileImage>();
+                map.put(pointer, list);
+            }
+            list.add(image);
+        }
+        return map;
+    }
+
+    private static class WellPointer
+    {
+        private static WellPointer create(TileImage image)
+        {
+            return new WellPointer(image.getDatasetCode(), image.getRow(), image.getColumn());
+        }
+
+        private final String datasetCode;
+
+        private final int row;
+
+        private final int column;
+
+        public WellPointer(String datasetCode, int row, int column)
+        {
+            this.datasetCode = datasetCode;
+            this.row = row;
+            this.column = column;
+        }
+
+        public String getDatasetCode()
+        {
+            return datasetCode;
+        }
+
+        public int getRow()
+        {
+            return row;
+        }
+
+        public int getColumn()
+        {
+            return column;
+        }
+
+        @Override
+        public final boolean equals(final Object obj)
+        {
+            WellPointer that = (WellPointer) obj;
+            return row == that.row && column == that.column && datasetCode.equals(that.datasetCode);
+        }
+
+        @Override
+        public final int hashCode()
+        {
+            return (column * 2343 + row * 9876) ^ datasetCode.hashCode();
+        }
+
+        @Override
+        public String toString()
+        {
+            return ToStringBuilder.reflectionToString(this,
+                    ModifiedShortPrefixToStringStyle.MODIFIED_SHORT_PREFIX_STYLE);
+        }
+    }
+
+    private ImagesWithParams tryLoadImagesReport(List<ExternalDataPE> imageDatasets)
+    {
+        if (imageDatasets.size() == 0)
+        {
+            return null;
+        }
+        List<String> datasetCodes = asCodes(imageDatasets);
+        // NOTE: assumes that all datasets are from the same datastore
+        String datastoreCode = imageDatasets.get(0).getDataStore().getCode();
+        List<TileImage> images =
+                DatasetLoader.loadImages(datasetCodes, datastoreCode, externalDataTable);
+        List<PlateImageParameters> imageParameters =
+                DatasetLoader.loadImageParameters(datasetCodes, datastoreCode, externalDataTable);
+        return new ImagesWithParams(images, imageParameters);
+    }
+
+    private static class ImagesWithParams extends AbstractHashable
+    {
+        private List<TileImage> images;
+
+        private Map<String/* dataset code */, PlateImageParameters> paramsMap;
+
+        public ImagesWithParams(List<TileImage> images, List<PlateImageParameters> imageParameters)
+        {
+            this.images = images;
+            this.paramsMap = asMap(imageParameters);
+        }
+
+        private static Map<String, PlateImageParameters> asMap(
+                List<PlateImageParameters> imageParameters)
+        {
+            Map<String, PlateImageParameters> map = new HashMap<String, PlateImageParameters>();
+            for (PlateImageParameters params : imageParameters)
+            {
+                map.put(params.getDatasetCode(), params);
+            }
+            return map;
+        }
+
+        public List<TileImage> getImages()
+        {
+            return images;
+        }
+
+        public Map<String, PlateImageParameters> getParamsMap()
+        {
+            return paramsMap;
+        }
+    }
+
+    private static List<String> asCodes(List<ExternalDataPE> datasets)
+    {
+        List<String> codes = new ArrayList<String>();
+        for (ExternalDataPE dataset : datasets)
+        {
+            codes.add(dataset.getCode());
+        }
+        return codes;
+    }
+
+    private static Map<String/* dataset code */, ExternalDataPE> asSampleMap(
+            List<ExternalDataPE> datasets)
+    {
+        Map<String, ExternalDataPE> map = new HashMap<String, ExternalDataPE>();
+        for (ExternalDataPE dataset : datasets)
+        {
+            map.put(dataset.getCode(), dataset);
+        }
+        return map;
+    }
+
+    private static List<ExternalDataPE> loadImageDatasets(List<WellLocation> locations,
+            IExternalDataTable externalDataTable)
+    {
+        List<ExternalDataPE> imageDatasets = new ArrayList<ExternalDataPE>();
+        List<TechId> plateIds = extractPlateIds(locations);
+        for (TechId plateId : plateIds)
+        {
+            List<ExternalDataPE> datasets =
+                    PlateContentLoader.loadDatasets(plateId, externalDataTable);
+            imageDatasets.addAll(filterImageDatasets(datasets));
+        }
+        return imageDatasets;
+    }
+
+    private static List<ExternalDataPE> filterImageDatasets(List<ExternalDataPE> datasets)
+    {
+        List<ExternalDataPE> result = new ArrayList<ExternalDataPE>();
+        for (ExternalDataPE dataset : datasets)
+        {
+            if (dataset.getDataSetType().getCode().equalsIgnoreCase(
+                    ScreeningConstants.IMAGE_DATASET_TYPE))
+            {
+                result.add(dataset);
+            }
+        }
+        return result;
+    }
+
+    private static List<TechId> extractPlateIds(List<WellLocation> locations)
+    {
+        Set<Long> ids = new HashSet<Long>();
+        for (WellLocation loc : locations)
+        {
+            ids.add(loc.getPlate().getId());
+        }
+        return asTechIdList(ids);
+    }
+
+    private static List<TechId> asTechIdList(Set<Long> ids)
+    {
+        List<TechId> result = new ArrayList<TechId>();
+        Iterator<Long> iter = ids.iterator();
+        while (iter.hasNext())
+        {
+            result.add(new TechId(iter.next()));
+        }
+        return result;
+    }
+
+    private List<WellLocation> loadLocations(TechId geneMaterialId,
+            ExperimentIdentifier experimentIdentifier)
     {
         long experimentId = loadExperimentId(experimentIdentifier);
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
index e93c746891976ad37fd836e09d0eaf5ba3532875..317a359bc211df6240e9052b42b84adef8bf2f8a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
@@ -30,7 +30,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
@@ -40,8 +39,9 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningCons
 import ch.systemsx.cisd.openbis.plugin.screening.server.IScreeningBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImage;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImage;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImageParameters;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.TileImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
@@ -76,7 +76,7 @@ public class PlateContentLoader
         Sample plate = loadPlate(plateId);
         List<ExternalDataPE> datasets = loadDatasets(plateId, externalDataTable);
 
-        PlateImages images = tryLoadImages(datasets, externalDataTable);
+        TileImages images = tryLoadImages(datasets, externalDataTable);
         List<WellMetadata> wells = loadWells(plateId);
         DatasetReference imageAnalysisDataset = tryFindImageAnalysisDataset(datasets);
 
@@ -97,7 +97,9 @@ public class PlateContentLoader
                 tryFindDataset(datasets, ScreeningConstants.IMAGE_ANALYSIS_DATASET_TYPE);
         if (dataset != null)
         {
-            return new DatasetReference(dataset.getCode(), dataset.getDataStore().getCode());
+            DataStorePE dataStore = dataset.getDataStore();
+            return new DatasetReference(dataset.getCode(), dataStore.getCode(), dataStore
+                    .getDownloadUrl());
         } else
         {
             return null;
@@ -119,7 +121,7 @@ public class PlateContentLoader
         return createWells(wells);
     }
 
-    private PlateImages tryLoadImages(List<ExternalDataPE> datasets,
+    private TileImages tryLoadImages(List<ExternalDataPE> datasets,
             IExternalDataTable externalDataTable)
     {
         ExternalDataPE dataset = tryFindDataset(datasets, ScreeningConstants.IMAGE_DATASET_TYPE);
@@ -132,28 +134,27 @@ public class PlateContentLoader
         }
     }
 
-    private List<ExternalDataPE> loadDatasets(TechId plateId, IExternalDataTable externalDataTable)
+    protected static List<ExternalDataPE> loadDatasets(TechId plateId,
+            IExternalDataTable externalDataTable)
     {
         externalDataTable.loadBySampleTechId(plateId);
         List<ExternalDataPE> externalData = externalDataTable.getExternalData();
         return externalData;
     }
 
-    private PlateImages loadImages(IExternalDataTable externalDataTable, ExternalDataPE dataset)
+    private TileImages loadImages(IExternalDataTable externalDataTable, ExternalDataPE dataset)
     {
         DataStorePE dataStore = dataset.getDataStore();
         String datasetCode = dataset.getCode();
         List<String> datasets = Arrays.asList(datasetCode);
         String datastoreCode = dataStore.getCode();
-        TableModel plateReport =
-                externalDataTable.createReportFromDatasets(
-                        ScreeningConstants.PLATE_VIEWER_REPORT_KEY, datastoreCode, datasets);
-        TableModel imageParamsReport =
-                externalDataTable.createReportFromDatasets(
-                        ScreeningConstants.PLATE_IMAGE_PARAMS_REPORT_KEY, datastoreCode, datasets);
+        List<TileImage> plateReport =
+                DatasetLoader.loadImages(datasets, datastoreCode, externalDataTable);
+        List<PlateImageParameters> imageParamsReports =
+                DatasetLoader.loadImageParameters(datasets, datastoreCode, externalDataTable);
 
-        return PlateImage.createImages(new DatasetReference(datasetCode, datastoreCode), dataStore
-                .getDownloadUrl(), plateReport, imageParamsReport);
+        return TileImages.create(new DatasetReference(datasetCode, datastoreCode, dataStore
+                .getDownloadUrl()), plateReport, imageParamsReports.get(0));
     }
 
     private static ExternalDataPE tryFindDataset(List<ExternalDataPE> datasets, String datasetType)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/DatasetReference.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/DatasetReference.java
index 523b8d43e3434d9f67612470cac6bf19c65ff718..f6baa9626337a4750aacae34e0370936e7654d94 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/DatasetReference.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/DatasetReference.java
@@ -25,25 +25,28 @@ import com.google.gwt.user.client.rpc.IsSerializable;
  */
 public class DatasetReference implements IsSerializable
 {
-    private String code;
+    private String datasetCode;
 
     private String datastoreCode;
 
+    private String downloadUrl;
+
     // GWT only
     @SuppressWarnings("unused")
     private DatasetReference()
     {
     }
 
-    public DatasetReference(String code, String datastoreCode)
+    public DatasetReference(String code, String datastoreCode, String downloadUrl)
     {
-        this.code = code;
+        this.datasetCode = code;
         this.datastoreCode = datastoreCode;
+        this.downloadUrl = downloadUrl;
     }
 
     public String getCode()
     {
-        return code;
+        return datasetCode;
     }
 
     public String getDatastoreCode()
@@ -51,4 +54,9 @@ public class DatasetReference implements IsSerializable
         return datastoreCode;
     }
 
+    public String getDownloadUrl()
+    {
+        return downloadUrl;
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateContent.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateContent.java
index 2023c683801aea066029dbcf2b6ed822b457ffbb..20c26536220904dfd363e80cef22af3d969f4c3b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateContent.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateContent.java
@@ -33,7 +33,7 @@ public class PlateContent implements IsSerializable
 
     private List<WellMetadata> wells;
 
-    private PlateImages imagesOrNull;
+    private TileImages imagesOrNull;
 
     private DatasetReference imageAnalysisDatasetOrNull;
 
@@ -43,7 +43,7 @@ public class PlateContent implements IsSerializable
     {
     }
 
-    public PlateContent(Sample plate, List<WellMetadata> wells, PlateImages imagesOrNull,
+    public PlateContent(Sample plate, List<WellMetadata> wells, TileImages imagesOrNull,
             DatasetReference imageAnalysisDatasetOrNull)
     {
         this.plate = plate;
@@ -58,7 +58,7 @@ public class PlateContent implements IsSerializable
     }
 
     /** can be null */
-    public PlateImages tryGetImages()
+    public TileImages tryGetImages()
     {
         return imagesOrNull;
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImage.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImage.java
deleted file mode 100644
index 8726cb8691fa26fe12080759b238bdc706f06a80..0000000000000000000000000000000000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImage.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2009 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.basic.dto;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.IsSerializable;
-
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ImageTableCell;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IntegerTableCell;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
-
-/**
- * @author Tomasz Pylak
- */
-public class PlateImage implements IsSerializable
-{
-    // -------- column headers used in a DSS service to describe images for a plate ------
-
-    public static final String IMAGE = "Thumbnail";
-
-    public static final String CHANNEL = "Channel";
-
-    public static final String TILE = "Tile";
-
-    public static final String COLUMN = "Column";
-
-    public static final String ROW = "Row";
-
-    public static final String DATASET_CODE = "Dataset Code";
-
-    // ----------
-
-    /**
-     * @param plateReport report of a screening plugun with images for the whole plate
-     */
-    public static final PlateImages createImages(DatasetReference dataset, String downloadUrl,
-            TableModel plateReport, TableModel imageParamsReport)
-    {
-        return new PlateImages(dataset, downloadUrl, createImageList(plateReport),
-                createImageParams(imageParamsReport));
-    }
-
-    private static PlateImageParameters createImageParams(TableModel imageParamsReport)
-    {
-        PlateImageParameters params = new PlateImageParameters();
-        assert imageParamsReport.getRows().size() == 1 : "exactly one row expected in imageParamsReport";
-        List<ISerializableComparable> values = imageParamsReport.getRows().get(0).getValues();
-
-        params.setRowsNum(asNum(values.get(0)));
-        params.setColsNum(asNum(values.get(1)));
-        params.setTileRowsNum(asNum(values.get(2)));
-        params.setTileColsNum(asNum(values.get(3)));
-        params.setChannelsNum(asNum(values.get(4)));
-        return params;
-    }
-
-    private static final List<PlateImage> createImageList(TableModel plateReport)
-    {
-        List<TableModelRow> rows = plateReport.getRows();
-        List<PlateImage> images = new ArrayList<PlateImage>();
-        for (TableModelRow row : rows)
-        {
-            images.add(createImage(row));
-        }
-        return images;
-    }
-
-    // creates a DTO for an image from an unstructured report row
-    private static PlateImage createImage(TableModelRow row)
-    {
-        List<ISerializableComparable> values = row.getValues();
-        PlateImage image = new PlateImage();
-        image.setRow(asNum(values.get(1)));
-        image.setColumn(asNum(values.get(2)));
-        image.setTile(asNum(values.get(3)));
-        image.setChannel(asNum(values.get(4)));
-        image.setImagePath(asImagePath(values.get(5)));
-        return image;
-    }
-
-    private static String asImagePath(ISerializableComparable serializableComparable)
-    {
-        return ((ImageTableCell) serializableComparable).getPath();
-    }
-
-    private static int asNum(ISerializableComparable serializableComparable)
-    {
-        return (int) ((IntegerTableCell) serializableComparable).getNumber();
-    }
-
-    // ------------------------------------------
-
-    private String imagePath;
-
-    private int row;
-
-    private int column;
-
-    private int tile;
-
-    private int channel;
-
-    public String getImagePath()
-    {
-        return imagePath;
-    }
-
-    public void setImagePath(String imagePath)
-    {
-        this.imagePath = imagePath;
-    }
-
-    public int getRow()
-    {
-        return row;
-    }
-
-    public void setRow(int row)
-    {
-        this.row = row;
-    }
-
-    public int getColumn()
-    {
-        return column;
-    }
-
-    public void setColumn(int column)
-    {
-        this.column = column;
-    }
-
-    /** numbered from 1 */
-    public int getTile()
-    {
-        return tile;
-    }
-
-    public void setTile(int tile)
-    {
-        this.tile = tile;
-    }
-
-    /** numbered from 1 */
-    public int getChannel()
-    {
-        return channel;
-    }
-
-    public void setChannel(int channel)
-    {
-        this.channel = channel;
-    }
-}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImageParameters.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImageParameters.java
index 376532763ddfc4a06e4ca11982ee72ac95ee50f7..9e2c6adda15b539b3f7a071bd79b64c745ff5779 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImageParameters.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImageParameters.java
@@ -25,19 +25,8 @@ import com.google.gwt.user.client.rpc.IsSerializable;
  */
 public class PlateImageParameters implements IsSerializable
 {
-    // -------- column headers used in a DSS service to describe images for a plate ------
-
-    public static final String ROWS = "Rows";
-
-    public static final String COLUMNS = "Columns";
-
-    public static final String TILE_ROWS_NUM = "Tile rows";
-
-    public static final String TILE_COLS_NUM = "Tile columns";
-
-    public static final String CHANNELS_NUM = "Number of channels";
-
-    // ----------
+    // dataset code for which plate parameters are valid
+    private String datasetCode;
 
     private int rowsNum;
 
@@ -99,4 +88,13 @@ public class PlateImageParameters implements IsSerializable
         this.channelsNum = channelsNum;
     }
 
+    public String getDatasetCode()
+    {
+        return datasetCode;
+    }
+
+    public void setDatasetCode(String datasetCode)
+    {
+        this.datasetCode = datasetCode;
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImage.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImage.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4b4f91da53c0deae716e41c24e2a7111854954b
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImage.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009 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.basic.dto;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Image of one tile in one channel.
+ * 
+ * @author Tomasz Pylak
+ */
+public class TileImage implements IsSerializable
+{
+    private String datasetCode;
+
+    private String imagePath;
+
+    private int row;
+
+    private int column;
+
+    private int tile;
+
+    private int channel;
+
+    public String getImagePath()
+    {
+        return imagePath;
+    }
+
+    public void setImagePath(String imagePath)
+    {
+        this.imagePath = imagePath;
+    }
+
+    public int getRow()
+    {
+        return row;
+    }
+
+    public void setRow(int row)
+    {
+        this.row = row;
+    }
+
+    public int getColumn()
+    {
+        return column;
+    }
+
+    public void setColumn(int column)
+    {
+        this.column = column;
+    }
+
+    /** numbered from 1 */
+    public int getTile()
+    {
+        return tile;
+    }
+
+    public void setTile(int tile)
+    {
+        this.tile = tile;
+    }
+
+    /** numbered from 1 */
+    public int getChannel()
+    {
+        return channel;
+    }
+
+    public void setChannel(int channel)
+    {
+        this.channel = channel;
+    }
+
+    public String getDatasetCode()
+    {
+        return datasetCode;
+    }
+
+    public void setDatasetCode(String datasetCode)
+    {
+        this.datasetCode = datasetCode;
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImages.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImages.java
similarity index 70%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImages.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImages.java
index a035a73d555b8dff28d78ae10eb3397ef8f5b41e..cbdbc436cc804e1cae0ba6d68305c34f9f1fecb4 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImages.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/TileImages.java
@@ -21,38 +21,41 @@ import java.util.List;
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
- * Describes images in one dataset and the way to fetch them.
+ * Describes images in one dataset and URLs to them.
  * 
  * @author Tomasz Pylak
  */
-public class PlateImages implements IsSerializable
+public class TileImages implements IsSerializable
 {
-    private DatasetReference dataset;
+    public static final TileImages create(DatasetReference dataset, List<TileImage> plateImages,
+            PlateImageParameters imageParams)
+    {
+        return new TileImages(dataset, plateImages, imageParams);
+    }
 
-    private String downloadUrl;
+    private DatasetReference dataset;
 
-    private List<PlateImage> images;
+    private List<TileImage> images;
 
     private PlateImageParameters imageParameters;
 
     // GWT only
     @SuppressWarnings("unused")
-    private PlateImages()
+    private TileImages()
     {
     }
 
-    public PlateImages(DatasetReference dataset, String downloadUrl,
-            List<PlateImage> images, PlateImageParameters imageParameters)
+    public TileImages(DatasetReference dataset, List<TileImage> images,
+            PlateImageParameters imageParameters)
     {
         this.dataset = dataset;
-        this.downloadUrl = downloadUrl;
         this.images = images;
         this.imageParameters = imageParameters;
     }
 
     public String getDownloadUrl()
     {
-        return downloadUrl;
+        return dataset.getDownloadUrl();
     }
 
     public String getDatasetCode()
@@ -65,7 +68,7 @@ public class PlateImages implements IsSerializable
         return dataset.getDatastoreCode();
     }
 
-    public List<PlateImage> getImages()
+    public List<TileImage> getImages()
     {
         return images;
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/WellLocation.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/WellLocation.java
index 80adfdb79a6e5831c270bda637619361deb9a9d7..14392a8258ddc8aebf118d2aa76b9a0e74846717 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/WellLocation.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/WellLocation.java
@@ -31,6 +31,9 @@ public class WellLocation implements IsSerializable
 
     private EntityReference materialContent;
 
+    // contains only images for this well
+    private TileImages imagesOrNull;
+
     // GWT only
     @SuppressWarnings("unused")
     private WellLocation()
@@ -58,4 +61,14 @@ public class WellLocation implements IsSerializable
     {
         return materialContent;
     }
+
+    public TileImages tryGetImages()
+    {
+        return imagesOrNull;
+    }
+
+    public void setImages(TileImages images)
+    {
+        this.imagesOrNull = images;
+    }
 }
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/.gitignore b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/.gitignore
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ServerInterfaceRegressionTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ServerInterfaceRegressionTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a41070434f1e68617a9f89a7cc2fc50e2306fe6
--- /dev/null
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ServerInterfaceRegressionTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 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;
+
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.shared.RegressionTestCase;
+
+/**
+ * @author Tomasz Pylak
+ */
+public class ServerInterfaceRegressionTest extends RegressionTestCase
+{
+    @Test
+    public void testServerAnnotations()
+    {
+        assertMandatoryMethodAnnotations(IScreeningServer.class);
+    }
+}