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)