From 3a6075c8f096e06ba635c76b9ee7c61b348beb57 Mon Sep 17 00:00:00 2001
From: tpylak <tpylak>
Date: Tue, 21 Jun 2011 13:02:03 +0000
Subject: [PATCH] LMS-2280 ranks in "gene in all assays" view

SVN: 21780
---
 .../application/DisplayTypeIDGenerator.java   |   6 +-
 ...aterialFeaturesFromAllExperimentsGrid.java |   2 +-
 .../MaterialReplicaFeatureSummaryGrid.java    |   2 +-
 .../MaterialReplicaSummarySection.java        |   2 +-
 ...tureVectorsFromAllExperimentsProvider.java |  21 +-
 .../resultset/ScreeningProviderMessages.java  |   2 +-
 .../screening/server/ScreeningServer.java     |   3 +-
 .../BasicWellContentQueryResult.java          |  36 +++
 .../ExperimentReferenceQueryResult.java       |  37 +++
 .../server/dataaccess/IScreeningQuery.java    |  58 ++++-
 .../dataaccess/PatternMatchingUtils.java      |  35 +++
 .../dataaccess/WellContentQueryResult.java    |  17 +-
 .../ExperimentFeatureVectorSummaryLoader.java |   5 +-
 ...alAllAssaysFeatureVectorSummaryLoader.java | 230 +++++++++++-------
 .../MaterialFeatureVectorSummaryLoader.java   |   8 +-
 .../server/logic/WellContentLoader.java       |  18 +-
 .../logic/WellFeatureCollectionLoader.java    |   2 +
 .../logic/WellReplicaSummaryCalculator.java   |  66 +++--
 .../dto/MaterialIdFeatureVectorSummary.java   |   6 +-
 .../dto/ExperimentFeatureVectorSummary.java   |   1 +
 .../dto/MaterialFeatureVectorSummary.java     |   4 +-
 ...erialFeatureVectorSummaryParametrized.java |  16 +-
 .../MaterialSimpleFeatureVectorSummary.java   |  12 +-
 .../basic/dto/MaterialSummarySettings.java    |  12 +-
 .../shared/basic/dto/ScreeningConstants.java  |   3 -
 .../server/dataaccess/ScreeningDAOTest.java   |  15 ++
 .../WellReplicaSummaryCalculatorTest.java     |   6 +-
 27 files changed, 451 insertions(+), 174 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/BasicWellContentQueryResult.java
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ExperimentReferenceQueryResult.java
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/PatternMatchingUtils.java

diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/DisplayTypeIDGenerator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/DisplayTypeIDGenerator.java
index 43d41a1ff05..a0929d89762 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/DisplayTypeIDGenerator.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/DisplayTypeIDGenerator.java
@@ -35,17 +35,15 @@ public enum DisplayTypeIDGenerator implements IDisplayTypeIDGenerator
 
     PLATE_LOCATIONS_MATERIAL_SECTION("plate-locations-material-section"),
 
-    REPLICA_SUMMARY_MATERIAL_SECTION("replica-summary-material-section"),
-
     EXPERIMENT_PLATE_LOCATIONS_SECTION("plate-locations-experiment-section"),
 
     EXPERIMENT_WELL_MATERIALS_SECTION("experiment-well-materials-section"),
 
     EXPERIMENT_FEATURE_VECTOR_SUMMARY_SECTION("experiment-feature-vector-summary-section"),
     
-    MATERIAL_REPLICA_FEATURE_SUMMARY_SECTION("material-replica-feature-summary-section"),
+    MATERIAL_REPLICA_SUMMARY_SECTION("material-replica-summary-section"),
     
-    MATERIAL_FEATURES_FROM_ALL_EXPERIMENTS_SECTION("material-features-from-all-experiments-section");
+    MATERIAL_FEATURES_FROM_ALL_EXPERIMENTS_SECTION("material-features-all-experiments-section");
 
     private final String genericNameOrPrefix;
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialFeaturesFromAllExperimentsGrid.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialFeaturesFromAllExperimentsGrid.java
index b133d560620..3202c0f4bec 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialFeaturesFromAllExperimentsGrid.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialFeaturesFromAllExperimentsGrid.java
@@ -76,7 +76,7 @@ public class MaterialFeaturesFromAllExperimentsGrid extends
             ExperimentSearchByProjectCriteria experimentSearchCriteria)
     {
         super(viewContext.getCommonViewContext(), BROWSER_ID, true,
-                DisplayTypeIDGenerator.MATERIAL_REPLICA_FEATURE_SUMMARY_SECTION);
+                DisplayTypeIDGenerator.MATERIAL_REPLICA_SUMMARY_SECTION);
         this.screeningViewContext = viewContext;
         this.material = material;
         this.experimentSearchCriteria = experimentSearchCriteria;
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryGrid.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryGrid.java
index 002728f9541..5824e787ae9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryGrid.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryGrid.java
@@ -64,7 +64,7 @@ public class MaterialReplicaFeatureSummaryGrid extends
             TechId experimentId, TechId materialId)
     {
         super(viewContext.getCommonViewContext(), BROWSER_ID, true,
-                DisplayTypeIDGenerator.MATERIAL_REPLICA_FEATURE_SUMMARY_SECTION);
+                DisplayTypeIDGenerator.MATERIAL_REPLICA_SUMMARY_SECTION);
         this.specificViewContext = viewContext;
         this.experimentId = experimentId;
         this.materialId = materialId;
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaSummarySection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaSummarySection.java
index b96b8c2a36a..7e6b9072041 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaSummarySection.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaSummarySection.java
@@ -39,7 +39,7 @@ class MaterialReplicaSummarySection extends TabContent
         this.restrictGlobalScopeLinkToProject = restrictGlobalScopeLinkToProject;
 
         setHeaderVisible(false);
-        setIds(DisplayTypeIDGenerator.REPLICA_SUMMARY_MATERIAL_SECTION);
+        setIds(DisplayTypeIDGenerator.MATERIAL_REPLICA_SUMMARY_SECTION);
     }
 
     @Override
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/MaterialFeatureVectorsFromAllExperimentsProvider.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/MaterialFeatureVectorsFromAllExperimentsProvider.java
index c654ca05107..73bf0219c3d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/MaterialFeatureVectorsFromAllExperimentsProvider.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/MaterialFeatureVectorsFromAllExperimentsProvider.java
@@ -86,7 +86,11 @@ public class MaterialFeatureVectorsFromAllExperimentsProvider extends
         {
             for (CodeAndLabel codeAndLabel : summary.getFeatureDescriptions())
             {
-                columnGroup.column(codeAndLabel.getCode()).withTitle(codeAndLabel.getLabel());
+                columnGroup.column(getFeatureValueColumnId(codeAndLabel)).withTitle(
+                        codeAndLabel.getLabel());
+                columnGroup.column(getFeatureRankColumnId(codeAndLabel)).withTitle(
+                        ScreeningProviderMessages.RANK_COLUMN_MSG);
+
             }
         }
     }
@@ -100,11 +104,24 @@ public class MaterialFeatureVectorsFromAllExperimentsProvider extends
         builder.column(EXPERIMENT).addString(experiment.getCode());
 
         float[] features = row.getFeatureVectorSummary();
+        int[] ranks = row.getFeatureVectorRanks();
         List<CodeAndLabel> descriptions = row.getFeatureDescriptions();
         for (int i = 0; i < features.length; i++)
         {
             CodeAndLabel description = descriptions.get(i);
-            builder.column(description.getCode()).addDouble((double) features[i]);
+            builder.column(getFeatureValueColumnId(description)).addDouble((double) features[i]);
+            builder.column(getFeatureRankColumnId(description)).addInteger(new Long(ranks[i]));
         }
     }
+
+    private String getFeatureValueColumnId(CodeAndLabel codeAndLabel)
+    {
+        return "value-" + codeAndLabel.getCode();
+    }
+
+    private String getFeatureRankColumnId(CodeAndLabel codeAndLabel)
+    {
+        return "rank-" + codeAndLabel.getCode();
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/ScreeningProviderMessages.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/ScreeningProviderMessages.java
index a0487553756..67d475733da 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/ScreeningProviderMessages.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/resultset/ScreeningProviderMessages.java
@@ -23,7 +23,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.client.web.server.resultset;
  */
 class ScreeningProviderMessages
 {
-    public static final String RANK_COLUMN_MSG = " Rank";
+    public static final String RANK_COLUMN_MSG = "Rank";
 
     public static String getRankColumnHeader(int numberOfMaterialsInExperiment)
     {
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 953cfef8ebd..558b4df4dad 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
@@ -349,8 +349,9 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
         MaterialSummarySettings settings = new MaterialSummarySettings();
         settings.setAggregationType(MaterialReplicaSummaryAggregationType.MEDIAN);
         settings.setFeatureCodes(new ArrayList<String>());
+        settings.setReplicaMatrialTypePatterns(new String[]
+            { "GENE", "CONTROL", "COMPOUND" });
         settings.setMaterialDetailsPropertyType(ScreeningConstants.GENE_SYMBOLS);
-        settings.setReplicaMatrialTypePatterns(ScreeningConstants.REPLICA_METERIAL_TYPE_PATTERN);
         settings.setBiologicalReplicatePropertyTypeCodes("CONCENTRATION", "SIRNA");
         return settings;
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/BasicWellContentQueryResult.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/BasicWellContentQueryResult.java
new file mode 100644
index 00000000000..76182c72cab
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/BasicWellContentQueryResult.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess;
+
+import ch.rinn.restrictions.Private;
+
+/**
+ * Basic information about well content which allows to compute rankings.
+ * 
+ * @author Tomasz Pylak
+ */
+@Private
+public class BasicWellContentQueryResult
+{
+    public String well_code;
+
+    public String plate_perm_id;
+
+    public String exp_perm_id;
+
+    public long material_content_id;
+}
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ExperimentReferenceQueryResult.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ExperimentReferenceQueryResult.java
new file mode 100644
index 00000000000..377299c9bed
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ExperimentReferenceQueryResult.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess;
+
+/**
+ * A pointer to the experiment.
+ * 
+ * @author Tomasz Pylak
+ */
+public class ExperimentReferenceQueryResult
+{
+    public long exp_id;
+
+    public String exp_code;
+
+    public String exp_type_code;
+
+    public String exp_perm_id;
+
+    public String proj_code;
+
+    public String space_code;
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
index fc63e1dd5ee..8fbef51d14e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/IScreeningQuery.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess;
 
+import java.util.List;
+
 import net.lemnik.eodsql.BaseQuery;
 import net.lemnik.eodsql.DataIterator;
 import net.lemnik.eodsql.Select;
@@ -32,7 +34,8 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.StringArrayMapper;
  * @author Tomasz Pylak
  */
 @Private
-@Friend(toClasses = WellContentQueryResult.class)
+@Friend(toClasses =
+    { WellContentQueryResult.class, BasicWellContentQueryResult.class })
 public interface IScreeningQuery extends BaseQuery
 {
 
@@ -61,7 +64,8 @@ public interface IScreeningQuery extends BaseQuery
                     + "      join samples pl on well.samp_id_part_of = pl.id"
                     + "      join experiments exp on pl.expe_id = exp.id  "
                     + "      join experiment_types exp_type on exp.exty_id = exp_type.id  "
-                    + "      join projects on exp.proj_id = projects.id   join spaces on projects.space_id = spaces.id  "
+                    + "      join projects on exp.proj_id = projects.id     "
+                    + "      join spaces on projects.space_id = spaces.id  "
                     + "      join sample_types pl_type on pl.saty_id = pl_type.id   "
                     + "      join sample_types well_type on well.saty_id = well_type.id  "
                     + "      join material_types well_material_type on well_material.maty_id = well_material_type.id";
@@ -188,6 +192,27 @@ public interface IScreeningQuery extends BaseQuery
     public DataIterator<WellContentQueryResult> getPlateMappingForMaterialType(String spaceCode,
             String plateCode, String materialTypeCode);
 
+    /**
+     * @param materialTypesPattern only materials with a type matching to this pattern will be
+     *            considered
+     * @return the material to well plate mapping for all the wells of the specified experiment.
+     */
+    @Select(sql = "select "
+            + "     well.code as well_code, "
+            + "     pl.perm_id as plate_perm_id, "
+            + "     exp.perm_id as exp_perm_id, "
+            + "     well_props.mate_prop_id as material_content_id "
+            + "from experiments exp "
+            + "     join samples pl on pl.expe_id = exp.id "
+            + "     join samples well on well.samp_id_part_of = pl.id "
+            + "     join sample_properties well_props on well_props.samp_id = well.id "
+            + "     join materials well_material on well_props.mate_prop_id = well_material.id "
+            + "     join material_types well_material_type on well_material.maty_id = well_material_type.id "
+            + "where pl.samp_id_part_of is null and exp.id = ?{1} "
+            + "      and well_material_type.code similar to ?{2}", fetchSize = FETCH_SIZE)
+    public List<BasicWellContentQueryResult> getPlateLocationsForExperiment(long experimentId,
+            String materialTypesPattern);
+
     /**
      * @return the material to well plate mapping for the given <var>spaceCode</var> and
      *         <var>plateCode</var>. Consider all material types. Only fills <var>well_code</var>,
@@ -249,4 +274,33 @@ public interface IScreeningQuery extends BaseQuery
             + "       AND well_material.maty_id = ?{2}", fetchSize = FETCH_SIZE)
     public DataIterator<Long> getMaterialsForExperimentWells(long experimentId, long materialTypeId);
 
+    static final String EXPERIMENTS_WITH_MATERIAL_SELECT =
+            "         select distinct                 "
+                    + "      exp.id as exp_id,                        "
+                    + "      exp.code as exp_code,                    "
+                    + "      exp.perm_id as exp_perm_id,              "
+                    + "      exp_type.code as exp_type_code,          "
+                    + "      projects.code as proj_code,              "
+                    + "      spaces.code as space_code               "
+                    + " from materials well_material"
+                    + "      join sample_properties well_props on well_props.mate_prop_id = well_material.id "
+                    + "      join samples well on well_props.samp_id = well.id"
+                    + "      join experiments exp on well.expe_id = exp.id "
+                    + "      join experiment_types exp_type on exp.exty_id = exp_type.id "
+                    + "      join projects on exp.proj_id = projects.id     "
+                    + "      join spaces on projects.space_id = spaces.id  ";
+
+    /** @returns experiments in which a given material has been screened */
+    @Select(sql = EXPERIMENTS_WITH_MATERIAL_SELECT + " where well_material.id = ?{1}")
+    public List<ExperimentReferenceQueryResult> getExperimentsWithMaterial(long materialId);
+
+    /**
+     * @returns experiments restricted to the specified project in which a given material has been
+     *          screened
+     */
+    @Select(sql = EXPERIMENTS_WITH_MATERIAL_SELECT
+            + " where well_material.id = ?{1} and exp.proj_id = ?{2}")
+    public List<ExperimentReferenceQueryResult> getExperimentsWithMaterial(long materialId,
+            long projectId);
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/PatternMatchingUtils.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/PatternMatchingUtils.java
new file mode 100644
index 00000000000..f42b962f3d1
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/PatternMatchingUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess;
+
+import ch.systemsx.cisd.openbis.plugin.screening.server.logic.ScreeningUtils;
+
+/**
+ * @author Tomasz Pylak
+ */
+public class PatternMatchingUtils
+{
+    /**
+     * Changes a list into a regular expression which matches in 'SIMILAR TO' postgres constructions
+     * with texts which contains any element of the list as a prefix.
+     */
+    public static String asPostgresSimilarExpression(String[] substrings)
+    {
+        return ScreeningUtils.asSubstringExpression(substrings, "%");
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/WellContentQueryResult.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/WellContentQueryResult.java
index 5bfbe41b4f1..e20ef78e867 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/WellContentQueryResult.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/WellContentQueryResult.java
@@ -22,7 +22,7 @@ import ch.rinn.restrictions.Private;
  * @author Tomasz Pylak
  */
 @Private
-public class WellContentQueryResult
+public class WellContentQueryResult extends ExperimentReferenceQueryResult
 {
     // well pointer
 
@@ -44,21 +44,8 @@ public class WellContentQueryResult
 
     public String plate_perm_id;
 
-    // a pointer to the experiment of the plate
-
-    public long exp_id;
-
-    public String exp_code;
-
-    public String exp_type_code;
-
-    public String exp_perm_id;
-
-    public String proj_code;
-
-    public String space_code;
-
     // a pointer to a material which was being searched for inside a well
+
     // NOTE: this information is filled just in few queries.
     @Deprecated
     public long material_content_id;
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ExperimentFeatureVectorSummaryLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ExperimentFeatureVectorSummaryLoader.java
index edaab707f70..07baa2ae640 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ExperimentFeatureVectorSummaryLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ExperimentFeatureVectorSummaryLoader.java
@@ -113,7 +113,7 @@ public class ExperimentFeatureVectorSummaryLoader extends AbstractContentLoader
             List<? extends IWellData> wellDataList)
     {
         return WellReplicaSummaryCalculator.calculateReplicasFeatureVectorSummaries(wellDataList,
-                settings.getAggregationType());
+                settings.getAggregationType(), false);
     }
 
     private static List<MaterialFeatureVectorSummary> enrichWithMaterial(
@@ -270,7 +270,8 @@ public class ExperimentFeatureVectorSummaryLoader extends AbstractContentLoader
 
     private static Material tryFindReplicaMaterial(Sample well, MaterialSummarySettings settings)
     {
-        String replicaMatrialTypePattern = settings.getReplicaMatrialTypePattern();
+        String replicaMatrialTypePattern =
+                ScreeningUtils.asJavaRegExpr(settings.getReplicaMatrialTypeSubstrings());
         if (replicaMatrialTypePattern == null)
         {
             return null;
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialAllAssaysFeatureVectorSummaryLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialAllAssaysFeatureVectorSummaryLoader.java
index 90cf9b3dc54..2710fc71240 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialAllAssaysFeatureVectorSummaryLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialAllAssaysFeatureVectorSummaryLoader.java
@@ -23,22 +23,27 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.lang.time.StopWatch;
+
 import ch.systemsx.cisd.common.collections.CollectionUtils;
 import ch.systemsx.cisd.common.collections.CollectionUtils.ICollectionMappingFunction;
-import ch.systemsx.cisd.common.collections.GroupByMap;
-import ch.systemsx.cisd.common.collections.IKeyExtractor;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.plugin.screening.server.IScreeningBusinessObjectFactory;
+import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.BasicWellContentQueryResult;
+import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.ExperimentReferenceQueryResult;
+import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.IScreeningQuery;
+import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.PatternMatchingUtils;
 import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.IWellData;
+import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialIdFeatureVectorSummary;
 import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.WellData;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ExperimentReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.FeatureVectorValues;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialSimpleFeatureVectorSummary;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialSummarySettings;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.FeatureVectorLoader.WellFeatureCollection;
 
@@ -55,146 +60,191 @@ public class MaterialAllAssaysFeatureVectorSummaryLoader extends AbstractContent
             IDAOFactory daoFactory, TechId materialId, TechId projectTechIdOrNull,
             MaterialSummarySettings settings)
     {
-        List<WellContent> assayWellsForMaterial = null;
+        IScreeningQuery dao = createDAO(daoFactory);
+        List<ExperimentReference> experiments =
+                fetchExperiments(materialId, projectTechIdOrNull, dao);
+
+        return new MaterialAllAssaysFeatureVectorSummaryLoader(session, businessObjectFactory,
+                daoFactory, dao, settings).loadMaterialFeatureVectorsFromAllAssays(materialId,
+                experiments);
+    }
+
+    private static List<ExperimentReference> fetchExperiments(TechId materialId,
+            TechId projectTechIdOrNull, IScreeningQuery dao)
+    {
+        List<ExperimentReferenceQueryResult> experimentRefs;
         if (projectTechIdOrNull == null)
         {
-            // load results from all experiments
-            assayWellsForMaterial =
-                    WellContentLoader.loadOnlyMetadata(session, businessObjectFactory, daoFactory,
-                            materialId);
+            experimentRefs = dao.getExperimentsWithMaterial(materialId.getId());
         } else
         {
             // load results only for experiments within a given project
-            assayWellsForMaterial =
-                    WellContentLoader.loadOnlyMetadataForProject(session, businessObjectFactory,
-                            daoFactory, materialId, projectTechIdOrNull);
+            experimentRefs =
+                    dao.getExperimentsWithMaterial(materialId.getId(), projectTechIdOrNull.getId());
         }
-        return new MaterialAllAssaysFeatureVectorSummaryLoader(session, businessObjectFactory,
-                daoFactory, settings).loadMaterialFeatureVectorsFromAllAssays(materialId,
-                assayWellsForMaterial);
+        return asExperimentReferences(experimentRefs);
+    }
+
+    private static List<ExperimentReference> asExperimentReferences(
+            List<ExperimentReferenceQueryResult> experiments)
+    {
+        return CollectionUtils
+                .map(experiments,
+                        new ICollectionMappingFunction<ExperimentReference, ExperimentReferenceQueryResult>()
+                            {
+                                public ExperimentReference map(
+                                        ExperimentReferenceQueryResult experiment)
+                                {
+                                    return createExperimentReference(experiment);
+                                }
+                            });
+    }
+
+    private static ExperimentReference createExperimentReference(ExperimentReferenceQueryResult exp)
+    {
+        return new ExperimentReference(exp.exp_id, exp.exp_perm_id, exp.exp_code,
+                exp.exp_type_code, exp.proj_code, exp.space_code);
     }
 
     private final MaterialSummarySettings settings;
 
+    private final IScreeningQuery screeningQuery;
+
     private MaterialAllAssaysFeatureVectorSummaryLoader(Session session,
             IScreeningBusinessObjectFactory businessObjectFactory, IDAOFactory daoFactory,
-            MaterialSummarySettings settings)
+            IScreeningQuery screeningQuery, MaterialSummarySettings settings)
     {
         super(session, businessObjectFactory, daoFactory);
         this.settings = settings;
+        this.screeningQuery = screeningQuery;
+    }
+
+    private List<BasicWellContentQueryResult> fetchWellLocations(ExperimentReference experiment)
+    {
+        String materialTypePattern =
+                PatternMatchingUtils.asPostgresSimilarExpression(settings
+                        .getReplicaMatrialTypeSubstrings());
+        return screeningQuery.getPlateLocationsForExperiment(experiment.getId(),
+                materialTypePattern);
     }
 
     /**
      * Note that different experiments can have different set of features!
      */
     private List<MaterialSimpleFeatureVectorSummary> loadMaterialFeatureVectorsFromAllAssays(
-            TechId materialId, List<WellContent> allAssayWellsForMaterial)
+            TechId materialId, List<ExperimentReference> experiments)
     {
-        Set<PlateIdentifier> plates = extractPlates(allAssayWellsForMaterial);
-        WellFeatureCollection<FeatureVectorValues> allWellFeaturesOrNull =
-                tryLoadWellSingleFeatureVectors(plates);
-
-        Map<ExperimentReference, Set<WellReference>> wellsForExperimentMap =
-                groupWellsByExperiment(allAssayWellsForMaterial);
-
         List<MaterialSimpleFeatureVectorSummary> summaries =
                 new ArrayList<MaterialSimpleFeatureVectorSummary>();
-        for (ExperimentReference experiment : wellsForExperimentMap.keySet())
+        StopWatch watch = new StopWatch();
+        watch.start();
+        for (ExperimentReference experiment : experiments)
         {
-            Set<WellReference> experimentWells = wellsForExperimentMap.get(experiment);
+            operationLog.info("Fetching analysis summary for experiment " + experiment);
+            List<BasicWellContentQueryResult> allWells = fetchWellLocations(experiment);
 
-            MaterialSimpleFeatureVectorSummary summary =
-                    calculateExperimentFeatureVectorSummary(materialId, experiment,
-                            experimentWells, allWellFeaturesOrNull);
-            summaries.add(summary);
+            Set<PlateIdentifier> plates = extractPlates(allWells);
+            WellFeatureCollection<FeatureVectorValues> allWellFeaturesOrNull =
+                    tryLoadWellSingleFeatureVectors(plates);
+            if (allWellFeaturesOrNull == null)
+            {
+                summaries.add(new MaterialSimpleFeatureVectorSummary(experiment));
+            } else
+            {
+
+                Map<WellReference, Long/* material id */> wellToMaterialMap =
+                        createWellToMaterialMap(allWells);
+
+                MaterialSimpleFeatureVectorSummary summary =
+                        calculateExperimentFeatureVectorSummary(materialId, experiment,
+                                allWellFeaturesOrNull, wellToMaterialMap);
+                summaries.add(summary);
+            }
         }
+        operationLog.info(String.format(
+                "Fetching all experiment analysis summary for material %d took %d msec",
+                materialId.getId(), watch.getTime()));
         return summaries;
     }
 
-    private MaterialSimpleFeatureVectorSummary calculateExperimentFeatureVectorSummary(
-            TechId materialId, ExperimentReference experiment, Set<WellReference> experimentWells,
-            WellFeatureCollection<FeatureVectorValues> allWellFeaturesOrNull)
+    private static Map<WellReference, Long/* material id */> createWellToMaterialMap(
+            List<BasicWellContentQueryResult> wells)
     {
-        if (allWellFeaturesOrNull == null)
+        Map<WellReference, Long> wellToMaterialMap = new HashMap<WellReference, Long>();
+        for (BasicWellContentQueryResult well : wells)
         {
-            return new MaterialSimpleFeatureVectorSummary(experiment);
+            WellReference wellReference = createWellReference(well);
+            wellToMaterialMap.put(wellReference, well.material_content_id);
         }
+        return wellToMaterialMap;
+    }
 
+    private static WellReference createWellReference(BasicWellContentQueryResult well)
+    {
+        WellLocation wellLocation = WellLocation.parseLocationStr(well.well_code);
+        return new WellReference(wellLocation, well.plate_perm_id);
+    }
+
+    private MaterialSimpleFeatureVectorSummary calculateExperimentFeatureVectorSummary(
+            TechId materialId, ExperimentReference experiment,
+            WellFeatureCollection<FeatureVectorValues> experimentFeatures,
+            Map<WellReference, Long> wellToMaterialMap)
+    {
+        // we have to calculate summaries for all materials in the experiment to get the right
+        // ranking of the specified material
         List<IWellData> experimentWellData =
-                selectExperimentWellData(experimentWells, allWellFeaturesOrNull, materialId);
-        float[] summaryFeatureVector =
-                WellReplicaSummaryCalculator.calculateSummaryFeatureVector(experimentWellData,
-                        settings.getAggregationType());
+                createWellData(wellToMaterialMap, experimentFeatures.getFeatures());
+        List<MaterialIdFeatureVectorSummary> experimentSummaries =
+                WellReplicaSummaryCalculator.calculateReplicasFeatureVectorSummaries(
+                        experimentWellData, settings.getAggregationType(), false);
+
+        // select the summary of the right material
+        MaterialIdFeatureVectorSummary materialSummary =
+                findMaterialSummary(materialId, experimentSummaries);
         return new MaterialSimpleFeatureVectorSummary(experiment,
-                allWellFeaturesOrNull.getFeatureCodesAndLabels(), summaryFeatureVector);
+                experimentFeatures.getFeatureCodesAndLabels(),
+                materialSummary.getFeatureVectorSummary(), materialSummary.getFeatureVectorRanks());
     }
 
-    private static List<IWellData> selectExperimentWellData(Set<WellReference> experimentWells,
-            WellFeatureCollection<FeatureVectorValues> allWellFeatures, TechId materialId)
+    private MaterialIdFeatureVectorSummary findMaterialSummary(TechId materialId,
+            List<MaterialIdFeatureVectorSummary> summaries)
     {
-        List<IWellData> experimentWellDataList = new ArrayList<IWellData>();
-        List<FeatureVectorValues> features = allWellFeatures.getFeatures();
-        for (FeatureVectorValues feature : features)
+        for (MaterialIdFeatureVectorSummary summary : summaries)
         {
-            if (experimentWells.contains(feature.getWellReference()))
+            if (summary.getMaterial().equals(materialId.getId()))
             {
-                float[] values = WellFeatureCollectionLoader.asFeatureVectorValues(feature);
-                IWellData wellData = new WellData(materialId.getId(), values);
-                experimentWellDataList.add(wellData);
+                return summary;
             }
         }
-        return experimentWellDataList;
+        throw new IllegalStateException("It should not happen: no summary found for material "
+                + materialId);
     }
 
-    private static Map<ExperimentReference, Set<WellReference>> groupWellsByExperiment(
-            List<WellContent> allAssayWellsForMaterial)
+    // connects each well with a material with its feature vector
+    private static List<IWellData> createWellData(
+            Map<WellReference, Long/* material id */> wellToMaterialMap,
+            List<FeatureVectorValues> features)
     {
-        GroupByMap<ExperimentReference, WellContent> expToWellContentMap =
-                GroupByMap.create(allAssayWellsForMaterial,
-                        new IKeyExtractor<ExperimentReference, WellContent>()
-                            {
-                                public ExperimentReference getKey(WellContent wellContent)
-                                {
-                                    return wellContent.getExperiment();
-                                }
-                            });
-        return convertToWellReferences(expToWellContentMap);
-    }
-
-    private static Map<ExperimentReference, Set<WellReference>> convertToWellReferences(
-            GroupByMap<ExperimentReference, WellContent> expToWellContentMap)
-    {
-        Map<ExperimentReference, Set<WellReference>> map =
-                new HashMap<ExperimentReference, Set<WellReference>>();
-        for (ExperimentReference exp : expToWellContentMap.getKeys())
+        List<IWellData> experimentWellDataList = new ArrayList<IWellData>();
+        for (FeatureVectorValues feature : features)
         {
-            List<WellContent> wellContents = expToWellContentMap.getOrDie(exp);
-            map.put(exp, asWellReferences(wellContents));
+            Long materialId = wellToMaterialMap.get(feature.getWellReference());
+            if (materialId != null)
+            {
+                float[] values = WellFeatureCollectionLoader.asFeatureVectorValues(feature);
+                IWellData wellData = new WellData(materialId, values);
+                experimentWellDataList.add(wellData);
+            }
         }
-        return map;
-    }
-
-    private static Set<WellReference> asWellReferences(List<WellContent> wellContents)
-    {
-        List<WellReference> wells =
-                CollectionUtils.map(wellContents,
-                        new ICollectionMappingFunction<WellReference, WellContent>()
-                            {
-                                public WellReference map(WellContent wellContent)
-                                {
-                                    return new WellReference(wellContent.tryGetLocation(),
-                                            wellContent.getPlate().getPermId());
-                                }
-                            });
-        return new HashSet<WellReference>(wells);
+        return experimentWellDataList;
     }
 
-    private static Set<PlateIdentifier> extractPlates(List<WellContent> wells)
+    private static Set<PlateIdentifier> extractPlates(List<BasicWellContentQueryResult> allWells)
     {
         Set<PlateIdentifier> plates = new HashSet<PlateIdentifier>();
-        for (WellContent well : wells)
+        for (BasicWellContentQueryResult well : allWells)
         {
-            String platePermId = well.getPlate().getPermId();
+            String platePermId = well.plate_perm_id;
             PlateIdentifier plateIdent = PlateIdentifier.createFromPermId(platePermId);
             plates.add(plateIdent);
         }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoader.java
index 09604792a2d..e0eb9b912cf 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoader.java
@@ -86,7 +86,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
         }
 
         MaterialIdFeatureVectorSummary generalSummary = backendResult.getGeneralSummary();
-        float[] featureVectorDeviatons = generalSummary.getFeatureVectorDeviations();
+        float[] featureVectorDeviatons = generalSummary.tryGetFeatureVectorDeviations();
         float[] featureVectorSummaries = generalSummary.getFeatureVectorSummary();
         int[] featureVectorRanks = generalSummary.getFeatureVectorRanks();
 
@@ -98,7 +98,9 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
             MaterialReplicaFeatureSummary replicaRow = new MaterialReplicaFeatureSummary();
             replicaRows.add(replicaRow);
 
-            replicaRow.setFeatureVectorDeviation(featureVectorDeviatons[i]);
+            double deviation =
+                    featureVectorDeviatons == null ? Double.NaN : featureVectorDeviatons[i];
+            replicaRow.setFeatureVectorDeviation(deviation);
             replicaRow.setFeatureVectorSummary(featureVectorSummaries[i]);
             replicaRow.setFeatureVectorRank(featureVectorRanks[i]);
             replicaRow.setFeatureDescription(featureDescriptions.get(i));
@@ -261,7 +263,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
     {
         List<MaterialIdFeatureVectorSummary> featureSummaries =
                 WellReplicaSummaryCalculator.calculateReplicasFeatureVectorSummaries(
-                        experimentWellDataList, settings.getAggregationType());
+                        experimentWellDataList, settings.getAggregationType(), true);
         return tryFindMaterialSummary(materialId, featureSummaries);
     }
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellContentLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellContentLoader.java
index 2fd5caa4e82..4b3eb9c3c6e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellContentLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellContentLoader.java
@@ -738,12 +738,11 @@ public class WellContentLoader extends AbstractContentLoader
         MaterialSearchCriteria materialSearchCriteria =
                 materialCriteria.getMaterialSearchCriteria();
 
-        ExperimentSearchCriteria experimentCriteria =
-                materialCriteria.getExperimentCriteria();
+        ExperimentSearchCriteria experimentCriteria = materialCriteria.getExperimentCriteria();
         SingleExperimentSearchCriteria experimentOrNull = experimentCriteria.tryGetExperiment();
         BasicProjectIdentifier projectOrNull = experimentCriteria.tryGetProjectIdentifier();
 
-        IScreeningQuery dao = createDAO(daoFactory);
+        IScreeningQuery dao = createDAO();
         if (materialSearchCriteria.tryGetMaterialCodesOrProperties() != null)
         {
             MaterialSearchCodesCriteria codesCriteria =
@@ -882,7 +881,7 @@ public class WellContentLoader extends AbstractContentLoader
     private List<WellContent> loadLocations(TechId geneMaterialId, TechId experimentId)
     {
         DataIterator<WellContentQueryResult> locations =
-                createDAO(daoFactory).getPlateLocationsForMaterialId(geneMaterialId.getId(),
+                createDAO().getPlateLocationsForMaterialId(geneMaterialId.getId(),
                         experimentId.getId());
 
         return convert(locations);
@@ -891,18 +890,23 @@ public class WellContentLoader extends AbstractContentLoader
     private List<WellContent> loadLocations(TechId geneMaterialId)
     {
         DataIterator<WellContentQueryResult> locations =
-                createDAO(daoFactory).getPlateLocationsForMaterialId(geneMaterialId.getId());
+                createDAO().getPlateLocationsForMaterialId(geneMaterialId.getId());
         return convert(locations);
     }
 
     private List<WellContent> loadLocationsForProject(TechId geneMaterialId, TechId projectId)
     {
         DataIterator<WellContentQueryResult> locations =
-                createDAO(daoFactory).getPlateLocationsForMaterialAndProjectIds(
-                        geneMaterialId.getId(), projectId.getId());
+                createDAO().getPlateLocationsForMaterialAndProjectIds(geneMaterialId.getId(),
+                        projectId.getId());
         return convert(locations);
     }
 
+    private IScreeningQuery createDAO()
+    {
+        return createDAO(daoFactory);
+    }
+
     private List<WellContent> convert(Iterable<WellContentQueryResult> queryResults)
     {
         List<WellContent> wellContents = convertAndRemoveDuplicateWells(queryResults);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellFeatureCollectionLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellFeatureCollectionLoader.java
index 73cb2b26159..12081462f8b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellFeatureCollectionLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellFeatureCollectionLoader.java
@@ -190,6 +190,8 @@ public class WellFeatureCollectionLoader extends AbstractContentLoader
         }
     }
 
+    // TODO 2011-06-21, Tomasz Pylak: this looks pretty unefficient. Could we do this erlier,
+    // avoiding converting these objects?
     public static float[] asFeatureVectorValues(FeatureVectorValues featureVector)
     {
         FeatureValue[] featureValues = featureVector.getFeatureValues();
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java
index 518f0d53227..317f6f47b78 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java
@@ -41,20 +41,26 @@ public class WellReplicaSummaryCalculator
     /**
      * Calculates summaries and ranks for each group of well replicas (biological or technical).
      * Usually a replica is determined by the material in the well, e.g. gene or compound.
+     * 
+     * @param calculateDeviations if true then deviations for each aggregation will be calculated as
+     *            well
      */
     public static List<MaterialIdFeatureVectorSummary> calculateReplicasFeatureVectorSummaries(
             List<? extends IWellData> wellDataList,
-            MaterialReplicaSummaryAggregationType aggregationType)
+            MaterialReplicaSummaryAggregationType aggregationType, boolean calculateDeviations)
     {
         validate(wellDataList);
         WellReplicaSummaryCalculator calculator =
                 new WellReplicaSummaryCalculator(wellDataList, aggregationType);
         List<MaterialIdFeatureVectorSummary> summaries =
-                calculator.calculateReplicasFeatureVectorSummaries();
+                calculator.calculateReplicasFeatureVectorSummaries(calculateDeviations);
         return summaries;
     }
 
-    /** Calculates one aggregated number for each feature, taking all specified wells into account. */
+    /**
+     * Calculates one aggregated number for each feature, taking all specified wells (which should b
+     * technical replicates) into account.
+     */
     public static float[] calculateSummaryFeatureVector(
             List<? extends IWellData> techicalReplicaWells,
             MaterialReplicaSummaryAggregationType aggregationType)
@@ -62,7 +68,7 @@ public class WellReplicaSummaryCalculator
         validate(techicalReplicaWells);
         int numberOfFeatures = getNumberOfFeatures(techicalReplicaWells);
         return calculateSummaryFeatureVector(techicalReplicaWells, aggregationType,
-                numberOfFeatures).getAggregates();
+                numberOfFeatures, false).getAggregates();
     }
 
     private static void validate(List<? extends IWellData> wellDataList)
@@ -108,10 +114,11 @@ public class WellReplicaSummaryCalculator
                     });
     }
 
-    private List<MaterialIdFeatureVectorSummary> calculateReplicasFeatureVectorSummaries()
+    private List<MaterialIdFeatureVectorSummary> calculateReplicasFeatureVectorSummaries(
+            boolean calculateDeviations)
     {
         Map<Long/* replica id */, SummaryFeatureVector> replicaToSummaryMap =
-                calculateSummaryFeatures();
+                calculateSummaryFeatures(calculateDeviations);
         Map<Long/* replica id */, int[]/* ranks for each feature */> ranks =
                 calculateRanks(replicaToSummaryMap, numberOfFeatures);
 
@@ -125,7 +132,8 @@ public class WellReplicaSummaryCalculator
             // array not empty, all materials are the same
             MaterialIdFeatureVectorSummary summary =
                     new MaterialIdFeatureVectorSummary(replicaId, summaryFeatures.getAggregates(),
-                            summaryFeatures.getDeviation(), ranks.get(replicaId), numberOfReplicas);
+                            summaryFeatures.tryGetDeviations(), ranks.get(replicaId),
+                            numberOfReplicas);
             summaries.add(summary);
         }
         return summaries;
@@ -206,7 +214,7 @@ public class WellReplicaSummaryCalculator
         return ranks;
     }
 
-    private Map<Long, SummaryFeatureVector> calculateSummaryFeatures()
+    private Map<Long, SummaryFeatureVector> calculateSummaryFeatures(boolean calculateDeviations)
     {
         Map<Long/* replica id */, SummaryFeatureVector> replicaToSummaryMap =
                 new HashMap<Long, SummaryFeatureVector>();
@@ -215,7 +223,8 @@ public class WellReplicaSummaryCalculator
         {
             List<IWellData> replicaWells = replicaToWellDataMap.getOrDie(replicaId);
             SummaryFeatureVector summary =
-                    calculateSummaryFeatureVector(replicaWells, aggregationType, numberOfFeatures);
+                    calculateSummaryFeatureVector(replicaWells, aggregationType, numberOfFeatures,
+                            calculateDeviations);
             replicaToSummaryMap.put(replicaId, summary);
         }
         return replicaToSummaryMap;
@@ -226,12 +235,12 @@ public class WellReplicaSummaryCalculator
     {
         private final float[] aggregate;
 
-        private final float[] deviation;
+        private final float[] deviationsOrNull;
 
-        public SummaryFeatureVector(float[] aggregate, float[] deviation)
+        public SummaryFeatureVector(float[] aggregate, float[] deviationsOrNull)
         {
             this.aggregate = aggregate;
-            this.deviation = deviation;
+            this.deviationsOrNull = deviationsOrNull;
         }
 
         public float[] getAggregates()
@@ -239,38 +248,55 @@ public class WellReplicaSummaryCalculator
             return aggregate;
         }
 
-        public float[] getDeviation()
+        /** null if not calculated */
+        public float[] tryGetDeviations()
         {
-            return deviation;
+            return deviationsOrNull;
         }
     }
 
     private static SummaryFeatureVector calculateSummaryFeatureVector(
             List<? extends IWellData> replicaWells,
-            MaterialReplicaSummaryAggregationType aggregationType, int numberOfFeatures)
+            MaterialReplicaSummaryAggregationType aggregationType, int numberOfFeatures,
+            boolean calculateDeviations)
     {
         switch (aggregationType)
         {
             case MEDIAN:
-                return calculateMedianVector(replicaWells, numberOfFeatures);
+                return calculateMedianVector(replicaWells, numberOfFeatures, calculateDeviations);
             default:
                 throw new IllegalStateException("Unhandled aggregation type: " + aggregationType);
         }
     }
 
     private static SummaryFeatureVector calculateMedianVector(
-            List<? extends IWellData> replicaWells, int numberOfFeatures)
+            List<? extends IWellData> replicaWells, int numberOfFeatures,
+            boolean calculateDeviations)
     {
         float[] medians = new float[numberOfFeatures];
+        for (int featureIx = 0; featureIx < numberOfFeatures; featureIx++)
+        {
+            medians[featureIx] = calculateMedian(replicaWells, featureIx);
+        }
+        float[] deviations = null;
+        if (calculateDeviations)
+        {
+            deviations = calculateDeviations(replicaWells, numberOfFeatures, medians);
+        }
+        return new SummaryFeatureVector(medians, deviations);
+    }
+
+    private static float[] calculateDeviations(List<? extends IWellData> replicaWells,
+            int numberOfFeatures, float[] medians)
+    {
         float[] deviations = new float[numberOfFeatures];
         for (int featureIx = 0; featureIx < numberOfFeatures; featureIx++)
         {
-            float median = calculateMedian(replicaWells, featureIx);
-            medians[featureIx] = median;
+            float median = medians[featureIx];
             deviations[featureIx] =
                     calculateMedianAbsoluteDeviation(median, replicaWells, featureIx);
         }
-        return new SummaryFeatureVector(medians, deviations);
+        return deviations;
     }
 
     private static void sortBySelectedFeature(List<IWellData> replicaWells, int featureIx)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialIdFeatureVectorSummary.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialIdFeatureVectorSummary.java
index 669f265961e..58312443c95 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialIdFeatureVectorSummary.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialIdFeatureVectorSummary.java
@@ -32,17 +32,17 @@ public class MaterialIdFeatureVectorSummary extends MaterialFeatureVectorSummary
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
     public MaterialIdFeatureVectorSummary(Long materialId, float[] featureVectorSummary,
-            float[] featureVectorDeviations, int[] featureVectorRanks,
+            float[] featureVectorDeviationsOrNull, int[] featureVectorRanks,
             int numberOfMaterialsInExperiment)
     {
-        super(materialId, featureVectorSummary, featureVectorDeviations, featureVectorRanks,
+        super(materialId, featureVectorSummary, featureVectorDeviationsOrNull, featureVectorRanks,
                 numberOfMaterialsInExperiment);
     }
 
     public MaterialFeatureVectorSummary createWithMaterial(Material material)
     {
         return new MaterialFeatureVectorSummary(material, getFeatureVectorSummary(),
-                getFeatureVectorDeviations(), getFeatureVectorRanks(),
+                tryGetFeatureVectorDeviations(), getFeatureVectorRanks(),
                 getNumberOfMaterialsInExperiment());
     }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ExperimentFeatureVectorSummary.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ExperimentFeatureVectorSummary.java
index ce32a28209f..2b8033f6d47 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ExperimentFeatureVectorSummary.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ExperimentFeatureVectorSummary.java
@@ -33,6 +33,7 @@ public class ExperimentFeatureVectorSummary implements ISerializable
 
     private ExperimentReference experiment;
 
+    // summaries without computed deviation
     private List<MaterialFeatureVectorSummary> materialsSummary;
 
     // has the same length as feature vectors in all material summaries
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummary.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummary.java
index 0edf2bd23b5..400dcbcfab3 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummary.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummary.java
@@ -36,10 +36,10 @@ public class MaterialFeatureVectorSummary extends
     }
 
     public MaterialFeatureVectorSummary(Material material, float[] featureVectorSummary,
-            float[] featureVectorDeviations, int[] featureVectorRanks,
+            float[] featureVectorDeviationsOrNull, int[] featureVectorRanks,
             int numberOfMaterialsInExperiment)
     {
-        super(material, featureVectorSummary, featureVectorDeviations, featureVectorRanks,
+        super(material, featureVectorSummary, featureVectorDeviationsOrNull, featureVectorRanks,
                 numberOfMaterialsInExperiment);
     }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummaryParametrized.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummaryParametrized.java
index f5270fe8886..1fd6ce82f9a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummaryParametrized.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialFeatureVectorSummaryParametrized.java
@@ -31,13 +31,17 @@ public class MaterialFeatureVectorSummaryParametrized<T> implements ISerializabl
 
     private T material;
 
+    private int numberOfMaterialsInExperiment;
+
+    // --- one element for each feature: summary, deviation and rank
+
     private float[] featureVectorSummary;
 
-    private float[] featureVectorDeviations;
+    private float[] featureVectorDeviationsOrNull;
 
     private int[] featureVectorRanks;
 
-    private int numberOfMaterialsInExperiment;
+    // ---
 
     // GTW
     protected MaterialFeatureVectorSummaryParametrized()
@@ -45,12 +49,12 @@ public class MaterialFeatureVectorSummaryParametrized<T> implements ISerializabl
     }
 
     public MaterialFeatureVectorSummaryParametrized(T material, float[] featureVectorSummary,
-            float[] featureVectorDeviations, int[] featureVectorRanks,
+            float[] featureVectorDeviationsOrNull, int[] featureVectorRanks,
             int numberOfMaterialsInExperiment)
     {
         this.material = material;
         this.featureVectorSummary = featureVectorSummary;
-        this.featureVectorDeviations = featureVectorDeviations;
+        this.featureVectorDeviationsOrNull = featureVectorDeviationsOrNull;
         this.featureVectorRanks = featureVectorRanks;
         this.numberOfMaterialsInExperiment = numberOfMaterialsInExperiment;
     }
@@ -65,9 +69,9 @@ public class MaterialFeatureVectorSummaryParametrized<T> implements ISerializabl
         return featureVectorSummary;
     }
 
-    public float[] getFeatureVectorDeviations()
+    public float[] tryGetFeatureVectorDeviations()
     {
-        return featureVectorDeviations;
+        return featureVectorDeviationsOrNull;
     }
 
     public int[] getFeatureVectorRanks()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSimpleFeatureVectorSummary.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSimpleFeatureVectorSummary.java
index f9094b78fd7..09850659f3b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSimpleFeatureVectorSummary.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSimpleFeatureVectorSummary.java
@@ -41,6 +41,8 @@ public class MaterialSimpleFeatureVectorSummary implements ISerializable
 
     private float[] featureVectorSummary;
 
+    private int[] featureVectorRanks;
+
     // GTW
     @SuppressWarnings("unused")
     private MaterialSimpleFeatureVectorSummary()
@@ -53,15 +55,17 @@ public class MaterialSimpleFeatureVectorSummary implements ISerializable
      */
     public MaterialSimpleFeatureVectorSummary(ExperimentReference experiment)
     {
-        this(experiment, new ArrayList<CodeAndLabel>(), new float[0]);
+        this(experiment, new ArrayList<CodeAndLabel>(), new float[0], new int[0]);
     }
 
     public MaterialSimpleFeatureVectorSummary(ExperimentReference experiment,
-            List<CodeAndLabel> featureDescriptions, float[] featureVectorSummary)
+            List<CodeAndLabel> featureDescriptions, float[] featureVectorSummary,
+            int[] featureVectorRanks)
     {
         this.experiment = experiment;
         this.featureDescriptions = featureDescriptions;
         this.featureVectorSummary = featureVectorSummary;
+        this.featureVectorRanks = featureVectorRanks;
     }
 
     public ExperimentReference getExperiment()
@@ -79,4 +83,8 @@ public class MaterialSimpleFeatureVectorSummary implements ISerializable
         return featureVectorSummary;
     }
 
+    public int[] getFeatureVectorRanks()
+    {
+        return featureVectorRanks;
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSummarySettings.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSummarySettings.java
index aeb36e868e5..3c05eae5d5a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSummarySettings.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialSummarySettings.java
@@ -37,8 +37,10 @@ public class MaterialSummarySettings implements ISerializable
 
     private List<String> featureCodes;
 
-    private String replicaMatrialTypePattern;
+    private String[] replicaMatrialTypeSubstrings;
 
+    // well property codes which links to the material which determins which biological replicate it
+    // is, e.g. siRNA or compound
     private List<String> biologicalReplicatePropertyTypeCodes;
 
     private MaterialReplicaSummaryAggregationType aggregationType;
@@ -53,14 +55,14 @@ public class MaterialSummarySettings implements ISerializable
         this.featureCodes = featureCodes;
     }
 
-    public String getReplicaMatrialTypePattern()
+    public String[] getReplicaMatrialTypeSubstrings()
     {
-        return replicaMatrialTypePattern;
+        return replicaMatrialTypeSubstrings;
     }
 
-    public void setReplicaMatrialTypePatterns(String replicaMatrialTypePattern)
+    public void setReplicaMatrialTypePatterns(String[] replicaMatrialTypeSubstrings)
     {
-        this.replicaMatrialTypePattern = replicaMatrialTypePattern;
+        this.replicaMatrialTypeSubstrings = replicaMatrialTypeSubstrings;
     }
 
     public List<String> getBiologicalReplicatePropertyTypeCodes()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java
index 576e5d0fafb..14accb1d7b2 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java
@@ -131,9 +131,6 @@ public class ScreeningConstants
     /** Used to import Qiagen siRNA libraries. */
     public static final String LIBRARY_PLUGIN_TYPE_CODE = "LIBRARY";
 
-    /** Types of materials which should be for grouping the analysis results */
-    public static final String REPLICA_METERIAL_TYPE_PATTERN = ".*GENE.*|.*CONTROL.*|.*COMPOUND.*";
-
     // --- !!!!!! It's discouraged to use this constant, try hard not to do that !!!!!!!! ---
 
     /** It's discouraged to use this constant, use {@link #HCS_PLATE_SAMPLE_TYPE_PATTERN} instead. */
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ScreeningDAOTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ScreeningDAOTest.java
index f589680be44..08a2026c2b8 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ScreeningDAOTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/dataaccess/ScreeningDAOTest.java
@@ -173,4 +173,19 @@ public class ScreeningDAOTest extends AbstractScreeningDAOTest
 
     }
 
+    @Test
+    public void testGetGlobalBasicPlateLocations()
+    {
+        List<BasicWellContentQueryResult> locations =
+                EntityListingTestUtils.asList(query.getPlateLocationsForExperiment(1, "%GENE%"));
+        AssertJUnit.assertEquals(0, locations.size());
+
+        List<ExperimentReferenceQueryResult> experiments = query.getExperimentsWithMaterial(1);
+        AssertJUnit.assertEquals(0, experiments.size());
+
+        experiments = query.getExperimentsWithMaterial(1, 1);
+        AssertJUnit.assertEquals(0, experiments.size());
+
+    }
+
 }
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java
index 739e1be813f..93b89f8be44 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java
@@ -66,13 +66,13 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit
         assertArraysEqual(new float[]
             { 1.5f, 6 }, repl1.getFeatureVectorSummary());
         assertArraysEqual(new float[]
-            { 0.5f, 2 }, repl1.getFeatureVectorDeviations());
+            { 0.5f, 2 }, repl1.tryGetFeatureVectorDeviations());
 
         MaterialIdFeatureVectorSummary repl2 = summary.get(1 - replica1Ix);
         assertArraysEqual(new float[]
             { 1, 100 }, repl2.getFeatureVectorSummary());
         assertArraysEqual(new float[]
-            { 0, 90 }, repl2.getFeatureVectorDeviations());
+            { 0, 90 }, repl2.tryGetFeatureVectorDeviations());
 
         assertArraysEqual(new int[]
             { 1, 2 }, repl1.getFeatureVectorRanks());
@@ -212,6 +212,6 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit
     private List<MaterialIdFeatureVectorSummary> calculate(List<IWellData> wellDataList)
     {
         return WellReplicaSummaryCalculator.calculateReplicasFeatureVectorSummaries(wellDataList,
-                MaterialReplicaSummaryAggregationType.MEDIAN);
+                MaterialReplicaSummaryAggregationType.MEDIAN, true);
     }
 }
-- 
GitLab