diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/FeatureTableBuilder.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/FeatureTableBuilder.java
index 050450642423419764aa02943ab7fba51676afff..2400cc8bd383735c82a41d0d5a7835f87aff78c1 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/FeatureTableBuilder.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/FeatureTableBuilder.java
@@ -18,14 +18,14 @@ package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
@@ -49,12 +49,11 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgFe
  */
 public class FeatureTableBuilder
 {
-    private static final class Bundle
+    // stores all feature vectors of one dataset
+    private static final class DatasetFeaturesBundle
     {
         private ImgDatasetDTO dataSet;
 
-        private FeatureVectorDatasetWellReference reference;
-
         private Map<ImgFeatureDefDTO, List<ImgFeatureValuesDTO>> featureDefToValuesMap;
     }
 
@@ -62,67 +61,142 @@ public class FeatureTableBuilder
 
     private final IEncapsulatedOpenBISService service;
 
-    private final List<Bundle> bundles;
+    private final List<DatasetFeaturesBundle> bundles;
 
     private final Map<CodeAndLabel, Integer> featureCodeLabelToIndexMap;
 
     private final Set<String> featureCodes;
-    
+
     private final boolean useAllFeatures;
 
+    /** fetches all features of specified wells */
+    public static WellFeatureCollection fetchWellFeatures(
+            List<FeatureVectorDatasetWellReference> references, IImagingReadonlyQueryDAO dao,
+            IEncapsulatedOpenBISService service)
+    {
+        return fetchWellFeatures(references, new ArrayList<String>(), dao, service);
+    }
+
     /**
-     * Creates an instance for specified DAO and openBIS service.
+     * fetches specified features of specified wells
+     * 
+     * @param featureCodes empty list means no filtering.
      */
-    public FeatureTableBuilder(IImagingReadonlyQueryDAO dao, IEncapsulatedOpenBISService service)
+    public static WellFeatureCollection fetchWellFeatures(
+            List<FeatureVectorDatasetWellReference> references, List<String> featureCodes,
+            IImagingReadonlyQueryDAO dao, IEncapsulatedOpenBISService service)
     {
-        this(Collections.<String> emptyList(), dao, service);
+        FeatureTableBuilder builder = new FeatureTableBuilder(featureCodes, dao, service);
+        Set<String> datasetCodes = extractDatasetCodes(references);
+        for (String datasetCode : datasetCodes)
+        {
+            builder.addFeatureVectorsOfDataSet(datasetCode);
+        }
+        List<FeatureTableRow> features = builder.createFeatureTableRows(references);
+        return new WellFeatureCollection(features, builder.getCodesAndLabels());
+    }
+
+    /**
+     * fetches specified features of all wells
+     * 
+     * @param featureCodes empty list means no filtering.
+     */
+    public static WellFeatureCollection fetchDatasetFeatures(List<String> datasetCodes,
+            List<String> featureCodes, IImagingReadonlyQueryDAO dao,
+            IEncapsulatedOpenBISService service)
+    {
+        FeatureTableBuilder builder = new FeatureTableBuilder(featureCodes, dao, service);
+        for (String datasetCode : datasetCodes)
+        {
+            builder.addFeatureVectorsOfDataSet(datasetCode);
+        }
+        List<FeatureTableRow> features = builder.createFeatureTableRows();
+        return new WellFeatureCollection(features, builder.getCodesAndLabels());
+    }
+
+    public static class WellFeatureCollection
+    {
+        private final List<FeatureTableRow> features;
+
+        private final List<CodeAndLabel> featureNames;
+
+        public WellFeatureCollection(List<FeatureTableRow> features, List<CodeAndLabel> featureNames)
+        {
+            this.features = features;
+            this.featureNames = featureNames;
+        }
+
+        public List<FeatureTableRow> getFeatures()
+        {
+            return features;
+        }
+
+        public List<CodeAndLabel> getFeatureCodesAndLabels()
+        {
+            return featureNames;
+        }
+
+        public List<String> getFeatureCodes()
+        {
+            List<String> codes = new ArrayList<String>();
+            for (CodeAndLabel codeAndTitle : featureNames)
+            {
+                codes.add(codeAndTitle.getCode());
+            }
+            return codes;
+        }
+
+        public List<String> getFeatureLabels()
+        {
+            List<String> labels = new ArrayList<String>();
+            for (CodeAndLabel codeAndTitle : featureNames)
+            {
+                labels.add(codeAndTitle.getLabel());
+            }
+            return labels;
+        }
+    }
+
+    private static Set<String> extractDatasetCodes(
+            List<FeatureVectorDatasetWellReference> references)
+    {
+        Set<String> datasetCodes = new HashSet<String>();
+        for (FeatureVectorDatasetWellReference ref : references)
+        {
+            datasetCodes.add(ref.getDatasetCode());
+        }
+        return datasetCodes;
     }
 
     /**
      * Creates an instance for specified DAO and openBIS service but filters on specified features.
      * 
-     * @param featureCodes And empty list means no filtering.
+     * @param featureCodes empty list means no filtering.
      */
-    public FeatureTableBuilder(List<String> featureCodes, IImagingReadonlyQueryDAO dao,
+    FeatureTableBuilder(List<String> featureCodes, IImagingReadonlyQueryDAO dao,
             IEncapsulatedOpenBISService service)
     {
         this.dao = dao;
         this.service = service;
-        bundles = new ArrayList<Bundle>();
+        bundles = new ArrayList<DatasetFeaturesBundle>();
         featureCodeLabelToIndexMap = new LinkedHashMap<CodeAndLabel, Integer>();
         this.featureCodes = new LinkedHashSet<String>(featureCodes);
         this.useAllFeatures = featureCodes.isEmpty();
     }
 
-    /**
-     * Adds feature vectors for specified data set, marking the well position.
-     */
-    public Bundle addFeatureVectorsOfDataSet(FeatureVectorDatasetWellReference reference)
-    {
-        final Bundle bundle = addFeatureVectorsOfDataSet(reference.getDatasetCode());
-        bundle.reference = reference;
-        return bundle;
-    }
-
     /**
      * Adds feature vectors for specified data set.
      */
-    public Bundle addFeatureVectorsOfDataSet(String dataSetCode)
+    DatasetFeaturesBundle addFeatureVectorsOfDataSet(String dataSetCode)
     {
         final ImgDatasetDTO dataSet = dao.tryGetDatasetByPermId(dataSetCode);
         if (dataSet == null)
         {
             throw new UserFailureException("Unkown data set " + dataSetCode);
         }
-        final Bundle bundle = new Bundle();
-        final List<ImgFeatureDefDTO> featureDefinitions =
-                dao.listFeatureDefsByDataSetId(dataSet.getId());
+        final DatasetFeaturesBundle bundle = new DatasetFeaturesBundle();
         final Map<String, ImgFeatureDefDTO> featureCodeToDefMap =
-                new LinkedHashMap<String, ImgFeatureDefDTO>();
-        for (ImgFeatureDefDTO def : featureDefinitions)
-        {
-            featureCodeToDefMap.put(def.getCode(), def);
-        }
+                createFeatureCodeToDefMap(dao, dataSet);
         bundle.dataSet = dataSet;
         bundle.featureDefToValuesMap = new HashMap<ImgFeatureDefDTO, List<ImgFeatureValuesDTO>>();
         bundles.add(bundle);
@@ -138,8 +212,8 @@ public class FeatureTableBuilder
                 CodeAndLabel codeAndLabel = getCodeAndLabel(featureDefinition);
                 if (featureCodeLabelToIndexMap.containsKey(codeAndLabel) == false)
                 {
-                    featureCodeLabelToIndexMap.put(codeAndLabel,
-                            new Integer(featureCodeLabelToIndexMap.size()));
+                    featureCodeLabelToIndexMap.put(codeAndLabel, new Integer(
+                            featureCodeLabelToIndexMap.size()));
                 }
                 List<ImgFeatureValuesDTO> featureValueSets =
                         dao.getFeatureValues(featureDefinition);
@@ -154,50 +228,92 @@ public class FeatureTableBuilder
         return bundle;
     }
 
+    private static Map<String, ImgFeatureDefDTO> createFeatureCodeToDefMap(
+            IImagingReadonlyQueryDAO dao, final ImgDatasetDTO dataSet)
+    {
+        final List<ImgFeatureDefDTO> featureDefinitions =
+                dao.listFeatureDefsByDataSetId(dataSet.getId());
+        final Map<String, ImgFeatureDefDTO> featureCodeToDefMap =
+                new LinkedHashMap<String, ImgFeatureDefDTO>();
+        for (ImgFeatureDefDTO def : featureDefinitions)
+        {
+            featureCodeToDefMap.put(def.getCode(), def);
+        }
+        return featureCodeToDefMap;
+    }
+
     /**
-     * Returns all feature codes/labels found. If the feature code list in the constructor is not empty the
-     * result will a list where the codes are a subset of this list.
+     * Returns all feature codes/labels found. If the feature code list in the constructor is not
+     * empty the result will a list where the codes are a subset of this list.
      */
-    public List<CodeAndLabel> getCodesAndLabels()
+    List<CodeAndLabel> getCodesAndLabels()
     {
         return new ArrayList<CodeAndLabel>(featureCodeLabelToIndexMap.keySet());
     }
 
     /**
-     * Returns all features per well coordinates.
+     * Returns all features for previously loaded datasets. Features for all plate wells are
+     * returned.
      */
-    public List<FeatureTableRow> createFeatureTableRows()
+    List<FeatureTableRow> createFeatureTableRows()
     {
         List<FeatureTableRow> rows = new ArrayList<FeatureTableRow>();
-        for (Bundle bundle : bundles)
+        for (DatasetFeaturesBundle bundle : bundles)
         {
             String dataSetCode = bundle.dataSet.getPermId();
             ImgContainerDTO container = dao.getContainerById(bundle.dataSet.getContainerId());
             SampleIdentifier identifier = service.tryToGetSampleIdentifier(container.getPermId());
-            if (bundle.reference == null)
+            for (int rowIndex = 1; rowIndex <= container.getNumberOfRows(); rowIndex++)
             {
-                for (int rowIndex = 1; rowIndex <= container.getNumberOfRows(); rowIndex++)
+                for (int colIndex = 1; colIndex <= container.getNumberOfColumns(); colIndex++)
                 {
-                    for (int colIndex = 1; colIndex <= container.getNumberOfColumns(); colIndex++)
-                    {
-                        final FeatureTableRow row =
-                                createFeatureTableRow(bundle.featureDefToValuesMap, dataSetCode,
-                                        identifier, null, new WellPosition(rowIndex, colIndex));
-                        rows.add(row);
-                    }
+                    final FeatureTableRow row =
+                            createFeatureTableRow(bundle.featureDefToValuesMap, dataSetCode,
+                                    identifier, null, new WellPosition(rowIndex, colIndex));
+                    rows.add(row);
                 }
-            } else
-            {
-                final FeatureTableRow row =
-                        createFeatureTableRow(bundle.featureDefToValuesMap, dataSetCode,
-                                identifier, bundle.reference, bundle.reference.getWellPosition());
-                rows.add(row);
+            }
+        }
+        return rows;
+    }
 
+    /**
+     * Returns all features for the specified wells in previously loaded datasets.
+     */
+    private List<FeatureTableRow> createFeatureTableRows(
+            List<FeatureVectorDatasetWellReference> references)
+    {
+        Map<String/* dataset code */, DatasetFeaturesBundle> bundleMap = createBundleMap(bundles);
+        List<FeatureTableRow> rows = new ArrayList<FeatureTableRow>();
+        for (FeatureVectorDatasetWellReference reference : references)
+        {
+            String dataSetCode = reference.getDatasetCode();
+            DatasetFeaturesBundle bundle = bundleMap.get(dataSetCode);
+            if (bundle == null)
+            {
+                throw new IllegalStateException("Dataset has not been loaded: " + dataSetCode);
             }
+            ImgContainerDTO container = dao.getContainerById(bundle.dataSet.getContainerId());
+            SampleIdentifier identifier = service.tryToGetSampleIdentifier(container.getPermId());
+            final FeatureTableRow row =
+                    createFeatureTableRow(bundle.featureDefToValuesMap, dataSetCode, identifier,
+                            reference, reference.getWellPosition());
+            rows.add(row);
         }
         return rows;
     }
 
+    private static HashMap<String, DatasetFeaturesBundle> createBundleMap(
+            List<DatasetFeaturesBundle> bundles)
+    {
+        HashMap<String, DatasetFeaturesBundle> map = new HashMap<String, DatasetFeaturesBundle>();
+        for (DatasetFeaturesBundle bundle : bundles)
+        {
+            map.put(bundle.dataSet.getPermId(), bundle);
+        }
+        return map;
+    }
+
     private FeatureTableRow createFeatureTableRow(
             Map<ImgFeatureDefDTO, List<ImgFeatureValuesDTO>> featureDefToValuesMap,
             String dataSetCode, SampleIdentifier identifier,
@@ -227,13 +343,13 @@ public class FeatureTableBuilder
             Integer index = featureCodeLabelToIndexMap.get(getCodeAndLabel(featureDefinition));
             assert index != null : "No index for feature " + featureDefinition.getCode();
             valueArray[index] =
-                    featureValues.getForWellLocation(wellPosition.getWellRow(), wellPosition
-                            .getWellColumn());
+                    featureValues.getForWellLocation(wellPosition.getWellRow(),
+                            wellPosition.getWellColumn());
         }
         row.setFeatureValues(valueArray);
         return row;
     }
-    
+
     private CodeAndLabel getCodeAndLabel(final ImgFeatureDefDTO featureDefinition)
     {
         return new CodeAndLabel(featureDefinition.getCode(), featureDefinition.getLabel());
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
index 68b258f71310dc3b304e2b5f5332266503e228e5..2cb872ff7e233cd4d192a27b0af6a54e05205fb1 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
@@ -18,8 +18,10 @@ package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableBuilder.WellFeatureCollection;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
@@ -83,10 +85,11 @@ public class TabularDataGraphServlet extends AbstractTabularDataGraphServlet
 
         private void initialize()
         {
-            final FeatureTableBuilder tableBuilder = new FeatureTableBuilder(dao, service);
-            tableBuilder.addFeatureVectorsOfDataSet(dataSetCode);
+            WellFeatureCollection featureCollection =
+                    FeatureTableBuilder.fetchDatasetFeatures(Arrays.asList(dataSetCode),
+                            new ArrayList<String>(), dao, service);
 
-            List<CodeAndLabel> featureCodeAndLabels = tableBuilder.getCodesAndLabels();
+            List<CodeAndLabel> featureCodeAndLabels = featureCollection.getFeatureCodesAndLabels();
             int headerTokensLength = featureCodeAndLabels.size() + 3;
             headerLabels = new String[headerTokensLength];
             headerLabels[0] = WELL_NAME_COLUMN;
@@ -106,7 +109,7 @@ public class TabularDataGraphServlet extends AbstractTabularDataGraphServlet
 
             lines = new ArrayList<String[]>();
 
-            final List<FeatureTableRow> rows = tableBuilder.createFeatureTableRows();
+            final List<FeatureTableRow> rows = featureCollection.getFeatures();
             for (FeatureTableRow row : rows)
             {
                 String[] line = new String[headerTokensLength];
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisMergedRowsReportingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisMergedRowsReportingPlugin.java
index 2651d27379774e094d761b4ca84088aff1086c6e..1777e782a4130882ee8b7a54b8d8aa023e4dad35 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisMergedRowsReportingPlugin.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisMergedRowsReportingPlugin.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Properties;
 
 import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableBuilder;
+import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableBuilder.WellFeatureCollection;
 import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableRow;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractDatastorePlugin;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IReportingPluginTask;
@@ -79,14 +80,14 @@ public class ImageAnalysisMergedRowsReportingPlugin extends AbstractDatastorePlu
 
     public TableModel createReport(List<DatasetDescription> datasets)
     {
-        FeatureTableBuilder featureTableBuilder = new FeatureTableBuilder(getDAO(), getService());
-        for (DatasetDescription datasetDescription : datasets)
-        {
-            String dataSetCode = datasetDescription.getDatasetCode();
-            featureTableBuilder.addFeatureVectorsOfDataSet(dataSetCode);
-        }
-        List<CodeAndLabel> codeAndLabels = featureTableBuilder.getCodesAndLabels();
-        List<FeatureTableRow> rows = featureTableBuilder.createFeatureTableRows();
+        List<String> datasetCodes = extractDatasetCodes(datasets);
+        ArrayList<String> featureCodes = new ArrayList<String>(); // fetch all
+        WellFeatureCollection featuresCollection =
+                FeatureTableBuilder.fetchDatasetFeatures(datasetCodes, featureCodes, getDAO(),
+                        getService());
+
+        List<CodeAndLabel> codeAndLabels = featuresCollection.getFeatureCodesAndLabels();
+        List<FeatureTableRow> rows = featuresCollection.getFeatures();
         SimpleTableModelBuilder builder = new SimpleTableModelBuilder(true);
         builder.addHeader(DATA_SET_CODE_TITLE);
         builder.addHeader(PLATE_IDENTIFIER_TITLE);
@@ -121,6 +122,16 @@ public class ImageAnalysisMergedRowsReportingPlugin extends AbstractDatastorePlu
         return builder.getTableModel();
     }
 
+    private static List<String> extractDatasetCodes(List<DatasetDescription> datasets)
+    {
+        List<String> datasetCodes = new ArrayList<String>();
+        for (DatasetDescription datasetDescription : datasets)
+        {
+            datasetCodes.add(datasetDescription.getDatasetCode());
+        }
+        return datasetCodes;
+    }
+
     private IImagingReadonlyQueryDAO getDAO()
     {
         synchronized (this)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
index aeae8f6b4fb3bc6cfc180cb86b4eb34f1572001e..f0b29b0f271e046633ba7e96746ac2fec4629311 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
@@ -20,6 +20,7 @@ import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -37,10 +38,11 @@ import ch.systemsx.cisd.common.io.IContent;
 import ch.systemsx.cisd.openbis.dss.etl.AbsoluteImageReference;
 import ch.systemsx.cisd.openbis.dss.etl.HCSImageDatasetLoaderFactory;
 import ch.systemsx.cisd.openbis.dss.etl.IHCSImageDatasetLoader;
+import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDatasetDownloadServlet.Size;
 import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDssServiceRpc;
 import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableBuilder;
+import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableBuilder.WellFeatureCollection;
 import ch.systemsx.cisd.openbis.dss.generic.server.FeatureTableRow;
-import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDatasetDownloadServlet.Size;
 import ch.systemsx.cisd.openbis.dss.generic.server.images.ImageChannelStackReference;
 import ch.systemsx.cisd.openbis.dss.generic.server.images.ImageChannelsUtils;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
@@ -173,8 +175,9 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
         Size imageSize = getImageSize(dataset, imageAccessor);
         PlateImageParameters params = imageAccessor.getImageParameters();
         int tilesNumber = params.getTileColsNum() * params.getTileRowsNum();
-        return new ImageDatasetMetadata(dataset, params.getChannelsCodes(), params
-                .getChannelsLabels(), tilesNumber, imageSize.getWidth(), imageSize.getHeight());
+        return new ImageDatasetMetadata(dataset, params.getChannelsCodes(),
+                params.getChannelsLabels(), tilesNumber, imageSize.getWidth(),
+                imageSize.getHeight());
     }
 
     private static Size getImageSize(IImageDatasetIdentifier dataset,
@@ -235,20 +238,18 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
     private FeatureVectorDataset createFeatureVectorDataset(String sessionToken,
             FeatureVectorDatasetReference dataset, List<String> featureCodes)
     {
-        FeatureTableBuilder builder =
-                new FeatureTableBuilder(featureCodes, getDAO(), getOpenBISService());
-        builder.addFeatureVectorsOfDataSet(dataset.getDatasetCode());
-        List<FeatureTableRow> featureTableRows = builder.createFeatureTableRows();
+        WellFeatureCollection datasetFeatures =
+                FeatureTableBuilder.fetchDatasetFeatures(Arrays.asList(dataset.getDatasetCode()),
+                        featureCodes, getDAO(), getOpenBISService());
         List<FeatureVector> featureVectors = new ArrayList<FeatureVector>();
-        for (FeatureTableRow featureTableRow : featureTableRows)
+        for (FeatureTableRow featureTableRow : datasetFeatures.getFeatures())
         {
             WellPosition wellPosition = featureTableRow.getWellPosition();
             double[] values = featureTableRow.getFeatureValuesAsDouble();
             featureVectors.add(new FeatureVector(wellPosition, values));
         }
-        List<String> codes = getCodes(builder);
-        List<String> labels = getLabels(builder);
-        return new FeatureVectorDataset(dataset, codes, labels, featureVectors);
+        return new FeatureVectorDataset(dataset, datasetFeatures.getFeatureCodes(),
+                datasetFeatures.getFeatureLabels(), featureVectors);
     }
 
     private List<String> normalize(List<String> names)
@@ -266,16 +267,17 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
             List<String> featureNames)
     {
         checkDatasetsAuthorizationForIDatasetIdentifier(sessionToken, datasetWellReferences);
-        final FeatureTableBuilder builder =
-                createFeatureTableBuilder(datasetWellReferences, normalize(featureNames));
-        return createFeatureVectorList(builder);
+        WellFeatureCollection features =
+                FeatureTableBuilder.fetchWellFeatures(datasetWellReferences, featureNames, dao,
+                        getOpenBISService());
+        return createFeatureVectorList(features);
     }
 
     private List<FeatureVectorWithDescription> createFeatureVectorList(
-            final FeatureTableBuilder builder)
+            final WellFeatureCollection features)
     {
-        final List<String> featureCodes = getCodes(builder);
-        final List<FeatureTableRow> featureTableRows = builder.createFeatureTableRows();
+        final List<String> featureCodes = features.getFeatureCodes();
+        final List<FeatureTableRow> featureTableRows = features.getFeatures();
         final List<FeatureVectorWithDescription> result =
                 new ArrayList<FeatureVectorWithDescription>(featureTableRows.size());
         for (FeatureTableRow featureTableRow : featureTableRows)
@@ -285,28 +287,6 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
         return result;
     }
 
-    private List<String> getCodes(FeatureTableBuilder builder)
-    {
-        List<CodeAndLabel> featureCodesAndLabels = builder.getCodesAndLabels();
-        List<String> codes = new ArrayList<String>();
-        for (CodeAndLabel codeAndTitle : featureCodesAndLabels)
-        {
-            codes.add(codeAndTitle.getCode());
-        }
-        return codes;
-    }
-
-    private List<String> getLabels(FeatureTableBuilder builder)
-    {
-        List<CodeAndLabel> featureCodesAndLabels = builder.getCodesAndLabels();
-        List<String> labels = new ArrayList<String>();
-        for (CodeAndLabel codeAndTitle : featureCodesAndLabels)
-        {
-            labels.add(codeAndTitle.getLabel());
-        }
-        return labels;
-    }
-
     private FeatureVectorWithDescription createFeatureVector(FeatureTableRow featureTableRow,
             final List<String> featureCodes)
     {
@@ -314,18 +294,6 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
                 featureTableRow.getFeatureValuesAsDouble());
     }
 
-    private FeatureTableBuilder createFeatureTableBuilder(
-            List<FeatureVectorDatasetWellReference> plateWellReferences, List<String> featureCodes)
-    {
-        final FeatureTableBuilder builder =
-                new FeatureTableBuilder(featureCodes, getDAO(), getOpenBISService());
-        for (FeatureVectorDatasetWellReference datasetWellReference : plateWellReferences)
-        {
-            builder.addFeatureVectorsOfDataSet(datasetWellReference);
-        }
-        return builder;
-    }
-
     public InputStream loadImages(String sessionToken, List<PlateImageReference> imageReferences)
     {
         checkDatasetsAuthorizationForIDatasetIdentifier(sessionToken, imageReferences);
@@ -381,8 +349,8 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
         {
             ImageChannelStackReference channelStackReference =
                     ImageChannelStackReference.createFromLocations(wellLocation, tileLocation);
-            return ImageChannelsUtils.getImage(imageAccessor, channelStackReference, imageRef
-                    .getChannel(), null);
+            return ImageChannelsUtils.getImage(imageAccessor, channelStackReference,
+                    imageRef.getChannel(), null);
         } catch (EnvironmentFailureException e)
         {
             operationLog.error("Error reading image.", e);