Skip to content
Snippets Groups Projects
Commit d791a88e authored by tpylak's avatar tpylak
Browse files

LMS-2190 show images in a grid, fix heights

SVN: 21159
parent e3e87a61
No related branches found
No related tags found
No related merge requests found
Showing
with 610 additions and 293 deletions
......@@ -47,6 +47,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
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.WellMetadata;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -119,7 +120,7 @@ public interface IScreeningClientService extends IClientService
* for the well, all but the first one are ignored. If there is no image dataset for the well,
* the whole well is ignored.
*/
public List<WellContent> listWellImages(TechId materialId, TechId experimentId)
public List<WellReplicaImage> listWellImages(TechId materialId, TechId experimentId)
throws UserFailureException;
/**
......
......@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
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.WellMetadata;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -96,7 +97,7 @@ public interface IScreeningClientServiceAsync extends IClientServiceAsync
* @see IScreeningClientService#listWellImages(TechId, TechId)
*/
public void listWellImages(TechId materialId, TechId experimentId,
AsyncCallback<List<WellContent>> callback);
AsyncCallback<List<WellReplicaImage>> callback);
/**
* @see IScreeningClientService#prepareExportPlateWells(TableExportCriteria)
......@@ -192,6 +193,7 @@ public interface IScreeningClientServiceAsync extends IClientServiceAsync
IResultSetConfig<String, TableModelRowWithObject<MaterialReplicaFeatureSummary>> resultSetConfig,
TechId experimentId, TechId materialId,
AsyncCallback<TypedTableResultSet<MaterialReplicaFeatureSummary>> callback);
/**
* @see IScreeningClientService#prepareExportMaterialReplicaFeatureSummary(TableExportCriteria)
*/
......
......@@ -59,9 +59,7 @@ public class LogicalImageViewer
{
private static final String NO_IMAGES_AVAILABLE_MSG = "No images available";
private static final int ONE_IMAGE_WIDTH_PX = 200;
private static final int ONE_IMAGE_HEIGHT_PX = 120;
private static final int ONE_IMAGE_SIZE_PX = 120;
private static final int CHANNEL_SPLITER_AND_LABEL_HEIGHT_PX = 120;
......@@ -161,7 +159,8 @@ public class LogicalImageViewer
private int getSeriesImageWidgetHeight()
{
return CHANNEL_SPLITER_AND_LABEL_HEIGHT_PX + getImageHeight(logicalImageReference)
return CHANNEL_SPLITER_AND_LABEL_HEIGHT_PX
+ getImageHeight(ONE_IMAGE_SIZE_PX, logicalImageReference)
* logicalImageReference.getTileRowsNum();
}
......@@ -176,8 +175,8 @@ public class LogicalImageViewer
String sessionId = getSessionId(viewContext);
setAdjustColorsButtonState(adjustColorsButton,
channelReferences.getChannelCodes());
int imageWidth = getImageWidth(logicalImageReference);
int imageHeight = getImageHeight(logicalImageReference);
int imageWidth = getImageWidth(ONE_IMAGE_SIZE_PX, logicalImageReference);
int imageHeight = getImageHeight(ONE_IMAGE_SIZE_PX, logicalImageReference);
return LogicalImageSeriesGrid.create(sessionId, channelStackImages,
channelReferences, imageWidth, imageHeight);
}
......@@ -288,7 +287,7 @@ public class LogicalImageViewer
setAdjustColorsButtonState(adjustColorsButton,
channelReferences.getChannelCodes());
String sessionId = getSessionId(viewContext);
return createTilesGrid(channelReferences, sessionId);
return createTilesGrid(channelReferences, sessionId, ONE_IMAGE_SIZE_PX, true);
}
};
......@@ -340,17 +339,18 @@ public class LogicalImageViewer
return "true".equals(viewContext.getPropertyOrNull("image-viewer-enabled"));
}
private static LayoutContainer createTilesGrid(LogicalImageChannelsReference channelReferences,
String sessionId)
/** Creates a widget with a representative image of the specified logical image. */
public static LayoutContainer createTilesGrid(LogicalImageChannelsReference channelReferences,
String sessionId, int imageSizePx, boolean createImageLinks)
{
LogicalImageReference images = channelReferences.getBasicImage();
return createTilesGrid(channelReferences, sessionId, getImageWidth(images),
getImageHeight(images), true);
return createTilesGrid(channelReferences, sessionId, getImageWidth(imageSizePx, images),
getImageHeight(imageSizePx, images), createImageLinks);
}
/** Creates a widget with a representative image of the specified logical image. */
public static LayoutContainer createTilesGrid(LogicalImageChannelsReference channelReferences,
String sessionId, int imageWidth, int imageHeight, boolean createImageLinks)
private static LayoutContainer createTilesGrid(LogicalImageChannelsReference channelReferences,
String sessionId, int logicalImageWidth, int logicalImageHeight,
boolean createImageLinks)
{
LogicalImageReference images = channelReferences.getBasicImage();
LayoutContainer container = new LayoutContainer(new TableLayout(images.getTileColsNum()));
......@@ -359,7 +359,7 @@ public class LogicalImageViewer
for (int col = 1; col <= images.getTileColsNum(); col++)
{
ImageUrlUtils.addImageUrlWidget(container, sessionId, channelReferences, row, col,
imageWidth, imageHeight, createImageLinks);
logicalImageWidth, logicalImageHeight, createImageLinks);
}
}
return container;
......@@ -389,16 +389,16 @@ public class LogicalImageViewer
return viewContext.getModel().getSessionContext().getSessionID();
}
private static int getImageHeight(LogicalImageReference images)
private static int getImageHeight(int imageSizePx, LogicalImageReference images)
{
float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
return (int) (ONE_IMAGE_HEIGHT_PX * imageSizeMultiplyFactor);
return (int) (imageSizePx * imageSizeMultiplyFactor);
}
private static int getImageWidth(LogicalImageReference images)
private static int getImageWidth(int imageSizePx, LogicalImageReference images)
{
float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
return (int) (ONE_IMAGE_WIDTH_PX * imageSizeMultiplyFactor);
return (int) (imageSizePx * imageSizeMultiplyFactor);
}
private static float getImageSizeMultiplyFactor(LogicalImageReference images)
......
......@@ -16,7 +16,12 @@
package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.extjs.gxt.ui.client.Style.Orientation;
......@@ -30,6 +35,7 @@ import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.Viewport;
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;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Widget;
......@@ -58,8 +64,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.d
import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ui.columns.specific.ScreeningLinkExtractor;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
/**
* A viewer that comprises several UI elements to produce a holistic UI for material replica feature
......@@ -69,7 +75,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellImage;
*/
public class MaterialReplicaFeatureSummaryViewer
{
private static final int WELL_IMAGES_SIZE_PX = 400;
private static final int ONE_IMAGE_SIZE_PX = 80;
public static void openTab(IViewContext<IScreeningClientServiceAsync> screeningViewContext,
String experimentPermId, MaterialIdentifier materialIdentifier)
......@@ -196,7 +202,7 @@ public class MaterialReplicaFeatureSummaryViewer
};
}
private class ImagesFoundCallback extends AbstractAsyncCallback<List<WellContent>>
private class ImagesFoundCallback extends AbstractAsyncCallback<List<WellReplicaImage>>
{
private final LayoutContainer panel;
......@@ -207,14 +213,14 @@ public class MaterialReplicaFeatureSummaryViewer
}
@Override
protected void process(List<WellContent> images)
protected void process(List<WellReplicaImage> images)
{
panel.add(createImagesViewer(images));
panel.add(createImagePanel(images));
panel.layout();
}
}
private Widget createImagesViewer(List<? extends WellImage> images)
private Widget createImagePanel(List<WellReplicaImage> images)
{
if (images.isEmpty())
{
......@@ -226,27 +232,161 @@ public class MaterialReplicaFeatureSummaryViewer
ChannelChooserPanel channelChooser = new ChannelChooserPanel(defaultChannelState);
LayoutContainer panel = new LayoutContainer();
panel.setLayout(new RowLayout());
Html headingWidget = createHeader("<br><br><hr>" + "Images" + "<br><br>");
panel.add(headingWidget, new RowData(1, -1));
panel.add(new Html("<br>"), new RowData(1, -1));
panel.add(channelChooser);
LayoutContainer imagePanel = new LayoutContainer();
imagePanel.setScrollMode(Scroll.AUTOY);
imagePanel.setLayout(new RowLayout());
int imageSize = Math.min(100, WELL_IMAGES_SIZE_PX / images.size());
for (WellImage wellImage : images)
Map<String, List<WellReplicaImage>> labelToReplicasMap = createSortedImageMap(images);
String orphanGroupKey = null;
List<WellReplicaImage> orphanTechnicalReplicates = labelToReplicasMap.get(orphanGroupKey);
if (orphanTechnicalReplicates != null)
{
panel.add(createOrphanTechnicalReplicatesPanel(orphanTechnicalReplicates,
channelChooser));
labelToReplicasMap.remove(orphanGroupKey);
}
panel.add(createBiologicalReplicatesImagesPanel(labelToReplicasMap, channelChooser));
if (screeningViewContext.isSimpleOrEmbeddedMode() == false)
{
Widget imageViewer = createImageViewer(wellImage, channelChooser, imageSize);
imagePanel.add(imageViewer);
// 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);
}
// TODO 2011-04-12, Tomasz Pylak: correct the height
double imagePanelHeight = Math.min(500, images.size() * imageSize + 150);
panel.add(imagePanel, new RowData(1, imagePanelHeight));
return panel;
}
private Widget createImageViewer(final WellImage image, ChannelChooserPanel channelChooser,
final int imageSize)
private Widget createOrphanTechnicalReplicatesPanel(
List<WellReplicaImage> orphanTechnicalReplicates, ChannelChooserPanel channelChooser)
{
LayoutContainer imagePanel = new LayoutContainer();
for (WellReplicaImage image : orphanTechnicalReplicates)
{
LayoutContainer imageWithLabel = new LayoutContainer();
imageWithLabel.setLayout(new RowLayout());
Widget label =
createTechnicalReplicateLabel(image.getTechnicalReplicateSequenceNumber());
imageWithLabel.add(label);
Widget imageViewer = createImageViewer(image.getWellImage(), channelChooser);
imageWithLabel.add(imageViewer);
imagePanel.add(imageWithLabel);
}
return imagePanel;
}
private LayoutContainer createBiologicalReplicatesImagesPanel(
Map<String, List<WellReplicaImage>> labelToReplicasMap,
ChannelChooserPanel channelChooser)
{
int maxReplicaNumber = calcMaxReplicaNumber(labelToReplicasMap);
LayoutContainer imagePanel = new LayoutContainer();
TableLayout layout = new TableLayout(maxReplicaNumber + 1);
layout.setBorder(1);
imagePanel.setLayout(layout);
addImageTableHeader(maxReplicaNumber, imagePanel);
List<String> sortedLabels = sortCopy(labelToReplicasMap.keySet());
for (String label : sortedLabels)
{
List<WellReplicaImage> sortedTechnicalReplicates = labelToReplicasMap.get(label);
imagePanel.add(new Text(label));
for (int i = 0; i < maxReplicaNumber; i++)
{
if (i < sortedTechnicalReplicates.size())
{
WellImage wellImage = sortedTechnicalReplicates.get(i).getWellImage();
Widget imageViewer = createImageViewer(wellImage, channelChooser);
imagePanel.add(imageViewer);
} else
{
imagePanel.add(createEmptyBox());
}
}
}
return imagePanel;
}
private static List<String> sortCopy(Set<String> values)
{
List<String> sorted = new ArrayList<String>(values);
Collections.sort(sorted);
return sorted;
}
private void addImageTableHeader(int maxReplicaNumber, LayoutContainer imagePanel)
{
for (int i = 0; i <= maxReplicaNumber; i++)
{
if (i == 0)
{
imagePanel.add(createEmptyBox());
} else
{
imagePanel.add(createTechnicalReplicateLabel(i));
}
}
}
private Widget createTechnicalReplicateLabel(int technicalReplicateSequence)
{
return new Text("repl. " + technicalReplicateSequence);
}
private Widget createEmptyBox()
{
return new Text();
}
private static int calcMaxReplicaNumber(Map<String, List<WellReplicaImage>> labelToReplicasMap)
{
int max = 0;
for (List<WellReplicaImage> technicalReplicates : labelToReplicasMap.values())
{
max = Math.max(max, technicalReplicates.size());
}
return max;
}
private static Map<String/* label */, List<WellReplicaImage>> createSortedImageMap(
List<WellReplicaImage> images)
{
Map<String, List<WellReplicaImage>> map = new HashMap<String, List<WellReplicaImage>>();
for (WellReplicaImage image : images)
{
String label = image.tryGetBiologicalReplicateLabel();
List<WellReplicaImage> technicalReplicas = map.get(label);
if (technicalReplicas == null)
{
technicalReplicas = new ArrayList<WellReplicaImage>();
}
technicalReplicas.add(image);
map.put(label, technicalReplicas);
}
sortTechnicalReplicas(map);
return map;
}
private static void sortTechnicalReplicas(Map<String, List<WellReplicaImage>> map)
{
for (List<WellReplicaImage> technicalReplicas : map.values())
{
Collections.sort(technicalReplicas, new Comparator<WellReplicaImage>()
{
public int compare(WellReplicaImage arg1, WellReplicaImage arg2)
{
Integer s1 = arg1.getTechnicalReplicateSequenceNumber();
Integer s2 = arg2.getTechnicalReplicateSequenceNumber();
return s1.compareTo(s2);
}
});
}
}
private Widget createImageViewer(final WellImage image, ChannelChooserPanel channelChooser)
{
assert image.tryGetImageDataset() != null;
final ISimpleChanneledViewerFactory viewerFactory = new ISimpleChanneledViewerFactory()
......@@ -254,7 +394,7 @@ public class MaterialReplicaFeatureSummaryViewer
public Widget create(List<String> channels)
{
return WellContentDialog.createImageViewerForChannel(screeningViewContext,
image, imageSize, imageSize, channels);
image, ONE_IMAGE_SIZE_PX, channels);
}
};
ChannelWidgetWithListener widgetWithListener = new ChannelWidgetWithListener(viewerFactory);
......@@ -271,6 +411,7 @@ public class MaterialReplicaFeatureSummaryViewer
{
final LayoutContainer panel = new Viewport();
panel.setLayout(new RowLayout(Orientation.VERTICAL));
panel.setScrollMode(Scroll.AUTOY);
final Widget northPanel = createNorth(screeningViewContext, experiment, material);
panel.add(northPanel);
......@@ -278,8 +419,8 @@ public class MaterialReplicaFeatureSummaryViewer
final IDisposableComponent gridComponent =
MaterialReplicaFeatureSummaryGrid.create(screeningViewContext, new TechId(
experiment), new TechId(material));
// TODO 2011-04-13, Tomasz Pylak: fix height
panel.add(gridComponent.getComponent(), new RowData(1, 400));
// 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));
screeningViewContext.getService().listWellImages(new TechId(material.getId()),
new TechId(experiment.getId()), new ImagesFoundCallback(panel));
......@@ -339,6 +480,14 @@ public class MaterialReplicaFeatureSummaryViewer
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;
}
private static String getMaterialType(Material material)
{
String materialTypeCode = material.getMaterialType().getCode();
......@@ -352,14 +501,6 @@ public class MaterialReplicaFeatureSummaryViewer
return ("" + text.charAt(0)).toUpperCase() + text.substring(1).toLowerCase();
}
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;
}
private static String getMaterialName(Material material)
{
if (material.getEntityType().getCode()
......@@ -393,9 +534,8 @@ public class MaterialReplicaFeatureSummaryViewer
{
public void onClick(ClickEvent event)
{
// TODO KE: ugly, ugly, ugly !!! We bind ourselves with
// TODO KE: We bind ourselves with
// the implementation of the other view instead of relying on the browser
// report a refactoring JIRA
FeatureVectorSummaryViewer.openTab(viewContext, experiment.getPermId());
}
}, linkUrl);
......
......@@ -136,7 +136,7 @@ public class WellContentDialog extends Dialog
*/
public static Widget createImageViewerForChannel(
final IViewContext<IScreeningClientServiceAsync> viewContext,
final WellImage wellImage, int imageWidthPx, int imageHeightPx, List<String> channels)
final WellImage wellImage, int imageSizePx, List<String> channels)
{
final ImageDatasetEnrichedReference imageDataset = tryGetImageDataset(wellImage);
if (imageDataset == null)
......@@ -162,8 +162,8 @@ public class WellContentDialog extends Dialog
LogicalImageChannelsReference channelReferences =
LogicalImageChannelsReference.createWithoutOverlays(wellImages, channels);
LayoutContainer staticTilesGrid =
LogicalImageViewer.createTilesGrid(channelReferences, sessionId, imageWidthPx,
imageHeightPx, createImageLinks);
LogicalImageViewer.createTilesGrid(channelReferences, sessionId, imageSizePx,
createImageLinks);
if (imageParameters.isMultidimensional())
{
......
......@@ -104,9 +104,7 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
private static final String CHOOSE_ONE_EXPERIMENT_TEXT = "Choose one experiment...";
private static final int IMAGE_WIDTH_PX = 200;
private static final int IMAGE_HEIGHT_PX = 120;
private static final int IMAGE_SIZE_PX = 80;
// by experiment perm id
public static void openTab(
......@@ -679,8 +677,7 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
public Widget create(List<String> channels)
{
return WellContentDialog.createImageViewerForChannel(
viewContext, entity, IMAGE_WIDTH_PX,
IMAGE_HEIGHT_PX, channels);
viewContext, entity, IMAGE_SIZE_PX, channels);
}
};
ChannelWidgetWithListener widgetWithListener =
......
......@@ -32,7 +32,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.TypedTableModelBuilder;
import ch.systemsx.cisd.openbis.plugin.screening.shared.IScreeningServer;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaFeatureSummaryResult;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaSubgroupFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialBiologicalReplicateFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaSummaryAggregationType;
/**
......@@ -68,14 +68,14 @@ class MaterialReplicaFeatureSummaryProvider extends
TypedTableModelBuilder<MaterialReplicaFeatureSummary> builder =
new TypedTableModelBuilder<MaterialReplicaFeatureSummary>();
MaterialReplicaFeatureSummaryResult replicaResult =
server.getFeatureVectorReplicaSummary(sessionToken, experimentId, materialId);
server.getMaterialFeatureVectorSummary(sessionToken, experimentId, materialId);
builder.addColumn(FEATURE);
builder.addColumn(MEDIAN).withDataType(DataTypeCode.REAL);
builder.addColumn(DEVIATION).withDataType(DataTypeCode.REAL);
builder.addColumn(RANK).withDataType(DataTypeCode.INTEGER);
List<MaterialReplicaFeatureSummary> rows = replicaResult.getReplicaSummaries();
List<MaterialReplicaFeatureSummary> rows = replicaResult.getFeatureSummaries();
List<String> subgroupLabels = replicaResult.getSubgroupLabels();
if (rows.isEmpty())
{
......@@ -88,7 +88,7 @@ class MaterialReplicaFeatureSummaryProvider extends
builder.columnGroup(subgroup);
}
if (rows.get(0).getDefaultSubgroup() != null)
if (rows.get(0).getTechnicalReplicates() != null)
{
builder.columnGroup(DEFAULT_SUBGROUP);
}
......@@ -111,24 +111,24 @@ class MaterialReplicaFeatureSummaryProvider extends
builder.column(DEVIATION).addDouble(row.getFeatureVectorDeviation());
builder.column(RANK).addInteger((long) row.getFeatureVectorRank());
MaterialReplicaSubgroupFeatureSummary defaultSubgroup = row.getDefaultSubgroup();
MaterialBiologicalReplicateFeatureSummary defaultSubgroup = row.getTechnicalReplicates();
if (defaultSubgroup != null)
{
addSubgroup(builder, DEFAULT_SUBGROUP, "", defaultSubgroup);
}
int numSubgroups = subgroupLabels.size();
List<MaterialReplicaSubgroupFeatureSummary> subgroups = row.getReplicaSubgroups();
List<MaterialBiologicalReplicateFeatureSummary> subgroups = row.getBiologicalRelicates();
for (int i = 0; i < numSubgroups; i++)
{
String subgroupLabel = subgroupLabels.get(i);
MaterialReplicaSubgroupFeatureSummary subgroup = subgroups.get(i);
MaterialBiologicalReplicateFeatureSummary subgroup = subgroups.get(i);
addSubgroup(builder, subgroupLabel, subgroupLabel, subgroup);
}
}
private void addSubgroup(TypedTableModelBuilder<MaterialReplicaFeatureSummary> builder,
String groupId, String groupLabel, MaterialReplicaSubgroupFeatureSummary subgroup)
String groupId, String groupLabel, MaterialBiologicalReplicateFeatureSummary subgroup)
{
IColumnGroup columnGroup = builder.columnGroup(groupId);
......
......@@ -67,6 +67,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConst
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.WellMetadata;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -212,7 +213,7 @@ public final class ScreeningClientService extends AbstractClientService implemen
return prepareExportEntities(criteria);
}
public List<WellContent> listWellImages(TechId materialId, TechId experimentId)
public List<WellReplicaImage> listWellImages(TechId materialId, TechId experimentId)
throws UserFailureException
{
return server.listWellImages(getSessionToken(), materialId, experimentId);
......@@ -355,6 +356,7 @@ public final class ScreeningClientService extends AbstractClientService implemen
materialId);
return listEntities(provider, resultSetConfig);
}
public String prepareExportFeatureVectorSummary(
TableExportCriteria<TableModelRowWithObject<MaterialFeatureVectorSummary>> criteria)
throws UserFailureException
......
......@@ -102,6 +102,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
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.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -204,12 +205,12 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
materialCriteria);
}
public List<WellContent> listWellImages(String sessionToken, TechId materialId,
public List<WellReplicaImage> listWellImages(String sessionToken, TechId materialId,
TechId experimentId)
{
Session session = getSession(sessionToken);
return WellContentLoader.loadWithImages(session, businessObjectFactory, getDAOFactory(),
materialId, experimentId);
materialId, experimentId, createDefaultSettings());
}
public List<Material> listMaterials(String sessionToken, WellSearchCriteria materialCriteria)
......@@ -311,11 +312,11 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
settings.setAggregationType(MaterialReplicaSummaryAggregationType.MEDIAN);
settings.setFeatureCodes(new ArrayList<String>());
settings.setReplicaMatrialTypePatterns(ScreeningConstants.REPLICA_METERIAL_TYPE_PATTERN);
settings.setSubgroupPropertyTypeCodes("CONCENTRATION", "SIRNA");
settings.setBiologicalReplicatePropertyTypeCodes("CONCENTRATION", "SIRNA");
return settings;
}
public MaterialReplicaFeatureSummaryResult getFeatureVectorReplicaSummary(String sessionToken,
public MaterialReplicaFeatureSummaryResult getMaterialFeatureVectorSummary(String sessionToken,
TechId experimentId, TechId materialId)
{
Session session = getSession(sessionToken);
......
......@@ -62,6 +62,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -118,7 +119,7 @@ final class ScreeningServerLogger extends AbstractServerLogger implements IScree
return null;
}
public List<WellContent> listWellImages(String sessionToken, TechId materialId,
public List<WellReplicaImage> listWellImages(String sessionToken, TechId materialId,
TechId experimentId)
{
logAccess(sessionToken, "listWellImages", "material(%s) experiment(%s)", materialId,
......@@ -352,7 +353,7 @@ final class ScreeningServerLogger extends AbstractServerLogger implements IScree
return null;
}
public MaterialReplicaFeatureSummaryResult getFeatureVectorReplicaSummary(String sessionToken,
public MaterialReplicaFeatureSummaryResult getMaterialFeatureVectorSummary(String sessionToken,
TechId experimentId, TechId materialId)
{
logAccess(sessionToken, "getFeatureVectorReplicaSummary",
......
......@@ -17,10 +17,8 @@
package ch.systemsx.cisd.openbis.plugin.screening.server.logic;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import ch.rinn.restrictions.Private;
import ch.systemsx.cisd.common.collections.CollectionUtils;
......@@ -30,26 +28,25 @@ 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.basic.dto.CodeAndLabel;
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.Sample;
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.logic.dto.IWellData;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialAllReplicasFeatureVectors;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialReplicaSubgroupFeatureVector;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialSingleReplicaFeatureVector;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialBiologicalReplicateFeatureVector;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.MaterialTechnicalReplicateFeatureVector;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto.WellDataCollection;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialBiologicalReplicateFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialFeatureVectorSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaFeatureSummaryResult;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaSubgroupFeatureSummary;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplicaSummaryAggregationType;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialSummarySettings;
/**
* Loads feature vectors (details and statistics) for the specified material in the specified
* experiment.
* For the specified material in the specified experiment loads feature vectors (details and
* statistics).<br>
* Considers only one dataset of a particular type per plate.
*
* @author Tomasz Pylak
*/
......@@ -62,35 +59,27 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
IScreeningBusinessObjectFactory businessObjectFactory, IDAOFactory daoFactory,
TechId materialId, TechId experimentId, MaterialSummarySettings settings)
{
MaterialAllReplicasFeatureVectors result =
MaterialAllReplicasFeatureVectors resultOrNull =
new MaterialFeatureVectorSummaryLoader(session, businessObjectFactory, daoFactory,
settings).tryLoadMaterialFeatureVectors(materialId, experimentId);
if (result == null)
{
return createEmptyMaterialReplicaFeatureSummaryResult();
}
return convert(result);
}
private static MaterialReplicaFeatureSummaryResult createEmptyMaterialReplicaFeatureSummaryResult()
{
return new MaterialReplicaFeatureSummaryResult(new ArrayList<String>(),
new ArrayList<MaterialReplicaFeatureSummary>());
List<MaterialReplicaFeatureSummary> replicaRows = convertToFeatureRows(resultOrNull);
List<String> subgroupLabels = tryGetSubgroupLabels(resultOrNull);
return new MaterialReplicaFeatureSummaryResult(subgroupLabels, replicaRows);
}
private static MaterialReplicaFeatureSummaryResult convert(
private static List<MaterialReplicaFeatureSummary> convertToFeatureRows(
MaterialAllReplicasFeatureVectors backendResult)
{
List<String> subgroupLabels = new ArrayList<String>();
final List<MaterialReplicaSubgroupFeatureVector> backendSubgroups =
backendResult.getSubgroups();
for (MaterialReplicaSubgroupFeatureVector backendSubgroup : backendSubgroups)
List<MaterialReplicaFeatureSummary> replicaRows =
new ArrayList<MaterialReplicaFeatureSummary>();
if (backendResult == null)
{
subgroupLabels.add(backendSubgroup.getSubgroupLabel());
return replicaRows;
}
final List<MaterialBiologicalReplicateFeatureVector> backendSubgroups =
backendResult.getSubgroups();
List<MaterialReplicaFeatureSummary> replicaRows =
new ArrayList<MaterialReplicaFeatureSummary>();
float[] featureVectorDeviatons =
backendResult.getGeneralSummary().getFeatureVectorDeviations();
float[] featureVectorSummaries =
......@@ -113,41 +102,54 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
float[] defaultFeatureValues = extractFeatureValues(i, backendResult.getReplicas());
if (defaultFeatureValues != null)
{
MaterialReplicaSubgroupFeatureSummary defaultReplica =
new MaterialReplicaSubgroupFeatureSummary(defaultFeatureValues, 0,
MaterialBiologicalReplicateFeatureSummary defaultReplica =
new MaterialBiologicalReplicateFeatureSummary(defaultFeatureValues, 0,
MaterialReplicaSummaryAggregationType.MEDIAN);
replicaRow.setDefaultSubgroup(defaultReplica);
replicaRow.setTechnicalReplicates(defaultReplica);
}
List<MaterialReplicaSubgroupFeatureSummary> subgroups =
new ArrayList<MaterialReplicaSubgroupFeatureSummary>();
replicaRow.setReplicaSubgroups(subgroups);
List<MaterialBiologicalReplicateFeatureSummary> subgroups =
new ArrayList<MaterialBiologicalReplicateFeatureSummary>();
replicaRow.setBiologicalRelicates(subgroups);
for (int tmp = 0; tmp < backendSubgroups.size(); tmp++)
{
MaterialReplicaSubgroupFeatureVector backendGroup = backendSubgroups.get(tmp);
MaterialBiologicalReplicateFeatureVector backendGroup = backendSubgroups.get(tmp);
final float[] aggregatedSummaries = backendGroup.getAggregatedSummary();
float[] featureValues =
extractFeatureValues(i, backendGroup.getSingleReplicaValues());
MaterialReplicaSubgroupFeatureSummary subgroup =
new MaterialReplicaSubgroupFeatureSummary(featureValues,
extractFeatureValues(i, backendGroup.getTechnicalReplicatesValues());
MaterialBiologicalReplicateFeatureSummary subgroup =
new MaterialBiologicalReplicateFeatureSummary(featureValues,
aggregatedSummaries[i], backendGroup.getSummaryAggregationType());
subgroups.add(subgroup);
}
}
return replicaRows;
}
return new MaterialReplicaFeatureSummaryResult(subgroupLabels, replicaRows);
private static List<String> tryGetSubgroupLabels(
MaterialAllReplicasFeatureVectors backendResultOrNull)
{
List<String> subgroupLabels = new ArrayList<String>();
if (backendResultOrNull == null)
{
return subgroupLabels;
}
for (MaterialBiologicalReplicateFeatureVector backendSubgroup : backendResultOrNull
.getSubgroups())
{
subgroupLabels.add(backendSubgroup.getSubgroupLabel());
}
return subgroupLabels;
}
private static float[] extractFeatureValues(int i,
List<MaterialSingleReplicaFeatureVector> replicas)
List<MaterialTechnicalReplicateFeatureVector> replicas)
{
float[] result = new float[replicas.size()];
for (int pos = 0; pos < result.length; pos++)
{
float[] aggregatedValues = replicas.get(pos).getFeatueVectorSummary();
float[] aggregatedValues = replicas.get(pos).getFeatueVector();
result[pos] = aggregatedValues[i];
}
return result;
}
......@@ -165,165 +167,112 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
private MaterialAllReplicasFeatureVectors tryLoadMaterialFeatureVectors(TechId materialId,
TechId experimentId)
{
WellDataCollection wellDataCollection = tryLoadWellData(experimentId);
if (wellDataCollection == null)
WellDataCollection experimentWells = tryLoadWellData(experimentId);
if (experimentWells == null)
{
return null;
}
return tryLoadMaterialFeatureVectors(materialId, wellDataCollection);
return tryLoadMaterialFeatureVectors(materialId, experimentWells);
}
@Private
MaterialAllReplicasFeatureVectors tryLoadMaterialFeatureVectors(TechId materialId,
WellDataCollection wellDataCollection)
WellDataCollection experimentWells)
{
MaterialFeatureVectorSummary materialGeneralSummary =
tryCalculateMaterialSummary(materialId, wellDataCollection);
tryCalculateMaterialSummary(materialId, experimentWells);
if (materialGeneralSummary == null)
{
return null;
}
List<IWellData> materialWellDataList =
filterWellsByMaterial(wellDataCollection.getWellDataList(), materialId);
GroupByMap<Double, IWellData> subgroupMap = groupBySubgroup(materialWellDataList);
List<MaterialReplicaSubgroupFeatureVector> subgroups = Collections.emptyList();
List<MaterialSingleReplicaFeatureVector> replicas = Collections.emptyList();
if (hasNoSubgroups(subgroupMap))
List<IWellData> materialWells =
filterWellsByMaterial(experimentWells.getWellDataList(), materialId);
ReplicateSequenceProvider replicaSequences =
new ReplicateSequenceProvider(materialWells,
settings.getBiologicalReplicatePropertyTypeCodes());
List<MaterialBiologicalReplicateFeatureVector> subgroups = Collections.emptyList();
List<MaterialTechnicalReplicateFeatureVector> replicas = Collections.emptyList();
if (replicaSequences.hasNoBiologicalReplicates())
{
replicas = createReplicas(materialWellDataList);
replicas = createTechnicalReplicas(materialWells, replicaSequences);
} else
{
subgroups = createSubgroups(subgroupMap);
subgroups = createBiologicalReplicates(materialWells, replicaSequences);
}
return new MaterialAllReplicasFeatureVectors(wellDataCollection.getFeatureDescriptions(),
return new MaterialAllReplicasFeatureVectors(experimentWells.getFeatureDescriptions(),
materialGeneralSummary, subgroups, replicas);
}
private List<MaterialReplicaSubgroupFeatureVector> createSubgroups(
GroupByMap<Double, IWellData> subgroupMap)
private List<MaterialBiologicalReplicateFeatureVector> createBiologicalReplicates(
List<IWellData> materialWells, ReplicateSequenceProvider replicaSequences)
{
List<MaterialReplicaSubgroupFeatureVector> subgroups =
new ArrayList<MaterialReplicaSubgroupFeatureVector>();
GroupByMap<Integer, IWellData> biologicalReplicateMap =
groupByBiologicalReplicate(materialWells, replicaSequences);
List<MaterialBiologicalReplicateFeatureVector> subgroups =
new ArrayList<MaterialBiologicalReplicateFeatureVector>();
MaterialReplicaSummaryAggregationType aggregationType = settings.getAggregationType();
int subgroupSequenceNumber = 1;
Collection<Double> sortedKeys = sortSubgroupKeys(subgroupMap.getKeys());
for (Double subgroupKey : sortedKeys)
for (Integer biologicalReplicateSeq : replicaSequences.getBiologicalReplicateKeys())
{
if (subgroupKey != null)
{
List<IWellData> subgroupWellDataList = subgroupMap.getOrDie(subgroupKey);
MaterialReplicaSubgroupFeatureVector subgroup =
createSubgroup(subgroupWellDataList, subgroupSequenceNumber,
aggregationType);
subgroups.add(subgroup);
subgroupSequenceNumber++;
}
List<IWellData> technicalReplicateWells =
biologicalReplicateMap.getOrDie(biologicalReplicateSeq);
MaterialBiologicalReplicateFeatureVector subgroup =
createBiologicalReplicate(technicalReplicateWells, replicaSequences,
aggregationType);
subgroups.add(subgroup);
}
return subgroups;
}
private static Collection<Double> sortSubgroupKeys(Set<Double> keys)
{
ArrayList<Double> sortedKeys = new ArrayList<Double>(keys);
Collections.sort(sortedKeys);
return sortedKeys;
}
private MaterialReplicaSubgroupFeatureVector createSubgroup(
List<IWellData> subgroupWellDataList, int subgroupSequenceNumber,
private MaterialBiologicalReplicateFeatureVector createBiologicalReplicate(
List<IWellData> technicalReplicateWells, ReplicateSequenceProvider replicaSequences,
MaterialReplicaSummaryAggregationType aggregationType)
{
float[] aggregatedSummary =
WellReplicaSummaryCalculator.calculateSummaryFeatureVector(subgroupWellDataList,
WellReplicaSummaryCalculator.calculateSummaryFeatureVector(technicalReplicateWells,
aggregationType);
List<MaterialSingleReplicaFeatureVector> replicas = createReplicas(subgroupWellDataList);
String subgroupLabel = getSubgroupLabel(subgroupWellDataList, subgroupSequenceNumber);
return new MaterialReplicaSubgroupFeatureVector(replicas, aggregatedSummary,
List<MaterialTechnicalReplicateFeatureVector> replicas =
createTechnicalReplicas(technicalReplicateWells, replicaSequences);
String subgroupLabel = getSubgroupLabel(technicalReplicateWells, replicaSequences);
return new MaterialBiologicalReplicateFeatureVector(replicas, aggregatedSummary,
aggregationType, subgroupLabel);
}
private String getSubgroupLabel(List<IWellData> subgroupWellDataList, int subgroupSequenceNumber)
private String getSubgroupLabel(List<IWellData> subgroupWellDataList,
ReplicateSequenceProvider replicaSequences)
{
assert subgroupWellDataList.size() > 0 : "empty subgroup";
// all wells belong to the same subgroup, so it does not matter which one we take
Sample well = subgroupWellDataList.get(0).getWell();
IEntityProperty subgroupProperty = tryFindSubgroupProperty(well);
assert subgroupProperty != null : "cannot fnd the subgroup property";
String propertyLabel = subgroupProperty.getPropertyType().getLabel();
Material subgroupMaterial = subgroupProperty.getMaterial();
if (subgroupMaterial != null)
{
return propertyLabel + " " + subgroupSequenceNumber;
} else
{
return propertyLabel + " " + subgroupProperty.tryGetAsString();
}
}
/**
* A subgroup can be e.g. oligo or compound concentration.
*/
private GroupByMap<Double, IWellData> groupBySubgroup(List<IWellData> materialWellDataList)
{
return GroupByMap.create(materialWellDataList, new IKeyExtractor<Double, IWellData>()
{
public Double getKey(IWellData wellData)
{
return tryFindSubgroup(wellData.getWell());
}
});
}
private Double tryFindSubgroup(Sample well)
{
IEntityProperty subgroupProperty = tryFindSubgroupProperty(well);
if (subgroupProperty == null)
{
return null;
}
return tryExtractSubgroupValue(subgroupProperty);
}
private IEntityProperty tryFindSubgroupProperty(Sample well)
{
List<String> subgroupPropertyTypeCodes = settings.getSubgroupPropertyTypeCodes();
if (subgroupPropertyTypeCodes == null)
{
return null;
}
return tryFindProperty(well.getProperties(), subgroupPropertyTypeCodes);
return replicaSequences.getBiologicalReplicateLabel(well);
}
private MaterialFeatureVectorSummary tryCalculateMaterialSummary(TechId materialId,
WellDataCollection wellDataCollection)
WellDataCollection experimentWellDataList)
{
List<MaterialFeatureVectorSummary> featureSummaries =
calculateReplicasFeatureVectorSummaries(wellDataCollection);
calculateReplicasFeatureVectorSummaries(experimentWellDataList);
return tryFindMaterialSummary(materialId, featureSummaries);
}
private static List<MaterialSingleReplicaFeatureVector> createReplicas(
List<IWellData> materialWellDataList)
private static List<MaterialTechnicalReplicateFeatureVector> createTechnicalReplicas(
List<IWellData> materialWellDataList, ReplicateSequenceProvider replicaSequences)
{
List<MaterialSingleReplicaFeatureVector> replicas =
new ArrayList<MaterialSingleReplicaFeatureVector>();
int replicaSequenceNumber = 1;
List<MaterialTechnicalReplicateFeatureVector> replicas =
new ArrayList<MaterialTechnicalReplicateFeatureVector>();
for (IWellData wellData : materialWellDataList)
{
MaterialSingleReplicaFeatureVector featureVector =
new MaterialSingleReplicaFeatureVector(replicaSequenceNumber++,
int replicaSequenceNumber = replicaSequences.getTechnicalReplicateSequenceNum(wellData);
MaterialTechnicalReplicateFeatureVector featureVector =
new MaterialTechnicalReplicateFeatureVector(replicaSequenceNumber,
wellData.getFeatureVector());
replicas.add(featureVector);
}
return replicas;
}
private static boolean hasNoSubgroups(GroupByMap<Double, IWellData> subgroupMap)
{
return subgroupMap.getKeys().size() == 1 && subgroupMap.getKeys().contains(null);
}
private static List<IWellData> filterWellsByMaterial(List<IWellData> wellDataList,
final TechId materialId)
{
......@@ -336,6 +285,21 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
});
}
/**
* A subgroup can be e.g. oligo or compound concentration.
*/
private GroupByMap<Integer, IWellData> groupByBiologicalReplicate(
List<IWellData> materialWellDataList, final ReplicateSequenceProvider replicaSequences)
{
return GroupByMap.create(materialWellDataList, new IKeyExtractor<Integer, IWellData>()
{
public Integer getKey(IWellData wellData)
{
return replicaSequences.tryGetBiologicalReplicateSequenceNum(wellData.getWell());
}
});
}
private static MaterialFeatureVectorSummary tryFindMaterialSummary(TechId materialId,
List<MaterialFeatureVectorSummary> featureSummaries)
{
......@@ -348,33 +312,4 @@ public class MaterialFeatureVectorSummaryLoader extends ExperimentFeatureVectorS
}
return null;
}
private static Double tryExtractSubgroupValue(IEntityProperty subgroupProperty)
{
Material subgroupMaterial = subgroupProperty.getMaterial();
if (subgroupMaterial != null)
{
return new Double(subgroupMaterial.getId());
}
try
{
return new Double(subgroupProperty.tryGetAsString());
} catch (NumberFormatException ex)
{
return null;
}
}
private static IEntityProperty tryFindProperty(List<IEntityProperty> properties,
List<String> subgroupPropertyTypeCodes)
{
for (IEntityProperty property : properties)
{
if (subgroupPropertyTypeCodes.contains(property.getPropertyType().getCode()))
{
return property;
}
}
return null;
}
}
/*
* 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.logic;
import java.util.ArrayList;
import java.util.Collection;
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;
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.Material;
/**
* Provides sequence numbers for technical and biological well replicates for a fixed material.
*
* @author Tomasz Pylak
*/
class ReplicateSequenceProvider
{
private final List<String> biologicalReplicatePropertyTypeCodesOrNull;
private final Map<Double/* subgroup key */, Integer/* biological replicate sequence number */> biologicalReplicateSeqMap;
private final Map<Long/* well id */, Integer/* technical replicate sequence number */> technicalReplicateSeqMap;
public ReplicateSequenceProvider(List<? extends IEntityPropertiesHolder> replicaWells,
List<String> 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()))
{
if (biologicalReplicateKey != null)
{
biologicalReplicateSeqMap.put(biologicalReplicateKey, biologicalReplicateSeq++);
}
int technicalReplicateSeq = 1;
List<IEntityPropertiesHolder> technicalReplicates =
biologicalReplicates.getOrDie(biologicalReplicateKey);
for (IEntityPropertiesHolder technicalReplicate : technicalReplicates)
{
technicalReplicateSeqMap.put(technicalReplicate.getId(), technicalReplicateSeq++);
}
}
}
public Collection<Integer> getBiologicalReplicateKeys()
{
return createSortedCopy(biologicalReplicateSeqMap.values());
}
private GroupByMap<Double, IEntityPropertiesHolder> groupByBiologicalReplicate(
List<? extends IEntityPropertiesHolder> wells)
{
return GroupByMap.create(wells, new IKeyExtractor<Double, IEntityPropertiesHolder>()
{
public Double getKey(IEntityPropertiesHolder well)
{
return tryFindSubgroup(well);
}
});
}
/** Subgroup sequence, the same for all technical replicates of one biological replicate. */
public Integer tryGetBiologicalReplicateSequenceNum(IEntityPropertiesHolder well)
{
Double subgroupKey = tryFindSubgroup(well);
if (subgroupKey == null)
{
return null;
}
Integer seqNum = biologicalReplicateSeqMap.get(subgroupKey);
assert seqNum != null : "no biological replicate found for " + subgroupKey;
return seqNum;
}
/**
* Technical Replicate Sequence (unique in one biological replicate)
*/
public int getTechnicalReplicateSequenceNum(IEntityPropertiesHolder well)
{
return technicalReplicateSeqMap.get(well.getId());
}
private static <T extends Comparable<T>> Collection<T> createSortedCopy(Collection<T> keys)
{
ArrayList<T> sortedKeys = new ArrayList<T>(keys);
Collections.sort(sortedKeys);
return sortedKeys;
}
public boolean hasNoBiologicalReplicates()
{
Set<Double> keys = biologicalReplicateSeqMap.keySet();
return keys.size() == 1 && keys.contains(null);
}
public String getBiologicalReplicateLabel(IEntityPropertiesHolder well)
{
int biologicalReplicateSeq = tryGetBiologicalReplicateSequenceNum(well);
IEntityProperty subgroupProperty = tryFindSubgroupProperty(well);
assert subgroupProperty != null : "cannot fnd the subgroup property";
boolean isMaterialProperty = (subgroupProperty.getMaterial() != null);
String propertyLabel = subgroupProperty.getPropertyType().getLabel();
if (isMaterialProperty)
{
return propertyLabel + " " + biologicalReplicateSeq;
} else
{
return propertyLabel + " " + subgroupProperty.tryGetAsString();
}
}
private Double tryFindSubgroup(IEntityPropertiesHolder well)
{
IEntityProperty subgroupProperty = tryFindSubgroupProperty(well);
if (subgroupProperty == null)
{
return null;
}
return tryExtractSubgroupValue(subgroupProperty);
}
private IEntityProperty tryFindSubgroupProperty(IEntityPropertiesHolder well)
{
if (biologicalReplicatePropertyTypeCodesOrNull == null)
{
return null;
}
return tryFindProperty(well.getProperties(), biologicalReplicatePropertyTypeCodesOrNull);
}
private static Double tryExtractSubgroupValue(IEntityProperty subgroupProperty)
{
Material subgroupMaterial = subgroupProperty.getMaterial();
if (subgroupMaterial != null)
{
return new Double(subgroupMaterial.getId());
}
try
{
return new Double(subgroupProperty.tryGetAsString());
} catch (NumberFormatException ex)
{
return null;
}
}
private static IEntityProperty tryFindProperty(List<IEntityProperty> properties,
List<String> subgroupPropertyTypeCodes)
{
for (IEntityProperty property : properties)
{
if (subgroupPropertyTypeCodes.contains(property.getPropertyType().getCode()))
{
return property;
}
}
return null;
}
}
\ No newline at end of file
......@@ -65,10 +65,12 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetReferen
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.ImageDatasetParameters;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialSummarySettings;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.NamedFeatureVector;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellFeatureVectorReference;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria.ExperimentSearchCriteria;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria.MaterialSearchCodesCriteria;
......@@ -138,28 +140,59 @@ public class WellContentLoader extends AbstractContentLoader
* for the well, all but the first one are ignored. If there is no image dataset for the well,
* the whole well is ignored.
*/
public static List<WellContent> loadWithImages(Session session,
public static List<WellReplicaImage> loadWithImages(Session session,
IScreeningBusinessObjectFactory businessObjectFactory, IDAOFactory daoFactory,
TechId materialId, TechId experimentId)
TechId materialId, TechId experimentId, MaterialSummarySettings settings)
{
WellContentLoader loader =
new WellContentLoader(session, businessObjectFactory, daoFactory);
List<WellContent> locations = loader.loadLocations(materialId, experimentId.getId());
return loader.enrichWithSingleImageDatasets(locations);
locations = loader.enrichWithSingleImageDatasets(locations);
return annotateWithReplicaLabels(locations, settings);
}
private static List<WellReplicaImage> annotateWithReplicaLabels(
List<WellContent> wellsWithImages, MaterialSummarySettings settings)
{
ReplicateSequenceProvider replicaSequences =
new ReplicateSequenceProvider(wellsWithImages,
settings.getBiologicalReplicatePropertyTypeCodes());
List<WellReplicaImage> wellReplicaImages = new ArrayList<WellReplicaImage>();
for (WellContent wellContent : wellsWithImages)
{
wellReplicaImages.add(annotateWithReplicaLabels(wellContent, replicaSequences));
}
return wellReplicaImages;
}
private static WellReplicaImage annotateWithReplicaLabels(WellContent wellContent,
ReplicateSequenceProvider replicaSequences)
{
int technicalReplicaSequenceNumber =
replicaSequences.getTechnicalReplicateSequenceNum(wellContent);
String biologicalReplicateLabel = replicaSequences.getBiologicalReplicateLabel(wellContent);
return new WellReplicaImage(wellContent, technicalReplicaSequenceNumber,
biologicalReplicateLabel);
}
private List<WellContent> enrichWithSingleImageDatasets(List<WellContent> locations)
{
HCSImageDatasetLoader datasetsRetriever =
createImageDatasetsRetriever(extractPlates(locations));
Set<PlateIdentifier> plateIdentifiers = extractPlates(locations);
Map<Long, DatasetImagesReference> plateToDatasetReferenceMap =
loadPlateToSingleImageDatasetMap(plateIdentifiers);
return enrichWithSingleImageDatasets(locations, plateToDatasetReferenceMap);
}
private Map<Long, DatasetImagesReference> loadPlateToSingleImageDatasetMap(
Set<PlateIdentifier> plateIdentifiers)
{
HCSImageDatasetLoader datasetsRetriever = createImageDatasetsRetriever(plateIdentifiers);
Collection<ExternalData> imageDatasets = datasetsRetriever.getImageDatasets();
if (imageDatasets.isEmpty())
{
return Collections.emptyList();
return new HashMap<Long, DatasetImagesReference>();
}
Map<Long, DatasetImagesReference> plateToDatasetReferenceMap =
createPlateToSingleDatasetReferenceMap(imageDatasets);
return enrichWithSingleImageDatasets(locations, plateToDatasetReferenceMap);
return createPlateToSingleDatasetReferenceMap(imageDatasets);
}
/** Note: locations without a corresponding image dataset are removed */
......
......@@ -16,6 +16,7 @@
package ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
import ch.systemsx.cisd.openbis.plugin.screening.server.logic.WellReplicaSummaryCalculator;
......@@ -26,7 +27,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.server.logic.WellReplicaSummary
*
* @author Tomasz Pylak
*/
public interface IWellData
public interface IWellData extends IEntityPropertiesHolder
{
/** @return feature vector for the well */
float[] getFeatureVector();
......
......@@ -22,10 +22,10 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable
private MaterialFeatureVectorSummary generalSummary;
// NOTE: Can be empty.
private List<MaterialReplicaSubgroupFeatureVector> subgroups;
private List<MaterialBiologicalReplicateFeatureVector> subgroups;
// NOTE: Can be empty. Used for replicas which have no subgroups
private List<MaterialSingleReplicaFeatureVector> replicas;
private List<MaterialTechnicalReplicateFeatureVector> replicas;
// GWT only
@SuppressWarnings("unused")
......@@ -35,8 +35,8 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable
public MaterialAllReplicasFeatureVectors(List<CodeAndLabel> featureDescriptions,
MaterialFeatureVectorSummary generalSummary,
List<MaterialReplicaSubgroupFeatureVector> subgroups,
List<MaterialSingleReplicaFeatureVector> replicas)
List<MaterialBiologicalReplicateFeatureVector> subgroups,
List<MaterialTechnicalReplicateFeatureVector> replicas)
{
this.featureDescriptions = featureDescriptions;
this.generalSummary = generalSummary;
......@@ -54,12 +54,12 @@ public class MaterialAllReplicasFeatureVectors implements ISerializable
return generalSummary;
}
public List<MaterialReplicaSubgroupFeatureVector> getSubgroups()
public List<MaterialBiologicalReplicateFeatureVector> getSubgroups()
{
return subgroups;
}
public List<MaterialSingleReplicaFeatureVector> getReplicas()
public List<MaterialTechnicalReplicateFeatureVector> getReplicas()
{
return replicas;
}
......
......@@ -12,11 +12,11 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.MaterialReplic
*
* @author Tomasz Pylak
*/
public class MaterialReplicaSubgroupFeatureVector implements ISerializable
public class MaterialBiologicalReplicateFeatureVector implements ISerializable
{
private static final long serialVersionUID = ServiceVersionHolder.VERSION;
private List<MaterialSingleReplicaFeatureVector> singleReplicaValues;
private List<MaterialTechnicalReplicateFeatureVector> technicalReplicatesValues;
// e.g. average or median of all replica values in this supgroup
// This is the aggregation of a subgroup of replicas for e.g. the same SIRNA
......@@ -29,24 +29,24 @@ public class MaterialReplicaSubgroupFeatureVector implements ISerializable
// GWT only
@SuppressWarnings("unused")
private MaterialReplicaSubgroupFeatureVector()
private MaterialBiologicalReplicateFeatureVector()
{
}
public MaterialReplicaSubgroupFeatureVector(
List<MaterialSingleReplicaFeatureVector> singleReplicaValues,
public MaterialBiologicalReplicateFeatureVector(
List<MaterialTechnicalReplicateFeatureVector> singleReplicaValues,
float[] aggregatedSummary,
MaterialReplicaSummaryAggregationType summaryAggregationType, String subgroupLabel)
{
this.singleReplicaValues = singleReplicaValues;
this.technicalReplicatesValues = singleReplicaValues;
this.aggregatedSummary = aggregatedSummary;
this.summaryAggregationType = summaryAggregationType;
this.subgroupLabel = subgroupLabel;
}
public List<MaterialSingleReplicaFeatureVector> getSingleReplicaValues()
public List<MaterialTechnicalReplicateFeatureVector> getTechnicalReplicatesValues()
{
return singleReplicaValues;
return technicalReplicatesValues;
}
public float[] getAggregatedSummary()
......
......@@ -24,34 +24,35 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
*
* @author Tomasz Pylak
*/
public class MaterialSingleReplicaFeatureVector implements ISerializable
public class MaterialTechnicalReplicateFeatureVector implements ISerializable
{
private static final long serialVersionUID = ServiceVersionHolder.VERSION;
private int replicaSequenceNumber;
private int technicalReplicateSequenceNumber;
private float[] featueVectorSummary;
private float[] featueVector;
// GWT only
@SuppressWarnings("unused")
private MaterialSingleReplicaFeatureVector()
private MaterialTechnicalReplicateFeatureVector()
{
}
public MaterialSingleReplicaFeatureVector(int replicaSequenceNumber, float[] featueVectorSummary)
public MaterialTechnicalReplicateFeatureVector(int technicalReplicateSequenceNumber,
float[] featueVector)
{
this.replicaSequenceNumber = replicaSequenceNumber;
this.featueVectorSummary = featueVectorSummary;
this.technicalReplicateSequenceNumber = technicalReplicateSequenceNumber;
this.featueVector = featueVector;
}
public int getReplicaSequenceNumber()
public int getTechnicalReplicateSequenceNumber()
{
return replicaSequenceNumber;
return technicalReplicateSequenceNumber;
}
public float[] getFeatueVectorSummary()
public float[] getFeatueVector()
{
return featueVectorSummary;
return featueVector;
}
}
......@@ -17,7 +17,9 @@
package ch.systemsx.cisd.openbis.plugin.screening.server.logic.dto;
import java.util.Arrays;
import java.util.List;
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.Sample;
......@@ -70,4 +72,14 @@ public class WellData implements IWellData
return "repl " + replicaId + ": " + Arrays.toString(featureVector);
}
public List<IEntityProperty> getProperties()
{
return well.getProperties();
}
public Long getId()
{
return well.getId();
}
}
......@@ -55,6 +55,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.PlateImages;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellReplicaImage;
import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria;
/**
......@@ -121,7 +122,7 @@ public interface IScreeningServer extends IServer
*/
@Transactional(readOnly = true)
@RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
public List<WellContent> listWellImages(String sessionToken, TechId materialId,
public List<WellReplicaImage> listWellImages(String sessionToken, TechId materialId,
@AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId);
/**
......@@ -223,7 +224,7 @@ public interface IScreeningServer extends IServer
*/
@Transactional(readOnly = true)
@RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
public MaterialReplicaFeatureSummaryResult getFeatureVectorReplicaSummary(String sessionToken,
public MaterialReplicaFeatureSummaryResult getMaterialFeatureVectorSummary(String sessionToken,
@AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId,
TechId materialId);
}
......@@ -22,10 +22,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
/**
* @author Kaloyan Enimanev
*/
public class MaterialReplicaSubgroupFeatureSummary implements ISerializable
public class MaterialBiologicalReplicateFeatureSummary implements ISerializable
{
private static final long serialVersionUID = ServiceVersionHolder.VERSION;
// i-th element is the value for (i+1) technical replicate
private float[] featureValues;
// e.g. average or median of all replica values in this subgroup
......@@ -39,11 +40,11 @@ public class MaterialReplicaSubgroupFeatureSummary implements ISerializable
// GWT only
@SuppressWarnings("unused")
private MaterialReplicaSubgroupFeatureSummary()
private MaterialBiologicalReplicateFeatureSummary()
{
}
public MaterialReplicaSubgroupFeatureSummary(float[] featureValues, float aggregatedSummary,
public MaterialBiologicalReplicateFeatureSummary(float[] featureValues, float aggregatedSummary,
MaterialReplicaSummaryAggregationType summaryAggregationType)
{
this.featureValues = featureValues;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment