diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
index c9ce265d97df5f7a44caca87151e0e3e2eb3b058..5cdfd90f7b90f3f903240df8c84232ad453f46b3 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientService.java
@@ -31,6 +31,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GenericTableRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -67,6 +68,12 @@ public interface IScreeningClientService extends IClientService
      */
     public PlateContent getPlateContent(TechId sampleId) throws UserFailureException;
 
+    /**
+     * Fetches information about a plate: metadata and images for wells. The specified dataset is
+     * supposed to be in BDS-HCS format.
+     */
+    public PlateImages getPlateContentForDataset(TechId datasetId);
+
     /**
      * @return well locations which belong to a parent plate connected to a specified experiment.
      *         Each well will have a material property (e.g. oligo), which is connected through
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
index 0b305f9ddadf9742d4c43f41e48a9e241a5a29f3..666829ac2fe7d4ffc2de97feba0297d7b649880a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/IScreeningClientServiceAsync.java
@@ -31,6 +31,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GenericTableRow;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -51,6 +52,10 @@ public interface IScreeningClientServiceAsync extends IClientServiceAsync
     /** @see IScreeningClientService#getPlateContent(TechId) */
     public void getPlateContent(TechId sampleId, final AsyncCallback<PlateContent> callback);
 
+    /** @see IScreeningClientService#getPlateContentForDataset(TechId) */
+    public void getPlateContentForDataset(TechId datasetId,
+            AsyncCallback<PlateImages> createDisplayPlateCallback);
+
     /** @see IScreeningClientService#getDataSetInfo(TechId) */
     public void getDataSetInfo(TechId datasetTechId, AsyncCallback<ExternalData> callback);
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateDatasetViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateDatasetViewer.java
index be4325867536984bffa69be64ce76d1e5c34330b..aec6262d48efef0a0991db1f55c0edfc5fb3bee2 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateDatasetViewer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateDatasetViewer.java
@@ -63,8 +63,7 @@ public final class PlateDatasetViewer extends GenericDataSetViewer
     protected List<SingleSectionPanel> createAdditionalSectionPanels()
     {
         List<SingleSectionPanel> sections = new ArrayList<SingleSectionPanel>();
-        // TODO 2010-02-09, Tomasz Pylak: implement me
-        // sections.add(PlateLayoutSection.createForDataset(screeningViewContext, datasetId));
+        sections.add(new PlateLayoutDatasetSection(screeningViewContext, datasetId));
         return sections;
     }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutDatasetSection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutDatasetSection.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed79a7d18bf2b25d46e6a1eef4fdbef53c71bb83
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutDatasetSection.java
@@ -0,0 +1,89 @@
+/*
+ * 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.detailviewers;
+
+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.button.Button;
+import com.extjs.gxt.ui.client.widget.layout.RowLayout;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+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.SingleSectionPanel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningViewContext;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
+
+/**
+ * A section of dataset detail view for datasets containing HCS images. Shows where the oligo and
+ * gene samples are located on the plate and allow to check the content of the well quickly.
+ * 
+ * @author Tomasz Pylak
+ */
+public class PlateLayoutDatasetSection extends SingleSectionPanel
+{
+    public static final String ID_SUFFIX = "PlateLayoutDatasetSection";
+
+    public PlateLayoutDatasetSection(ScreeningViewContext viewContext, TechId datasetId)
+    {
+        super("Plate Layout");
+        add(new Text(viewContext.getMessage(Dict.LOAD_IN_PROGRESS)));
+        viewContext.getService().getPlateContentForDataset(datasetId,
+                createDisplayPlateCallback(viewContext));
+        setDisplayID(DisplayTypeIDGenerator.SAMPLE_SECTION, ID_SUFFIX);
+    }
+
+    private AsyncCallback<PlateImages> createDisplayPlateCallback(final ScreeningViewContext context)
+    {
+        return new AbstractAsyncCallback<PlateImages>(context)
+            {
+                @Override
+                protected void process(PlateImages plateContent)
+                {
+                    removeAll();
+                    setLayout(new RowLayout());
+                    setScrollMode(Scroll.AUTO);
+
+                    renderPlate(plateContent, context);
+                    addMetadataTable(plateContent.getPlate(), context);
+
+                    layout();
+                }
+            };
+    }
+
+    private void renderPlate(PlateImages plateImages, ScreeningViewContext viewContext)
+    {
+        LayoutContainer container = new LayoutContainer();
+        container.add(PlateLayouter.createVisualization(plateImages, viewContext));
+        add(container, PlateLayouter.createRowLayoutMarginData());
+    }
+
+    private void addMetadataTable(final Sample plate,
+            final IViewContext<IScreeningClientServiceAsync> viewContext)
+    {
+        Button generateButton = PlateLayouter.createPlateMetadataButton(plate, viewContext);
+        add(generateButton, PlateLayouter.createRowLayoutMarginData());
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSampleSection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSampleSection.java
new file mode 100644
index 0000000000000000000000000000000000000000..681f9ee46c071c51c98ff5a620852093b5948166
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSampleSection.java
@@ -0,0 +1,179 @@
+/*
+ * 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.detailviewers;
+
+import java.util.Arrays;
+
+import com.extjs.gxt.ui.client.Style.Scroll;
+import com.extjs.gxt.ui.client.event.ButtonEvent;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.Component;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.Text;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.layout.RowLayout;
+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.SingleSectionPanel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetReportGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedDatasetCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningConstants;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningViewContext;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+
+/**
+ * A section of plate detail view which shows where the oligo and gene samples are located on the
+ * plate and allow to check the content of the well quickly.
+ * 
+ * @author Tomasz Pylak
+ */
+public class PlateLayoutSampleSection extends SingleSectionPanel
+{
+    public static final String ID_SUFFIX = "PlateLayoutSection";
+
+    public PlateLayoutSampleSection(ScreeningViewContext viewContext, TechId sampleId)
+    {
+        super("Plate Layout");
+        add(new Text(viewContext.getMessage(Dict.LOAD_IN_PROGRESS)));
+        viewContext.getService().getPlateContent(sampleId, createDisplayPlateCallback(viewContext));
+        setDisplayID(DisplayTypeIDGenerator.SAMPLE_SECTION, ID_SUFFIX);
+    }
+
+    private AsyncCallback<PlateContent> createDisplayPlateCallback(
+            final ScreeningViewContext context)
+    {
+        return new AbstractAsyncCallback<PlateContent>(context)
+            {
+                @Override
+                protected void process(PlateContent plateContent)
+                {
+                    removeAll();
+                    setLayout(new RowLayout());
+                    setScrollMode(Scroll.AUTO);
+
+                    renderPlate(plateContent, context);
+                    addImageAnalysisButton(plateContent, viewContext);
+
+                    addMetadataTable(plateContent, context);
+
+                    layout();
+                }
+            };
+    }
+
+    private void addImageAnalysisButton(final PlateContent plateContent,
+            final IViewContext<?> viewContext)
+    {
+        Component analysisPanel;
+        int datasetsNumber = plateContent.getImageAnalysisDatasetsNumber();
+        final DatasetReference dataset = plateContent.tryGetImageAnalysisDataset();
+        if (dataset != null)
+        {
+            assert datasetsNumber == 1 : "only one image analysis dataset expected, but found: "
+                    + datasetsNumber;
+            Button generateButton =
+                    new Button("Show Image Analysis Results", new SelectionListener<ButtonEvent>()
+                        {
+                            @Override
+                            public void componentSelected(ButtonEvent ce)
+                            {
+                                generateImageAnalysisReport(viewContext, dataset, plateContent);
+                            }
+                        });
+            analysisPanel = generateButton;
+        } else
+        {
+            if (datasetsNumber == 0)
+            {
+                analysisPanel = new Text("No image analysis data is available.");
+            } else
+            {
+                analysisPanel =
+                        new Text("There are " + datasetsNumber + " analysis datasets, "
+                                + "select the one of your interest from the 'Data Sets' section "
+                                + "and go to its detail view to see the image analysis results.");
+            }
+        }
+        add(analysisPanel, PlateLayouter.createRowLayoutMarginData());
+    }
+
+    private void generateImageAnalysisReport(IViewContext<?> viewContext, DatasetReference dataset,
+            PlateContent plateContent)
+    {
+        DatastoreServiceDescription service = createImageAnalysisReporter(dataset, plateContent);
+        DisplayedOrSelectedDatasetCriteria criteria =
+                DisplayedOrSelectedDatasetCriteria.createSelectedItems(Arrays.asList(dataset
+                        .getCode()));
+        DataSetReportGenerator.generate(viewContext.getCommonViewContext(), service, criteria);
+    }
+
+    private DatastoreServiceDescription createImageAnalysisReporter(DatasetReference dataset,
+            PlateContent plateContent)
+    {
+        String reportLabel = "Image Analysis of " + plateContent.getPlate().getCode();
+        return new DatastoreServiceDescription(ScreeningConstants.PLATE_IMAGE_ANALYSIS_REPORT_KEY,
+                reportLabel, new String[] {}, dataset.getDatastoreCode());
+    }
+
+    private void renderPlate(PlateContent plateContent, ScreeningViewContext viewContext)
+    {
+        LayoutContainer container = new LayoutContainer();
+        Widget datasetNumberLegend = tryRenderImageDatasetsNumberLegend(plateContent, viewContext);
+        if (datasetNumberLegend != null)
+        {
+            container.add(datasetNumberLegend);
+        }
+        container.add(PlateLayouter.createVisualization(plateContent.getPlateImages(), viewContext));
+
+        add(container, PlateLayouter.createRowLayoutMarginData());
+    }
+
+    private Widget tryRenderImageDatasetsNumberLegend(PlateContent plateContent,
+            IViewContext<?> viewContext)
+    {
+        int datasetsNumber = plateContent.getImageDatasetsNumber();
+        if (datasetsNumber == 0)
+        {
+            return new Text("No images data is available.");
+        } else if (datasetsNumber == 1)
+        {
+            return null;
+        } else
+        {
+            return new Text("There are " + datasetsNumber + " datasets with images, "
+                    + "select the one of your interest from the 'Data Sets' section "
+                    + "and go to its detail view to browse acquired images.");
+        }
+    }
+
+    private void addMetadataTable(final PlateContent plateContent,
+            final IViewContext<IScreeningClientServiceAsync> viewContext)
+    {
+        Button generateButton =
+                PlateLayouter.createPlateMetadataButton(plateContent.getPlate(), viewContext);
+        add(generateButton, PlateLayouter.createRowLayoutMarginData());
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayouter.java
similarity index 57%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSection.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayouter.java
index daf0eb615d9ec6cb3fc69b204920226fbbf79123..3ef47c606c7e126be6ab9e51a7e2d66a8198f7c1 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayoutSection.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateLayouter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 ETH Zuerich, CISD
+ * Copyright 2010 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.
@@ -17,10 +17,8 @@
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
-import com.extjs.gxt.ui.client.Style.Scroll;
 import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.ButtonEvent;
 import com.extjs.gxt.ui.client.event.Events;
@@ -35,204 +33,50 @@ import com.extjs.gxt.ui.client.widget.layout.RowData;
 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.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.SingleSectionPanel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DefaultTabItem;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DispatcherHelper;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplayTypeIDGenerator;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItem;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItemFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageDomain;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetReportGenerator;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
-import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedDatasetCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
 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.plugin.screening.client.web.client.IScreeningClientServiceAsync;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ScreeningConstants;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningViewContext;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ChannelChooser.DefaultChannelState;
-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.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
- * A section of plate detail view which shows where the oligo and gene samples are located on the
- * plate and allow to check the content of the well quickly.
+ * Utilities to create plate visualization.
  * 
  * @author Tomasz Pylak
  */
-public class PlateLayoutSection extends SingleSectionPanel
+public class PlateLayouter
 {
     private static final String CONTROL_MATERIAL_TYPE = "CONTROL";
 
-    public static final String ID_SUFFIX = "PlateLayoutSection";
-
-    private final TechId sampleId;
-
-    public PlateLayoutSection(ScreeningViewContext viewContext, TechId sampleId)
-    {
-        super("Plate Layout");
-        this.sampleId = sampleId;
-        add(new Text(viewContext.getMessage(Dict.LOAD_IN_PROGRESS)));
-        viewContext.getService().getPlateContent(sampleId, createDisplayPlateCallback(viewContext));
-        setDisplayID(DisplayTypeIDGenerator.SAMPLE_SECTION, ID_SUFFIX);
-    }
-
-    private AsyncCallback<PlateContent> createDisplayPlateCallback(
-            final ScreeningViewContext context)
-    {
-        return new AbstractAsyncCallback<PlateContent>(context)
-            {
-                @Override
-                protected void process(PlateContent plateContent)
-                {
-                    removeAll();
-                    setLayout(new RowLayout());
-                    setScrollMode(Scroll.AUTO);
-
-                    renderPlate(plateContent, context);
-                    addImageAnalysisButton(plateContent, viewContext);
-
-                    addMetadataTable(plateContent, context);
-
-                    layout();
-                }
-            };
-    }
-
-    private void addImageAnalysisButton(final PlateContent plateContent,
-            final IViewContext<?> viewContext)
-    {
-        Component analysisPanel;
-        int datasetsNumber = plateContent.getImageAnalysisDatasetsNumber();
-        final DatasetReference dataset = plateContent.tryGetImageAnalysisDataset();
-        if (dataset != null)
-        {
-            assert datasetsNumber == 1 : "only one image analysis dataset expected, but found: "
-                    + datasetsNumber;
-            Button generateButton =
-                    new Button("Show Image Analysis Results", new SelectionListener<ButtonEvent>()
-                        {
-                            @Override
-                            public void componentSelected(ButtonEvent ce)
-                            {
-                                generateImageAnalysisReport(viewContext, dataset, plateContent);
-                            }
-                        });
-            analysisPanel = generateButton;
-        } else
-        {
-            if (datasetsNumber == 0)
-            {
-                analysisPanel = new Text("No image analysis data is available.");
-            } else
-            {
-                analysisPanel =
-                        new Text("There are " + datasetsNumber + " analysis datasets, "
-                                + "select the one of your interest from the 'Data Sets' section "
-                                + "and go to its detail view to see the image analysis results.");
-            }
-        }
-        add(analysisPanel, createMarginLayoutData());
-    }
-
-    private void generateImageAnalysisReport(IViewContext<?> viewContext, DatasetReference dataset,
-            PlateContent plateContent)
-    {
-        DatastoreServiceDescription service = createImageAnalysisReporter(dataset, plateContent);
-        DisplayedOrSelectedDatasetCriteria criteria =
-                DisplayedOrSelectedDatasetCriteria.createSelectedItems(Arrays.asList(dataset
-                        .getCode()));
-        DataSetReportGenerator.generate(viewContext.getCommonViewContext(), service, criteria);
-    }
-
-    private DatastoreServiceDescription createImageAnalysisReporter(DatasetReference dataset,
-            PlateContent plateContent)
-    {
-        String reportLabel = "Image Analysis of " + plateContent.getPlate().getCode();
-        return new DatastoreServiceDescription(ScreeningConstants.PLATE_IMAGE_ANALYSIS_REPORT_KEY,
-                reportLabel, new String[] {}, dataset.getDatastoreCode());
-    }
-
-    private void renderPlate(PlateContent plateContent, ScreeningViewContext viewContext)
+    /** @return widget with plate visualization - all the wells and possibility to browse images. */
+    public static Widget createVisualization(PlateImages plateImages,
+            ScreeningViewContext viewContext)
     {
-        LayoutContainer container = new LayoutContainer();
-        Widget datasetNumberLegend = tryRenderImageDatasetsNumberLegend(plateContent, viewContext);
-        if (datasetNumberLegend != null)
-        {
-            container.add(datasetNumberLegend);
-        }
-        container.add(renderWellsMatrix(plateContent, viewContext));
+        final LayoutContainer container = new LayoutContainer();
+        container.setLayout(new RowLayout());
+        LayoutContainer wellsMatrix = renderWellsMatrix(plateImages, viewContext);
+        container.add(wellsMatrix);
         container.add(renderWellsLegend());
-
-        add(container, createMarginLayoutData());
+        return container;
     }
 
-    private Widget tryRenderImageDatasetsNumberLegend(PlateContent plateContent,
-            IViewContext<?> viewContext)
-    {
-        int datasetsNumber = plateContent.getImageDatasetsNumber();
-        if (datasetsNumber == 0)
-        {
-            return new Text("No images data is available.");
-        } else if (datasetsNumber == 1)
-        {
-            return null;
-        } else
-        {
-            return new Text("There are " + datasetsNumber + " datasets with images, "
-                    + "select the one of your interest from the 'Data Sets' section "
-                    + "and go to its detail view to browse acquired images.");
-        }
-    }
-
-    private RowData createMarginLayoutData()
-    {
-        RowData layoutData = new RowData();
-        layoutData.setMargins(new Margins(10));
-        return layoutData;
-    }
-
-    private LayoutContainer renderWellsLegend()
-    {
-        LayoutContainer legend = new LayoutContainer();
-        legend.setLayout(new TableLayout(2));
-
-        TableData mergedColumns = new TableData();
-        mergedColumns.setColspan(2);
-
-        Component verticalSeparator = createBox();
-        verticalSeparator.setHeight("10");
-        legend.add(verticalSeparator, mergedColumns);
-
-        legend.add(new Text("Put a mouse on a well or click on it to get the details."),
-                mergedColumns);
-        legend.add(new Text("Legend:"), mergedColumns);
-
-        legend.add(createNonEmptyWell(false));
-        legend.add(new Text("Non-empty well"));
-
-        legend.add(createNonEmptyWell(true));
-        legend.add(new Text("Control well"));
-
-        legend.add(createEmptyWellWidget());
-        legend.add(new Text("Empty well"));
-
-        return legend;
-    }
-
-    private LayoutContainer renderWellsMatrix(PlateContent plateContent,
+    private static LayoutContainer renderWellsMatrix(PlateImages plateContent,
             ScreeningViewContext viewContext)
     {
         WellData[][] wellMatrix = createMatrix(plateContent);
@@ -250,7 +94,7 @@ public class PlateLayoutSection extends SingleSectionPanel
     }
 
     private static List<Widget> createWellWidgets(WellData[][] wellMatrix,
-            PlateContent plateContent, ScreeningViewContext viewContext)
+            PlateImages plateContent, ScreeningViewContext viewContext)
     {
         List<Widget> wellWidgets = new ArrayList<Widget>();
         int rowsNum = wellMatrix.length;
@@ -324,7 +168,33 @@ public class PlateLayoutSection extends SingleSectionPanel
         }
     }
 
-    // ------ end todo
+    private static LayoutContainer renderWellsLegend()
+    {
+        LayoutContainer legend = new LayoutContainer();
+        legend.setLayout(new TableLayout(2));
+
+        TableData mergedColumns = new TableData();
+        mergedColumns.setColspan(2);
+
+        Component verticalSeparator = createBox();
+        verticalSeparator.setHeight("10");
+        legend.add(verticalSeparator, mergedColumns);
+
+        legend.add(new Text("Put a mouse on a well or click on it to get the details."),
+                mergedColumns);
+        legend.add(new Text("Legend:"), mergedColumns);
+
+        legend.add(createNonEmptyWell(false));
+        legend.add(new Text("Non-empty well"));
+
+        legend.add(createNonEmptyWell(true));
+        legend.add(new Text("Control well"));
+
+        legend.add(createEmptyWellWidget());
+        legend.add(new Text("Empty well"));
+
+        return legend;
+    }
 
     private static Component createEmptyWellWidget()
     {
@@ -334,7 +204,7 @@ public class PlateLayoutSection extends SingleSectionPanel
     }
 
     private static Component createWellWidget(final WellData wellData,
-            final PlateContent plateContent, final DefaultChannelState channelState,
+            final PlateImages plateContent, final DefaultChannelState channelState,
             final ScreeningViewContext viewContext)
     {
         Component widget = createContentWell(wellData);
@@ -416,7 +286,7 @@ public class PlateLayoutSection extends SingleSectionPanel
 
     // Elements will not contain null even if well is empty.
     // Numbering starts with 1 so row and column with index 0 are left empty.
-    private static WellData[][] createMatrix(PlateContent plateContent)
+    private static WellData[][] createMatrix(PlateImages plateContent)
     {
         WellData[][] matrix = createWellData(plateContent);
         List<WellMetadata> wells = plateContent.getWells();
@@ -432,7 +302,7 @@ public class PlateLayoutSection extends SingleSectionPanel
         return matrix;
     }
 
-    private static WellData[][] createWellData(PlateContent plateContent)
+    private static WellData[][] createWellData(PlateImages plateContent)
     {
         WellData[][] data =
                 new WellData[plateContent.getRowsNum() + 1][plateContent.getColsNum() + 1];
@@ -446,41 +316,53 @@ public class PlateLayoutSection extends SingleSectionPanel
         return data;
     }
 
-    private void addMetadataTable(final PlateContent plateContent,
+    // ---------
+
+    /** @return a button which shows a grid with the plate metadata */
+    public static Button createPlateMetadataButton(final Sample plate,
             final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
-        final Button generateButton =
-                new Button("Show Plate Report", new SelectionListener<ButtonEvent>()
-                    {
+        return new Button("Show Plate Report", new SelectionListener<ButtonEvent>()
+            {
+                @Override
+                public void componentSelected(ButtonEvent ce)
+                {
+                    DispatcherHelper.dispatchNaviEvent(createPlateMetadataTabFactory());
+                }
 
-                        @Override
-                        public void componentSelected(ButtonEvent ce)
+                private ITabItemFactory createPlateMetadataTabFactory()
+                {
+                    return new ITabItemFactory()
                         {
-                            final ITabItemFactory tabFactory = new ITabItemFactory()
-                                {
-                                    public ITabItem create()
-                                    {
-                                        return DefaultTabItem.create("Plate Report: "
-                                                + plateContent.getPlate().getCode(),
-                                                PlateMetadataBrowser.create(viewContext, sampleId),
-                                                viewContext);
-                                    }
-
-                                    public String getId()
-                                    {
-                                        return GenericConstants.ID_PREFIX + "plate-metadata-"
-                                                + plateContent.getPlate().getId();
-                                    }
-
-                                    public HelpPageIdentifier getHelpPageIdentifier()
-                                    {
-                                        return new HelpPageIdentifier(HelpPageDomain.SAMPLE,
-                                                HelpPageAction.VIEW);
-                                    }
-                                };
-                            DispatcherHelper.dispatchNaviEvent(tabFactory);
-                        }
-                    });
-        add(generateButton, createMarginLayoutData());
+                            public ITabItem create()
+                            {
+                                return DefaultTabItem.create("Plate Report: " + plate.getCode(),
+                                        PlateMetadataBrowser.create(viewContext, new TechId(plate
+                                                .getId())), viewContext);
+                            }
+
+                            public String getId()
+                            {
+                                return GenericConstants.ID_PREFIX + "plate-metadata-"
+                                        + plate.getId();
+                            }
+
+                            public HelpPageIdentifier getHelpPageIdentifier()
+                            {
+                                return new HelpPageIdentifier(HelpPageDomain.SAMPLE,
+                                        HelpPageAction.VIEW);
+                            }
+                        };
+                }
+            });
+    }
+
+    /** @return layout data with big margin */
+    public static RowData createRowLayoutMarginData()
+    {
+        RowData layoutData = new RowData();
+        layoutData.setMargins(new Margins(10));
+        return layoutData;
     }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateSampleViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateSampleViewer.java
index 6dbd98312f6febb0d4716f9a7a606ea82c892e02..5ff75844eddbc2af02468ff1296a12e3780c64e2 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateSampleViewer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PlateSampleViewer.java
@@ -64,7 +64,7 @@ public final class PlateSampleViewer extends GenericSampleViewer
     protected List<SingleSectionPanel> createAdditionalSectionPanels()
     {
         List<SingleSectionPanel> sections = new ArrayList<SingleSectionPanel>();
-        sections.add(new PlateLayoutSection(screeningViewContext, sampleId));
+        sections.add(new PlateLayoutSampleSection(screeningViewContext, sampleId));
         return sections;
     }
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellData.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellData.java
index 9503d5a496db223e50b1509d83661a852ff8779d..8aa5bb1c779652a4b2acfbb67cd4107949226511 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellData.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellData.java
@@ -17,8 +17,8 @@
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentIdentifier;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetImagesReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
@@ -35,21 +35,21 @@ class WellData
 
     private ExperimentIdentifier experimentIdentifier;
 
-    public static WellData create(PlateContent plateContent, WellLocation location)
+    public static WellData create(PlateImages plateImages, WellLocation location)
     {
-        ExperimentIdentifier experimentIdentifier = getExperimentIdentifier(plateContent);
-        WellImages wellImages = tryCreateWellImages(plateContent, location);
+        ExperimentIdentifier experimentIdentifier = getExperimentIdentifier(plateImages);
+        WellImages wellImages = tryCreateWellImages(plateImages, location);
         return new WellData(wellImages, experimentIdentifier);
     }
 
-    private static ExperimentIdentifier getExperimentIdentifier(PlateContent plateContent)
+    private static ExperimentIdentifier getExperimentIdentifier(PlateImages plateImages)
     {
-        return ExperimentIdentifier.createIdentifier(plateContent.getPlate().getExperiment());
+        return ExperimentIdentifier.createIdentifier(plateImages.getPlate().getExperiment());
     }
 
-    private static WellImages tryCreateWellImages(PlateContent plateContent, WellLocation location)
+    private static WellImages tryCreateWellImages(PlateImages plateImages, WellLocation location)
     {
-        DatasetImagesReference images = plateContent.tryGetImages();
+        DatasetImagesReference images = plateImages.tryGetImages();
         if (images != null)
         {
             return new WellImages(images.getImageParameters(), images.getDownloadUrl(), location);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
index 321653f6050157cfbe6c17153b7066512bcffc31..3fdb09cdd642940c28693ab832d46a632415e4e4 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/PlateMetadataProvider.java
@@ -38,7 +38,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
 /**
  * Original data provider for plate content.
- *
+ * 
  * @author Izabela Adamczyk
  */
 class PlateMetadataProvider implements IOriginalDataProvider<GenericTableRow>
@@ -51,7 +51,7 @@ class PlateMetadataProvider implements IOriginalDataProvider<GenericTableRow>
     public PlateMetadataProvider(IScreeningServer server, String sessionToken, TechId plateId)
     {
         plateContent = server.getPlateContent(sessionToken, plateId);
-        wells = plateContent.getWells();
+        wells = plateContent.getPlateImages().getWells();
     }
 
     public List<GenericTableRow> getOriginalData() throws UserFailureException
@@ -89,34 +89,39 @@ class PlateMetadataProvider implements IOriginalDataProvider<GenericTableRow>
     {
         List<Column> columns = new ArrayList<Column>();
         Column codeColumn =
-                new Column(GenericTableColumnHeader.untitledLinkableStringHeader(PlateMetadataStaticColumns.WELL
-                        .ordinal(), PlateMetadataStaticColumns.WELL.colId()));
+                new Column(GenericTableColumnHeader.untitledLinkableStringHeader(
+                        PlateMetadataStaticColumns.WELL.ordinal(), PlateMetadataStaticColumns.WELL
+                                .colId()));
         columns.add(codeColumn);
 
         Column typeColumn =
-                new Column(GenericTableColumnHeader.untitledStringHeader(PlateMetadataStaticColumns.TYPE
-                        .ordinal(), PlateMetadataStaticColumns.TYPE.colId()));
+                new Column(GenericTableColumnHeader.untitledStringHeader(
+                        PlateMetadataStaticColumns.TYPE.ordinal(), PlateMetadataStaticColumns.TYPE
+                                .colId()));
         columns.add(typeColumn);
 
         Column contentColumn =
                 new Column(GenericTableColumnHeader.untitledLinkableStringHeader(
-                        PlateMetadataStaticColumns.CONTENT.ordinal(), PlateMetadataStaticColumns.CONTENT.colId()));
+                        PlateMetadataStaticColumns.CONTENT.ordinal(),
+                        PlateMetadataStaticColumns.CONTENT.colId()));
         columns.add(contentColumn);
 
         Column contentTypeColumn =
-                new Column(GenericTableColumnHeader.untitledStringHeader(PlateMetadataStaticColumns.CONTENT_TYPE
-                        .ordinal(), PlateMetadataStaticColumns.CONTENT_TYPE.colId()));
+                new Column(GenericTableColumnHeader.untitledStringHeader(
+                        PlateMetadataStaticColumns.CONTENT_TYPE.ordinal(),
+                        PlateMetadataStaticColumns.CONTENT_TYPE.colId()));
         columns.add(contentTypeColumn);
 
         Column geneCodeColumn =
                 new Column(GenericTableColumnHeader.untitledLinkableStringHeader(
-                        PlateMetadataStaticColumns.INHIBITED_GENE.ordinal(), PlateMetadataStaticColumns.INHIBITED_GENE
-                                .colId()));
+                        PlateMetadataStaticColumns.INHIBITED_GENE.ordinal(),
+                        PlateMetadataStaticColumns.INHIBITED_GENE.colId()));
         columns.add(geneCodeColumn);
 
         Column showGeneColumn =
                 new Column(GenericTableColumnHeader.untitledLinkableStringHeader(
-                        PlateMetadataStaticColumns.GENE_DETAILS.ordinal(), PlateMetadataStaticColumns.GENE_DETAILS.colId()));
+                        PlateMetadataStaticColumns.GENE_DETAILS.ordinal(),
+                        PlateMetadataStaticColumns.GENE_DETAILS.colId()));
         columns.add(showGeneColumn);
         int fixedColumns = columns.size();
         PropertyColumns contentPropertyColumns = new PropertyColumns();
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
index ab8d5618d833dc41d5111d9ceca58dcc5062c2fc..6c7aad01fe97e35f28122eb4b4455e99eff15028 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ScreeningClientService.java
@@ -44,6 +44,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningCli
 import ch.systemsx.cisd.openbis.plugin.screening.shared.IScreeningServer;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.ResourceNames;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -137,6 +138,17 @@ public final class ScreeningClientService extends AbstractClientService implemen
         }
     }
 
+    public PlateImages getPlateContentForDataset(TechId datasetId)
+    {
+        try
+        {
+            return server.getPlateContentForDataset(getSessionToken(), datasetId);
+        } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public List<WellContent> getPlateLocations(TechId geneMaterialId,
             ExperimentIdentifier experimentIdentifier) throws UserFailureException
     {
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/IScreeningBusinessObjectFactory.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/IScreeningBusinessObjectFactory.java
index 31d2d18fbf62f98754ccfc0737be1b3b8be90905..43ab486ff286f0a5696629389f6e069a0bfa1bcc 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/IScreeningBusinessObjectFactory.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/IScreeningBusinessObjectFactory.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.plugin.screening.server;
 
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
@@ -42,4 +43,6 @@ public interface IScreeningBusinessObjectFactory
     public ISampleLister createSampleLister(Session session);
 
     public IMaterialLister createMaterialLister(Session session);
+
+    public IExternalDataBO createExternalDataBO(Session session);
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningBusinessObjectFactory.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningBusinessObjectFactory.java
index 64116aed3385d95e84c6c2d2fb592ced15c3f58b..be2fdc699e56b5fe052da4c046186b0706d39ff0 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningBusinessObjectFactory.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningBusinessObjectFactory.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.server;
 import org.springframework.stereotype.Component;
 
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
@@ -68,4 +69,9 @@ public final class ScreeningBusinessObjectFactory extends AbstractPluginBusiness
         return getCommonBusinessObjectFactory().createMaterialBO(session);
     }
 
+    public IExternalDataBO createExternalDataBO(Session session)
+    {
+        return getCommonBusinessObjectFactory().createExternalDataBO(session);
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
index 0a7ee7b25877fa36b61388b3c799f472a9e6edf3..c5e42a75b7f5fae59cb7752ef191a1d824069d99 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
@@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.server.logic.PlateContentLoader
 import ch.systemsx.cisd.openbis.plugin.screening.shared.IScreeningServer;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.ResourceNames;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -122,6 +123,12 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
         return PlateContentLoader.load(session, businessObjectFactory, plateId);
     }
 
+    public PlateImages getPlateContentForDataset(String sessionToken, TechId datasetId)
+    {
+        Session session = getSession(sessionToken);
+        return PlateContentLoader.loadForDataset(session, businessObjectFactory, datasetId);
+    }
+
     public List<WellContent> getPlateLocations(String sessionToken, TechId geneMaterialId,
             ExperimentIdentifier experimentIdentifier)
     {
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 0fc49e476068d45b3c11b9691bcefa0333391beb..7513e7970f9d4d316d806c8768df734884c2fa9d 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
@@ -31,6 +31,7 @@ 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.shared.IScreeningServer;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -62,28 +63,33 @@ final class ScreeningServerLogger extends AbstractServerLogger implements IScree
 
     public PlateContent getPlateContent(String sessionToken, TechId plateId)
     {
-        logTracking(sessionToken, "getPlateContent", "PLATE(%s)", plateId.getId());
+        logAccess(sessionToken, "getPlateContent", "PLATE(%s)", plateId.getId());
+        return null;
+    }
+
+    public PlateImages getPlateContentForDataset(String sessionToken, TechId datasetId)
+    {
+        logAccess(sessionToken, "getPlateContentForDataset", "DATASET(%s)", datasetId.getId());
         return null;
     }
 
     public List<WellContent> getPlateLocations(String sessionToken, TechId geneMaterialId,
             ExperimentIdentifier experimentIdentifier)
     {
-        logTracking(sessionToken, "getPlateLocations",
-                "geneMaterialId(%s) experimentIdentifier(%s)", geneMaterialId.getId(),
-                experimentIdentifier);
+        logAccess(sessionToken, "getPlateLocations", "geneMaterialId(%s) experimentIdentifier(%s)",
+                geneMaterialId.getId(), experimentIdentifier);
         return null;
     }
 
     public Material getMaterialInfo(String sessionToken, TechId materialId)
     {
-        logTracking(sessionToken, "getMaterialInfo", "materialId(%s)", materialId.getId());
+        logAccess(sessionToken, "getMaterialInfo", "materialId(%s)", materialId.getId());
         return null;
     }
 
     public ExternalData getDataSetInfo(String sessionToken, TechId datasetId)
     {
-        logTracking(sessionToken, "getDataSetInfo", "datasetId(%s)", datasetId.getId());
+        logAccess(sessionToken, "getDataSetInfo", "datasetId(%s)", datasetId.getId());
         return null;
     }
 }
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 caa98fed997b63fd3ed3d7eef906662d7b65b3fb..161b24102cc4f4ed1a704c61d68b2310f9836bb2 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
@@ -20,6 +20,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister;
@@ -41,6 +43,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReferen
 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.DatasetImagesReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 
@@ -51,12 +54,27 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
  */
 public class PlateContentLoader
 {
+    /**
+     * loads data about the plate for a specified sample id. Attaches information about images and
+     * image analysis only if one dataset with such a data exist.
+     */
     public static PlateContent load(Session session,
             IScreeningBusinessObjectFactory businessObjectFactory, TechId plateId)
     {
         return new PlateContentLoader(session, businessObjectFactory).getPlateContent(plateId);
     }
 
+    /**
+     * loads data about the plate for a specified dataset, which is supposed to contain images in
+     * BDS-HCS format.
+     */
+    public static PlateImages loadForDataset(Session session,
+            IScreeningBusinessObjectFactory businessObjectFactory, TechId datasetId)
+    {
+        return new PlateContentLoader(session, businessObjectFactory)
+                .getPlateContentForDataset(datasetId);
+    }
+
     private final Session session;
 
     private final IScreeningBusinessObjectFactory businessObjectFactory;
@@ -68,6 +86,29 @@ public class PlateContentLoader
         this.businessObjectFactory = businessObjectFactory;
     }
 
+    private PlateImages getPlateContentForDataset(TechId datasetId)
+    {
+        ExternalDataPE externalData = loadDataset(datasetId);
+        SamplePE plate = externalData.tryGetSample();
+        if (plate == null)
+        {
+            throw UserFailureException.fromTemplate("Dataset '%s' has no sample connected.",
+                    externalData.getCode());
+        }
+        List<WellMetadata> wells = loadWells(new TechId(plate.getId()));
+        DatasetImagesReference datasetImagesReference =
+                loadImages(businessObjectFactory.createExternalDataTable(session), externalData);
+        return new PlateImages(translate(plate), wells, datasetImagesReference);
+    }
+
+    private ExternalDataPE loadDataset(TechId datasetId)
+    {
+        IExternalDataBO externalDataBO = businessObjectFactory.createExternalDataBO(session);
+        externalDataBO.loadDataByTechId(datasetId);
+        ExternalDataPE externalData = externalDataBO.getExternalData();
+        return externalData;
+    }
+
     private PlateContent getPlateContent(TechId plateId)
     {
         IExternalDataTable externalDataTable =
@@ -101,6 +142,11 @@ public class PlateContentLoader
         ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
         sampleBO.loadDataByTechId(plateId);
         SamplePE sample = sampleBO.getSample();
+        return translate(sample);
+    }
+
+    private Sample translate(SamplePE sample)
+    {
         return SampleTranslator.translate(sample, session.getBaseIndexURL());
     }
 
@@ -153,10 +199,12 @@ public class PlateContentLoader
         return externalData;
     }
 
-    private DatasetImagesReference loadImages(IExternalDataTable externalDataTable, ExternalDataPE dataset)
+    private DatasetImagesReference loadImages(IExternalDataTable externalDataTable,
+            ExternalDataPE dataset)
     {
         PlateImageParameters imageParameters = loadImageParams(dataset, externalDataTable);
-        return DatasetImagesReference.create(ScreeningUtils.createDatasetReference(dataset), imageParameters);
+        return DatasetImagesReference.create(ScreeningUtils.createDatasetReference(dataset),
+                imageParameters);
     }
 
     private PlateImageParameters loadImageParams(ExternalDataPE dataset,
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/IScreeningServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/IScreeningServer.java
index 1458612628efe9f66dd32491c6d03c013ea6749d..fd6bade5a70d9c6fc2277a2e9d0a969bf854da1e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/IScreeningServer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/IScreeningServer.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.GroupIdentifierPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleTechIdPredicate;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.AbstractTechIdPredicate.DataSetTechIdPredicate;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
@@ -34,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
 
 /**
@@ -51,6 +53,14 @@ public interface IScreeningServer extends IServer
     public PlateContent getPlateContent(String sessionToken,
             @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId plateId);
 
+    /**
+     * Returns plate content for a specified HCS_IMAGE dataset.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public PlateImages getPlateContentForDataset(String sessionToken,
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId datasetId);
+
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
     public List<WellContent> getPlateLocations(
@@ -83,6 +93,6 @@ public interface IScreeningServer extends IServer
      */
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
-    public ExternalData getDataSetInfo(String sessionToken, TechId datasetId);
-
+    public ExternalData getDataSetInfo(String sessionToken,
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId datasetId);
 }
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 b3e3114cc8b4f43a9b92b78d29790a4d0a5299f3..1add940049f0e896343ad0f65f9170b8d6374884 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
@@ -30,12 +30,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
  */
 public class PlateContent implements IsSerializable
 {
-    private Sample plate;
-
-    private List<WellMetadata> wellsMetadata;
-
-    // not null if exactly one image dataset exists
-    private DatasetImagesReference imagesOrNull;
+    private PlateImages plateImages;
 
     // not null if exactly one image analysis dataset exists
     private DatasetReference imageAnalysisDatasetOrNull;
@@ -58,66 +53,34 @@ public class PlateContent implements IsSerializable
                 || (imagesOrNull == null && imageDatasetsNumber != 1);
         assert (imageAnalysisDatasetOrNull != null && imageAnalysisDatasetsNumber == 1)
                 || (imageAnalysisDatasetOrNull == null && imageAnalysisDatasetsNumber != 1);
-        this.plate = plate;
-        this.wellsMetadata = wells;
-        this.imagesOrNull = imagesOrNull;
+        this.plateImages = new PlateImages(plate, wells, imagesOrNull);
         this.imageDatasetsNumber = imageDatasetsNumber;
         this.imageAnalysisDatasetOrNull = imageAnalysisDatasetOrNull;
         this.imageAnalysisDatasetsNumber = imageAnalysisDatasetsNumber;
     }
 
-    public List<WellMetadata> getWells()
-    {
-        return wellsMetadata;
-    }
-
-    /** can be null */
-    public DatasetImagesReference tryGetImages()
-    {
-        return imagesOrNull;
-    }
-
     public DatasetReference tryGetImageAnalysisDataset()
     {
         return imageAnalysisDatasetOrNull;
     }
 
-    public Sample getPlate()
-    {
-        return plate;
-    }
-
-    public int getRowsNum()
+    public int getImageDatasetsNumber()
     {
-        if (imagesOrNull != null)
-        {
-            return imagesOrNull.getImageParameters().getRowsNum();
-        } else
-        {
-            // TODO 2009-12-09, Tomasz Pylak: calculate rows number on the basis of metadata
-            return 16;
-        }
+        return imageDatasetsNumber;
     }
 
-    public int getColsNum()
+    public int getImageAnalysisDatasetsNumber()
     {
-        if (imagesOrNull != null)
-        {
-            return imagesOrNull.getImageParameters().getColsNum();
-        } else
-        {
-            // TODO 2009-12-09, Tomasz Pylak: calculate rows number on the basis of metadata
-            return 24;
-        }
+        return imageAnalysisDatasetsNumber;
     }
 
-    public int getImageDatasetsNumber()
+    public PlateImages getPlateImages()
     {
-        return imageDatasetsNumber;
+        return plateImages;
     }
 
-    public int getImageAnalysisDatasetsNumber()
+    public Sample getPlate()
     {
-        return imageAnalysisDatasetsNumber;
+        return plateImages.getPlate();
     }
 }
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/PlateImages.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec68f5d272705bc4d4b458df8822017b7436a97f
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/PlateImages.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2010 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.List;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+
+/**
+ * DTO with metadata of a plate and all its wells + reference to a dataset with plate images.
+ * 
+ * @author Tomasz Pylak
+ */
+public class PlateImages implements IsSerializable
+{
+    private Sample plate;
+
+    private List<WellMetadata> wellsMetadata;
+
+    // null if dataset with images does not exist
+    private DatasetImagesReference imagesOrNull;
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private PlateImages()
+    {
+    }
+
+    public PlateImages(Sample plate, List<WellMetadata> wellsMetadata,
+            DatasetImagesReference imagesOrNull)
+    {
+        this.plate = plate;
+        this.wellsMetadata = wellsMetadata;
+        this.imagesOrNull = imagesOrNull;
+    }
+
+    public List<WellMetadata> getWells()
+    {
+        return wellsMetadata;
+    }
+
+    /** can be null */
+    public DatasetImagesReference tryGetImages()
+    {
+        return imagesOrNull;
+    }
+
+    public Sample getPlate()
+    {
+        return plate;
+    }
+
+    public int getRowsNum()
+    {
+        if (imagesOrNull != null)
+        {
+            return imagesOrNull.getImageParameters().getRowsNum();
+        } else
+        {
+            // TODO 2009-12-09, Tomasz Pylak: calculate rows number on the basis of metadata
+            return 16;
+        }
+    }
+
+    public int getColsNum()
+    {
+        if (imagesOrNull != null)
+        {
+            return imagesOrNull.getImageParameters().getColsNum();
+        } else
+        {
+            // TODO 2009-12-09, Tomasz Pylak: calculate rows number on the basis of metadata
+            return 24;
+        }
+    }
+}