From 1f916bd1c0d2fafba363b8c8ce259eb24c760b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sophia=20M=C3=A4dler?= <15019107+sophiamaedler@users.noreply.github.com> Date: Fri, 21 Feb 2025 13:10:26 +0100 Subject: [PATCH] remove deprecated timecourse code --- src/scportrait/pipeline/project.py | 1003 ----------------- .../pipeline/segmentation/segmentation.py | 445 -------- .../pipeline/segmentation/workflows.py | 120 -- 3 files changed, 1568 deletions(-) diff --git a/src/scportrait/pipeline/project.py b/src/scportrait/pipeline/project.py index fb5cf2c3..20b86465 100644 --- a/src/scportrait/pipeline/project.py +++ b/src/scportrait/pipeline/project.py @@ -1249,1006 +1249,3 @@ def select( name=name, ) self.get_project_status() - - -# this class has not yet been set up to be used with spatialdata -# class TimecourseProject(Project): -# """ -# TimecourseProject class used to create a scPortrait project for datasets that have multiple fields of view that should be processed and analysed together. -# It is also capable of handling multiple timepoints for the same field of view or a combiantion of both. Like the base scPortrait :func:`Project `, -# it manages all of the scPortrait processing steps. Because the input data has a different dimensionality than the base scPortrait :func:`Project ` class, -# it requires the use of specialized processing classes that are able to handle this additional dimensionality. - -# Parameters -# ---------- -# location_path : str -# Path to the folder where to project should be created. The folder is created in case the specified folder does not exist. -# config_path : str, optional, default "" -# Path pointing to a valid configuration file. The file will be copied to the project directory and renamed to the name specified in ``DEFAULT_FEATURIZATION_DIR_NAME``. If no config is specified, the existing config in the project directory will be used, if possible. See the section configuration to find out more about the config file. -# debug : bool, default False -# When set to True debug outputs will be printed where applicable. -# overwrite : bool, default False -# When set to True, the processing step directory will be completely deleted and newly created when called. -# segmentation_f : Class, default None -# Class containing segmentation workflow. -# extraction_f : Class, default None -# Class containing extraction workflow. -# featurization_f : Class, default None -# Class containing featurization workflow. -# selection_f : Class, default None -# Class containing selection workflow. - -# Attributes -# ---------- -# DEFAULT_CONFIG_NAME : str, default "config.yml" -# Default config name which is used for the config file in the project directory. This name needs to be used when no config is supplied and the config is manually created in the project folder. -# DEFAULT_INPUT_IMAGE_NAME: str, default "input_segmentation.h5" -# Default file name for loading the input image. -# DEFAULT_SEGMENTATION_DIR_NAME : str, default "segmentation" -# Default foldername for the segmentation process. -# DEFAULT_EXTRACTION_DIR_NAME : str, default "extraction" -# Default foldername for the extraction process. -# DEFAULT_FEATURIZATION_DIR_NAME : str, default "selection" -# Default foldername for the featurization process. -# DEFAULT_SELECTION_DIR_NAME : str, default "featurization" -# Default foldername for the selection process. -# """ - -# DEFAULT_INPUT_IMAGE_NAME = "input_segmentation.h5" - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - -# def load_input_from_array(self, img, label, overwrite=False): -# """ -# Function to load imaging data from an array into the TimecourseProject. - -# The provided array needs to fullfill the following conditions: -# - shape: NCYX -# - all images need to have the same dimensions and the same number of channels -# - channels need to be in the following order: nucleus, cytosol other channels -# - dtype uint16. - -# Parameters -# ---------- -# img : numpy.ndarray -# Numpy array of shape “[num_images, channels, height, width]”. -# label : numpy.ndarray -# Numpy array of shape “[num_images, num_labels]” containing the labels for each image. The labels need to have the following structure: "image_index", "unique_image_identifier", "..." -# overwrite : bool, default False -# If set to True, the function will overwrite the existing input image. -# """ - -# """ -# Function to load imaging data from an array into the TimecourseProject. - -# The provided array needs to fullfill the following conditions: -# - shape: NCYX -# - all images need to have the same dimensions and the same number of channels -# - channels need to be in the following order: nucleus, cytosol other channels -# - dtype uint16. - -# Parameters -# ---------- -# img : numpy.ndarray -# Numpy array of shape “[num_images, channels, height, width]”. -# label : numpy.ndarray -# Numpy array of shape “[num_images, num_labels]” containing the labels for each image. The labels need to have the following structure: "image_index", "unique_image_identifier", "..." -# overwrite : bool, default False -# If set to True, the function will overwrite the existing input image. -# """ - -# # check if already exists if so throw error message -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# if not overwrite: -# if os.path.isfile(path): -# sys.exit("File already exists") -# else: -# overwrite = True - -# if overwrite: -# # column labels -# column_labels = label.columns.to_list() - -# # create .h5 dataset to which all results are written -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) -# hf = h5py.File(path, "w") -# dt = h5py.special_dtype(vlen=str) -# hf.create_dataset("label_names", data=column_labels, chunks=None, dtype=dt) -# hf.create_dataset( -# "labels", data=label.astype(str).values, chunks=None, dtype=dt -# ) -# hf.create_dataset( -# "input_images", data=img, chunks=(1, 1, img.shape[2], img.shape[2]) -# ) - -# hf.close() - -# def load_input_from_files( -# self, -# input_dir, -# channels, -# timepoints, -# plate_layout, -# img_size=1080, -# overwrite=False, -# ): -# """ -# Function to load timecourse experiments recorded with an opera phenix into the TimecourseProject. - -# Before being able to use this function the exported images from the opera phenix first need to be parsed, sorted and renamed using the `sparcstools package `_. - -# In addition a plate layout file needs to be created that contains the information on imaged experiment and the experimental conditions for each well. This file needs to be in the following format, -# using the well notation ``RowXX_WellXX``: - -# .. csv-table:: -# :header: "Well", "Condition1", "Condition2", ... -# :widths: auto - -# "RowXX_WellXX", "A", "B", ... - -# A tab needs to be used as a seperator and the file saved as a .tsv file. - -# Parameters -# ---------- -# input_dir : str -# Path to the directory containing the sorted images from the opera phenix. -# channels : list(str) -# List containing the names of the channels that should be loaded. -# timepoints : list(str) -# List containing the names of the timepoints that should be loaded. Will return a warning if you try to load a timepoint that is not found in the data. -# plate_layout : str -# Path to the plate layout file. For the format please see above. -# img_size : int, default 1080 -# Size of the images that should be loaded. All images will be cropped to this size. -# overwrite : bool, default False -# If set to True, the function will overwrite the existing input image. - -# Example -# ------- -# >>> channels = ["DAPI", "Alexa488", "mCherry"] -# >>> timepoints = ["Timepoint"+str(x).zfill(3) for x in list(range(1, 3))] -# >>> input_dir = "path/to/sorted/outputs/from/sparcstools" -# >>> plate_layout = "plate_layout.tsv" - -# >>> project.load_input_from_files(input_dir = input_dir, channels = channels, timepoints = timepoints, plate_layout = plate_layout, overwrite = True) - -# Function to load timecourse experiments recorded with an opera phenix into the TimecourseProject. - -# Before being able to use this function the exported images from the opera phenix first need to be parsed, sorted and renamed using the `sparcstools package `_. - -# In addition a plate layout file needs to be created that contains the information on imaged experiment and the experimental conditions for each well. This file needs to be in the following format, -# using the well notation ``RowXX_WellXX``: - -# .. csv-table:: -# :header: "Well", "Condition1", "Condition2", ... -# :widths: auto - -# "RowXX_WellXX", "A", "B", ... - -# A tab needs to be used as a seperator and the file saved as a .tsv file. - -# Parameters -# ---------- -# input_dir : str -# Path to the directory containing the sorted images from the opera phenix. -# channels : list(str) -# List containing the names of the channels that should be loaded. -# timepoints : list(str) -# List containing the names of the timepoints that should be loaded. Will return a warning if you try to load a timepoint that is not found in the data. -# plate_layout : str -# Path to the plate layout file. For the format please see above. -# img_size : int, default 1080 -# Size of the images that should be loaded. All images will be cropped to this size. -# overwrite : bool, default False -# If set to True, the function will overwrite the existing input image. - -# Example -# ------- -# >>> channels = ["DAPI", "Alexa488", "mCherry"] -# >>> timepoints = ["Timepoint"+str(x).zfill(3) for x in list(range(1, 3))] -# >>> input_dir = "path/to/sorted/outputs/from/sparcstools" -# >>> plate_layout = "plate_layout.tsv" - -# >>> project.load_input_from_files(input_dir = input_dir, channels = channels, timepoints = timepoints, plate_layout = plate_layout, overwrite = True) - -# """ - -# # check if already exists if so throw error message -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# if not overwrite: -# if os.path.isfile(path): -# sys.exit("File already exists") -# else: -# overwrite = True - -# if overwrite: -# self.img_size = img_size - -# def _read_write_images(dir, indexes, h5py_path): -# # unpack indexes -# index_start, index_end = indexes - -# # get information on directory -# well = re.search( -# "Row.._Well[0-9][0-9]", dir -# ).group() # need to use re.search and not match sinde the identifier is not always at the beginning of the name -# region = re.search("r..._c...$", dir).group() - -# # list all images within directory -# path = os.path.join(input_dir, dir) -# files = os.listdir(path) - -# # filter to only contain the timepoints of interest -# files = np.sort([x for x in files if x.startswith(tuple(timepoints))]) - -# # checkt to make sure all timepoints are actually there -# _timepoints = np.unique( -# [re.search("Timepoint[0-9][0-9][0-9]", x).group() for x in files] -# ) - -# sum = 0 -# for timepoint in timepoints: -# if timepoint in _timepoints: -# sum += 1 -# continue -# else: -# print(f"No images found for Timepoint {timepoint}") - -# self.log( -# f"{sum} different timepoints found of the total {len(timepoints)} timepoints given." -# ) - -# # read images for that region -# imgs = np.empty( -# (n_timepoints, n_channels, img_size, img_size), dtype="uint16" -# ) -# for ix, channel in enumerate(channels): -# images = [x for x in files if channel in x] - -# for i, im in enumerate(images): -# image = imread(os.path.join(path, im)) - -# if isinstance(image.dtype, np.uint8): -# image = image.astype("uint16") * np.iinfo(np.uint8).max - -# self._check_image_dtype(image) -# imgs[i, ix, :, :] = image.astype("uint16") - -# # create labelling -# column_values = [] -# for column in plate_layout.columns: -# column_values.append(plate_layout.loc[well, column]) - -# list_input = [ -# list(range(index_start, index_end)), -# [dir + "_" + x for x in timepoints], -# [dir] * n_timepoints, -# timepoints, -# [well] * n_timepoints, -# [region] * n_timepoints, -# ] -# list_input = [np.array(x) for x in list_input] - -# for x in column_values: -# list_input.append(np.array([x] * n_timepoints)) - -# labelling = np.array(list_input).T - -# input_images[index_start:index_end, :, :, :] = imgs -# labels[index_start:index_end] = labelling - -# # read plate layout -# plate_layout = pd.read_csv(plate_layout, sep="\s+|;|,", engine="python") -# plate_layout = plate_layout.set_index("Well") - -# column_labels = [ -# "index", -# "ID", -# "location", -# "timepoint", -# "well", -# "region", -# ] + plate_layout.columns.tolist() - -# # get information on number of timepoints and number of channels -# n_timepoints = len(timepoints) -# n_channels = len(channels) -# wells = np.unique(plate_layout.index.tolist()) - -# # get all directories contained within the input dir -# directories = os.listdir(input_dir) -# if ".DS_Store" in directories: -# directories.remove( -# ".DS_Store" -# ) # need to remove this because otherwise it gives errors -# if ".ipynb_checkpoints" in directories: -# directories.remove(".ipynb_checkpoints") - -# # filter directories to only contain those listed in the plate layout -# directories = [ -# _dir -# for _dir in directories -# if re.search("Row.._Well[0-9][0-9]", _dir).group() in wells -# ] - -# # check to ensure that imaging data is found for all wells listed in plate_layout -# _wells = [ -# re.search("Row.._Well[0-9][0-9]", _dir).group() for _dir in directories -# ] -# not_found = [well for well in _wells if well not in wells] -# if len(not_found) > 0: -# print( -# "following wells listed in plate_layout not found in imaging data:", -# not_found, -# ) -# self.log( -# f"following wells listed in plate_layout not found in imaging data: {not_found}" -# ) - -# # check to make sure that timepoints given and timepoints found in data acutally match! -# _timepoints = [] - -# # create .h5 dataset to which all results are written -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# # for some reason this directory does not always exist so check to make sure it does otherwise the whole reading of stuff fails -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# with h5py.File(path, "w") as hf: -# dt = h5py.special_dtype(vlen=str) -# hf.create_dataset( -# "label_names", (len(column_labels)), chunks=None, dtype=dt -# ) -# hf.create_dataset( -# "labels", -# (len(directories) * n_timepoints, len(column_labels)), -# chunks=None, -# dtype=dt, -# ) - -# hf.create_dataset( -# "input_images", -# (len(directories) * n_timepoints, n_channels, img_size, img_size), -# chunks=(1, 1, img_size, img_size), -# dtype="uint16", -# ) - -# label_names = hf.get("label_names") -# labels = hf.get("labels") -# input_images = hf.get("input_images") - -# label_names[:] = column_labels - -# # ------------------ -# # start reading data -# # ------------------ - -# indexes = [] -# # create indexes -# start_index = 0 -# for i, _ in enumerate(directories): -# stop_index = start_index + n_timepoints -# indexes.append((start_index, stop_index)) -# start_index = stop_index - -# # iterate through all directories and add to .h5 -# # this is not implemented with multithreaded processing because writing multi-threaded to hdf5 is hard -# # multithreaded reading is easier - -# for dir, index in tqdm( -# zip(directories, indexes), total=len(directories) -# ): -# _read_write_images(dir, index, h5py_path=path) - -# def load_input_from_stitched_files( -# self, -# input_dir, -# channels, -# timepoints, -# plate_layout, -# overwrite=False, -# ): -# """ -# Function to load timecourse experiments recorded with opera phenix into .h5 dataformat for further processing. -# Assumes that stitched images for all files have already been assembled. - -# Args: -# input_dir (str): path to directory containing the stitched images -# channels (list(str)): list of strings indicating which channels should be loaded -# timepoints (list(str)): list of strings indicating which timepoints should be loaded -# plate_layout (str): path to csv file containing the plate layout -# overwrite (bool, optional): boolean indicating if existing files should be overwritten. Defaults to False. -# """ - -# # check if already exists if so throw error message -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# if not overwrite: -# if os.path.isfile(path): -# sys.exit("File already exists") -# else: -# overwrite = True - -# if overwrite: - -# def _read_write_images(well, indexes, h5py_path): -# # unpack indexes -# index_start, index_end = indexes - -# # list all images for that well -# _files = [_file for _file in files if well in _file] - -# # filter to only contain the timepoints of interest -# _files = np.sort([x for x in _files if x.startswith(tuple(timepoints))]) - -# # checkt to make sure all timepoints are actually there -# _timepoints = np.unique( -# [re.search("Timepoint[0-9][0-9][0-9]", x).group() for x in _files] -# ) - -# sum = 0 -# for timepoint in timepoints: -# if timepoint in _timepoints: -# sum += 1 -# continue -# else: -# print(f"No images found for Timepoint {timepoint}") - -# self.log( -# f"{sum} different timepoints found of the total {len(timepoints)} timepoints given." -# ) - -# # read images for that region -# imgs = np.empty( -# (n_timepoints, n_channels, size1, size2), dtype="uint16" -# ) -# for ix, channel in enumerate(channels): -# images = [x for x in _files if channel in x] - -# for i, im in enumerate(images): -# image = imread(os.path.join(input_dir, im), 0).astype("uint16") - -# # check if image is too small and if yes, pad the image with black pixels -# if image.shape[0] < size1 or image.shape[1] < size2: -# image = np.pad( -# image, -# ( -# (0, np.max((size1 - image.shape[0], 0))), -# (0, np.max((size2 - image.shape[1], 0))), -# ), -# mode="constant", -# constant_values=0, -# ) -# self.log( -# f"Image {im} with the index {i} is too small and was padded with black pixels. " -# f"Image shape after padding: {image.shape}." -# ) - -# # perform cropping so that all stitched images have the same size -# x, y = image.shape -# diff1 = x - size1 -# diff1x = int(np.floor(diff1 / 2)) -# diff1y = int(np.ceil(diff1 / 2)) -# diff2 = y - size2 -# diff2x = int(np.floor(diff2 / 2)) -# diff2y = int(np.ceil(diff2 / 2)) - -# cropped = image[ -# slice(diff1x, x - diff1y), slice(diff2x, y - diff2y) -# ] - -# imgs[i, ix, :, :] = cropped - -# # create labelling -# column_values = [] -# for column in plate_layout.columns: -# column_values.append(plate_layout.loc[well, column]) - -# list_input = [ -# list(range(index_start, index_end)), -# [well + "_" + x for x in timepoints], -# [well] * n_timepoints, -# timepoints, -# [well] * n_timepoints, -# ] -# list_input = [np.array(x) for x in list_input] - -# for x in column_values: -# list_input.append(np.array([x] * n_timepoints)) - -# labelling = np.array(list_input).T - -# input_images[index_start:index_end, :, :, :] = imgs -# labels[index_start:index_end] = labelling - -# # read plate layout -# plate_layout = pd.read_csv(plate_layout, sep="\s+|;|,", engine="python") -# plate_layout = plate_layout.set_index("Well") - -# column_labels = [ -# "index", -# "ID", -# "location", -# "timepoint", -# "well", -# ] + plate_layout.columns.tolist() - -# # get information on number of timepoints and number of channels -# n_timepoints = len(timepoints) -# n_channels = len(channels) -# wells = np.unique(plate_layout.index.tolist()) - -# # get all files contained within the input dir -# files = os.listdir(input_dir) -# files = [file for file in files if file.endswith(".tif")] - -# # filter directories to only contain those listed in the plate layout -# files = [ -# _dir -# for _dir in files -# if re.search("Row.._Well[0-9][0-9]", _dir).group() in wells -# ] - -# # check to ensure that imaging data is found for all wells listed in plate_layout -# _wells = [re.search("Row.._Well[0-9][0-9]", _dir).group() for _dir in files] -# not_found = [well for well in _wells if well not in wells] -# if len(not_found) > 0: -# print( -# "following wells listed in plate_layout not found in imaging data:", -# not_found, -# ) -# self.log( -# f"following wells listed in plate_layout not found in imaging data: {not_found}" -# ) - -# # get image size and subtract 10 pixels from each edge -# # will adjust all merged images to this dimension to ensure that they all have the same dimensions and can be loaded into the same hdf5 file -# size1, size2 = imagesize.get(os.path.join(input_dir, files[0])) -# size1 = size1 - 2 * 10 -# size2 = size2 - 2 * 10 -# self.img_size = (size1, size2) - -# # create .h5 dataset to which all results are written -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# # for some reason this directory does not always exist so check to make sure it does otherwise the whole reading of stuff fails -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# with h5py.File(path, "w") as hf: -# dt = h5py.special_dtype(vlen=str) -# hf.create_dataset( -# "label_names", (len(column_labels)), chunks=None, dtype=dt -# ) -# hf.create_dataset( -# "labels", -# (len(wells) * n_timepoints, len(column_labels)), -# chunks=None, -# dtype=dt, -# ) -# hf.create_dataset( -# "input_images", -# (len(wells) * n_timepoints, n_channels, size1, size2), -# chunks=(1, 1, size1, size2), -# dtype="uint16", -# ) - -# label_names = hf.get("label_names") -# labels = hf.get("labels") -# input_images = hf.get("input_images") - -# label_names[:] = column_labels - -# # ------------------ -# # start reading data -# # ------------------ - -# indexes = [] -# # create indexes -# start_index = 0 -# for i, _ in enumerate(wells): -# stop_index = start_index + n_timepoints -# indexes.append((start_index, stop_index)) -# start_index = stop_index - -# # iterate through all directories and add to .h5 -# # this is not implemented with multithreaded processing because writing multi-threaded to hdf5 is hard -# # multithreaded reading is easier - -# for well, index in tqdm(zip(wells, indexes), total=len(wells)): -# _read_write_images(well, index, h5py_path=path) - -# def load_input_from_files_and_merge( -# self, -# input_dir, -# channels, -# timepoints, -# plate_layout, -# img_size=1080, -# stitching_channel="Alexa488", -# overlap=0.1, -# max_shift=10, -# overwrite=False, -# nucleus_channel="DAPI", -# cytosol_channel="Alexa488", -# ): -# """ -# Function to load timecourse experiments recorded with an opera phenix into a TimecourseProject. In addition to loading the images, -# this wrapper function also stitches images acquired in the same well (this assumes that the tiles were aquired with overlap and in a rectangular shape) -# using the `sparcstools package `_. Implementation of this function is currently still slow for many wells/timepoints as stitching -# is handled consecutively and not in parallel. This will be fixed in the future. - -# Parameters -# ---------- -# input_dir : str -# Path to the directory containing the sorted images from the opera phenix. -# channels : list(str) -# List containing the names of the channels that should be loaded. -# timepoints : list(str) -# List containing the names of the timepoints that should be loaded. Will return a warning if you try to load a timepoint that is not found in the data. -# plate_layout : str -# Path to the plate layout file. For the format please see above. -# img_size : int, default 1080 -# Size of the images that should be loaded. All images will be cropped to this size. -# stitching_channel : str, default "Alexa488" -# string indicated on which channel the stitching should be calculated. -# overlap : float, default 0.1 -# float indicating the overlap between the tiles that were aquired. -# max_shift : int, default 10 -# int indicating the maximum shift that is allowed when stitching the tiles. If a calculated shift is larger than this threshold -# between two tiles then the position of these tiles is not updated and is set according to the calculated position based on the overlap. -# overwrite : bool, default False -# If set to True, the function will overwrite the existing input image. -# nucleus_channel : str, default "DAPI" -# string indicating the channel that should be used for the nucleus channel. -# cytosol_channel : str, default "Alexa488" -# string indicating the channel that should be used for the cytosol channel. - -# """ - -# from sparcstools.stitch import generate_stitched - -# # check if already exists if so throw error message -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# if not overwrite: -# if os.path.isfile(path): -# sys.exit("File already exists.") -# else: -# overwrite = True - -# if overwrite: -# self.img_size = img_size - -# self.log(f"Reading all images included in directory {input_dir}.") - -# images = os.listdir(input_dir) -# images = [x for x in images if x.endswith((".tiff", ".tif"))] - -# _timepoints = np.sort(list(set([x.split("_")[0] for x in images]))) -# _wells = np.sort( -# list( -# set( -# [ -# re.match(".*_Row[0-9][0-9]_Well[0-9][0-9]", x).group()[13:] -# for x in images -# ] -# ) -# ) -# ) - -# # apply filtering to only get those that are in the plate layout file -# plate_layout = pd.read_csv(plate_layout, sep="\s+|;|,", engine="python") -# plate_layout = plate_layout.set_index("Well") - -# column_labels = [ -# "index", -# "ID", -# "location", -# "timepoint", -# "well", -# "region", -# ] + plate_layout.columns.tolist() - -# # get information on number of timepoints and number of channels -# n_timepoints = len(timepoints) -# n_channels = len(channels) -# wells = np.unique(plate_layout.index.tolist()) - -# _wells = [x for x in _wells if x in wells] -# _timepoints = [x for x in _timepoints if x in timepoints] - -# not_found_wells = [well for well in _wells if well not in wells] -# not_found_timepoints = [ -# timepoint for timepoint in _timepoints if timepoint not in timepoints -# ] - -# if len(not_found_wells) > 0: -# print( -# "following wells listed in plate_layout not found in imaging data:", -# not_found_wells, -# ) -# self.log( -# f"following wells listed in plate_layout not found in imaging data: {not_found_wells}" -# ) - -# if len(not_found_timepoints) > 0: -# print( -# "following timepoints given not found in imaging data:", -# not_found_timepoints, -# ) -# self.log( -# f"following timepoints given not found in imaging data: {not_found_timepoints}" -# ) - -# self.log("Will perform merging over the following specs:") -# self.log(f"Wells: {_wells}") -# self.log(f"Timepoints: {_timepoints}") - -# # create .h5 dataset to which all results are written -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) - -# # for some reason this directory does not always exist so check to make sure it does otherwise the whole reading of stuff fails -# if not os.path.isdir( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ): -# os.makedirs( -# os.path.join(self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME) -# ) - -# with h5py.File(path, "w") as hf: -# dt = h5py.special_dtype(vlen=str) -# hf.create_dataset( -# "label_names", (len(column_labels)), chunks=None, dtype=dt -# ) -# hf.create_dataset( -# "labels", -# (len(_wells) * n_timepoints, len(column_labels)), -# chunks=None, -# dtype=dt, -# ) -# label_names = hf.get("label_names") -# labels = hf.get("labels") - -# label_names[:] = column_labels - -# run_number = 0 -# for timepoint in tqdm(_timepoints): -# for well in tqdm(_wells): -# RowID = well.split("_")[0] -# WellID = well.split("_")[1] -# zstack_value = 1 - -# # define patter to recognize which slide should be stitched -# # remember to adjust the zstack value if you aquired zstacks and want to stitch a speciifc one in the parameters above - -# pattern = ( -# f"{timepoint}_{RowID}_{WellID}" -# + "_{channel}_" -# + "zstack" -# + str(zstack_value).zfill(3) -# + "_r{row:03}_c{col:03}.tif" -# ) - -# merged_images, channels = generate_stitched( -# input_dir, -# well, -# pattern, -# outdir="/", -# overlap=overlap, -# max_shift=max_shift, -# do_intensity_rescale=True, -# stitching_channel=stitching_channel, -# filetype="return_array", -# export_XML=False, -# plot_QC=False, -# ) - -# if run_number == 0: -# img_size1 = merged_images.shape[1] - 2 * 10 -# img_size2 = merged_images.shape[2] - 2 * 10 -# # create this after the first image is stitched and we have the dimensions -# hf.create_dataset( -# "input_images", -# ( -# len(_wells) * n_timepoints, -# n_channels, -# img_size1, -# img_size2, -# ), -# chunks=(1, 1, img_size1, img_size2), -# ) -# input_images = hf.get("input_images") - -# # crop so that all images have the same size -# _, x, y = merged_images.shape -# diff1 = x - img_size1 -# diff1x = int(np.floor(diff1 / 2)) -# diff1y = int(np.ceil(diff1 / 2)) -# diff2 = y - img_size2 -# diff2x = int(np.floor(diff2 / 2)) -# diff2y = int(np.ceil(diff2 / 2)) -# cropped = merged_images[ -# :, slice(diff1x, x - diff1y), slice(diff2x, y - diff2y) -# ] - -# # create labelling -# column_values = [] -# for column in plate_layout.columns: -# column_values.append(plate_layout.loc[well, column]) - -# list_input = [ -# str(run_number), -# f"{well}_{timepoint}_all", -# f"{well}_all", -# timepoint, -# well, -# "stitched", -# ] - -# for x in column_values: -# list_input.append(x) - -# # reorder to fit to timecourse sorting -# allocated_channels = [] -# allocated_indexes = [] -# if nucleus_channel in channels: -# nucleus_index = channels.index(nucleus_channel) -# allocated_channels.append(nucleus_channel) -# allocated_indexes.append(nucleus_index) -# else: -# print("nucleus_channel not found in supplied channels!!!") - -# if cytosol_channel in channels: -# cytosol_index = channels.index(cytosol_channel) -# allocated_channels.append(cytosol_channel) -# allocated_indexes.append(cytosol_index) -# else: -# print("cytosol_channel not found in supplied channels!!!") - -# all_other_indexes = [ -# channels.index(x) -# for x in channels -# if x not in allocated_channels -# ] -# all_other_indexes = list(np.sort(all_other_indexes)) - -# index_list = allocated_indexes + all_other_indexes -# cropped = np.array([cropped[x, :, :] for x in index_list]) - -# self.log( -# f"adjusted channels to the following order: {[channels[i] for i in index_list]}" -# ) -# input_images[run_number, :, :, :] = cropped -# labels[run_number] = list_input -# run_number += 1 -# self.log( -# f"finished stitching and saving well {well} for timepoint {timepoint}." -# ) - -# def adjust_segmentation_indexes(self): -# self.segmentation_f.adjust_segmentation_indexes() - -# def segment(self, overwrite=False, *args, **kwargs): -# """ -# segment timecourse project with the defined segmentation method. -# """ - -# if overwrite: -# # delete segmentation and classes from .hdf5 to be able to create new again -# path = os.path.join( -# self.directory, -# self.DEFAULT_SEGMENTATION_DIR_NAME, -# self.DEFAULT_INPUT_IMAGE_NAME, -# ) -# with h5py.File(path, "a") as hf: -# if "segmentation" in hf.keys(): -# del hf["segmentation"] -# if "classes" in hf.keys(): -# del hf["classes"] - -# # delete generated files to make clean -# classes_path = os.path.join( -# self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME, "classes.csv" -# ) -# log_path = os.path.join( -# self.directory, self.DEFAULT_SEGMENTATION_DIR_NAME, "processing.log" -# ) -# if os.path.isfile(classes_path): -# os.remove(classes_path) -# if os.path.isfile(log_path): -# os.remove(log_path) - -# print("If Segmentation already existed removed.") - -# if self.segmentation_f is None: -# raise ValueError("No segmentation method defined") - -# else: -# self.segmentation_f(*args, **kwargs) - -# def extract(self, *args, **kwargs): -# """ -# Extract single cells from a timecourse project with the defined extraction method. -# """ - -# if self.extraction_f is None: -# raise ValueError("No extraction method defined") - -# input_segmentation = self.segmentation_f.get_output() -# input_dir = os.path.join( -# self.project_location, self.DEFAULT_SEGMENTATION_DIR_NAME, "classes.csv" -# ) -# self.extraction_f(input_segmentation, input_dir, *args, **kwargs) diff --git a/src/scportrait/pipeline/segmentation/segmentation.py b/src/scportrait/pipeline/segmentation/segmentation.py index 71499a39..1fdb71c0 100644 --- a/src/scportrait/pipeline/segmentation/segmentation.py +++ b/src/scportrait/pipeline/segmentation/segmentation.py @@ -1126,448 +1126,3 @@ def complete_segmentation(self, input_image, force_run=False): self._cleanup_shards(sharding_plan_complete, keep_plots=False) self.log("=== completed sharded segmentation === ") - - -############################################# -###### TIMECOURSE/BATCHED METHODS ########### -############################################# - -## These functions have not yet been adapted to the new spatial data format and are not yet functional. - -# class TimecourseSegmentation(Segmentation): -# """Segmentation helper class used for creating segmentation workflows working with timecourse data.""" - -# DEFAULT_SEGMENTATION_FILE = "input_segmentation.h5" -# DEFAULT_INPUT_IMAGE_NAME = "input_segmentation.h5" -# PRINT_MAPS_ON_DEBUG = True -# DEFAULT_CHANNELS_NAME = "input_images" -# DEFAULT_MASK_NAME = "segmentation" - -# channel_colors = [ -# "#e60049", -# "#0bb4ff", -# "#50e991", -# "#e6d800", -# "#9b19f5", -# "#ffa300", -# "#dc0ab4", -# "#b3d4ff", -# "#00bfa0", -# ] - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - -# self.index = None -# self.input_path = None - -# if not hasattr(self, "method"): -# raise AttributeError( -# "No BaseSegmentationType defined, please set attribute ``BaseSegmentationMethod``" -# ) - -# def initialize_as_shard(self, index, input_path, _tmp_seg_path): -# """Initialize Segmentation Step with further parameters needed for federated segmentation. - -# Important: -# This function is intented for internal use by the :class:`ShardedSegmentation` helper class. In most cases it is not relevant to the creation of custom segmentation workflows. - -# Args: -# index (int): Unique indexes of the elements that need to be segmented. -# input_path (str): Location of the input hdf5 file. During sharded segmentation the :class:`ShardedSegmentation` derived helper class will save the input image in form of a hdf5 file. This makes the input image available for parallel reading by the segmentation processes. -# """ -# self.index = index -# self.input_path = input_path -# self._tmp_seg_path = _tmp_seg_path -# self.create_temp_dir() - -# def call_as_shard(self): -# """Wrapper function for calling a sharded segmentation. - -# Important: -# This function is intended for internal use by the :class:`ShardedSegmentation` helper class. In most cases it is not relevant to the creation of custom segmentation workflows. - -# """ -# with h5py.File(self.input_path, "r") as hf: -# hdf_input = hf.get(self.DEFAULT_CHANNELS_NAME) - -# if isinstance(self.index, int): -# self.index = [self.index] - -# for index in self.index: -# self.current_index = index -# input_image = hdf_input[index, :, :, :] - -# self.log(f"Segmentation on index {index} started.") -# try: -# super().__call__(input_image) -# self.clear_temp_dir() -# except Exception: -# self.log(traceback.format_exc()) -# self.clear_temp_dir() -# self.log(f"Segmentation on index {index} completed.") - -# def save_segmentation( -# self, -# input_image, -# labels, -# classes, -# ): -# """ -# Saves the results of a segmentation at the end of the process by transferring it to the initialized -# memory mapped array - -# Args: -# labels (np.array): Numpy array of shape ``(height, width)``. Labels are all data which are saved as integer values. These are mostly segmentation maps with integer values corresponding to the labels of cells. -# classes (list(int)): List of all classes in the labels array, which have passed the filtering step. All classes contained in this list will be extracted. -# """ -# # reconnect to existing HDF5 for memory mapping segmentation results -# _tmp_seg = tempmmap.mmap_array_from_path(self._tmp_seg_path) - -# # size (C, H, W) is expected -# # dims are expanded in case (H, W) is passed -# labels = np.expand_dims(labels, axis=0) if len(labels.shape) == 2 else labels -# classes = np.array(list(classes)) - -# self.log(f"transferring {self.current_index} to temmporray memory mapped array") -# _tmp_seg[self.current_index] = labels - -# # close connect to temmpmmap file again -# del _tmp_seg - -# def _initialize_tempmmap_array(self): -# # create an empty HDF5 file prepared for using as a memory mapped temp array to save segmentation results to -# # this required when trying to segment so many images that the results can no longer fit into memory -# _tmp_seg_path = tempmmap.create_empty_mmap( -# shape=self.shape_segmentation, -# dtype=self.DEFAULT_SEGMENTATION_DTYPE, -# tmp_dir_abs_path=self._tmp_dir_path, -# ) -# self._tmp_seg_path = _tmp_seg_path - -# def _transfer_tempmmap_to_hdf5(self): -# _tmp_seg = tempmmap.mmap_array_from_path(self._tmp_seg_path) -# input_path = os.path.join(self.directory, self.DEFAULT_SEGMENTATION_FILE) - -# # create hdf5 datasets with temp_arrays as input -# with h5py.File(input_path, "a") as hf: -# # check if dataset already exists if so delete and overwrite -# if self.DEFAULT_MASK_NAME in hf.keys(): -# del hf[self.DEFAULT_MASK_NAME] -# self.log( -# "segmentation dataset already existe in hdf5, deleted and overwritten." -# ) -# hf.create_dataset( -# self.DEFAULT_MASK_NAME, -# shape=_tmp_seg.shape, -# chunks=(1, 2, self.shape_input_images[2], self.shape_input_images[3]), -# dtype=self.DEFAULT_SEGMENTATION_DTYPE, -# ) - -# # using this loop structure ensures that not all results are loaded in memory at any one timepoint -# for i in range(_tmp_seg.shape[0]): -# hf[self.DEFAULT_MASK_NAME][i] = _tmp_seg[i] - -# dt = h5py.special_dtype(vlen=self.DEFAULT_SEGMENTATION_DTYPE) - -# if "classes" in hf.keys(): -# del hf["classes"] -# self.log( -# "classes dataset already existed in hdf5, deleted and overwritten." -# ) - -# hf.create_dataset( -# "classes", -# shape=self.shape_classes, -# maxshape=(None), -# chunks=None, -# dtype=dt, -# ) - -# gc.collect() - -# def save_image(self, array, save_name="", cmap="magma", **kwargs): -# if np.issubdtype(array.dtype.type, np.integer): -# self.log(f"{save_name} will be saved as tif") -# data = array.astype(np.uint16) -# im = Image.fromarray(data) -# im.save(f"{save_name}.tif") - -# fig = plt.figure(frameon=False) -# fig.set_size_inches((10, 10)) -# ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0]) -# ax.set_axis_off() - -# fig.add_axes(ax) -# ax.imshow(array, cmap=cmap, **kwargs) - -# if save_name != "": -# plt.savefig(f"{save_name}.png") -# plt.show() -# plt.close() - -# def adjust_segmentation_indexes(self): -# """ -# The function iterates over all present segmented files and adjusts the indexes so that they are unique throughout. -# """ - -# self.log("resolve segmentation indexes") - -# path = os.path.join(self.directory, self.DEFAULT_INPUT_IMAGE_NAME) - -# with h5py.File(path, "a") as hf: -# hdf_labels = hf.get(self.DEFAULT_MASK_NAME) -# hdf_classes = hf.get("classes") - -# class_id_shift = 0 -# filtered_classes_combined = [] -# edge_classes_combined = [] - -# for i in tqdm( -# range(0, hdf_labels.shape[0]), -# total=hdf_labels.shape[0], -# desc="Adjusting Indexes", -# ): -# individual_hdf_labels = hdf_labels[i, :, :, :] -# num_shapes = np.max(individual_hdf_labels) -# shifted_map, edge_labels = shift_labels( -# individual_hdf_labels, class_id_shift, return_shifted_labels=True -# ) -# hdf_labels[i, :, :] = shifted_map - -# if set(np.unique(shifted_map[0])) != set(np.unique(shifted_map[1])): -# self.log( -# "Warning: Different classes in different segmentatio channels. Please report this example to the developers" -# ) -# self.log("set1 nucleus: set(np.unique(shifted_map[0]))") -# self.log("set2 cytosol: set(np.unique(shifted_map[1]))") - -# self.log( -# f"{set(np.unique(shifted_map[1]))- set(np.unique(shifted_map[0]))} not in nucleus mask" -# ) -# self.log( -# f"{set(np.unique(shifted_map[0]))- set(np.unique(shifted_map[1]))} not in cytosol mask" -# ) - -# filtered_classes = set(np.unique(shifted_map[0])) - set( -# [0] -# ) # remove background class -# final_classes = list(filtered_classes - set(edge_labels)) - -# hdf_labels[i, :, :] = shifted_map -# hdf_classes[i] = np.array(final_classes, dtype=self.DEFAULT_SEGMENTATION_DTYPE).reshape( -# 1, 1, -1 -# ) - -# # save all cells in general -# filtered_classes_combined.extend(filtered_classes) -# edge_classes_combined.extend(edge_labels) - -# # adjust class_id shift -# class_id_shift += num_shapes - -# edge_classes_combined = set(edge_classes_combined) -# classes_after_edges = list( -# set(filtered_classes_combined) - edge_classes_combined -# ) - -# self.log("Number of filtered classes combined after segmentation:") -# self.log(len(filtered_classes_combined)) - -# self.log("Number of classes in contact with image edges:") -# self.log(len(edge_classes_combined)) - -# self.log("Number of classes after removing image edges:") -# self.log(len(classes_after_edges)) - -# # save newly generated class list -# self.save_classes(classes_after_edges) - -# # sanity check of class reconstruction -# if self.debug: -# all_classes = set(hdf_labels[:].flatten()) -# if set(edge_classes_combined).issubset(set(all_classes)): -# self.log( -# "Sharding sanity check: edge classes are a full subset of all classes" -# ) -# elif len(set(all_classes)) - len(set(edge_classes_combined)) == len( -# set(classes_after_edges) -# ): -# self.log( -# "Sharding sanity check: sum of edge classes and classes after edges is equal to all classes." -# ) -# else: -# self.log( -# "Sharding sanity check: edge classes are NOT a full subset of all classes." -# ) - -# self.log("resolved segmentation list") - -# def process(self): -# input_path = os.path.join(self.directory, self.DEFAULT_SEGMENTATION_FILE) - -# with h5py.File(input_path, "r") as hf: -# input_images = hf.get(self.DEFAULT_CHANNELS_NAME) -# indexes = list(range(0, input_images.shape[0])) - -# # initialize segmentation dataset -# self.shape_input_images = input_images.shape -# self.shape_segmentation = ( -# input_images.shape[0], -# self.config["output_masks"], -# input_images.shape[2], -# input_images.shape[3], -# ) -# self.shape_classes = input_images.shape[0] - -# # initialize temp object to write segmentations too -# self._initialize_tempmmap_array() - -# self.log("Beginning segmentation without multithreading.") - -# # initialzie segmentation objects -# current_shard = self.method( -# self.config, -# self.directory, -# project_location=self.project_location, -# debug=self.debug, -# overwrite=self.overwrite, -# ) - -# current_shard.initialize_as_shard( -# indexes, input_path=input_path, _tmp_seg_path=self._tmp_seg_path -# ) - -# # calculate results for each shard -# results = [current_shard.call_as_shard()] - -# # save results to hdf5 -# self.log("Writing segmentation results to .hdf5 file.") -# self._transfer_tempmmap_to_hdf5() - -# # adjust segmentation indexes -# self.adjust_segmentation_indexes() -# self.log("Adjusted Indexes.") - - -# class MultithreadedSegmentation(TimecourseSegmentation): -# DEFAULT_SEGMENTATION_FILE = "input_segmentation.h5" -# DEFAULT_INPUT_IMAGE_NAME = "input_segmentation.h5" - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - -# if not hasattr(self, "method"): -# raise AttributeError( -# "No Segmentation method defined, please set attribute ``method``" -# ) - -# def initializer_function(self, gpu_id_list): -# current_process().gpu_id_list = gpu_id_list - -# def process(self): -# input_path = os.path.join(self.directory, self.DEFAULT_SEGMENTATION_FILE) - -# with h5py.File(input_path, "r") as hf: -# input_images = hf.get(self.DEFAULT_CHANNELS_NAME) -# indexes = list(range(0, input_images.shape[0])) - -# # initialize segmentation dataset -# self.shape_input_images = input_images.shape -# self.shape_segmentation = ( -# input_images.shape[0], -# self.config["output_masks"], -# input_images.shape[2], -# input_images.shape[3], -# ) -# self.shape_classes = input_images.shape[0] - -# # initialize temp object to write segmentations too -# self._initialize_tempmmap_array() -# segmentation_list = self.initialize_shard_list( -# indexes, input_path=input_path, _tmp_seg_path=self._tmp_seg_path -# ) - -# # make more verbose output for troubleshooting and timing purposes. -# n_threads = self.config["threads"] -# self.log(f"Beginning segmentation with {n_threads} threads.") -# self.log(f"A total of {len(segmentation_list)} processes need to be executed.") - -# # check that that number of GPUS is actually available -# if "nGPUS" not in self.config.keys(): -# self.config["nGPUs"] = torch.cuda.device_count() - -# nGPUS = self.config["nGPUs"] -# available_GPUs = torch.cuda.device_count() -# processes_per_GPU = self.config["threads"] - -# if available_GPUs < self.config["nGPUs"]: -# self.log(f"Found {available_GPUs} but {nGPUS} specified in config.") - -# if available_GPUs >= 1: -# n_processes = processes_per_GPU * available_GPUs -# else: -# n_processes = self.config["threads"] -# available_GPUs = ( -# 1 # default to 1 GPU if non are available and a CPU only method is run -# ) - -# # initialize a list of available GPUs -# gpu_id_list = [] -# for gpu_ids in range(available_GPUs): -# for _ in range(processes_per_GPU): -# gpu_id_list.append(gpu_ids) - -# self.log(f"Beginning segmentation on {available_GPUs} available GPUs.") - -# with mp.get_context(self.context).Pool( -# processes=n_processes, -# initializer=self.initializer_function, -# initargs=[gpu_id_list], -# ) as pool: -# results = list( -# tqdm( -# pool.imap(self.method.call_as_shard, segmentation_list), -# total=len(indexes), -# ) -# ) -# pool.close() -# pool.join() -# print("All segmentations are done.", flush=True) - -# self.log("Finished parallel segmentation") -# self.log("Transferring results to array.") - -# self._transfer_tempmmap_to_hdf5() -# self.adjust_segmentation_indexes() -# self.log("Adjusted Indexes.") - -# # cleanup variables to make sure memory is cleared up again -# del results -# gc.collect() - -# def initialize_shard_list(self, segmentation_list, input_path, _tmp_seg_path): -# _shard_list = [] - -# for i in tqdm( -# segmentation_list, total=len(segmentation_list), desc="Generating Shards" -# ): -# current_shard = self.method( -# self.config, -# self.directory, -# project_location=self.project_location, -# debug=self.debug, -# overwrite=self.overwrite, -# ) - -# current_shard.initialize_as_shard( -# i, input_path, _tmp_seg_path=_tmp_seg_path -# ) -# _shard_list.append(current_shard) - -# self.log(f"Shard list created with {len(_shard_list)} elements.") - -# return _shard_list - -# def get_output(self): -# return os.path.join(self.directory, self.DEFAULT_SEGMENTATION_FILE) diff --git a/src/scportrait/pipeline/segmentation/workflows.py b/src/scportrait/pipeline/segmentation/workflows.py index 1255d8ff..c0359dc4 100644 --- a/src/scportrait/pipeline/segmentation/workflows.py +++ b/src/scportrait/pipeline/segmentation/workflows.py @@ -2006,123 +2006,3 @@ def _execute_segmentation(self, input_image) -> None: class ShardedCytosolOnlySegmentationDownsamplingCellpose(ShardedSegmentation): method = CytosolOnlySegmentationDownsamplingCellpose - - -#### TIMECOURSE SEGMENTATION METHODS ##### -#### THIS SHOULD BE SWITCHED TO THE BATCHED CLASS IMPLEMENTED BY TIM #### -# currently these are not functional with the new spatialdata format - -# class WGA_TimecourseSegmentation(TimecourseSegmentation): -# """ -# Specialized Processing for Timecourse segmentation (i.e. smaller tiles not stitched together from many different wells and or timepoints). -# No intermediate results are saved and everything is written to one .hdf5 file. -# """ - -# class WGASegmentation_Timecourse(WGASegmentation, TimecourseSegmentation): -# method = WGASegmentation - -# method = WGASegmentation_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Multithreaded_WGA_TimecourseSegmentation(MultithreadedSegmentation): -# class WGASegmentation_Timecourse(WGASegmentation, TimecourseSegmentation): -# method = WGASegmentation - -# method = WGASegmentation_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Cytosol_Cellpose_TimecourseSegmentation(TimecourseSegmentation): -# """ -# Specialized Processing for Timecourse segmentation (i.e. smaller tiles not stitched together from many different wells and or timepoints). -# No intermediate results are saved and everything is written to one .hdf5 file. Uses Cellpose segmentation models. -# """ - -# class CytosolSegmentationCellpose_Timecourse( -# CytosolSegmentationCellpose, TimecourseSegmentation -# ): -# method = CytosolSegmentationCellpose - -# method = CytosolSegmentationCellpose_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Cytosol_Cellpose_Downsampling_TimecourseSegmentation(TimecourseSegmentation): -# """ -# Specialized Processing for Timecourse segmentation (i.e. smaller tiles not stitched together from many different wells and or timepoints). -# No intermediate results are saved and everything is written to one .hdf5 file. Uses Cellpose segmentation models. -# """ - -# class Cytosol_Segmentation_Downsampling_Cellpose_Timecourse( -# CytosolSegmentationDownsamplingCellpose, TimecourseSegmentation -# ): -# method = CytosolSegmentationDownsamplingCellpose - -# method = Cytosol_Segmentation_Downsampling_Cellpose_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class CytosolOnly_Cellpose_TimecourseSegmentation(TimecourseSegmentation): -# """ -# Specialized Processing for Timecourse segmentation (i.e. smaller tiles not stitched together from many different wells and or timepoints). -# No intermediate results are saved and everything is written to one .hdf5 file. Uses Cellpose segmentation models. -# """ - -# class CytosolOnly_Cellpose_TimecourseSegmentation( -# CytosolOnlySegmentationCellpose, TimecourseSegmentation -# ): -# method = CytosolOnlySegmentationCellpose - -# method = CytosolOnly_Cellpose_TimecourseSegmentation - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Multithreaded_Cytosol_Cellpose_TimecourseSegmentation(MultithreadedSegmentation): -# class CytosolSegmentationCellpose_Timecourse( -# CytosolSegmentationCellpose, TimecourseSegmentation -# ): -# method = CytosolSegmentationCellpose - -# method = CytosolSegmentationCellpose_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Multithreaded_Cytosol_Cellpose_Downsampling_TimecourseSegmentation( -# MultithreadedSegmentation -# ): -# class Cytosol_Segmentation_Downsampling_Cellpose_Timecourse( -# CytosolSegmentationDownsamplingCellpose, TimecourseSegmentation -# ): -# method = CytosolSegmentationDownsamplingCellpose - -# method = Cytosol_Segmentation_Downsampling_Cellpose_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs) - - -# class Multithreaded_CytosolOnly_Cellpose_TimecourseSegmentation( -# MultithreadedSegmentation -# ): -# class CytosolOnly_SegmentationCellpose_Timecourse( -# CytosolOnlySegmentationCellpose, TimecourseSegmentation -# ): -# method = CytosolOnlySegmentationCellpose - -# method = CytosolOnly_SegmentationCellpose_Timecourse - -# def __init__(self, *args, **kwargs): -# super().__init__(*args, **kwargs)