diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/FeatureVectorValues.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/FeatureVectorValues.java
index ff1dbf09870b386840fcb4bae6826a1e2e8d4bed..b67f042828f04296c1fc1c9f2876224f263af8fb 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/FeatureVectorValues.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/FeatureVectorValues.java
@@ -16,10 +16,12 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto;
 
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
 import ch.systemsx.cisd.openbis.generic.shared.basic.annotation.DoNotEscape;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CodeAndLabel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 
 /**
@@ -37,31 +39,75 @@ public class FeatureVectorValues implements ISerializable
 
     private Map<String /* feature label */, FeatureValue /* value */> featureMap;
 
+    private CodeAndLabel[] codesAndLabels;
+
+    private FeatureValue[] featureValues;
+
+    /**
+     * Convert the two arrays into a map. It is assumed that codesAndLabels has the same length as
+     * feature values (this is checked before calling this method).
+     */
+    static private Map<String, FeatureValue> asValueMap(CodeAndLabel[] codesAndLabels,
+            FeatureValue[] featureValues)
+    {
+        Map<String, FeatureValue> result = new LinkedHashMap<String, FeatureValue>();
+        for (int i = 0; i < featureValues.length; i++)
+        {
+            result.put(codesAndLabels[i].getLabel(), featureValues[i]);
+        }
+        return result;
+    }
+
     // GWT only
     @SuppressWarnings("unused")
     private FeatureVectorValues()
     {
     }
 
+    /**
+     * A copy constructor.
+     * 
+     * @param featureVector The object to copy.
+     */
+    public FeatureVectorValues(FeatureVectorValues featureVector)
+    {
+        this(featureVector.getFeatureVectorReference(), featureVector.getCodesAndLabels(),
+                featureVector.getFeatureValues(), featureVector.getFeatureMap());
+    }
+
     public FeatureVectorValues(String dataSetCode, WellLocation wellLocation, String platePermId,
-            Map<String, FeatureValue> featureMap)
+            CodeAndLabel[] codesAndLabels, FeatureValue[] featureValues)
     {
         this(new PlateWellFeatureVectorReference(dataSetCode, wellLocation, platePermId),
-                featureMap);
+                codesAndLabels, featureValues);
     }
 
     public FeatureVectorValues(PlateWellFeatureVectorReference featureVectorReference,
+            CodeAndLabel[] codesAndLabels, FeatureValue[] featureValues)
+    {
+        this(featureVectorReference, codesAndLabels, featureValues, null);
+    }
+
+    private FeatureVectorValues(PlateWellFeatureVectorReference featureVectorReference,
+            CodeAndLabel[] codesAndLabels, FeatureValue[] featureValues,
             Map<String, FeatureValue> featureMap)
     {
+        assert codesAndLabels.length == featureValues.length;
         this.featureVectorReference = featureVectorReference;
-        this.featureMap = featureMap;
+        this.codesAndLabels = codesAndLabels;
+        this.featureValues = featureValues;
+        this.featureMap =
+                (null == featureMap) ? asValueMap(codesAndLabels, featureValues) : featureMap;
+    }
+
+    public CodeAndLabel[] getCodesAndLabels()
+    {
+        return codesAndLabels;
     }
 
-    // NOTE: For performance reasons it is better not to call this method multiple times.
-    // Use getFeatureMap() instead.
     public FeatureValue[] getFeatureValues()
     {
-        return featureMap.values().toArray(new FeatureValue[0]);
+        return featureValues;
     }
 
     public Map<String, FeatureValue> getFeatureMap()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/dto/FeatureTableRow.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/dto/FeatureTableRow.java
index b2b3056de6612173193ec1eb75cfbb2d76cd28ae..75a5d828a42022246a472b7088765a1fb38ca254 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/dto/FeatureTableRow.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/dto/FeatureTableRow.java
@@ -37,8 +37,7 @@ public class FeatureTableRow extends FeatureVectorValues
 
     public FeatureTableRow(FeatureVectorValues featureVector)
     {
-        super(featureVector.getDataSetCode(), featureVector.getWellLocation(), featureVector
-                .getPlatePermId(), featureVector.getFeatureMap());
+        super(featureVector);
     }
 
     public FeatureVectorDatasetWellReference getReference()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/FeatureVectorLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/FeatureVectorLoader.java
index 4a09733f4374504caef2394f1219d28cbd6fcb44..073087d73db9bd2a5de01e4068bc753c0370cf04 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/FeatureVectorLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/FeatureVectorLoader.java
@@ -163,7 +163,7 @@ public class FeatureVectorLoader
         List<FeatureVectorValues> fvs = new ArrayList<FeatureVectorValues>();
         for (FeatureTableRow row : featureRows)
         {
-            fvs.add(new FeatureVectorValues(row.getFeatureVectorReference(), row.getFeatureMap()));
+            fvs.add(new FeatureVectorValues(row));
         }
         return new WellFeatureCollection<FeatureVectorValues>(fvs,
                 featureRowsCollection.getFeatureCodesAndLabels());
@@ -481,7 +481,7 @@ public class FeatureVectorLoader
         private List<ImgFeatureDefDTO> getRequestedFeatureDefinitions(ImgDatasetDTO dataset)
         {
             List<ImgFeatureDefDTO> def = requestedFeatureDefinitionsMap.tryGet(dataset.getId());
-            return def == null ? Collections.<ImgFeatureDefDTO>emptyList() : def;
+            return def == null ? Collections.<ImgFeatureDefDTO> emptyList() : def;
         }
 
         public List<ImgFeatureVocabularyTermDTO> getFeatureVocabularyTerms(ImgDatasetDTO dataSet)
@@ -717,20 +717,18 @@ public class FeatureVectorLoader
                 createFeatureValueArray(bundle.featureDefToValuesMap,
                         bundle.featureDefToVocabularyTerms, wellLocation);
         return new FeatureVectorValues(permId, wellLocation, bundle.container.getPermId(),
-                asValueMap(valueArray));
+                getCodeAndLabelArray(), valueArray);
     }
 
-    private Map<String, FeatureValue> asValueMap(FeatureValue[] valueArray)
+    private CodeAndLabel[] getCodeAndLabelArray()
     {
-        List<CodeAndLabel> features = getCodesAndLabels();
-        assert features.size() == valueArray.length;
-
-        Map<String, FeatureValue> result = new LinkedHashMap<String, FeatureValue>();
-        for (int i = 0; i < valueArray.length; i++)
+        CodeAndLabel[] codesAndLabels = new CodeAndLabel[featureCodeLabelToIndexMap.size()];
+        for (CodeAndLabel codeAndLabel : featureCodeLabelToIndexMap.keySet())
         {
-            result.put(features.get(i).getLabel(), valueArray[i]);
+            codesAndLabels[featureCodeLabelToIndexMap.get(codeAndLabel)] = codeAndLabel;
         }
-        return result;
+
+        return codesAndLabels;
     }
 
     private FeatureValue[] createFeatureValueArray(
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/heatmaps/WellTooltipGeneratorTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/heatmaps/WellTooltipGeneratorTest.java
index 7f2c36a031fadd47095463e9e41510850567b866..8b353f433dd4e178b95d37bea41718356c81ab72 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/heatmaps/WellTooltipGeneratorTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/heatmaps/WellTooltipGeneratorTest.java
@@ -20,9 +20,7 @@ import static ch.systemsx.cisd.openbis.plugin.screening.client.web.client.applic
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
@@ -154,18 +152,20 @@ public class WellTooltipGeneratorTest extends AssertJUnit
     private static FeatureVectorDataset createLargeFeatureVectorDataset()
     {
         int size = 40;
-        List<CodeAndLabel> featureNames = new ArrayList<CodeAndLabel>(size);
-        Map<String, FeatureValue> featureValuesMap = new LinkedHashMap<String, FeatureValue>();
+        CodeAndLabel[] featureNames = new CodeAndLabel[size];
+        FeatureValue[] featureValues = new FeatureValue[size];
         for (int i = 0; i < size; i++)
         {
             final String label = "Feature" + i;
             final FeatureValue featureValue = FeatureValue.createFloat(i);
-            featureNames.add(new CodeAndLabel(label, label));
-            featureValuesMap.put(label, featureValue);
+            featureNames[i] = new CodeAndLabel(label, label);
+            featureValues[i] = featureValue;
         }
         List<FeatureVectorValues> features = new ArrayList<FeatureVectorValues>();
-        features.add(new FeatureVectorValues(null, getLocation(WELL_A2), null, featureValuesMap));
-        return new FeatureVectorDataset(createDatasetReference(), features, featureNames);
+        features.add(new FeatureVectorValues(null, getLocation(WELL_A2), null, featureNames,
+                featureValues));
+        return new FeatureVectorDataset(createDatasetReference(), features,
+                Arrays.asList(featureNames));
     }
 
     private static FeatureVectorDataset createFeatureVectorDataset()
@@ -173,32 +173,20 @@ public class WellTooltipGeneratorTest extends AssertJUnit
 
         String[] featureLabels =
             { "FeatureX", "FeatureY" };
+        CodeAndLabel[] codesAndLabels =
+                new CodeAndLabel[]
+                    { new CodeAndLabel(featureLabels[0], featureLabels[0]),
+                            new CodeAndLabel(featureLabels[1], featureLabels[1]) };
 
         List<FeatureVectorValues> features = new ArrayList<FeatureVectorValues>();
-        features.add(new FeatureVectorValues(null, getLocation(WELL_A2), null,
-                createFeatureVectorMap(featureLabels, new FeatureValue[]
-                    { FeatureValue.createFloat(1), FeatureValue.createFloat(2) })));
-        features.add(new FeatureVectorValues(null, getLocation(WELL_B3), null,
-                createFeatureVectorMap(featureLabels, new FeatureValue[]
-                    { FeatureValue.createFloat(-1), FeatureValue.createFloat(-2) })));
-        return new FeatureVectorDataset(createDatasetReference(), features, Arrays.asList(
-                new CodeAndLabel(featureLabels[0], featureLabels[0]), new CodeAndLabel(
-                        featureLabels[1], featureLabels[1])));
-    }
-
-    private static Map<String, FeatureValue> createFeatureVectorMap(String[] labels,
-            FeatureValue[] values)
-    {
-        assert labels.length == values.length;
-
-        Map<String, FeatureValue> result = new LinkedHashMap<String, FeatureValue>();
-        for (int i = 0; i < labels.length; i++)
-        {
-            final String label = labels[i];
-            final FeatureValue featureValue = values[i];
-            result.put(label, featureValue);
-        }
-        return result;
+        features.add(new FeatureVectorValues(null, getLocation(WELL_A2), null, codesAndLabels,
+                new FeatureValue[]
+                    { FeatureValue.createFloat(1), FeatureValue.createFloat(2) }));
+        features.add(new FeatureVectorValues(null, getLocation(WELL_B3), null, codesAndLabels,
+                new FeatureValue[]
+                    { FeatureValue.createFloat(-1), FeatureValue.createFloat(-2) }));
+        return new FeatureVectorDataset(createDatasetReference(), features,
+                Arrays.asList(codesAndLabels));
     }
 
     private static DatasetReference createDatasetReference()