From 831e2f27d207c25a49cf582a39d65296253985ff Mon Sep 17 00:00:00 2001 From: tpylak <tpylak> Date: Tue, 10 May 2011 11:03:35 +0000 Subject: [PATCH] LMS-2190 gene and assay view polishing, small names refactoring SVN: 21192 --- .../FeatureVectorSummaryViewer.java | 45 +++--- .../detailviewers/LayoutUtils.java | 2 + .../MaterialReplicaFeatureSummaryViewer.java | 134 +++++++++------- .../detailviewers/PropertiesUtil.java | 148 ++++++++++++++++++ .../specific/ScreeningLinkExtractor.java | 2 +- ...MaterialReplicaFeatureSummaryProvider.java | 9 +- .../MaterialFeatureVectorSummaryLoader.java | 82 +++++++--- .../logic/ReplicateSequenceProvider.java | 33 ++-- .../server/logic/WellContentLoader.java | 5 +- .../MaterialAllReplicasFeatureVectors.java | 16 +- .../dto/MaterialReplicaFeatureSummary.java | 5 +- ...aterialFeatureVectorSummaryLoaderTest.java | 2 +- 12 files changed, 345 insertions(+), 138 deletions(-) create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PropertiesUtil.java diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/FeatureVectorSummaryViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/FeatureVectorSummaryViewer.java index 270396fe9a2..11c2b5c103b 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/FeatureVectorSummaryViewer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/FeatureVectorSummaryViewer.java @@ -18,10 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application. import java.util.Set; -import com.extjs.gxt.ui.client.Style.Orientation; -import com.extjs.gxt.ui.client.util.Margins; import com.extjs.gxt.ui.client.widget.Component; -import com.extjs.gxt.ui.client.widget.Html; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.layout.RowData; import com.extjs.gxt.ui.client.widget.layout.RowLayout; @@ -49,6 +46,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.u * * @author Kaloyan Enimanev */ +// TODO 2011-05-05, Tomasz Pylak: rename to ExperimentAnalysisSummaryViewer public class FeatureVectorSummaryViewer { @@ -115,14 +113,14 @@ public class FeatureVectorSummaryViewer @Override public String tryGetLink() { - return ScreeningLinkExtractor.createFeatureVectorSummaryBrowserLink(experiment - .getPermId()); + return ScreeningLinkExtractor + .createExperimentAnalysisSummaryBrowserLink(experiment.getPermId()); } @Override public String getTabTitle() { - return "Feature Vector Summary: " + experiment.getCode(); + return "Analysis Summary " + experiment.getCode(); } @Override @@ -139,14 +137,13 @@ public class FeatureVectorSummaryViewer { final LayoutContainer panel = new LayoutContainer(); - panel.setLayout(new RowLayout(Orientation.VERTICAL)); + panel.setLayout(new RowLayout()); - Widget northPanel = createNorth(viewContext, experiment); - panel.add(northPanel); + addHeader(panel, viewContext, experiment); final IDisposableComponent gridComponent = FeatureVectorSummaryGrid.create(viewContext, experiment); - panel.add(gridComponent.getComponent()); + panel.add(gridComponent.getComponent(), new RowData(-1, 1)); return new IDisposableComponent() { @@ -172,24 +169,26 @@ public class FeatureVectorSummaryViewer }; } - private static Widget createNorth(IViewContext<IScreeningClientServiceAsync> viewContext, - Experiment experiment) + private static void addHeader(LayoutContainer parentPanel, + IViewContext<IScreeningClientServiceAsync> viewContext, Experiment experiment) { + String headingText = "Assay " + experiment.getCode(); + LayoutContainer panel = new LayoutContainer(); - panel.setLayout(new RowLayout(Orientation.VERTICAL)); + panel.setLayout(new RowLayout()); - // NOTE: this should be refactored to an external CSS style - String headingText = "Assay " + experiment.getCode(); - Html headingWidget = new Html(headingText); - headingWidget.setTagName("h1"); - panel.add(headingWidget, new RowData(1, -1, headingTitleMargin())); + Widget headingWidget = PropertiesUtil.createHeaderTitle(headingText); + panel.add(headingWidget, PropertiesUtil.createHeaderTitleLayoutData()); - return panel; - } + LayoutContainer propertiesPanel = new LayoutContainer(); + propertiesPanel.setLayout(new RowLayout()); + int propsHeight = PropertiesUtil.addProperties(experiment, propertiesPanel, null); + panel.add(propertiesPanel, new RowData(1, -1)); - private static Margins headingTitleMargin() - { - return new Margins(0, 0, 20, 0); + int headersHeight = 15; + int totalHeight = propsHeight + headersHeight; + parentPanel.add(panel, + new RowData(-1, totalHeight, PropertiesUtil.createHeaderInfoMargin())); } } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LayoutUtils.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LayoutUtils.java index ba9e29158a7..25795762b8a 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LayoutUtils.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LayoutUtils.java @@ -26,6 +26,8 @@ import com.extjs.gxt.ui.client.widget.layout.RowData; */ public class LayoutUtils { + public static final int ONE_HEADER_LINE_HEIGHT_PX = 15; + private static final int MARGIN_SIZE_PX = 10; /** @return layout data with big margin on all sides */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryViewer.java index 5de170c288c..d22f5aab939 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryViewer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/MaterialReplicaFeatureSummaryViewer.java @@ -26,13 +26,12 @@ import java.util.Set; import com.extjs.gxt.ui.client.Style.Orientation; import com.extjs.gxt.ui.client.Style.Scroll; -import com.extjs.gxt.ui.client.util.Margins; import com.extjs.gxt.ui.client.widget.Component; -import com.extjs.gxt.ui.client.widget.HorizontalPanel; import com.extjs.gxt.ui.client.widget.Html; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.Text; import com.extjs.gxt.ui.client.widget.Viewport; +import com.extjs.gxt.ui.client.widget.layout.ColumnLayout; import com.extjs.gxt.ui.client.widget.layout.RowData; import com.extjs.gxt.ui.client.widget.layout.RowLayout; import com.extjs.gxt.ui.client.widget.layout.TableLayout; @@ -54,7 +53,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync; @@ -75,6 +73,14 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaIma */ public class MaterialReplicaFeatureSummaryViewer { + private static final String LOADING_IMAGES_DICT_MSG = "Loading images..."; + + private static final String REPLICATE_ABBREV_DICT_MSG = "repl."; + + private static final String NO_IMAGES_AVAILABLE_DICT_MSG = "No images available."; + + private static final String MATERIAL_ID_DICT_MSG = "Id"; + private static final int ONE_IMAGE_SIZE_PX = 80; public static void openTab(IViewContext<IScreeningClientServiceAsync> screeningViewContext, @@ -88,7 +94,7 @@ public class MaterialReplicaFeatureSummaryViewer private final IViewContext<IScreeningClientServiceAsync> screeningViewContext; - public MaterialReplicaFeatureSummaryViewer( + private MaterialReplicaFeatureSummaryViewer( IViewContext<IScreeningClientServiceAsync> screeningViewContext) { this.screeningViewContext = screeningViewContext; @@ -118,7 +124,6 @@ public class MaterialReplicaFeatureSummaryViewer screeningViewContext.getCommonService().getExperimentInfo(new TechId(experiment), new AbstractAsyncCallback<Experiment>(screeningViewContext) { - @Override protected void process(Experiment result) { @@ -147,7 +152,6 @@ public class MaterialReplicaFeatureSummaryViewer screeningViewContext.getService().getMaterialInfo(new TechId(material), new AbstractAsyncCallback<Material>(screeningViewContext) { - @Override protected void process(Material result) { @@ -204,19 +208,20 @@ public class MaterialReplicaFeatureSummaryViewer private class ImagesFoundCallback extends AbstractAsyncCallback<List<WellReplicaImage>> { - private final LayoutContainer panel; + private final LayoutContainer imagesPanel; - ImagesFoundCallback(LayoutContainer panel) + ImagesFoundCallback(LayoutContainer imagesPanel) { super(screeningViewContext); - this.panel = panel; + this.imagesPanel = imagesPanel; } @Override protected void process(List<WellReplicaImage> images) { - panel.add(createImagePanel(images)); - panel.layout(); + imagesPanel.removeAll(); + imagesPanel.add(createImagePanel(images)); + imagesPanel.layout(); } } @@ -224,7 +229,7 @@ public class MaterialReplicaFeatureSummaryViewer { if (images.isEmpty()) { - return new Text("No images available."); + return new Text(NO_IMAGES_AVAILABLE_DICT_MSG); } String displayTypeId = ScreeningDisplayTypeIDGenerator.EXPERIMENT_CHANNEL.createID(null); final IDefaultChannelState defaultChannelState = @@ -245,15 +250,20 @@ public class MaterialReplicaFeatureSummaryViewer labelToReplicasMap.remove(orphanGroupKey); } panel.add(createBiologicalReplicatesImagesPanel(labelToReplicasMap, channelChooser)); + ensureAllImagesVisible(panel); + return panel; + } + + // WORKAROUND: in normal mode the height of menu and tab is not taken into account, + // so we add empty space to make + private void ensureAllImagesVisible(LayoutContainer panel) + { if (screeningViewContext.isSimpleOrEmbeddedMode() == false) { - // WORKAROUND: in normal mode the height of menu and tab is not taken into account, - // so we add empty space to make Text box = new Text(); box.setHeight(100); panel.add(box); } - return panel; } private Widget createOrphanTechnicalReplicatesPanel( @@ -333,7 +343,7 @@ public class MaterialReplicaFeatureSummaryViewer private Widget createTechnicalReplicateLabel(int technicalReplicateSequence) { - return new Text("repl. " + technicalReplicateSequence); + return new Text(REPLICATE_ABBREV_DICT_MSG + " " + technicalReplicateSequence); } private Widget createEmptyBox() @@ -413,8 +423,8 @@ public class MaterialReplicaFeatureSummaryViewer panel.setLayout(new RowLayout(Orientation.VERTICAL)); panel.setScrollMode(Scroll.AUTOY); - final Widget northPanel = createNorth(screeningViewContext, experiment, material); - panel.add(northPanel); + Widget materialInfo = createMaterialInfo(screeningViewContext, experiment, material); + panel.add(materialInfo, new RowData(-1, -1, PropertiesUtil.createHeaderInfoMargin())); final IDisposableComponent gridComponent = MaterialReplicaFeatureSummaryGrid.create(screeningViewContext, new TechId( @@ -422,8 +432,11 @@ public class MaterialReplicaFeatureSummaryViewer // NOTE: if the width is 100% then the vertical scrollbar of the grid is not visible panel.add(gridComponent.getComponent(), new RowData(0.97, 400)); + LayoutContainer imagesPanel = new LayoutContainer(); + imagesPanel.add(new Text(LOADING_IMAGES_DICT_MSG)); + panel.add(imagesPanel); screeningViewContext.getService().listWellImages(new TechId(material.getId()), - new TechId(experiment.getId()), new ImagesFoundCallback(panel)); + new TechId(experiment.getId()), new ImagesFoundCallback(imagesPanel)); return new IDisposableComponent() { @@ -449,43 +462,45 @@ public class MaterialReplicaFeatureSummaryViewer }; } - private static Widget createNorth(IViewContext<IScreeningClientServiceAsync> viewContext, - Experiment experiment, Material material) + private static Widget createMaterialInfo( + final IViewContext<IScreeningClientServiceAsync> viewContext, + final Experiment experiment, final Material material) { - HorizontalPanel panel = new HorizontalPanel(); + LayoutContainer panel = new LayoutContainer(); + panel.setLayout(new RowLayout()); - Widget left = createNorthLeft(viewContext, experiment, material); - panel.add(left); + Widget headerWidget = createHeaderWithLinks(viewContext, experiment, material); + panel.add(headerWidget, PropertiesUtil.createHeaderTitleLayoutData()); - Widget right = createNorthRight(viewContext, experiment, material); - panel.add(right); + LayoutContainer materialPropertiesPanel = createMaterialPropertiesPanel(material); + panel.add(materialPropertiesPanel); return panel; } - private static Widget createNorthLeft( + private static Widget createHeaderWithLinks( final IViewContext<IScreeningClientServiceAsync> viewContext, final Experiment experiment, final Material material) { - LayoutContainer panel = new LayoutContainer(); - panel.setLayout(new RowLayout(Orientation.VERTICAL)); + Widget headingWidget = createHeaderTitle(experiment, material); + Text emptyBox = new Text(); + emptyBox.setWidth(200); + Widget assayAnalysisSummaryLink = + createAssayAnalysisSummaryLink(viewContext, experiment, material); + LayoutContainer headerPanel = new LayoutContainer(); + headerPanel.setLayout(new ColumnLayout()); + headerPanel.add(headingWidget); + headerPanel.add(emptyBox); + headerPanel.add(assayAnalysisSummaryLink); + return headerPanel; + } + private static Html createHeaderTitle(final Experiment experiment, final Material material) + { String headingText = getMaterialType(material) + " " + getMaterialName(material) + " in assay " + experiment.getCode(); - - Html headingWidget = createHeader(headingText); - panel.add(headingWidget, new RowData(1, -1, new Margins(0, 0, 20, 0))); - - return panel; - } - - private static Html createHeader(String headingText) - { - Html headingWidget = new Html(headingText); - // NOTE: this should be refactored to an external CSS style - headingWidget.setTagName("h1"); - return headingWidget; + return PropertiesUtil.createHeaderTitle(headingText); } private static String getMaterialType(Material material) @@ -506,29 +521,24 @@ public class MaterialReplicaFeatureSummaryViewer if (material.getEntityType().getCode() .equalsIgnoreCase(ScreeningConstants.GENE_PLUGIN_TYPE_CODE)) { - for (IEntityProperty property : material.getProperties()) + String geneSymbol = + PropertiesUtil.tryFindProperty(material, ScreeningConstants.GENE_SYMBOLS); + if (geneSymbol != null) { - if (property.getPropertyType().getCode() - .equalsIgnoreCase(ScreeningConstants.GENE_SYMBOLS)) - { - return property.tryGetAsString(); - } + return geneSymbol; } } return material.getCode(); } - private static Widget createNorthRight( + private static Widget createAssayAnalysisSummaryLink( final IViewContext<IScreeningClientServiceAsync> viewContext, final Experiment experiment, final Material material) { - LayoutContainer panel = new LayoutContainer(); - panel.setLayout(new RowLayout(Orientation.VERTICAL)); - // add link to feature vector summary for the experiment String linkUrl = - ScreeningLinkExtractor - .createFeatureVectorSummaryBrowserLink(experiment.getPermId()); + ScreeningLinkExtractor.createExperimentAnalysisSummaryBrowserLink(experiment + .getPermId()); String linkText = "Show assay " + experiment.getCode() + " summary"; Widget linkWidget = LinkRenderer.getLinkWidget(linkText, new ClickHandler() { @@ -539,11 +549,17 @@ public class MaterialReplicaFeatureSummaryViewer FeatureVectorSummaryViewer.openTab(viewContext, experiment.getPermId()); } }, linkUrl); + return linkWidget; + } - HorizontalPanel linkPanel = new HorizontalPanel(); - linkPanel.add(linkWidget); - panel.add(linkPanel, new RowData(-1, -1, new Margins(0, 0, 20, 200))); - - return panel; + private static LayoutContainer createMaterialPropertiesPanel(final Material material) + { + LayoutContainer propertiesPanel = new LayoutContainer(); + propertiesPanel.setLayout(new RowLayout()); + Map<String, String> additionalProperties = new HashMap<String, String>(); + additionalProperties.put(MATERIAL_ID_DICT_MSG, material.getCode()); + PropertiesUtil.addProperties(material, propertiesPanel, additionalProperties, + ScreeningConstants.GENE_SYMBOLS); + return propertiesPanel; } } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PropertiesUtil.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PropertiesUtil.java new file mode 100644 index 00000000000..37e4b9bbae0 --- /dev/null +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/PropertiesUtil.java @@ -0,0 +1,148 @@ +/* + * 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.client.web.client.application.detailviewers; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.Style.VerticalAlignment; +import com.extjs.gxt.ui.client.util.Margins; +import com.extjs.gxt.ui.client.widget.Html; +import com.extjs.gxt.ui.client.widget.LayoutContainer; +import com.extjs.gxt.ui.client.widget.Text; +import com.extjs.gxt.ui.client.widget.layout.RowData; +import com.extjs.gxt.ui.client.widget.layout.TableData; +import com.extjs.gxt.ui.client.widget.layout.TableLayout; + +import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils; +import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithProperties; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; + +/** + * Utility methods to display properties and header in the publication views. + * + * @author Tomasz Pylak + */ +public class PropertiesUtil +{ + public static String tryFindProperty(IEntityPropertiesHolder propertiesHolder, + String propertyCode) + { + for (IEntityProperty property : propertiesHolder.getProperties()) + { + if (property.getPropertyType().getCode().equalsIgnoreCase(propertyCode)) + { + return property.tryGetAsString(); + } + } + return null; + } + + /** @return estimated height */ + public static int addProperties(IEntityInformationHolderWithProperties propertiesHolder, + LayoutContainer panel, + Map<String/* label */, String/* value */> additionalPropertiesOrNull, + String... excludedPropertyCodes) + { + LayoutContainer propertiesPanel = new LayoutContainer(); + propertiesPanel.setLayout(new TableLayout(3)); + + Map<String, String> propertiesMap = + createSortedMap(propertiesHolder, excludedPropertyCodes, additionalPropertiesOrNull); + int height = 0; + for (Entry<String, String> entry : propertiesMap.entrySet()) + { + addProperty(propertiesPanel, entry.getKey(), entry.getValue()); + height += getEstimatedHeight(entry.getValue()); + } + panel.add(propertiesPanel); + return height; + } + + private static Map<String, String> createSortedMap( + IEntityInformationHolderWithProperties propertiesHolder, + String[] excludedPropertyCodes, Map<String, String> additionalPropertiesOrNull) + { + Set<String> excludedPropertyCodesSet = + new HashSet<String>(Arrays.asList(excludedPropertyCodes)); + + Map<String, String> propertiesMap = new TreeMap<String, String>(); + for (IEntityProperty property : propertiesHolder.getProperties()) + { + PropertyType propertyType = property.getPropertyType(); + if (excludedPropertyCodesSet.contains(propertyType.getCode()) == false) + { + String value = property.tryGetAsString(); + if (value != null && value.length() > 0) + { + propertiesMap.put(propertyType.getLabel(), value); + } + } + } + if (additionalPropertiesOrNull != null) + { + for (Entry<String, String> entry : additionalPropertiesOrNull.entrySet()) + { + propertiesMap.put(entry.getKey(), entry.getValue()); + } + } + return propertiesMap; + } + + private static void addProperty(LayoutContainer propertiesPanel, String label, String value) + { + TableData labelLayout = new TableData(HorizontalAlignment.RIGHT, VerticalAlignment.TOP); + labelLayout.setWidth("80px"); + propertiesPanel.add(new Html(label + ": "), labelLayout); + TableData spacerLayout = new TableData(); + spacerLayout.setWidth("5px"); + propertiesPanel.add(new Text(""), spacerLayout); + TableData valueLayout = new TableData(HorizontalAlignment.LEFT, VerticalAlignment.TOP); + propertiesPanel.add(new Html(StringEscapeUtils.unescapeHtml(value)), valueLayout); + } + + private static int getEstimatedHeight(String text) + { + int charsPerLine = 150; + return LayoutUtils.ONE_HEADER_LINE_HEIGHT_PX * ((text.length() / charsPerLine) + 1); + } + + public static Margins createHeaderInfoMargin() + { + return new Margins(3, 3, 10, 3); + } + + public static RowData createHeaderTitleLayoutData() + { + return new RowData(-1, -1, new Margins(0, 0, 5, 0)); + } + + public static Html createHeaderTitle(String headingText) + { + Html headingWidget = new Html(headingText); + // NOTE: this should be refactored to an external CSS style + headingWidget.setTagName("h1"); + return headingWidget; + } +} diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ui/columns/specific/ScreeningLinkExtractor.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ui/columns/specific/ScreeningLinkExtractor.java index fad783068ca..264b99992b7 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ui/columns/specific/ScreeningLinkExtractor.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ui/columns/specific/ScreeningLinkExtractor.java @@ -88,7 +88,7 @@ public class ScreeningLinkExtractor extends LinkExtractor return tryPrint(url); } - public static final String createFeatureVectorSummaryBrowserLink(String experimentPermId) + public static final String createExperimentAnalysisSummaryBrowserLink(String experimentPermId) { URLMethodWithParameters url = new URLMethodWithParameters(""); url.addParameter(BasicConstant.LOCATOR_ACTION_PARAMETER, FEATURE_VECTOR_SUMMARY_ACTION); diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/MaterialReplicaFeatureSummaryProvider.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/MaterialReplicaFeatureSummaryProvider.java index e8a3324832c..bcd8e51afe5 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/MaterialReplicaFeatureSummaryProvider.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/MaterialReplicaFeatureSummaryProvider.java @@ -88,7 +88,7 @@ class MaterialReplicaFeatureSummaryProvider extends builder.columnGroup(subgroup); } - if (rows.get(0).getTechnicalReplicates() != null) + if (rows.get(0).getDirectTechnicalReplicates() != null) { builder.columnGroup(DEFAULT_SUBGROUP); } @@ -111,7 +111,8 @@ class MaterialReplicaFeatureSummaryProvider extends builder.column(DEVIATION).addDouble(row.getFeatureVectorDeviation()); builder.column(RANK).addInteger((long) row.getFeatureVectorRank()); - MaterialBiologicalReplicateFeatureSummary defaultSubgroup = row.getTechnicalReplicates(); + MaterialBiologicalReplicateFeatureSummary defaultSubgroup = + row.getDirectTechnicalReplicates(); if (defaultSubgroup != null) { addSubgroup(builder, DEFAULT_SUBGROUP, "", defaultSubgroup); @@ -141,7 +142,9 @@ class MaterialReplicaFeatureSummaryProvider extends .withTitle(replicaColumnTitle).addDouble((double) featureValues[i]); } - if (false == DEFAULT_SUBGROUP.equals(groupId)) + // aggregates should be shown only for biological replicates which have more than one + // technical replicate + if (false == DEFAULT_SUBGROUP.equals(groupId) && featureValues.length > 1) { MaterialReplicaSummaryAggregationType aggregationType = subgroup.getSummaryAggregationType(); 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 ccc887bbf1f..672cee58449 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 @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.server.logic; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; import ch.rinn.restrictions.Private; @@ -77,8 +78,6 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS { return replicaRows; } - final List<MaterialBiologicalReplicateFeatureVector> backendSubgroups = - backendResult.getSubgroups(); float[] featureVectorDeviatons = backendResult.getGeneralSummary().getFeatureVectorDeviations(); @@ -99,18 +98,20 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS replicaRow.setFeatureVectorRank(featureVectorRanks[i]); replicaRow.setFeatureDescription(featureDescriptions.get(i)); - float[] defaultFeatureValues = extractFeatureValues(i, backendResult.getReplicas()); + float[] defaultFeatureValues = + extractFeatureValues(i, backendResult.getDirectTechnicalReplicates()); if (defaultFeatureValues != null) { MaterialBiologicalReplicateFeatureSummary defaultReplica = new MaterialBiologicalReplicateFeatureSummary(defaultFeatureValues, 0, MaterialReplicaSummaryAggregationType.MEDIAN); - replicaRow.setTechnicalReplicates(defaultReplica); + replicaRow.setDirectTechnicalReplicates(defaultReplica); } + final List<MaterialBiologicalReplicateFeatureVector> backendSubgroups = + backendResult.getBiologicalReplicates(); List<MaterialBiologicalReplicateFeatureSummary> subgroups = new ArrayList<MaterialBiologicalReplicateFeatureSummary>(); - replicaRow.setBiologicalRelicates(subgroups); for (int tmp = 0; tmp < backendSubgroups.size(); tmp++) { MaterialBiologicalReplicateFeatureVector backendGroup = backendSubgroups.get(tmp); @@ -122,6 +123,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS aggregatedSummaries[i], backendGroup.getSummaryAggregationType()); subgroups.add(subgroup); } + replicaRow.setBiologicalRelicates(subgroups); } return replicaRows; } @@ -135,7 +137,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS return subgroupLabels; } for (MaterialBiologicalReplicateFeatureVector backendSubgroup : backendResultOrNull - .getSubgroups()) + .getBiologicalReplicates()) { subgroupLabels.add(backendSubgroup.getSubgroupLabel()); } @@ -148,8 +150,8 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS float[] result = new float[replicas.size()]; for (int pos = 0; pos < result.length; pos++) { - float[] aggregatedValues = replicas.get(pos).getFeatueVector(); - result[pos] = aggregatedValues[i]; + float[] featureVector = replicas.get(pos).getFeatueVector(); + result[pos] = featureVector[i]; } return result; } @@ -191,15 +193,11 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS new ReplicateSequenceProvider(materialWells, settings.getBiologicalReplicatePropertyTypeCodes()); - List<MaterialBiologicalReplicateFeatureVector> subgroups = Collections.emptyList(); - List<MaterialTechnicalReplicateFeatureVector> replicas = Collections.emptyList(); - if (replicaSequences.hasNoBiologicalReplicates()) - { - replicas = createTechnicalReplicas(materialWells, replicaSequences); - } else - { - subgroups = createBiologicalReplicates(materialWells, replicaSequences); - } + List<MaterialBiologicalReplicateFeatureVector> subgroups = + createBiologicalReplicates(materialWells, replicaSequences); + List<MaterialTechnicalReplicateFeatureVector> replicas = + filterDirectTechnicalReplicas(materialWells, replicaSequences); + return new MaterialAllReplicasFeatureVectors(experimentWells.getFeatureDescriptions(), materialGeneralSummary, subgroups, replicas); } @@ -213,7 +211,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS List<MaterialBiologicalReplicateFeatureVector> subgroups = new ArrayList<MaterialBiologicalReplicateFeatureVector>(); MaterialReplicaSummaryAggregationType aggregationType = settings.getAggregationType(); - for (Integer biologicalReplicateSeq : replicaSequences.getBiologicalReplicateKeys()) + for (Integer biologicalReplicateSeq : replicaSequences.getBiologicalReplicateSequences()) { List<IWellData> technicalReplicateWells = biologicalReplicateMap.getOrDie(biologicalReplicateSeq); @@ -233,7 +231,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS WellReplicaSummaryCalculator.calculateSummaryFeatureVector(technicalReplicateWells, aggregationType); List<MaterialTechnicalReplicateFeatureVector> replicas = - createTechnicalReplicas(technicalReplicateWells, replicaSequences); + createTechnicalReplicates(technicalReplicateWells, replicaSequences); String subgroupLabel = getSubgroupLabel(technicalReplicateWells, replicaSequences); return new MaterialBiologicalReplicateFeatureVector(replicas, aggregatedSummary, aggregationType, subgroupLabel); @@ -246,7 +244,9 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS // all wells belong to the same subgroup, so it does not matter which one we take Sample well = subgroupWellDataList.get(0).getWell(); - return replicaSequences.getBiologicalReplicateLabel(well); + String label = replicaSequences.tryGetBiologicalReplicateLabel(well); + assert label != null : "no biological replicates!"; + return label; } private MaterialFeatureVectorSummary tryCalculateMaterialSummary(TechId materialId, @@ -257,14 +257,30 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS return tryFindMaterialSummary(materialId, featureSummaries); } - private static List<MaterialTechnicalReplicateFeatureVector> createTechnicalReplicas( - List<IWellData> materialWellDataList, ReplicateSequenceProvider replicaSequences) + // chooses wells which have no information about which biological replicate they are + private static List<MaterialTechnicalReplicateFeatureVector> filterDirectTechnicalReplicas( + List<IWellData> materialWellDataList, final ReplicateSequenceProvider replicaSequences) + { + List<IWellData> directTechnicalReplicas = + CollectionUtils.filter(materialWellDataList, new ICollectionFilter<IWellData>() + { + public boolean isPresent(IWellData element) + { + return replicaSequences.isBiologicalReplicate(element) == false; + } + }); + sortByTechnicalReplicateSequence(directTechnicalReplicas, replicaSequences); + return createTechnicalReplicates(directTechnicalReplicas, replicaSequences); + } + + private static List<MaterialTechnicalReplicateFeatureVector> createTechnicalReplicates( + List<IWellData> wells, final ReplicateSequenceProvider replicaSequences) { List<MaterialTechnicalReplicateFeatureVector> replicas = new ArrayList<MaterialTechnicalReplicateFeatureVector>(); - for (IWellData wellData : materialWellDataList) + for (IWellData wellData : wells) { - int replicaSequenceNumber = replicaSequences.getTechnicalReplicateSequenceNum(wellData); + int replicaSequenceNumber = replicaSequences.getTechnicalReplicateSequence(wellData); MaterialTechnicalReplicateFeatureVector featureVector = new MaterialTechnicalReplicateFeatureVector(replicaSequenceNumber, wellData.getFeatureVector()); @@ -273,6 +289,22 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS return replicas; } + private static void sortByTechnicalReplicateSequence(List<IWellData> materialWellDataList, + final ReplicateSequenceProvider replicaSequences) + { + Collections.sort(materialWellDataList, new Comparator<IWellData>() + { + public int compare(IWellData w1, IWellData w2) + { + Integer replicaSequenceNumber1 = + replicaSequences.getTechnicalReplicateSequence(w1); + Integer replicaSequenceNumber2 = + replicaSequences.getTechnicalReplicateSequence(w2); + return replicaSequenceNumber1.compareTo(replicaSequenceNumber2); + } + }); + } + private static List<IWellData> filterWellsByMaterial(List<IWellData> wellDataList, final TechId materialId) { @@ -295,7 +327,7 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS { public Integer getKey(IWellData wellData) { - return replicaSequences.tryGetBiologicalReplicateSequenceNum(wellData.getWell()); + return replicaSequences.tryGetBiologicalReplicateSequence(wellData.getWell()); } }); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ReplicateSequenceProvider.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ReplicateSequenceProvider.java index ba11ffca355..69d334ba5c0 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ReplicateSequenceProvider.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ReplicateSequenceProvider.java @@ -22,7 +22,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import ch.systemsx.cisd.common.collections.GroupByMap; import ch.systemsx.cisd.common.collections.IKeyExtractor; @@ -46,14 +45,15 @@ class ReplicateSequenceProvider public ReplicateSequenceProvider(List<? extends IEntityPropertiesHolder> replicaWells, List<String> biologicalReplicatePropertyTypeCodesOrNull) { - this.biologicalReplicatePropertyTypeCodesOrNull = biologicalReplicatePropertyTypeCodesOrNull; + this.biologicalReplicatePropertyTypeCodesOrNull = + biologicalReplicatePropertyTypeCodesOrNull; this.biologicalReplicateSeqMap = new LinkedHashMap<Double, Integer>(); this.technicalReplicateSeqMap = new LinkedHashMap<Long, Integer>(); GroupByMap<Double, IEntityPropertiesHolder> biologicalReplicates = groupByBiologicalReplicate(replicaWells); int biologicalReplicateSeq = 1; - for (Double biologicalReplicateKey : createSortedCopy(biologicalReplicates.getKeys())) + for (Double biologicalReplicateKey : biologicalReplicates.getKeys()) { if (biologicalReplicateKey != null) { @@ -70,7 +70,8 @@ class ReplicateSequenceProvider } } - public Collection<Integer> getBiologicalReplicateKeys() + /** @return sequences of biological replicas, all keys are not null. */ + public Collection<Integer> getBiologicalReplicateSequences() { return createSortedCopy(biologicalReplicateSeqMap.values()); } @@ -87,8 +88,14 @@ class ReplicateSequenceProvider }); } + /** @return true if this well has information about which biological replicate it is. */ + public boolean isBiologicalReplicate(IEntityPropertiesHolder well) + { + return tryFindSubgroup(well) != null; + } + /** Subgroup sequence, the same for all technical replicates of one biological replicate. */ - public Integer tryGetBiologicalReplicateSequenceNum(IEntityPropertiesHolder well) + public Integer tryGetBiologicalReplicateSequence(IEntityPropertiesHolder well) { Double subgroupKey = tryFindSubgroup(well); if (subgroupKey == null) @@ -103,7 +110,7 @@ class ReplicateSequenceProvider /** * Technical Replicate Sequence (unique in one biological replicate) */ - public int getTechnicalReplicateSequenceNum(IEntityPropertiesHolder well) + public int getTechnicalReplicateSequence(IEntityPropertiesHolder well) { return technicalReplicateSeqMap.get(well.getId()); } @@ -115,15 +122,13 @@ class ReplicateSequenceProvider return sortedKeys; } - public boolean hasNoBiologicalReplicates() + public String tryGetBiologicalReplicateLabel(IEntityPropertiesHolder well) { - Set<Double> keys = biologicalReplicateSeqMap.keySet(); - return keys.size() == 1 && keys.contains(null); - } - - public String getBiologicalReplicateLabel(IEntityPropertiesHolder well) - { - int biologicalReplicateSeq = tryGetBiologicalReplicateSequenceNum(well); + Integer biologicalReplicateSeq = tryGetBiologicalReplicateSequence(well); + if (biologicalReplicateSeq == null) + { + return null; + } IEntityProperty subgroupProperty = tryFindSubgroupProperty(well); assert subgroupProperty != null : "cannot fnd the subgroup property"; boolean isMaterialProperty = (subgroupProperty.getMaterial() != null); 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 99757e5a419..49a4459d5ff 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 @@ -169,8 +169,9 @@ public class WellContentLoader extends AbstractContentLoader ReplicateSequenceProvider replicaSequences) { int technicalReplicaSequenceNumber = - replicaSequences.getTechnicalReplicateSequenceNum(wellContent); - String biologicalReplicateLabel = replicaSequences.getBiologicalReplicateLabel(wellContent); + replicaSequences.getTechnicalReplicateSequence(wellContent); + String biologicalReplicateLabel = + replicaSequences.tryGetBiologicalReplicateLabel(wellContent); return new WellReplicaImage(wellContent, technicalReplicaSequenceNumber, biologicalReplicateLabel); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialAllReplicasFeatureVectors.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialAllReplicasFeatureVectors.java index 658782483fb..c509cde17e6 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialAllReplicasFeatureVectors.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/dto/MaterialAllReplicasFeatureVectors.java @@ -22,10 +22,10 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable private MaterialFeatureVectorSummary generalSummary; // NOTE: Can be empty. - private List<MaterialBiologicalReplicateFeatureVector> subgroups; + private List<MaterialBiologicalReplicateFeatureVector> biologicalReplicates; // NOTE: Can be empty. Used for replicas which have no subgroups - private List<MaterialTechnicalReplicateFeatureVector> replicas; + private List<MaterialTechnicalReplicateFeatureVector> directTechnicalReplicates; // GWT only @SuppressWarnings("unused") @@ -40,8 +40,8 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable { this.featureDescriptions = featureDescriptions; this.generalSummary = generalSummary; - this.subgroups = subgroups; - this.replicas = replicas; + this.biologicalReplicates = subgroups; + this.directTechnicalReplicates = replicas; } public List<CodeAndLabel> getFeatureDescriptions() @@ -54,14 +54,14 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable return generalSummary; } - public List<MaterialBiologicalReplicateFeatureVector> getSubgroups() + public List<MaterialBiologicalReplicateFeatureVector> getBiologicalReplicates() { - return subgroups; + return biologicalReplicates; } - public List<MaterialTechnicalReplicateFeatureVector> getReplicas() + public List<MaterialTechnicalReplicateFeatureVector> getDirectTechnicalReplicates() { - return replicas; + return directTechnicalReplicates; } } \ No newline at end of file diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialReplicaFeatureSummary.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialReplicaFeatureSummary.java index eb94e95da5d..a5e5d35e584 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialReplicaFeatureSummary.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/MaterialReplicaFeatureSummary.java @@ -96,12 +96,13 @@ public class MaterialReplicaFeatureSummary implements ISerializable this.biologicalRelicates = replicaSubgroups; } - public MaterialBiologicalReplicateFeatureSummary getTechnicalReplicates() + public MaterialBiologicalReplicateFeatureSummary getDirectTechnicalReplicates() { return technicalReplicates; } - public void setTechnicalReplicates(MaterialBiologicalReplicateFeatureSummary defaultReplica) + public void setDirectTechnicalReplicates( + MaterialBiologicalReplicateFeatureSummary defaultReplica) { this.technicalReplicates = defaultReplica; } diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoaderTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoaderTest.java index f966bad4db2..d347bdeac9d 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoaderTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/MaterialFeatureVectorSummaryLoaderTest.java @@ -95,7 +95,7 @@ public class MaterialFeatureVectorSummaryLoaderTest extends AssertJUnit assertEquals(featuresDesc, featureVectors.getFeatureDescriptions()); int groupId = 1; - for (MaterialBiologicalReplicateFeatureVector subgroup : featureVectors.getSubgroups()) + for (MaterialBiologicalReplicateFeatureVector subgroup : featureVectors.getBiologicalReplicates()) { switch (groupId) { -- GitLab