#! /usr/bin/env python # This is an example Jython dropbox for importing HCS image datasets import os from ch.systemsx.cisd.openbis.dss.etl.dto.api.v1 import * from ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto import Geometry <<<<<<< .mine from ch.systemsx.cisd.common.fileconverter import FileConverter, Tiff2PngConversionStrategy from ch.systemsx.cisd.common.mail import From from ch.systemsx.cisd.openbis.generic.shared.dto import NewProperty # ------------ # Dropbox specific image dataset registration. You may want to modify this part. # ------------ """ type of the new image dataset """ IMAGE_DATASET_TYPE = "HCS_IMAGE" """ file format code of files in a new image dataset """ IMAGE_FILE_FORMAT = "TIFF" """ type of the new analysis dataset """ ANALYSIS_DATASET_TYPE = "HCS_IMAGE_ANALYSIS_DATA" """ file format of the analysis dataset """ ANALYSIS_FILE_FORMAT = "CSV" """ type of the new image overlay dataset """ OVERLAY_IMAGE_DATASET_TYPE = "HCS_IMAGE_SEGMENTATION_OVERLAY" """ file format of the image overlay dataset """ OVERLAY_IMAGE_FILE_FORMAT = "PNG" """ space where the plate for which the dataset has been acquired exist """ PLATE_SPACE = "DEMO" """ only files with these extensions will be recognized as images """ RECOGNIZED_IMAGES_EXTENSIONS = ["tiff", "tif", "png", "gif", "jpg", "jpeg"] """ should thumbnails be generated? """ GENERATE_THUMBNAILS = True """ the maximal width and height of the generated thumbnails """ MAX_THUMNAIL_WIDTH_AND_HEIGHT = 256 """ number of threads that are used for thumbnail generation will be equal to: this constant * number of processor cores """ ALLOWED_MACHINE_LOAD_DURING_THUMBNAIL_GENERATION = 1.0 """ should all dataset in one experiment use the same channels? """ STORE_CHANNELS_ON_EXPERIMENT_LEVEL = False """ should the original data be stored in the original form or should we pack them into one container? """ ORIGINAL_DATA_STORAGE_FORMAT = OriginalDataStorageFormat.UNCHANGED # --------- """ name of the color which should be treated as transparent in overlays """ OVERLAYS_TRANSPARENT_COLOR = "black" """ sample type code of the plate, needed if a new sample is registered automatically """ PLATE_TYPE_CODE = "PLATE" """ project and experiment where new plates will be registered """ DEFAULT_PROJECT_CODE = "TEST" DEFAULT_EXPERIMENT_CODE = "SANOFI" PLATE_GEOMETRY_PROPERTY_CODE = "$PLATE_GEOMETRY" PLATE_GEOMETRY = "384_WELLS_16X24" ANALYSIS_RUN_PROPERTY_CODE = "ANALYSIS_RUN" # --------- """ extracts code of the sample from the directory name """ def extract_sample_code(incoming_name): file_basename = extract_file_basename(incoming_name) #return file_basename.split(".")[0] code = file_basename[file_basename.find("plates_") + 7 : file_basename.rfind("_") ] if code == "": code = file_basename return code """ For a given tile number and tiles geometry returns a (x,y) tuple which describes where the tile is located on the well. """ def get_tile_coords(tile_num, tile_geometry): columns = tile_geometry[1] row = ((tile_num - 1) / columns) + 1 col = ((tile_num - 1) % columns) + 1 return (row, col) """ Parameters: image_tokens_list - list of ImageTokens Returns: (rows, columns) tuple describing the matrix of tiles (aka fields or sides) in the well """ def get_tile_geometry(image_tokens_list): max_tile = get_max_tile_number(image_tokens_list) if max_tile % 4 == 0 and max_tile != 4: return (max_tile / 4, 4) elif max_tile % 3 == 0: return (max_tile / 3, 3) elif max_tile % 2 == 0: return (max_tile / 2, 2) else: return (max_tile, 1) """ Creates ImageFileInfo for a given ImageTokens. Converts tile number to coordinates on the 'well matrix'. Example file name: A - 1(fld 1 wv Cy5 - Cy5).tif Returns: ImageTokens """ def create_image_tokens(path): image_tokens = ImageTokens() image_tokens.path = path basename = os.path.splitext(path)[0] wellText = basename[0:find(basename, "(")] # A - 1 image_tokens.well = wellText.replace(" - ", "") ======= >>>>>>> .r20043 class ImageDataSetFlexible(SimpleImageDataConfig): """ Extracts tile number, channel code and well code for a given relative path to an image. Will be called for each file found in the incoming directory which has the allowed image extension. Example file name: bDZ01-1A_wD17_s3_z123_t321_cGFP Returns: ImageMetadata """ def extractImageMetadata(self, imagePath): image_tokens = ImageMetadata() basename = os.path.splitext(imagePath)[0] # token_dict = {} for token in basename.split("_"): token_dict[token[:1]] = token[1:] image_tokens.well = token_dict["w"] fieldText = token_dict["s"] try: image_tokens.tileNumber = int(fieldText) except ValueError: raise Exception("Cannot parse field number from '" + fieldText + "' in '" + basename + "' file name.") image_tokens.channelCode = token_dict["c"] return image_tokens """ Overrides the default implementation which returns (1, maxTileNumber) geometry. <<<<<<< .mine overlay_dataset.setImageStorageConfiguraton(config) return overlay_dataset_details # --------------------- """ Creates the analysis dataset description. The dataset will be connected to the specified sample and parent dataset. Parameters: dataset - BasicDataSetInformation where the result will be stored """ def set_analysis_dataset(sample_space, sample_code, parent_dataset_code, dataset): dataset.setDatasetTypeCode(ANALYSIS_DATASET_TYPE) dataset.setFileFormatCode(ANALYSIS_FILE_FORMAT) dataset.setSample(sample_space, sample_code) dataset.setMeasured(False) dataset.setParentDatasetCode(parent_dataset_code) """ Creates registration details of the analysis dataset. Returns: DataSetRegistrationDetails """ def create_analysis_dataset_details(sample_space, sample_code, parent_dataset_code, analysis_run): registration_details = factory.createBasicRegistrationDetails() dataset = registration_details.getDataSetInformation() set_analysis_dataset(sample_space, sample_code, parent_dataset_code, dataset) analysis_run_property = NewProperty(ANALYSIS_RUN_PROPERTY_CODE, analysis_run) dataset.setDataSetProperties([ analysis_run_property ]) set_dataset_details(dataset, registration_details) return registration_details """ registers sample if it does not exist already """ def register_sample_if_necessary(space_code, project_code, experiment_code, sample_code): openbis = state.getOpenBisService() sampleIdentifier = SampleIdentifier.create(space_code, sample_code) if (openbis.tryGetSampleWithExperiment(sampleIdentifier) == None): sample = NewSample() sampleType = SampleType() sampleType.setCode(PLATE_TYPE_CODE) sample.setSampleType(sampleType) sample.setIdentifier(sampleIdentifier.toString()) property = dto.VocabularyTermEntityProperty(); vocabularyTerm = dto.VocabularyTerm(); vocabularyTerm.setCode(PLATE_GEOMETRY); property.setVocabularyTerm(vocabularyTerm); propertyType = dto.PropertyType(); dataType = dto.DataType(); dataType.setCode(dto.DataTypeCode.CONTROLLEDVOCABULARY); propertyType.setDataType(dataType); propertyType.setCode(PLATE_GEOMETRY_PROPERTY_CODE); property.setPropertyType(propertyType); sample.setProperties([ property ]) sample.setExperimentIdentifier("/" + space_code + "/" + project_code + "/" + experiment_code) openbis.registerSample(sample, None) # --------------------- def debug(*msg): print "".join(msg) ======= Calculates the width and height of the matrix of tiles (a.k.a. fields or sides) in the well. >>>>>>> .r20043 Parameter imageMetadataList: a list of metadata for each encountered image Parameter maxTileNumber: the biggest tile number among all encountered images Returns: Geometry """ def getTileGeometry(self, imageTokens, maxTileNumber): return Geometry.createFromRowColDimensions(maxTileNumber / 3, 3); """ Overrides the default implementation which does the same thing (to demonstrate how this can be done). For a given tile number and tiles geometry returns (x,y) which describes where the tile is located on the well. Parameter tileNumber: number of the tile Parameter tileGeometry: the geometry of the well matrix Returns: Location """ def getTileCoordinates(self, tileNumber, tileGeometry): columns = tileGeometry.getWidth() row = ((tileNumber - 1) / columns) + 1 col = ((tileNumber - 1) % columns) + 1 return Location(row, col) <<<<<<< .mine # create the image data set and put everything in it initially image_data_set = tr.createNewDataSet(image_dataset_details) image_data_set_folder = tr.moveFile(incoming.getPath(), image_data_set) img_dataset_code = image_data_set.getDataSetCode() # move overlays folder overlays_dir = find_dir(File(image_data_set_folder), OVERLAYS_DIR_PATTERN) if overlays_dir != None: tr_overlays = service.transaction(overlays_dir, factory) convert_to_png(overlays_dir.getPath(), OVERLAYS_TRANSPARENT_COLOR) overlay_dataset_details = create_overlay_dataset_details(overlays_dir, image_dataset_details.getDataSetInformation(), img_dataset_code, "png") overlays_data_set = tr_overlays.createNewDataSet(overlay_dataset_details) tr_overlays.moveFile(overlays_dir.getPath(), overlays_data_set, "overlays") tr_overlays.commit() ======= if incoming.isDirectory(): imageDataset = ImageDataSetFlexible() imageDataset.setRawImageDatasetType() imageDataset.setPlate("TEST", incoming.getName()) factory.registerImageDataset(imageDataset, incoming, service) >>>>>>> .r20043 <<<<<<< .mine # transform and move analysis file analysis_file = find_file_by_ext(File(image_data_set_folder), "xml") if analysis_file != None: tr_analysis = service.transaction(analysis_file, factory) analysis_run = extract_file_basename(analysis_file.getName()) analysis_registration_details = create_analysis_dataset_details( space_code, plate_code, img_dataset_code, analysis_run) analysis_data_set = tr_analysis.createNewDataSet(analysis_registration_details) analysis_data_set_file = tr_analysis.createNewFile(analysis_data_set, analysis_file.getName()) GEExplorerImageAnalysisResultParser(analysis_file.getPath()).writeCSV(File(analysis_data_set_file)) tr_analysis.commit() service.commit() notify(plate_code) register_images_with_overlays_and_analysis(incoming) ======= >>>>>>> .r20043