diff --git a/scripts/attributes/master.py b/scripts/attributes/master.py index 886beb3b96a4e18f6e77571d60644f3054ef1bb2..428ad2e3f69546d04dfbd83ebb636ac032786a59 100644 --- a/scripts/attributes/master.py +++ b/scripts/attributes/master.py @@ -10,12 +10,13 @@ from .cilia_attributes import cilia_morphology from ..files.xml_utils import get_h5_path_from_xml -def get_seg_path(folder, name, key): +def get_seg_path(folder, name, key=None): xml_path = os.path.join(folder, 'segmentations', '%s.xml' % name) path = get_h5_path_from_xml(xml_path, return_absolute_path=True) assert os.path.exists(path), path - with h5py.File(path, 'r') as f: - assert key in f, "%s not in %s" % (key, str(list(f.keys()))) + if key is not None: + with h5py.File(path, 'r') as f: + assert key in f, "%s not in %s" % (key, str(list(f.keys()))) return path @@ -59,13 +60,6 @@ def make_cell_tables(old_folder, folder, name, tmp_folder, resolution, med_expression_path, vc_out, tmp_folder, target) - # make table with morphology - morpho_out = os.path.join(table_folder, 'morphology.csv') - n_labels = len(label_ids) - write_morphology_cells(seg_path, base_out, nuc_mapping_table, morpho_out, - n_labels, resolution, tmp_folder, - target, max_jobs) - # region and semantic mapping region_out = os.path.join(table_folder, 'regions.csv') # need to make sure the inputs are copied / updated in @@ -76,6 +70,13 @@ def make_cell_tables(old_folder, folder, name, tmp_folder, resolution, image_folder, segmentation_folder, label_ids, tmp_folder, target, max_jobs) + # make table with morphology + morpho_out = os.path.join(table_folder, 'morphology.csv') + write_morphology_cells(seg_path, nuc_path, + base_out, morpho_out, + nuc_mapping_table, region_out, + tmp_folder, target, max_jobs) + # mapping to extrapolated intensities extrapol_mask = os.path.join(folder, 'images', 'sbem-6dpf-1-whole-mask-extrapolated.xml') extrapol_mask = get_h5_path_from_xml(extrapol_mask, return_absolute_path=True) @@ -107,18 +108,20 @@ def make_nucleus_tables(old_folder, folder, name, tmp_folder, resolution, # make the basic attributes table base_out = os.path.join(table_folder, 'default.csv') - label_ids = base_attributes(seg_path, seg_key, base_out, resolution, - tmp_folder, target=target, max_jobs=max_jobs, - correct_anchors=True) + base_attributes(seg_path, seg_key, base_out, resolution, + tmp_folder, target=target, max_jobs=max_jobs, + correct_anchors=True) + # make the morphology attribute table xml_raw = os.path.join(folder, 'images', 'sbem-6dpf-1-whole-raw.xml') raw_path = get_h5_path_from_xml(xml_raw, return_absolute_path=True) - # make the morphology attribute table + cell_seg_path = get_seg_path(folder, 'sbem-6dpf-1-whole-segmented-cells-labels') + chromatin_seg_path = get_seg_path(folder, 'sbem-6dpf-1-whole-segmented-chromatin-labels') morpho_out = os.path.join(table_folder, 'morphology.csv') - n_labels = len(label_ids) - write_morphology_nuclei(seg_path, raw_path, base_out, morpho_out, - n_labels, resolution, tmp_folder, - target, max_jobs) + write_morphology_nuclei(raw_path, seg_path, + cell_seg_path, chromatin_seg_path, + base_out, morpho_out, + tmp_folder, target, max_jobs) # mapping to extrapolated intensities extrapol_mask = os.path.join(folder, 'segmentations', 'sbem-6dpf-mask-extrapolated.xml') diff --git a/scripts/attributes/morphology.py b/scripts/attributes/morphology.py index f81ec103d594aaac4158eac30bf5be38d50a2e6f..c2e67a9183a62dc9c09b3c6e0a3d51bec16dafe2 100644 --- a/scripts/attributes/morphology.py +++ b/scripts/attributes/morphology.py @@ -5,24 +5,22 @@ from ..extension.attributes import MorphologyWorkflow def write_config(config_folder, config): - # something eats a lot of threads, let's at least reserve a few ... - config.update({'mem_limit': 24, 'threads_per_job': 4}) + config.update({'mem_limit': 24}) with open(os.path.join(config_folder, 'morphology.config'), 'w') as f: json.dump(config, f) -def write_morphology_nuclei(seg_path, raw_path, table_in_path, table_out_path, - n_labels, resolution, tmp_folder, target, max_jobs): +def write_morphology_nuclei(raw_path, nucleus_seg_path, chromatin_seg_path, + table_in_path, table_out_path, + tmp_folder, target, max_jobs): """ Write csv files of morphology stats for the nucleus segmentation - seg_path - string, file path to nucleus segmentation raw_path - string, file path to raw data - cell_table_path - string, file path to cell table + nucleus_seg_path - string, file path to nucleus segmentation + chromatin_seg_path - string, file path to chromatin segmentation table_in_path - string, file path to nucleus table table_out_path - string, file path to save new nucleus table - n_labels - int, number of labels - resolution - list or tuple, resolution of segmentation at scale 0 tmp_folder - string, temporary folder target - string, computation target (slurm or local) max_jobs - maximal number of jobs @@ -31,32 +29,37 @@ def write_morphology_nuclei(seg_path, raw_path, table_in_path, table_out_path, config_folder = os.path.join(tmp_folder, 'configs') write_config(config_folder, task.get_config()['morphology']) - seg_scale = 0 + # TODO double check these values + scale = 3 min_size = 18313 # Kimberly's lower size cutoff for nuclei + max_bb = '' # TODO t = task(tmp_folder=tmp_folder, max_jobs=max_jobs, config_dir=config_folder, target=target, - segmentation_path=seg_path, in_table_path=table_in_path, - output_path=table_out_path, resolution=list(resolution), - seg_scale=seg_scale, raw_scale=3, min_size=min_size, max_size=None, - raw_path=raw_path, prefix='nuclei', number_of_labels=n_labels) + compute_cell_features=False, raw_path=raw_path, + nucleus_segmentation_path=nucleus_seg_path, + chromatin_segmentation_path=chromatin_seg_path, + in_table_path=table_in_path, + output_path=table_out_path, + scale=scale, min_size=min_size, max_bb=max_bb) ret = luigi.build([t], local_scheduler=True) if not ret: raise RuntimeError("Nucleus morphology computation failed") -def write_morphology_cells(seg_path, table_in_path, cell_nuc_mapping_path, table_out_path, - n_labels, resolution, tmp_folder, target, max_jobs): +# TODO do we pass raw data? +def write_morphology_cells(cell_seg_path, nucleus_seg_path, + table_in_path, table_out_path, + nucleus_mapping_path, region_path, + resolution, tmp_folder, target, max_jobs): """ Write csv files of morphology stats for both the nucleus and cell segmentation - seg_path - string, file path to cell segmentation + cell_seg_path - string, file path to cell segmentation table_in_path - string, file path to cell table - cell_nuc_mapping_path - string, file path to numpy array mapping cells to nuclei + nucleus_mapping_path - string, file path to numpy array mapping cells to nuclei (first column cell id, second nucleus id) table_out_path - string, file path to save new cell table - n_labels - int, number of labels - resolution - list or tuple, resolution of segmentation at scale 0 tmp_folder - string, temporary folder target - string, computation target (slurm or local) max_jobs - maximal number of jobs @@ -65,16 +68,22 @@ def write_morphology_cells(seg_path, table_in_path, cell_nuc_mapping_path, table config_folder = os.path.join(tmp_folder, 'configs') write_config(config_folder, task.get_config()['morphology']) - seg_scale = 2 + # TODO check these values + scale = 2 min_size = 88741 # Kimberly's lower size cutoff for cells max_size = 600000000 # Kimberly's upper size cutoff for cells + max_bb = '' t = task(tmp_folder=tmp_folder, max_jobs=max_jobs, config_dir=config_folder, target=target, - segmentation_path=seg_path, in_table_path=table_in_path, - output_path=table_out_path, resolution=list(resolution), - seg_scale=seg_scale, min_size=min_size, max_size=max_size, - mapping_path=cell_nuc_mapping_path, prefix='cells', - number_of_labels=n_labels) + compute_cell_features=True, + cell_segmentation_path=cell_seg_path, + nucleus_segmentation_path=nucleus_seg_path, + in_table_path=table_in_path, + output_path=table_out_path, + scale=scale, max_bb=max_bb, + min_size=min_size, max_size=max_size, + nucleus_mapping_path=nucleus_mapping_path, + region_mapping_path=region_path) ret = luigi.build([t], local_scheduler=True) if not ret: raise RuntimeError("Cell morphology computation failed") diff --git a/scripts/extension/attributes/morphology.py b/scripts/extension/attributes/morphology.py index d1b3ed67f3dd03cb22fd743460999579330e9003..80f1cbb7b5c5ba4422443b4246dbcca018634959 100644 --- a/scripts/extension/attributes/morphology.py +++ b/scripts/extension/attributes/morphology.py @@ -3,6 +3,7 @@ import os import sys import json +from math import ceil import luigi import nifty.tools as nt @@ -12,7 +13,8 @@ import cluster_tools.utils.volume_utils as vu import cluster_tools.utils.function_utils as fu from cluster_tools.utils.task_utils import DummyTask from cluster_tools.cluster_tasks import SlurmTask, LocalTask -from scripts.extension.attributes.morphology_impl import morphology_impl +from scripts.extension.attributes.morphology_impl import (morphology_impl_cell, + morphology_impl_nucleus) # # Morphology Attribute Tasks @@ -27,32 +29,83 @@ class MorphologyBase(luigi.Task): src_file = os.path.abspath(__file__) allow_retry = False - # input volumes and graph - segmentation_path = luigi.Parameter() + # compute cell features or nucleus features? + compute_cell_features = luigi.BoolParameter() + + # paths to raw data and segmentations + # if the raw path is None, we don't compute intensity features + raw_path = luigi.Parameter(default=None) + # we always need the nucleus segmentation + nucleus_segmentation_path = luigi.Paramter() + # we only need the cell segmentation if we compute cell morphology features + cell_segmentation_path = luigi.Parameter(default=None) + # we only need the chromatin segmentation if we compute nucleus features + chromatin_segmentation_path = luigi.Paramter(default=None) + + # the scale used for computation, relative to the raw scale + scale = luigi.IntParameter(default=3) + + # the input tables paths for the default table, the + # nucleus mapping table and the region mapping table in_table_path = luigi.Parameter() + # only need the mapping paths for the nucleus features + nucleus_mapping_path = luigi.Paramter(default=None) + region_mapping_path = luigi.Paramter(default=None) + + # prefix for the output tables output_prefix = luigi.Parameter() - # resolution of the segmentation at full scale - resolution = luigi.ListParameter() - # scales of segmentation and raw data used for the computation - seg_scale = luigi.IntParameter() - raw_scale = luigi.IntParameter(default=3) - # prefix - prefix = luigi.Parameter() - number_of_labels = luigi.IntParameter() - # minimum and maximum sizes for objects + + # minimum and maximum sizes for objects / bounding box min_size = luigi.IntParameter() max_size = luigi.IntParameter(default=None) - # path for cell nucleus mapping, that is used for additional - # table filtering - mapping_path = luigi.IntParameter(default='') - # input path for intensity calcuation - # if '', intensities will not be calculated - raw_path = luigi.Parameter(default='') + max_bb = luigi.IntParameter() + dependency = luigi.TaskParameter(default=DummyTask()) def requires(self): return self.dependency + def _update_config_for_cells(self, config): + # check the relevant inputs for the cell morphology + assert self.cell_segmentation_path is not None + assert self.nucleus_mapping_path is not None + assert self.region_mapping_path is not None + config.update({'cell_segmentation_path': self.cell_segmentation_path, + 'nucleus_segmentation_path': self.nucleus_segmentation_path, + 'raw_path': self.raw_path, + 'output_prefix': self.output_prefix, + 'in_table_path': self.in_table_path, + 'nucleus_mapping_path': self.nucleus_mapping_path, + 'region_mapping_path': self.region_mapping_path, + 'scale': self.scale, 'max_bb': self.max_bb, + 'min_size': self.min_size, 'max_size': self.max_size}) + return config + + def _update_config_for_nuclei(self, config): + # check the relevant inputs for the nucleus morphology + assert self.chromatin_segmentation_path is not None + assert self.raw_path is not None + config.update({'nucleus_segmentation_path': self.nucleus_segmentation_path, + 'chromatin_segmentation_path': self.chromatin_segmentation_path, + 'raw_path': self.raw_path, + 'output_prefix': self.output_prefix, + 'in_table_path': self.in_table_path, + 'scale': self.scale, 'max_bb': self.max_bb, + 'min_size': self.min_size, 'max_size': self.max_size}) + return config + + def _get_number_of_labels(self): + seg_path = self.cell_segmentation_path if self.compute_cell_features else\ + self.nucleus_segmentation_path + key = 't00000/s00/0/cells' + with vu.file_reader(seg_path, 'r') as f: + n_labels = int(f[key].attrs['maxId']) + 1 + return n_labels + + def _compute_block_len(self, number_of_labels): + ids_per_job = int(ceil(float(number_of_labels) / self.max_jobs)) + return ids_per_job + def run_impl(self): # get the global config and init configs shebang = self.global_config_values()[0] @@ -60,34 +113,35 @@ class MorphologyBase(luigi.Task): # load the task config config = self.get_task_config() - # we hard-code the chunk-size to 1000 for now - block_list = vu.blocks_in_volume([self.number_of_labels], [1000]) - # update the config with input and graph paths and keys - # as well as block shape - config.update({'segmentation_path': self.segmentation_path, - 'output_prefix': self.output_prefix, - 'in_table_path': self.in_table_path, - 'raw_path': self.raw_path, - 'mapping_path': self.mapping_path, - 'seg_scale': self.seg_scale, - 'raw_scale': self.raw_scale, - 'resolution': self.resolution, - 'min_size': self.min_size, - 'max_size': self.max_size}) + if self.compute_cell_features: + config = self._update_config_for_cells(config) + else: + config = self._update_config_for_nuclei(config) + # TODO match block size and number of blocks + # we hard-code the chunk-size to 1000 for now + number_of_labels = self._get_number_of_labels() + block_len = self._compute_block_len(number_of_labels) + block_list = vu.blocks_in_volume([number_of_labels], [block_len]) + config.update({'block_len': block_len, + 'compute_cell_features': self.compute_cell_features, + 'number_of_labels': number_of_labels}) + + prefix = 'cells' if self.compute_cell_features else 'nuclei' # prime and run the job n_jobs = min(len(block_list), self.max_jobs) - self.prepare_jobs(n_jobs, block_list, config, self.prefix) - self.submit_jobs(n_jobs, self.prefix) + self.prepare_jobs(n_jobs, block_list, config, prefix) + self.submit_jobs(n_jobs, prefix) # wait till jobs finish and check for job success self.wait_for_jobs() - self.check_jobs(n_jobs, self.prefix) + self.check_jobs(n_jobs, prefix) def output(self): + prefix = 'cells' if self.compute_cell_features else 'nuclei' out_path = os.path.join(self.tmp_folder, - '%s_%s.log' % (self.task_name, self.prefix)) + '%s_%s.log' % (self.task_name, prefix)) return luigi.LocalTarget(out_path) @@ -108,6 +162,57 @@ class MorphologySlurm(MorphologyBase, SlurmTask): # +def _morphology_nuclei(config, table, label_start, label_stop): + # paths to raw data, nucleus segmentation and chromatin segmentation + raw_path = config['raw_path'] + nucleus_segmentation_path = config['nucleus_segmentation_path'] + chromatin_segmentation_path = config['chromatin_segmentation_path'] + # minimal / maximal size and maximal bounding box volume + min_size, max_size, max_bb = config['min_size'], config['max_size'], config['max_bb'] + # scale for nucleus segmentation, raw data and chromatin segmentation + raw_scale = config['scale'] + nucleus_scale = raw_scale - 3 + chromatin_scale = raw_scale - 1 # TODO is this correct? + # nucleus and chromatin resolution are hard-coded for now + nucleus_resolution = [0.1, 0.08, 0.08] + chromatin_resolution = [0.025, 0.02, 0.02] # TODO is this correct? + stats = morphology_impl_nucleus(nucleus_segmentation_path, raw_path, + chromatin_segmentation_path, + table, min_size, max_size, max_bb, + nucleus_resolution, chromatin_resolution, + nucleus_scale, raw_scale, chromatin_scale, + label_start, label_stop) + return stats + + +def _morphology_cells(config, table, label_start, label_stop): + # paths to raw data, nucleus segmentation and chromatin segmentation + raw_path = config['raw_path'] + cell_segmentation_path = config['cell_segmentation_path'] + nucleus_segmentation_path = config['nucleus_segmentation_path'] + # minimal / maximal size and maximal bounding box volume + min_size, max_size, max_bb = config['min_size'], config['max_size'], config['max_bb'] + # scale for nucleus segmentation, raw data and chromatin segmentation + raw_scale = config['scale'] + nucleus_scale = raw_scale - 3 + cell_scale = raw_scale - 1 # TODO is this correct? + # nucleus and chromatin resolution are hard-coded for now + nucleus_resolution = [0.1, 0.08, 0.08] + cell_resolution = [0.025, 0.02, 0.02] # TODO is this correct? + # mapping from cells to nuclei and from cells to regions + nucleus_mapping_path = config['mapping_path'] + region_mapping_path = config['region_mapping_path'] + stats = morphology_impl_cell(cell_segmentation_path, raw_path, + nucleus_segmentation_path, + table, nucleus_mapping_path, + region_mapping_path, + min_size, max_size, max_bb, + cell_resolution, nucleus_resolution, + cell_scale, raw_scale, nucleus_scale, + label_start, label_stop) + return stats + + def morphology(job_id, config_path): fu.log("start processing job %i" % job_id) @@ -116,38 +221,34 @@ def morphology(job_id, config_path): # get the config with open(config_path) as f: config = json.load(f) - segmentation_path = config['segmentation_path'] - in_table_path = config['in_table_path'] - raw_path = config['raw_path'] - mapping_path = config['mapping_path'] - output_prefix = config['output_prefix'] - - min_size = config['min_size'] - max_size = config['max_size'] - - resolution = config['resolution'] - raw_scale = config['raw_scale'] - seg_scale = config['seg_scale'] - - block_list = config['block_list'] # read the base table + in_table_path = config['in_table_path'] table = pd.read_csv(in_table_path, sep='\t') - # get the label ranges for this job + # determine the start and stop label for this job + block_list = config['block_list'] + block_len = config['block_len'] + assert len(block_list) == 1, "Expected a single block, got %i" % len(block_list) + + # get the label range for this job n_labels = table.shape[0] - blocking = nt.blocking([0], [n_labels], [1000]) - label_starts, label_stops = [], [] - for block_id in block_list: - block = blocking.getBlock(block_id) - label_starts.append(block.begin[0]) - label_stops.append(block.end[0]) - - stats = morphology_impl(segmentation_path, raw_path, table, mapping_path, - min_size, max_size, - resolution, raw_scale, seg_scale, - label_starts, label_stops) + blocking = nt.blocking([0], [n_labels], [block_len]) + block = blocking.getBlock(block_list[0]) + label_start, label_stop = block.begin, block.end + + # do we compute cell or nucleus features ? + compute_cell_features = config['compute_cell_features'] + if compute_cell_features: + fu.log("Compute morphology features for cells") + stats = _morphology_cells(config, table, label_start, label_stop) + else: + fu.log("Compute morphology features for nuclei") + stats = _morphology_nuclei(config, table, label_start, label_stop) + + # write the result + output_prefix = config['output_prefix'] output_path = output_prefix + '_job%i.csv' % job_id fu.log("Save result to %s" % output_path) stats.to_csv(output_path, index=False, sep='\t') diff --git a/scripts/extension/attributes/morphology_impl.py b/scripts/extension/attributes/morphology_impl.py index 3cf094733fc88c8aca6db54b8b6c783098f51e7a..0bf56fe23d852f650371a27b47a1cf93cc2c8ec5 100644 --- a/scripts/extension/attributes/morphology_impl.py +++ b/scripts/extension/attributes/morphology_impl.py @@ -394,7 +394,7 @@ def morphology_impl_nucleus(nucleus_segmentation_path, raw_path, chromatin_path, max_bb, nucleus_resolution, chromatin_resolution, nucleus_seg_scale, raw_scale, chromatin_scale, - label_starts, label_stops): + label_start, label_stop): """ Compute morphology features for nucleus segmentation. Can compute features for multiple label ranges. If you want to @@ -418,8 +418,8 @@ def morphology_impl_nucleus(nucleus_segmentation_path, raw_path, chromatin_path, nucleus_seg_scale [int] - scale level of the segmentation. raw_scale [int] - scale level of the raw data chromatin_scale [int] - scale level of the segmentation. - label_starts [listlike] - list with label start positions - label_stops [listlike] - list with label stop positions + label_start [int] - label start position + label_stop [int] - label stop position """ # keys for the different scales @@ -463,15 +463,14 @@ def morphology_impl_nucleus(nucleus_segmentation_path, raw_path, chromatin_path, ds = f[nucleus_seg_key] stats = [] - for label_a, label_b in zip(label_starts, label_stops): - log("Computing features from label-id %i to %i" % (label_a, label_b)) - stats.extend(morphology_features_for_label_range(table, ds, ds_raw, - ds_chromatin, - None, - scale_factor_nucleus_seg, scale_factor_raw, - scale_factor_chromatin, - None, - label_a, label_b)) + log("Computing features from label-id %i to %i" % (label_start, label_stop)) + stats = morphology_features_for_label_range(table, ds, ds_raw, + ds_chromatin, + None, + scale_factor_nucleus_seg, scale_factor_raw, + scale_factor_chromatin, + None, + label_start, label_stop) for var in f_raw, f_chromatin: if var is not None: @@ -492,7 +491,7 @@ def morphology_impl_cell(cell_segmentation_path, raw_path, max_bb, cell_resolution, nucleus_resolution, cell_seg_scale, raw_scale, nucleus_seg_scale, - label_starts, label_stops): + label_start, label_stop): """ Compute morphology features for cell segmentation. Can compute features for multiple label ranges. If you want to @@ -522,8 +521,8 @@ def morphology_impl_cell(cell_segmentation_path, raw_path, cell_seg_scale [int] - scale level of the segmentation raw_scale [int] - scale level of the raw data nucleus_seg_scale [int] - scale level of the segmentation. - label_starts [listlike] - list with label start positions - label_stops [listlike] - list with label stop positions + label_start [int] - label start position + label_stop [int] - label stop position """ # keys for the different scales @@ -565,16 +564,14 @@ def morphology_impl_cell(cell_segmentation_path, raw_path, with h5py.File(cell_segmentation_path, 'r') as f: ds = f[cell_seg_key] - stats = [] - for label_a, label_b in zip(label_starts, label_stops): - log("Computing features from label-id %i to %i" % (label_a, label_b)) - stats.extend(morphology_features_for_label_range(table, ds, ds_raw, - None, - ds_nucleus, - scale_factor_cell_seg, scale_factor_raw, - None, - scale_factor_nucleus, - label_a, label_b)) + log("Computing features from label-id %i to %i" % (label_start, label_stop)) + stats = morphology_features_for_label_range(table, ds, ds_raw, + None, + ds_nucleus, + scale_factor_cell_seg, scale_factor_raw, + None, + scale_factor_nucleus, + label_start, label_stop) for var in f_raw, f_nucleus: if var is not None: diff --git a/scripts/extension/attributes/workflow.py b/scripts/extension/attributes/workflow.py index 9c344cce1a6cb6c9f90f16b6ebfdbce37dcb78f0..741c906acc74946aea2739e2e4e595f483130ce0 100644 --- a/scripts/extension/attributes/workflow.py +++ b/scripts/extension/attributes/workflow.py @@ -36,27 +36,35 @@ class MergeTables(luigi.Task): class MorphologyWorkflow(WorkflowBase): - # input volumes and graph - segmentation_path = luigi.Parameter() + # compute cell features or nucleus features? + compute_cell_features = luigi.BoolParameter() + + # paths to raw data and segmentations + # if the raw path is None, we don't compute intensity features + raw_path = luigi.Parameter(default=None) + # we always need the nucleus segmentation + nucleus_segmentation_path = luigi.Paramter() + # we only need the cell segmentation if we compute cell morphology features + cell_segmentation_path = luigi.Parameter(default=None) + # we only need the chromatin segmentation if we compute nucleus features + chromatin_segmentation_path = luigi.Paramter(default=None) + + # the scale used for computation, relative to the raw scale + scale = luigi.IntParameter(default=3) + + # the input tables paths for the default table, the + # nucleus mapping table and the region mapping table in_table_path = luigi.Parameter() - output_path = luigi.Parameter() - # resolution of the segmentation at full scale - resolution = luigi.ListParameter() - # scales of segmentation and raw data used for the computation - seg_scale = luigi.IntParameter() - raw_scale = luigi.IntParameter(default=3) - # prefix - prefix = luigi.Parameter() - number_of_labels = luigi.IntParameter() - # minimum and maximum sizes for objects + # only need the mapping paths for the nucleus features + nucleus_mapping_path = luigi.Paramter(default=None) + region_mapping_path = luigi.Paramter(default=None) + + # minimum and maximum sizes for objects / bounding box min_size = luigi.IntParameter() max_size = luigi.IntParameter(default=None) - # path for cell nucleus mapping, that is used for additional - # table filtering - mapping_path = luigi.IntParameter(default='') - # input path for intensity calcuation - # if '', intensities will not be calculated - raw_path = luigi.Parameter(default='') + max_bb = luigi.IntParameter() + + output_path = luigi.Paramter() def requires(self): out_prefix = os.path.join(self.tmp_folder, 'sub_table_%s' % self.prefix) @@ -64,12 +72,15 @@ class MorphologyWorkflow(WorkflowBase): self._get_task_name('Morphology')) dep = morpho_task(tmp_folder=self.tmp_folder, config_dir=self.config_dir, dependency=self.dependency, max_jobs=self.max_jobs, - segmentation_path=self.segmentation_path, + compute_cell_features=self.compute_cell_features, + raw_path=self.raw_path, + nucleus_segmentation_path=self.nucleus_segmentation_path, + cell_segmentation_path=self.cell_segmentation_path, + chromatin_segmentation_path=self.chromatin_segmentation_path, in_table_path=self.in_table_path, output_prefix=out_prefix, - resolution=self.resolution, seg_scale=self.seg_scale, raw_scale=self.raw_scale, - prefix=self.prefix, number_of_labels=self.number_of_labels, - min_size=self.min_size, max_size=self.max_size, mapping_path=self.mapping_path, - raw_path=self.raw_path) + nucleus_mapping_path=self.nucleus_mapping_path, + region_mapping_path=self.region_mapping_path, + min_size=self.min_size, max_size=self.max_size, max_bb=self.max_bb) dep = MergeTables(output_prefix=out_prefix, output_path=self.output_path, max_jobs=self.max_jobs, dependency=dep)