/*
* Copyright (C) 2006-2014 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.formats;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import ome.model.IEnum;
import ome.model.IObject;
import ome.model.acquisition.Detector;
import ome.model.acquisition.DetectorSettings;
import ome.model.acquisition.Dichroic;
import ome.model.acquisition.Filter;
import ome.model.acquisition.FilterSet;
import ome.model.acquisition.ImagingEnvironment;
import ome.model.acquisition.Instrument;
import ome.model.acquisition.Laser;
import ome.model.acquisition.LightPath;
import ome.model.acquisition.LightSettings;
import ome.model.acquisition.LightSource;
import ome.model.acquisition.Microscope;
import ome.model.acquisition.OTF;
import ome.model.acquisition.Objective;
import ome.model.acquisition.ObjectiveSettings;
import ome.model.acquisition.StageLabel;
import ome.model.annotations.Annotation;
import ome.model.annotations.FileAnnotation;
import ome.model.containers.Dataset;
import ome.model.core.Channel;
import ome.model.core.Image;
import ome.model.core.LogicalChannel;
import ome.model.core.OriginalFile;
import ome.model.core.Pixels;
import ome.model.core.PlaneInfo;
import ome.model.enums.Format;
import ome.model.experiment.Experiment;
import ome.model.experiment.MicrobeamManipulation;
import ome.model.fs.Fileset;
import ome.model.fs.FilesetJobLink;
import ome.model.roi.Roi;
import ome.model.roi.Shape;
import ome.model.screen.Plate;
import ome.model.screen.Reagent;
import ome.model.screen.Screen;
import ome.model.screen.Well;
import ome.model.screen.WellSample;
import ome.model.screen.PlateAcquisition;
import ome.model.stats.StatsInfo;
import ome.system.ServiceFactory;
import ome.conditions.ApiUsageException;
import ome.conditions.ValidationException;
import ome.util.LSID;
import ome.util.SqlAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.perf4j.slf4j.Slf4JStopWatch;
import org.perf4j.StopWatch;
/**
* An OMERO metadata store. This particular metadata store requires the user to
* be logged into OMERO prior to use with the
* {@link ome.security.SecuritySystem#login(ome.system.Principal)} method. While
* attempts have been made to allow the caller to switch back and forth between
* Images and Pixels during metadata population it is <b>strongly</b>
* encouraged that at least Images and Pixels are populated in ascending order.
* For example: Image_1 --> Pixels_1, Pixels_2 followed by Image_2 --> Pixels_1,
* Pixels2, Pixels_3.
*
* @author Brian W. Loranger brain at lifesci.dundee.ac.uk
* @author Chris Allan callan at blackcat.ca
*/
public class OMEROMetadataStore
{
/** List of graphics domains we are checking.*/
private static String[] DOMAINS = {"jpeg", "png", "bmp", "gif", "tiff", "avi"};
/** Logger for this class. */
private static Logger log = LoggerFactory.getLogger(OMEROMetadataStore.class);
/** OMERO service factory; all other services are retrieved from here. */
private ServiceFactory sf;
private SqlAction sql;
/** A map of imageIndex vs. Image object ordered by first access. */
private Map<Integer, Image> imageList =
new LinkedHashMap<Integer, Image>();
/** A map of pixelsIndex vs. Pixels object ordered by first access. */
private Map<Integer, Pixels> pixelsList =
new LinkedHashMap<Integer, Pixels>();
/** A map of screenIndex vs. Screen object ordered by first access. */
private Map<Integer, Screen> screenList =
new LinkedHashMap<Integer, Screen>();
/** A map of plateIndex vs. Plate object ordered by first access. */
private Map<Integer, Plate> plateList =
new LinkedHashMap<Integer, Plate>();
/** A map of roiIndex vs. ROI object ordered by first access. */
private Map<Integer, Roi> roiList =
new LinkedHashMap<Integer, Roi>();
/** A map of wellIndex vs. Well object ordered by first access. */
private Map<Integer, Map<Integer, Well>> wellList =
new LinkedHashMap<Integer, Map<Integer, Well>>();
/** A map of instrumentIndex vs. Instrument object ordered by first access. */
private Map<Integer, Instrument> instrumentList =
new LinkedHashMap<Integer, Instrument>();
/** A map of experimentIndex vs. Experiment object ordered by first access. */
private Map<Integer, Experiment> experimentList =
new LinkedHashMap<Integer, Experiment>();
/**
* A map of Instrument vs. a map of otfIndex vs. OTF object ordered by
* first access.
*/
private Map<Instrument, Map<Integer, OTF>> otfList =
new LinkedHashMap<Instrument, Map<Integer, OTF>>();
/** A list of all objects we've received from the client and their LSIDs. */
private Map<LSID, IObject> lsidMap = new HashMap<LSID, IObject>();
/**
* Updates a given model object in our object graph.
* @param lsid LSID of model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should are used to describe the model
* object's graph location.
*/
public void updateObject(String lsid, IObject sourceObject,
Map<String, Integer> indexes)
{
lsidMap.put(new LSID(lsid), sourceObject);
if (sourceObject instanceof Image)
{
handle(lsid, (Image) sourceObject, indexes);
}
else if (sourceObject instanceof StageLabel)
{
handle(lsid, (StageLabel) sourceObject, indexes);
}
else if (sourceObject instanceof Pixels)
{
handle(lsid, (Pixels) sourceObject, indexes);
}
else if (sourceObject instanceof Channel)
{
handle(lsid, (Channel) sourceObject, indexes);
}
else if (sourceObject instanceof LogicalChannel)
{
handle(lsid, (LogicalChannel) sourceObject, indexes);
}
else if (sourceObject instanceof PlaneInfo)
{
handle(lsid, (PlaneInfo) sourceObject, indexes);
}
else if (sourceObject instanceof Instrument)
{
handle(lsid, (Instrument) sourceObject, indexes);
}
else if (sourceObject instanceof Microscope)
{
handle(lsid, (Microscope) sourceObject, indexes);
}
else if (sourceObject instanceof Objective)
{
handle(lsid, (Objective) sourceObject, indexes);
}
else if (sourceObject instanceof Detector)
{
handle(lsid, (Detector) sourceObject, indexes);
}
else if (sourceObject instanceof Dichroic)
{
handle(lsid, (Dichroic) sourceObject, indexes);
}
else if (sourceObject instanceof Filter)
{
handle(lsid, (Filter) sourceObject, indexes);
}
else if (sourceObject instanceof FilterSet)
{
handle(lsid, (FilterSet) sourceObject, indexes);
}
else if (sourceObject instanceof LightSource)
{
handle(lsid, (LightSource) sourceObject, indexes);
}
else if (sourceObject instanceof OTF)
{
handle(lsid, (OTF) sourceObject, indexes);
}
else if (sourceObject instanceof ImagingEnvironment)
{
handle(lsid, (ImagingEnvironment) sourceObject, indexes);
}
else if (sourceObject instanceof DetectorSettings)
{
handle(lsid, (DetectorSettings) sourceObject, indexes);
}
else if (sourceObject instanceof LightSettings)
{
handle(lsid, (LightSettings) sourceObject, indexes);
}
else if (sourceObject instanceof ObjectiveSettings)
{
handle(lsid, (ObjectiveSettings) sourceObject, indexes);
}
else if (sourceObject instanceof LightPath)
{
handle(lsid, (LightPath) sourceObject, indexes);
}
else if (sourceObject instanceof Screen)
{
handle(lsid, (Screen) sourceObject, indexes);
}
else if (sourceObject instanceof Plate)
{
handle(lsid, (Plate) sourceObject, indexes);
}
else if (sourceObject instanceof PlateAcquisition)
{
handle(lsid, (PlateAcquisition) sourceObject, indexes);
}
else if (sourceObject instanceof Well)
{
handle(lsid, (Well) sourceObject, indexes);
}
else if (sourceObject instanceof Reagent)
{
handle(lsid, (Reagent) sourceObject, indexes);
}
else if (sourceObject instanceof WellSample)
{
handle(lsid, (WellSample) sourceObject, indexes);
}
else if (sourceObject instanceof OriginalFile)
{
handle(lsid, (OriginalFile) sourceObject, indexes);
}
else if (sourceObject instanceof Annotation)
{
handle(lsid, (Annotation) sourceObject, indexes);
}
else if (sourceObject instanceof Experiment)
{
handle(lsid, (Experiment) sourceObject, indexes);
}
else if (sourceObject instanceof MicrobeamManipulation)
{
handle(lsid, (MicrobeamManipulation) sourceObject, indexes);
}
else if (sourceObject instanceof Roi)
{
handle(lsid, (Roi) sourceObject, indexes);
}
else if (sourceObject instanceof Shape)
{
handle(lsid, (Shape) sourceObject, indexes);
}
else
{
throw new ApiUsageException(
"Missing object handler for object type: "
+ sourceObject.getClass());
}
}
/**
* Updates our object graph references.
* @param referenceCache Client side LSID reference cache.
*/
public void updateReferences(Map<String, String[]> referenceCache)
{
// This function is mostly processing back-refrences. e.g. If the OME Schema
// has a AnnotationRef in ROI the referenceObject is Annotation and the
// targetObject is ROI.
for (String target : referenceCache.keySet())
{
for (String reference : referenceCache.get(target))
{
LSID targetLSID = new LSID(target);
IObject targetObject = lsidMap.get(targetLSID);
LSID referenceLSID = new LSID(reference);
IObject referenceObject = lsidMap.get(
new LSID(stripCustomSuffix(reference)));
log.debug(String.format(
"Updating reference handler for %s(%s) --> %s(%s).",
reference, referenceObject, target, targetObject));
if (targetObject instanceof DetectorSettings)
{
if (referenceObject instanceof Detector)
{
handleReference((DetectorSettings) targetObject,
(Detector) referenceObject);
continue;
}
}
else if (targetObject instanceof Image)
{
if (referenceObject instanceof Instrument)
{
handleReference((Image) targetObject,
(Instrument) referenceObject);
continue;
}
if (referenceObject instanceof Annotation)
{
handleReference((Image) targetObject,
(Annotation) referenceObject);
continue;
}
if (referenceObject instanceof Roi)
{
handleReference((Image) targetObject,
(Roi) referenceObject);
continue;
}
if (referenceObject instanceof Experiment)
{
handleReference((Image) targetObject,
(Experiment) referenceObject);
continue;
}
if (referenceObject instanceof MicrobeamManipulation)
{
handleReference((Image) targetObject,
(MicrobeamManipulation) referenceObject);
continue;
}
if (referenceLSID.toString().contains("DatasetI"))
{
int colonIndex = reference.indexOf(":");
long datasetId = Long.parseLong(
reference.substring(colonIndex + 1));
referenceObject = new Dataset(datasetId, false);
handleReference((Image) targetObject,
(Dataset) referenceObject);
continue;
}
}
else if (targetObject instanceof PlaneInfo)
{
if (referenceObject instanceof Annotation) {
handleReference((PlaneInfo) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof LightSource)
{
if (referenceObject instanceof LightSource)
{
handleReference((LightSource) targetObject,
(LightSource) referenceObject);
continue;
}
if (referenceObject instanceof Annotation) {
handleReference((LightSource) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Detector)
{
if (referenceObject instanceof Annotation) {
handleReference((Detector) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Dichroic)
{
if (referenceObject instanceof Annotation) {
handleReference((Dichroic) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Filter)
{
if (referenceObject instanceof Annotation) {
handleReference((Filter) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Instrument)
{
if (referenceObject instanceof Annotation) {
handleReference((Instrument) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Objective)
{
if (referenceObject instanceof Annotation) {
handleReference((Objective) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Shape)
{
if (referenceObject instanceof Annotation) {
handleReference((Shape) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof LightSettings)
{
if (referenceObject instanceof LightSource)
{
handleReference((LightSettings) targetObject,
(LightSource) referenceObject);
continue;
}
}
else if (targetObject instanceof LightPath)
{
if (referenceObject instanceof Dichroic)
{
handleReference((LightPath) targetObject,
(Dichroic) referenceObject);
continue;
}
if (referenceObject instanceof Filter)
{
handleReference((LightPath) targetObject,
(Filter) referenceObject, referenceLSID);
continue;
}
if (referenceObject instanceof Annotation) {
handleReference((LightPath) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Channel)
{
if (referenceObject instanceof OTF)
{
handleReference((Channel) targetObject,
(OTF) referenceObject);
continue;
}
if (referenceObject instanceof Annotation) {
handleReference((Channel) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof LogicalChannel)
{
if (referenceObject instanceof Filter)
{
handleReference((LogicalChannel) targetObject,
(Filter) referenceObject,
referenceLSID);
continue;
}
if (referenceObject instanceof FilterSet)
{
handleReference((LogicalChannel) targetObject,
(FilterSet) referenceObject);
continue;
}
}
else if (targetObject instanceof OTF)
{
if (referenceObject instanceof Objective)
{
handleReference((OTF) targetObject,
(Objective) referenceObject);
continue;
}
if (referenceObject instanceof FilterSet)
{
handleReference((OTF) targetObject,
(FilterSet) referenceObject);
continue;
}
}
else if (targetObject instanceof ObjectiveSettings)
{
if (referenceObject instanceof Objective)
{
handleReference((ObjectiveSettings) targetObject,
(Objective) referenceObject);
continue;
}
}
else if (targetObject instanceof WellSample)
{
if (referenceObject instanceof Image)
{
handleReference((WellSample) targetObject,
(Image) referenceObject);
continue;
}
}
else if (targetObject instanceof PlateAcquisition)
{
if (referenceObject instanceof WellSample)
{
handleReference((PlateAcquisition) targetObject,
(WellSample) referenceObject);
continue;
}
if (referenceObject instanceof Annotation)
{
handleReference((PlateAcquisition) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Pixels)
{
if (referenceObject instanceof OriginalFile)
{
handleReference((Pixels) targetObject,
(OriginalFile) referenceObject);
continue;
}
}
else if (targetObject instanceof FilterSet)
{
if (referenceObject instanceof Filter)
{
handleReference((FilterSet) targetObject,
(Filter) referenceObject,
referenceLSID);
continue;
}
if (referenceObject instanceof Dichroic)
{
handleReference((FilterSet) targetObject,
(Dichroic) referenceObject);
continue;
}
}
else if (targetObject instanceof Plate)
{
if (referenceLSID.toString().contains("ScreenI"))
{
int colonIndex = reference.indexOf(":");
long screenId = Long.parseLong(
reference.substring(colonIndex + 1));
referenceObject = new Screen(screenId, false);
handleReference((Plate) targetObject,
(Screen) referenceObject);
continue;
}
if (referenceObject instanceof Screen)
{
handleReference((Plate) targetObject,
(Screen) referenceObject);
continue;
}
if (referenceObject instanceof Annotation)
{
handleReference((Plate) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Screen)
{
if (referenceObject instanceof Plate)
{
handleReference((Screen) targetObject,
(Plate) referenceObject);
continue;
}
if (referenceObject instanceof Annotation) {
handleReference((Screen) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof Well)
{
if (referenceObject instanceof Reagent)
{
handleReference((Well) targetObject,
(Reagent) referenceObject);
continue;
}
}
else if (targetObject instanceof Reagent)
{
if (referenceObject instanceof Annotation) {
handleReference((Reagent) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof FileAnnotation)
{
if (referenceObject instanceof OriginalFile)
{
handleReference((FileAnnotation) targetObject,
(OriginalFile) referenceObject);
continue;
}
}
else if (targetObject instanceof Annotation)
{
if (referenceObject instanceof Annotation)
{
handleReference((Annotation) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof MicrobeamManipulation)
{
if (referenceObject instanceof Roi)
{
handleReference((MicrobeamManipulation) targetObject,
(Roi) referenceObject);
continue;
}
}
else if (targetObject instanceof Roi)
{
if (referenceObject instanceof Annotation) {
handleReference((Roi) targetObject,
(Annotation) referenceObject);
continue;
}
}
else if (targetObject instanceof PlateAcquisition)
{
if (referenceObject instanceof Annotation) {
handleReference((PlateAcquisition) targetObject,
(Annotation) referenceObject);
continue;
}
}
throw new ApiUsageException(String.format(
"Missing reference handler for %s(%s) --> %s(%s) reference.",
reference, referenceObject, target, targetObject));
}
}
}
/**
* Strips custom, reference only suffixes from LSID so that the object
* may be correctly looked up.
* @param LSID The LSID string to strip the suffix from.
* @return A new LSID string with the suffix stripped or <code>LSID</code>.
*/
private String stripCustomSuffix(String LSID)
{
if (LSID.endsWith("OMERO_EMISSION_FILTER")
|| LSID.endsWith("OMERO_EXCITATION_FILTER"))
{
return LSID.substring(0, LSID.lastIndexOf(':'));
}
return LSID;
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should are used to describe the model
* object's graph location.
*/
private void handle(String LSID, Image sourceObject,
Map<String, Integer> indexes)
{
int imageIndex = indexes.get("imageIndex");
imageList.put(imageIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Pixels sourceObject,
Map<String, Integer> indexes)
{
int imageIndex = indexes.get("imageIndex");
imageList.get(imageIndex).addPixels(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Channel sourceObject,
Map<String, Integer> indexes)
{
Pixels p = getPixels(indexes.get("imageIndex"), 0);
p.addChannel(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, LogicalChannel sourceObject,
Map<String, Integer> indexes)
{
Channel c = getChannel(indexes.get("imageIndex"), indexes.get("channelIndex"));
c.setLogicalChannel(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, PlaneInfo sourceObject,
Map<String, Integer> indexes)
{
int imageIndex = indexes.get("imageIndex");
Pixels p = imageList.get(imageIndex).getPrimaryPixels();
p.addPlaneInfo(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Instrument sourceObject,
Map<String, Integer> indexes)
{
int instrumentIndex = indexes.get("instrumentIndex");
instrumentList.put(instrumentIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Microscope sourceObject,
Map<String, Integer> indexes)
{
int instrumentIndex = indexes.get("instrumentIndex");
instrumentList.get(instrumentIndex).setMicroscope(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, StageLabel sourceObject,
Map<String, Integer> indexes)
{
Image i = getImage(indexes.get("imageIndex"));
i.setStageLabel(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Objective sourceObject,
Map<String, Integer> indexes)
{
Instrument i = getInstrument(indexes.get("instrumentIndex"));
i.addObjective(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Detector sourceObject,
Map<String, Integer> indexes)
{
Instrument i = getInstrument(indexes.get("instrumentIndex"));
i.addDetector(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, LightSource sourceObject,
Map<String, Integer> indexes)
{
Instrument i = instrumentList.get(indexes.get("instrumentIndex"));
i.addLightSource(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, OTF sourceObject,
Map<String, Integer> indexes)
{
Instrument i = instrumentList.get(indexes.get("instrumentIndex"));
i.addOTF(sourceObject);
Map<Integer, OTF> map = otfList.get(i);
if (map == null)
{
map = new HashMap<Integer, OTF>();
otfList.put(i, map);
}
map.put(indexes.get("otfIndex"), sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Dichroic sourceObject,
Map<String, Integer> indexes)
{
Instrument i = instrumentList.get(indexes.get("instrumentIndex"));
i.addDichroic(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Filter sourceObject,
Map<String, Integer> indexes)
{
Instrument i = instrumentList.get(indexes.get("instrumentIndex"));
i.addFilter(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, FilterSet sourceObject,
Map<String, Integer> indexes)
{
Instrument i = instrumentList.get(indexes.get("instrumentIndex"));
i.addFilterSet(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, ImagingEnvironment sourceObject,
Map<String, Integer> indexes)
{
Image i = imageList.get(indexes.get("imageIndex"));
i.setImagingEnvironment(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, DetectorSettings sourceObject,
Map<String, Integer> indexes)
{
LogicalChannel lc = getLogicalChannel(indexes.get("imageIndex"),
indexes.get("channelIndex"));
lc.setDetectorSettings(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, LightSettings sourceObject,
Map<String, Integer> indexes)
{
Integer imageIndex = indexes.get("imageIndex");
Integer channelIndex = indexes.get("channelIndex");
Integer experimentIndex = indexes.get("experimentIndex");
Integer microbeamManipulationIndex =
indexes.get("microbeamManipulationIndex");
if (experimentIndex != null)
{
Experiment e = experimentList.get(experimentIndex);
Iterator<MicrobeamManipulation> iter =
e.iterateMicrobeamManipulation();
for (int i = 0; i < e.sizeOfMicrobeamManipulation(); i++)
{
MicrobeamManipulation mm = iter.next();
if (i == microbeamManipulationIndex)
{
mm.addLightSettings(sourceObject);
}
}
}
else
{
LogicalChannel lc = getLogicalChannel(imageIndex, channelIndex);
lc.setLightSourceSettings(sourceObject);
}
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, ObjectiveSettings sourceObject,
Map<String, Integer> indexes)
{
Integer instrumentIndex = indexes.get("instrumentIndex");
Integer otfIndex = indexes.get("otfIndex");
Integer imageIndex = indexes.get("imageIndex");
if (instrumentIndex != null && otfIndex != null)
{
OTF o = getOTF(instrumentIndex, otfIndex);
o.setObjective(sourceObject.getObjective());
}
else
{
Image i = getImage(imageIndex);
i.setObjectiveSettings(sourceObject);
}
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, LightPath sourceObject,
Map<String, Integer> indexes)
{
Channel c = getChannel(
indexes.get("imageIndex"), indexes.get("channelIndex"));
c.getLogicalChannel().setLightPath(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Plate sourceObject,
Map<String, Integer> indexes)
{
int plateIndex = indexes.get("plateIndex");
wellList.put(plateIndex, new LinkedHashMap<Integer, Well>());
plateList.put(plateIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Well sourceObject,
Map<String, Integer> indexes)
{
int plateIndex = indexes.get("plateIndex");
int wellIndex = indexes.get("wellIndex");
getPlate(plateIndex).addWell(sourceObject);
wellList.get(plateIndex).put(wellIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Screen sourceObject,
Map<String, Integer> indexes)
{
int screenIndex = indexes.get("screenIndex");
screenList.put(screenIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Reagent sourceObject,
Map<String, Integer> indexes)
{
int screenIndex = indexes.get("screenIndex");
getScreen(screenIndex).addReagent(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, WellSample sourceObject,
Map<String, Integer> indexes)
{
int plateIndex = indexes.get("plateIndex");
int wellIndex = indexes.get("wellIndex");
Well w = getWell(plateIndex, wellIndex);
w.addWellSample(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Roi sourceObject,
Map<String, Integer> indexes)
{
roiList.put(indexes.get("roiIndex"), sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Shape sourceObject,
Map<String, Integer> indexes)
{
int roiIndex = indexes.get("roiIndex");
Roi r = getRoi(roiIndex);
r.addShape(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, OriginalFile sourceObject,
Map<String, Integer> indexes)
{
// No-op.
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Annotation sourceObject,
Map<String, Integer> indexes)
{
// No-op.
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, Experiment sourceObject,
Map<String, Integer> indexes)
{
int experimentIndex = indexes.get("experimentIndex");
experimentList.put(experimentIndex, sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, MicrobeamManipulation sourceObject,
Map<String, Integer> indexes)
{
int experimentIndex = indexes.get("experimentIndex");
Experiment e = experimentList.get(experimentIndex);
e.addMicrobeamManipulation(sourceObject);
}
/**
* Handles inserting a specific type of model object into our object graph.
* @param LSID LSID of the model object.
* @param sourceObject Model object itself.
* @param indexes Any indexes that should be used to reference the model
* object.
*/
private void handle(String LSID, PlateAcquisition sourceObject,
Map<String, Integer> indexes)
{
int plateIndex = indexes.get("plateIndex");
Plate p = getPlate(plateIndex);
p.addPlateAcquisition(sourceObject);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(DetectorSettings target, Detector reference)
{
target.setDetector(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, Instrument reference)
{
target.setInstrument(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, Dataset reference)
{
target.linkDataset(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightSource target, LightSource reference)
{
// The only possible linkage at this point is a Laser's pump.
Laser laser = (Laser) target;
laser.setPump(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightSettings target, LightSource reference)
{
target.setLightSource(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightPath target, Dichroic reference)
{
target.setDichroic(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightPath target, Filter reference,
LSID referenceLSID)
{
if (referenceLSID.toString().endsWith("OMERO_EMISSION_FILTER"))
{
target.linkEmissionFilter(reference);
}
else if (referenceLSID.toString().endsWith("OMERO_EXCITATION_FILTER"))
{
target.linkExcitationFilter(reference);
}
else
{
throw new ApiUsageException(String.format(
"Unable to handle LightPath --> Filter reference: %s",
referenceLSID));
}
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Channel target, OTF reference)
{
target.getLogicalChannel().setOtf(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Channel target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LogicalChannel target, FilterSet reference)
{
target.setFilterSet(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph. This method handles <b>secondary</b> excitation and
* emission filters so requires the LSID be passed in as well.
* @param target Target model object.
* @param reference Reference model object.
* @param referenceLSID LSID of the reference object.
*/
private void handleReference(LogicalChannel target, Filter reference,
LSID referenceLSID)
{
LightPath lightPath = target.getLightPath();
if (lightPath == null)
{
lightPath = new LightPath();
}
target.setLightPath(lightPath);
if (referenceLSID.toString().endsWith("OMERO_EMISSION_FILTER"))
{
lightPath.linkEmissionFilter(reference);
}
else if (referenceLSID.toString().endsWith("OMERO_EXCITATION_FILTER"))
{
lightPath.linkExcitationFilter(reference);
}
else
{
throw new ApiUsageException(String.format(
"Unable to handle LogicalChannel --> Filter reference: %s",
referenceLSID));
}
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(OTF target, Objective reference)
{
target.setObjective(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(OTF target, FilterSet reference)
{
target.setFilterSet(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(ObjectiveSettings target, Objective reference)
{
target.setObjective(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(WellSample target, Image reference)
{
reference.addWellSample(target);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(PlateAcquisition target, WellSample reference)
{
target.addWellSample(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(PlateAcquisition target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Pixels target, OriginalFile reference)
{
target.linkOriginalFile(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(FilterSet target, Dichroic reference)
{
target.setDichroic(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(FilterSet target, Filter reference,
LSID referenceLSID)
{
if (referenceLSID.toString().endsWith("OMERO_EMISSION_FILTER"))
{
target.linkEmissionFilter(reference);
}
else if (referenceLSID.toString().endsWith("OMERO_EXCITATION_FILTER"))
{
target.linkExcitationFilter(reference);
}
else
{
throw new ApiUsageException(String.format(
"Unable to handle FilterSet --> Filter reference: %s",
referenceLSID));
}
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, Roi reference)
{
target.addRoi(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, Experiment reference)
{
target.setExperiment(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Image target, MicrobeamManipulation reference)
{
// TODO: add code to handle this linking if needed
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Screen target, Plate reference)
{
if (!target.linkedPlateList().contains(reference))
{
target.linkPlate(reference);
}
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Screen target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Plate target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Detector target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Dichroic target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Filter target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Instrument target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightPath target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Objective target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Shape target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(LightSource target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Reagent target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Roi target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(PlaneInfo target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Plate target, Screen reference)
{
if (!target.linkedScreenList().contains(reference))
{
target.linkScreen(reference);
}
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Well target, Reagent reference)
{
target.linkReagent(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(FileAnnotation target, OriginalFile reference)
{
target.setFile(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(Annotation target, Annotation reference)
{
target.linkAnnotation(reference);
}
/**
* Handles linking a specific reference object to a target object in our
* object graph.
* @param target Target model object.
* @param reference Reference model object.
*/
private void handleReference(MicrobeamManipulation target, Roi reference)
{
// no-op as the ROIRef cannot be set on a MicrobeamManipulation
}
/**
* Retrieves an object from the internal object graph by LSID.
* @param lsid LSID of the object.
* @return See above. <code>null</code> if the object is not in the
* internal LSID map.
*/
public IObject getObjectByLSID(LSID lsid)
{
return lsidMap.get(lsid);
}
/**
* Returns an Image model object based on its indexes within the OMERO data
* model.
* @param imageIndex Image index.
* @return See above.
*/
private Image getImage(int imageIndex)
{
return imageList.get(imageIndex);
}
/**
* Returns a Pixels model object based on its indexes within the OMERO data
* model.
* @param imageIndex Image index.
* @param pixelsIndex Pixels index.
* @return See above.
*/
private Pixels getPixels(int imageIndex, int pixelsIndex)
{
return getImage(imageIndex).getPixels(pixelsIndex);
}
/**
* Returns an Instrument model object based on its indexes within the OMERO
* data model.
* @param instrumentIndex Instrument index.
* @return See above.
*/
private Instrument getInstrument(int instrumentIndex)
{
return instrumentList.get(instrumentIndex);
}
/**
* Returns an OTF model object based on its indexes within the OMERO
* data model.
* @param instrumentIndex Instrument index.
* @param otfIndex OTF index.
* @return See above.
*/
private OTF getOTF(int instrumentIndex, int otfIndex)
{
Instrument i = getInstrument(instrumentIndex);
return otfList.get(i).get(otfIndex);
}
/**
* Returns a Channel model object based on its indexes within the
* OMERO data model.
* @param imageIndex Image index.
* @param channelIndex channel index.
* @return See above.
*/
private Channel getChannel(int imageIndex, int channelIndex)
{
return getPixels(imageIndex, 0).getChannel(channelIndex);
}
/**
* Returns a LogicalChannel model object based on its indexes within the
* OMERO data model.
* @param imageIndex Image index.
* @param channelIndex channel index.
* @return See above.
*/
private LogicalChannel getLogicalChannel(int imageIndex,
int channelIndex)
{
return getChannel(imageIndex, channelIndex).getLogicalChannel();
}
/**
* Returns a Screen model object based on its indexes within the
* OMERO data model.
* @param screenIndex Screen index.
* @return See above.
*/
private Screen getScreen(int screenIndex)
{
return screenList.get(screenIndex);
}
/**
* Returns a Plate model object based on its indexes within the
* OMERO data model.
* @param plateIndex Plate index.
* @return See above.
*/
private Plate getPlate(int plateIndex)
{
return plateList.get(plateIndex);
}
/**
* Returns a Well model object based on its indexes within the
* OMERO data model.
* @param plateIndex Plate index.
* @param wellIndex Well index
* @return See above.
*/
private Well getWell(int plateIndex, int wellIndex)
{
return wellList.get(plateIndex).get(wellIndex);
}
/**
* Returns a Roi model object based on its indexes within the
* OMERO data model.
* @param roiIndex Roi index.
* @return See above.
*/
private Roi getRoi(int roiIndex)
{
return roiList.get(roiIndex);
}
/**
* Empty constructor for testing purposes.
*/
public OMEROMetadataStore() {}
/**
* Creates a new instance.
*
* @param factory a non-null, active {@link ServiceFactory}
* @param sql the SQL action instance
* @throws ValidationException if the factory is null or there
* is another error instantiating required services.
*/
public OMEROMetadataStore(ServiceFactory factory, SqlAction sql)
throws ValidationException
{
if (factory == null || sql == null)
throw new ValidationException("arguments cannot be null");
sf = factory;
this.sql = sql;
}
/*
* (non-Javadoc)
*
* @see loci.formats.MetadataStore#createRoot()
*/
public void createRoot()
{
imageList = new LinkedHashMap<Integer, Image>();
pixelsList = new LinkedHashMap<Integer, Pixels>();
screenList = new LinkedHashMap<Integer, Screen>();
plateList = new LinkedHashMap<Integer, Plate>();
roiList = new LinkedHashMap<Integer, Roi>();
wellList = new LinkedHashMap<Integer, Map<Integer, Well>>();
instrumentList = new LinkedHashMap<Integer, Instrument>();
experimentList = new LinkedHashMap<Integer, Experiment>();
otfList = new LinkedHashMap<Instrument, Map<Integer, OTF>>();
lsidMap = new LinkedHashMap<LSID, IObject>();
}
/**
* Compares two enumerations by reference and by ID.
* @param a First OMERO model object.
* @param b Second OMERO model object.
* @return <code>true</code> if <code>a == null && b == null</code>,
* <code>a == b</code> or <code>a.getId() == b.getId()</code>.
*/
private static boolean compare(IEnum a, IEnum b)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null)
{
return false;
}
return a.getId() == b.getId();
}
/**
* Compares two objects by reference existence and by value.
* @param a First object.
* @param b Second object.
* @return <code>true</code> if <code>a == null && b == null</code> or
* <code>a.equals(b)</code>.
*/
private static boolean compare(Object a, Object b)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null)
{
return false;
}
return a.equals(b);
}
/**
* Checks the entire object graph for sections that may be collapsed if
* the data is derived from a Plate. Collapsible points:
* <ul>
* <li>Image --> ObjectiveSettings</li>
* <li>Image --> Channel --> LogicalChannel --> LightSettings</li>
* <li>Image --> Channel --> LogicalChannel --> LightPath</li>
* <li>Image --> Channel --> LogicalChannel --> DetectorSettings</li>
* </ul>
*/
public void checkAndCollapseGraph()
{
// Ensure we're working with an SPW data set.
if (plateList.size() == 0)
{
return;
}
// Collapse down ObjectiveSettings by uniqueness
Set<ObjectiveSettings> objectiveSettings =
new HashSet<ObjectiveSettings>();
Set<LightSettings> lightSettings = new HashSet<LightSettings>();
Set<LightPath> lightPaths = new HashSet<LightPath>();
Set<DetectorSettings> detectorSettings =
new HashSet<DetectorSettings>();
Set<LogicalChannel> logicalChannels = new HashSet<LogicalChannel>();
Pixels pixels;
Channel channel;
LogicalChannel lc;
for (Image image : imageList.values())
{
pixels = image.getPrimaryPixels();
image.setObjectiveSettings(
getUniqueObjectiveSettings(objectiveSettings, image));
for (int c = 0; c < pixels.sizeOfChannels(); c++)
{
channel = pixels.getChannel(c);
lc = channel.getLogicalChannel();
lc.setLightSourceSettings(
getUniqueLightSettings(lightSettings, lc));
lc.setDetectorSettings(
getUniqueDetectorSettings(detectorSettings, lc));
lc.setLightPath(
getUniqueLightPath(lightPaths, lc.getLightPath()));
channel.setLogicalChannel(
getUniqueLogicalChannel(logicalChannels, lc));
}
}
log.info("Unique objective settings: " + objectiveSettings.size());
log.info("Unique light settings: " + lightSettings.size());
log.info("Unique detector settings: " + detectorSettings.size());
log.info("Unique light paths: " + lightPaths.size());
log.info("Unique logical channels: " + logicalChannels.size());
}
/**
* For all plates and all images which are not contained within a well,
* create a link from the {@link Fileset} to the given object.
*/
private void linkFileset(FilesetJobLink link)
{
final Fileset fs = link.parent().proxy(); // Unloaded
for (Image image : imageList.values())
{
image.setFileset(fs.proxy());
}
}
/**
* Finds the matching unique settings for an image.
* @param uniqueSettings Set of existing unique settings.
* @param image Image to find unique settings for.
* @return Matched unique settings or <code>null</code> if
* <code>lc.getObjectiveSettings() == null</code>.
*/
private ObjectiveSettings getUniqueObjectiveSettings(
Set<ObjectiveSettings> uniqueSettings, Image image)
{
ObjectiveSettings s1 = image.getObjectiveSettings();
if (s1 == null)
{
return null;
}
for (ObjectiveSettings s2 : uniqueSettings)
{
if (compare(s1.getCorrectionCollar(), s2.getCorrectionCollar())
&& compare(s1.getMedium(), s2.getMedium())
&& s1.getObjective() == s2.getObjective()
&& compare(s1.getRefractiveIndex(), s2.getRefractiveIndex()))
{
return s2;
}
}
uniqueSettings.add(s1);
return s1;
}
/**
* Finds the matching unique settings for a logical channel.
* @param uniqueSettings Set of existing unique settings.
* @param lc Logical channel to find unique settings for.
* @return Matched unique settings or <code>null</code> if
* <code>lc.getLightSourceSettings() == null</code>.
*/
private LightSettings getUniqueLightSettings(
Set<LightSettings> uniqueSettings, LogicalChannel lc)
{
LightSettings s1 = lc.getLightSourceSettings();
if (s1 == null)
{
return null;
}
for (LightSettings s2 : uniqueSettings)
{
if (compare(s1.getAttenuation(), s2.getAttenuation())
&& s1.getLightSource() == s2.getLightSource()
&& s1.getMicrobeamManipulation()
== s2.getMicrobeamManipulation()
&& compare(s1.getWavelength(), s2.getWavelength()))
{
return s2;
}
}
uniqueSettings.add(s1);
return s1;
}
/**
* Finds the matching unique settings for a logical channel.
* @param uniqueSettings Set of existing unique settings.
* @param lc Logical channel to find unique settings for.
* @return Matched unique settings or <code>null</code> if
* <code>lc.getDetectorSettings() == null</code>.
*/
private DetectorSettings getUniqueDetectorSettings(
Set<DetectorSettings> uniqueSettings, LogicalChannel lc)
{
DetectorSettings s1 = lc.getDetectorSettings();
if (s1 == null)
{
return null;
}
for (DetectorSettings s2 : uniqueSettings)
{
if (compare(s1.getBinning(), s2.getBinning())
&& s1.getDetector() == s2.getDetector()
&& compare(s1.getGain(), s2.getGain())
&& compare(s1.getOffsetValue(), s2.getOffsetValue())
&& compare(s1.getReadOutRate(), s2.getReadOutRate())
&& compare(s1.getVoltage(), s2.getVoltage()))
{
return s2;
}
}
uniqueSettings.add(s1);
return s1;
}
/**
* Finds the matching unique logical channel.
* @param uniqueChannels Set of existing unique logical channels.
* @param lc Logical channel to compare for uniqueness.
* @return Matched unique logical channel or <code>null</code> if
* <code>lc == null</code>.
*/
private LogicalChannel getUniqueLogicalChannel(
Set<LogicalChannel> uniqueChannels, LogicalChannel lc)
{
if (lc == null)
{
return null;
}
for (LogicalChannel lc2 : uniqueChannels)
{
if (compare(lc.getMode(), lc2.getMode())
&& compare(lc.getContrastMethod(), lc2.getContrastMethod())
&& compare(lc.getIllumination(), lc2.getIllumination())
&& compare(lc.getPhotometricInterpretation(),
lc2.getPhotometricInterpretation())
&& lc.getDetectorSettings() == lc2.getDetectorSettings()
&& compare(lc.getEmissionWave(), lc2.getEmissionWave())
&& compare(lc.getExcitationWave(), lc2.getExcitationWave())
&& lc.getFilterSet() == lc2.getFilterSet()
&& compare(lc.getFluor(), lc2.getFluor())
&& lc.getLightSourceSettings() == lc2.getLightSourceSettings()
&& compare(lc.getName(), lc2.getName())
&& compare(lc.getNdFilter(), lc2.getNdFilter())
&& lc.getOtf() == lc.getOtf()
&& compare(lc.getPinHoleSize(), lc2.getPinHoleSize())
&& compare(lc.getPockelCellSetting(), lc2.getPockelCellSetting())
&& compare(lc.getSamplesPerPixel(), lc2.getSamplesPerPixel())
&& lc.getLightPath() == lc2.getLightPath())
{
return lc2;
}
}
uniqueChannels.add(lc);
return lc;
}
/**
* Finds the matching unique light path.
* @param uniqueLightPaths Set of existing unique light paths.
* @param lp Light path to compare for uniqueness.
* @return Matched unique light path or <code>null</code> if
* <code>lp == null</code>.
*/
private LightPath getUniqueLightPath(
Set<LightPath> uniqueLightPaths, LightPath lp)
{
if (lp == null)
{
return null;
}
for (LightPath lp2 : uniqueLightPaths)
{
if (lp.getDichroic() == lp2.getDichroic()) {
// Excitation filters are ordered - no sorting required.
List<Filter> exFilters = lp.linkedExcitationFilterList();
List<Filter> exFilters2 = lp2.linkedExcitationFilterList();
if (exFilters.equals(exFilters2)) {
List<Filter> emFilters = lp.linkedEmissionFilterList();
List<Filter> emFilters2 = lp2.linkedEmissionFilterList();
// Emission filters are un-ordered - sorting required. If
// we do not sort out of order filters will cause
// List.equals() to fail.
Comparator<Filter> comparator = new ToStringComparator();
Collections.sort(emFilters, comparator);
Collections.sort(emFilters2, comparator);
if (emFilters.equals(emFilters2)) {
return lp2;
}
}
}
}
uniqueLightPaths.add(lp);
return lp;
}
/**
* Saves the current object graph to the database.
* @param link a link from the fileset to be linked from
* @return List of the Pixels objects with their attached object graphs
* that have been saved.
*/
public List<Pixels> saveToDB(FilesetJobLink link)
{
// Check the entire object graph, optimizing and sections that may
// be collapsed.
checkAndCollapseGraph();
linkFileset(link);
// Save the entire Image rooted graph using the "insert only"
// saveAndReturnIds(). DISABLED until we can find out what is causing
// the extreme memory usage on the graph reload.
StopWatch s1 = new Slf4JStopWatch("omero.saveImportGraph");
Image[] imageArray =
imageList.values().toArray(new Image[imageList.size()]);
IObject[] saved = sf.getUpdateService().saveAndReturnArray(imageArray);
s1.stop();
List<Pixels> toReturn = new ArrayList<Pixels>();
Image image;
Pixels pixels;
for (int i = 0; i < saved.length; i++)
{
image = (Image) saved[i];
pixels = image.getPrimaryPixels();
pixelsList.put(i, pixels);
toReturn.add(pixels);
}
//s2.stop();
return toReturn;
}
/**
* Checks if the format is a graphics format or not.
*
* @param value The value to check
* @return See above.
*/
private boolean isRGB(String value)
{
if (value == null) return false;
value = value.toLowerCase();
for (int i = 0; i < DOMAINS.length; i++) {
if (DOMAINS[i].equals(value)) {
return true;
}
}
return false;
}
/**
* Synchronize the minimum and maximum intensity values with those
* specified by the client and save them in the DB.
* @param imageChannelGlobalMinMax Minimums and maximums to update.
*/
public void populateMinMax(double[][][] imageChannelGlobalMinMax)
{
double[][] channelGlobalMinMax;
double[] globalMinMax;
Channel channel;
StatsInfo statsInfo;
Pixels pixels, unloadedPixels;
for (int i = 0; i < imageChannelGlobalMinMax.length; i++)
{
channelGlobalMinMax = imageChannelGlobalMinMax[i];
pixels = pixelsList.get(i);
Format f = pixels.getImage().getFormat();
String v = null;
if (f != null) {
v = f.getValue();
}
boolean rgb = isRGB(v);
String type = pixels.getPixelsType().getValue();
unloadedPixels = new Pixels(pixels.getId(), false);
for (int c = 0; c < channelGlobalMinMax.length; c++)
{
globalMinMax = channelGlobalMinMax[c];
channel = pixels.getChannel(c);
statsInfo = new StatsInfo();
if (rgb && "uint8".equals(type)) {
statsInfo.setGlobalMin(0.0);
statsInfo.setGlobalMax(255.0);
} else {
statsInfo.setGlobalMin(globalMinMax[0]);
statsInfo.setGlobalMax(globalMinMax[1]);
}
sql.setStatsInfo(channel, statsInfo);
}
}
}
/**
* Simple comparator that compares two filters by their stringified value.
* @author Emil Rozbicki <emil@glencoesoftware.com>
*
*/
class ToStringComparator implements Comparator<Filter>
{
@Override
public int compare(Filter a, Filter b) {
return a.toString().compareTo(b.toString());
}
}
}