diff --git a/integration-tests/templates/data-ibrain2/scripts/commonDropbox.py b/integration-tests/templates/data-ibrain2/scripts/commonDropbox.py index 57886ecb685070f75b445bc3df0c7fa4adc30a2c..a06c849e7b97112a8e822e0d20dd7b5a294c88d5 100755 --- a/integration-tests/templates/data-ibrain2/scripts/commonDropbox.py +++ b/integration-tests/templates/data-ibrain2/scripts/commonDropbox.py @@ -1,6 +1,7 @@ #! /usr/bin/env python import os +from java.io import File class AbstractPropertiesParser: _propertiesDict = None @@ -40,21 +41,18 @@ class AbstractPropertiesParser: # Returns: # an iterator which yields (propertyName, propertyValue) pairs def getPropertiesIter(self): - for key, value in self._propertiesDict.iteritems(): - yield (key, value) - + return [ (key, value) for key, value in self._propertiesDict.iteritems() ] + # All dataset properties. # Returns: # an iterator which yields (propertyCode, propertyValue) pairs def getDatasetPropertiesIter(self): - for key, value in self._propertiesDict.iteritems(): - if key.startswith(self.DATASET_PROPERTY_PREFIX): - yield (key, value) + return [ (key, value) for key, value in self._propertiesDict.iteritems() if key.startswith(self.DATASET_PROPERTY_PREFIX) ] class AbstractMetadataParser(AbstractPropertiesParser): METADATA_FILE="metadata.properties" - IBRAIN2_DATASET_ID_PROPERTY = "brain2.dataset.id" + IBRAIN2_DATASET_ID_PROPERTY = "ibrain2.dataset.id" DATASET_PROPERTY_PREFIX = "ibrain2." DATASET_TYPE_PROPERTY = "dataset.type" @@ -78,9 +76,10 @@ class AcquiredDatasetMetadataParser(AbstractMetadataParser): # Returns: # an iterator which yields (propertyCode, propertyValue) pairs def getDatasetPropertiesIter(self): - for propertyCode, value in AbstractPropertiesParser.getDatasetPropertiesIter(self): - yield (propertyCode, value) - yield (self.INSTRUMENT_PROPERTY, self.get(self.INSTRUMENT_PROPERTY)) + properties = AbstractPropertiesParser.getDatasetPropertiesIter(self) + properties = [ (key, value) for (key, value) in properties if key != "ibrain2.assay.id" ] + properties.append((self.INSTRUMENT_PROPERTY, self.get(self.INSTRUMENT_PROPERTY))) + return properties def getPlateCode(self): return self.get(self.PLATE_CODE_PRPOPERTY) @@ -111,7 +110,6 @@ class AssayParser(AbstractPropertiesParser): def _findAssayFile(self, incoming): for file in os.listdir(incoming): - print file if file.startswith(self.ASSAY_FILE_PREFIX): return file raise Exception("Assay file not found!") @@ -119,9 +117,9 @@ class AssayParser(AbstractPropertiesParser): def __init__(self, incoming): AbstractPropertiesParser.__init__(self, incoming, self._findAssayFile(incoming)) -class IBRAIN2Utils: +class RegistrationConfirmationUtils: """ path to the registration confirmation directory relative to the incoming dataset """ - CONFIRMATION_DIRECTORY = "../../registration-status" + CONFIRMATION_DIRECTORY = "registration-status" STATUS_PROPERTY = "storage_provider.storage.status" OK = "STORAGE_SUCCESS" @@ -132,31 +130,66 @@ class IBRAIN2Utils: IBRAIN2_STATUS_FILE_PREFIX = "ibrain2_dataset_id_" IBRAIN2_STATUS_FILE_SUFFIX = ".properties" - def _getStatusFileName(self, ibrain2DatasetId, incoming): - return incoming + "/" + self.CONFIRMATION_DIRECTORY + "/" + self.IBRAIN2_STATUS_FILE_PREFIX + ibrain2DatasetId + self.IBRAIN2_STATUS_FILE_SUFFIX + def _getDestinationDir(self, incoming): + return File(incoming).getParentFile().getParentFile().getParent() + "/" + self.CONFIRMATION_DIRECTORY + + def _getConfirmationFileName(self, ibrain2DatasetId): + return self.IBRAIN2_STATUS_FILE_PREFIX + ibrain2DatasetId + self.IBRAIN2_STATUS_FILE_SUFFIX + + def _getStatusFilePath(self, ibrain2DatasetId, incoming): + return self._getDestinationDir(incoming) + "/" + self._getConfirmationFileName(ibrain2DatasetId) def _prop(self, name, value): return name + " = " + value + "\n" def _writeConfirmationFile(self, ibrain2DatasetId, fileContent, incoming): - confirmationFile = self._getStatusFileName(ibrain2DatasetId, incoming) - file = open(confirmationFile, "w") + confirmationFile = self._getStatusFilePath(ibrain2DatasetId, incoming) + self._writeFile(confirmationFile, fileContent) + + def _writeFile(self, file, fileContent): + file = open(file, "w") file.write(fileContent) file.close() - + def createSuccessStatus(self, ibrain2DatasetId, openbisDatasetId, incoming): fileContent = self._prop(self.STATUS_PROPERTY, self.OK) fileContent += self._prop(AbstractMetadataParser.IBRAIN2_DATASET_ID_PROPERTY, ibrain2DatasetId) fileContent += self._prop(self.OPENBIS_DATASET_ID_PROPERTY, openbisDatasetId) self._writeConfirmationFile(ibrain2DatasetId, fileContent, incoming) - + def createFailureStatus(self, ibrain2DatasetId, errorMessage, incoming): fileContent = self._prop(self.STATUS_PROPERTY, self.ERROR) fileContent += self._prop(AbstractMetadataParser.IBRAIN2_DATASET_ID_PROPERTY, ibrain2DatasetId) fileContent += self._prop(self.ERROR_MSG_PROPERTY, errorMessage) self._writeConfirmationFile(ibrain2DatasetId, fileContent, incoming) - - + +# -------------- + +""" +Returns: + (plateSpace, plateCode) tuple for the plate connected with the specified dataset + or (error-message, None) if the dataset does not exist or is not connected to the plate. +""" +def tryGetConnectedPlate(state, openbisDatasetId): + openbis = state.getOpenBisService() + dataset = openbis.tryGetDataSet(openbisDatasetId) + if dataset != None: + plate = dataset.getSample() + if plate != None: + return (plate.getSpace().getCode(), plate.getCode()) + else: + return ("No plate is connected to the dataset: "+openbisDatasetId+".", None) + else: + return ("Dataset does not exist or is not accessible: "+openbisDatasetId+". "+ + "Maybe the dataset has not been registered yet. Try again later.", None) + +def createSuccessStatus(iBrain2DatasetId, dataset, incomingPath): + datasetCode = dataset.getDataSetCode() + RegistrationConfirmationUtils().createSuccessStatus(iBrain2DatasetId, datasetCode, incomingPath) + +def createFailureStatus(iBrain2DatasetId, throwable, incoming): + RegistrationConfirmationUtils().createFailureStatus(iBrain2DatasetId, throwable.getMessage(), incoming.getPath()) + # -------------- TODO: remove tests TEST_DIR = "/Users/tpylak/main/src/screening-demo/biozentrum/dropboxes/ibrain2-dropboxes-test" diff --git a/integration-tests/templates/data-ibrain2/scripts/commonImageDropbox.py b/integration-tests/templates/data-ibrain2/scripts/commonImageDropbox.py index 60372dc0da410aeaefabd3af4084edc86f689af7..c65b119c3e68f8c02c6fe653472c683b43c78a13 100755 --- a/integration-tests/templates/data-ibrain2/scripts/commonImageDropbox.py +++ b/integration-tests/templates/data-ibrain2/scripts/commonImageDropbox.py @@ -5,26 +5,31 @@ from ch.systemsx.cisd.openbis.dss.etl.dto.api.v1 import * from ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto import Geometry class IBrain2ImageDataSetConfig(SimpleImageDataConfig): - THUMBANAIL_SIZE = 200 - + THUMBANAIL_SIZE = 200 + def extractImageMetadata(self, imagePath): - image_tokens = ImageMetadata() - - basename = os.path.splitext(imagePath)[0] - # + basename = self.getFileBasename(imagePath) token_dict = {} for token in basename.split("_"): token_dict[token[:1]] = token[1:] - + + image_tokens = ImageMetadata() image_tokens.well = token_dict["w"] - fieldText = token_dict["s"] + image_tokens.tileNumber = self.fieldAsInt(token_dict["s"], basename) + image_tokens.channelCode = self.extractChannelCode(token_dict, basename) + return image_tokens + + def extractChannelCode(self, token_dict, basename): + return token_dict["c"] + + def getFileBasename(self, filePath): + return os.path.splitext(filePath)[0] + + def fieldAsInt(self, fieldText, basename): try: - image_tokens.tileNumber = int(fieldText) + return int(fieldText) except ValueError: raise Exception("Cannot parse field number from '" + fieldText + "' in '" + basename + "' file name.") - - image_tokens.channelCode = basename.split("_")[-1] + " ("+ token_dict["c"] + ")" - return image_tokens def geom(self, row, col): return Geometry.createFromRowColDimensions(row, col) @@ -48,4 +53,8 @@ class IBrain2ImageDataSetConfig(SimpleImageDataConfig): else: return self.geom(maxTileNumber, 1) +class IBrain2SegmentationImageDataSetConfig(IBrain2ImageDataSetConfig): + def extractChannelCode(self, token_dict, basename): + return basename.split("_")[-1] + " ("+ token_dict["c"] + ")" + \ No newline at end of file diff --git a/integration-tests/templates/data-ibrain2/scripts/hcs_image_overview.py b/integration-tests/templates/data-ibrain2/scripts/hcs_image_overview.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0162c6413ee914a45710885d293b02ccb5937b28 100755 --- a/integration-tests/templates/data-ibrain2/scripts/hcs_image_overview.py +++ b/integration-tests/templates/data-ibrain2/scripts/hcs_image_overview.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python + +import commonImageDropbox +import commonDropbox + +reload(commonImageDropbox) +reload(commonDropbox) + + +def setPropertiesAndRegister(imageDataset, iBrain2DatasetId, metadataParser, incoming, factory): + imageRegistrationDetails = factory.createImageRegistrationDetails(imageDataset, incoming) + for propertyCode, value in metadataParser.getDatasetPropertiesIter(): + imageRegistrationDetails.setPropertyValue(propertyCode, value) + + tr = service.transaction(incoming, factory) + dataset = tr.createNewDataSet(imageRegistrationDetails) + imageDataSetFolder = tr.moveFile(incoming.getPath(), dataset) + tr.commit() + commonDropbox.createSuccessStatus(iBrain2DatasetId, dataset, incoming.getPath()) + +# ------- + +# Global variable where we set the iBrain2 id of the dataset at the beginning, +# so that the rollback can use it as well. +iBrain2DatasetId = None + +def register(incomingPath): + metadataParser = commonDropbox.DerivedDatasetMetadataParser(incomingPath) + iBrain2DatasetId = metadataParser.getIBrain2DatasetId() + openbisDatasetParent = metadataParser.getParentDatasetPermId() + + (spaceOrError, plate) = commonDropbox.tryGetConnectedPlate(state, openbisDatasetParent) + if plate == None: + commonDropbox.RegistrationConfirmationUtils().createFailureStatus(iBrain2DatasetId, spaceOrError, incomingPath) + return + + imageDataset = commonImageDropbox.IBrain2ImageDataSetConfig() + imageDataset.setOverviewImageDatasetType() + imageDataset.setPlate(spaceOrError, plate) + imageDataset.setFileFormatType("JPG") + imageDataset.setRecognizedImageExtensions(["jpg", "jpeg", "png", "gif"]) + imageDataset.setStoreChannelsOnExperimentLevel(False) + imageDataset.setGenerateThumbnails(True) + imageDataset.setMaxThumbnailWidthAndHeight(imageDataset.THUMBANAIL_SIZE) + + setPropertiesAndRegister(imageDataset, iBrain2DatasetId, metadataParser, incoming, factory) + +def rollback_transaction(service, transaction, algorithmRunner, throwable): + commonDropbox.createFailureStatus(iBrain2DatasetId, throwable, incoming) + +if incoming.isDirectory(): + register(incoming.getPath()) + diff --git a/integration-tests/templates/data-ibrain2/scripts/hcs_image_raw.py b/integration-tests/templates/data-ibrain2/scripts/hcs_image_raw.py index b5446e3157640066d4340c5373748f152b048ef3..4ed722e4f4ea6218336b6e106cfc8283c009c524 100755 --- a/integration-tests/templates/data-ibrain2/scripts/hcs_image_raw.py +++ b/integration-tests/templates/data-ibrain2/scripts/hcs_image_raw.py @@ -1,7 +1,10 @@ #! /usr/bin/env python -from commonImageDropbox import IBrain2ImageDataSetConfig -from commonDropbox import AcquiredDatasetMetadataParser +import commonImageDropbox +import commonDropbox + +reload(commonImageDropbox) +reload(commonDropbox) """ Plate geometry which will be used. Other possible value: 96_WELLS_8X12 """ PLATE_GEOMETRY = "384_WELLS_16X24" @@ -14,8 +17,8 @@ PLATE_GEOMETRY_PROPERTY_CODE = "$PLATE_GEOMETRY" def createPlateWithExperimentIfNeeded(transaction, assayParser, plate, space): project = assayParser.get(assayParser.EXPERIMENTER_PROPERTY) experiment = assayParser.get(assayParser.ASSAY_ID_PROPERTY) - experimentDesc = assayParser.get(assayParser.ASSAY_DESC_PROPERTY) - experimentType = assayParser.get(assayParser.ASSAY_TYPE_PROPERTY) + experimentDesc = assayParser.get(assayParser.ASSAY_DESC_PROPERTY) + experimentType = assayParser.get(assayParser.ASSAY_TYPE_PROPERTY) sampleIdentifier = "/"+space+"/"+plate plate = transaction.getSample(sampleIdentifier) @@ -24,48 +27,46 @@ def createPlateWithExperimentIfNeeded(transaction, assayParser, plate, space): experiment = transaction.getExperiment(expIdentifier) if experiment == None: experiment = transaction.createNewExperiment(expIdentifier, SIRNA_EXP_TYPE) - openbisExpDesc = experimentDesc + "\ntype: "+experimentType + openbisExpDesc = experimentDesc + " (type: "+experimentType + ")" experiment.setPropertyValue("DESCRIPTION", openbisExpDesc) plate = transaction.createNewSample(sampleIdentifier, PLATE_TYPE_CODE) plate.setPropertyValue(PLATE_GEOMETRY_PROPERTY_CODE, PLATE_GEOMETRY) plate.setExperiment(experiment) + return plate -""" -TODO: -- -""" -if incoming.isDirectory(): - imageDataset = IBrain2ImageDataSetConfig() - imageDataset.setRawImageDatasetType() - metadataParser = AcquiredDatasetMetadataParser(incoming) - assayParser = AssayParser(incoming) - plate = metadataParser.getPlateCode() - space = assayParser.get(assayParser.LAB_LEADER_PROPERTY) +iBrain2DatasetId = None + +if incoming.isDirectory(): + incomingPath = incoming.getPath() + metadataParser = commonDropbox.AcquiredDatasetMetadataParser(incomingPath) + iBrain2DatasetId = metadataParser.getIBrain2DatasetId() + assayParser = commonDropbox.AssayParser(incomingPath) - imageDataset.setPlate(space, plate) + imageDataset = commonImageDropbox.IBrain2ImageDataSetConfig() + imageDataset.setRawImageDatasetType() imageDataset.setFileFormatType("TIFF") + imageDataset.setRecognizedImageExtensions(["tif", "tiff"]) + imageDataset.setStoreChannelsOnExperimentLevel(False) imageDataset.setGenerateThumbnails(True) imageDataset.setMaxThumbnailWidthAndHeight(imageDataset.THUMBANAIL_SIZE) - imageDataset.setRecognizedImageExtensions(["tif, tiff"]) - imageDataset.setStoreChannelsOnExperimentLevel(False) imageRegistrationDetails = factory.createImageRegistrationDetails(imageDataset, incoming) - for propertyCode, value in metadataParser.getPropertiesIter(): + for propertyCode, value in metadataParser.getDatasetPropertiesIter(): imageRegistrationDetails.setPropertyValue(propertyCode, value) tr = service.transaction(incoming, factory) - createPlateWithExperimentIfNeeded(tr, assayParser, plate, space) + plate = metadataParser.getPlateCode() + space = assayParser.get(assayParser.LAB_LEADER_PROPERTY) + plate = createPlateWithExperimentIfNeeded(tr, assayParser, plate, space) + dataset = tr.createNewDataSet(imageRegistrationDetails) - imageDataSetFolder = tr.moveFile(incoming.getPath(), dataset) - imageDatasetCode = dataset.getDataSetCode() - IBRAIN2Utils().createSuccessStatus(metadataParser.getIBrain2DatasetId(), imageDatasetCode, incoming) - print "Registered dataset:", imageDatasetCode + dataset.setSample(plate) + imageDataSetFolder = tr.moveFile(incomingPath, dataset) + tr.commit() + commonDropbox.createSuccessStatus(iBrain2DatasetId, dataset, incomingPath) -# TODO: test this !!! def rollback_transaction(service, transaction, algorithmRunner, throwable): - incoming = service.incomingDataSetFile - iBrain2DatasetId = AcquiredDatasetMetadataParser(incoming).getIBrain2DatasetId() - IBRAIN2Utils().createFailureStatus(iBrain2DatasetId, throwable.getMessage(), incoming) + commonDropbox.createFailureStatus(iBrain2DatasetId, throwable, incoming) \ No newline at end of file diff --git a/integration-tests/templates/data-ibrain2/scripts/hcs_image_segmentation.py b/integration-tests/templates/data-ibrain2/scripts/hcs_image_segmentation.py index 409e1a3331de11a9a13efa829300df5468789208..c61504efbf6a3aed9e3f3d0ed499fbf6fc31f618 100755 --- a/integration-tests/templates/data-ibrain2/scripts/hcs_image_segmentation.py +++ b/integration-tests/templates/data-ibrain2/scripts/hcs_image_segmentation.py @@ -1,13 +1,9 @@ #! /usr/bin/env python # This is a dropbox for importing HCS segmentation image datasets -import IBrain2ImageDataSetConfig from common-image-dropbox - -""" -TODO: -- check if parent exists and exit otherwise (ask Eva) -- -""" +from commonImageDropbox import IBrain2ImageDataSetConfig +from ch.systemsx.cisd.openbis.dss.etl.dto.api.v1 import * + if incoming.isDirectory(): imageDataset = IBrain2ImageDataSetConfig() imageDataset.setSegmentationImageDatasetType()