Source code for ClearMap.Analysis.Measurements.ShapeDetection
# -*- coding: utf-8 -*-
"""
ShapeDetection
==============
Module with routines for shape and size detection of objects such as cells.
Note
----
The shape detection is based on a seeded and masked watershed. The module is
based on the ndimage library. For faster implementation of intensity
and radial measurements see the modules listed below.
See also
--------
:mod:`ClearMap.Analysis.Measurements.MeasureExpression` and
:mod:`ClearMap.Analysis.Measurements.MeasureRadius`
"""
__author__ = 'Christoph Kirst <christoph.kirst.ck@gmail.com>'
__license__ = 'GPLv3 - GNU General Pulic License v3 (see LICENSE.txt)'
__copyright__ = 'Copyright © 2020 by Christoph Kirst'
__webpage__ = 'http://idisco.info'
__download__ = 'http://www.github.com/ChristophKirst/ClearMap2'
import numpy as np
import skimage.morphology
import scipy.ndimage.measurements
#from scipy.ndimage.measurements import watershed_ift
#from skimage.measure import regionprops
import ClearMap.IO.IO as io
import ClearMap.Analysis.Measurements.Voxelization as vox
import ClearMap.Utils.Timer as tmr
import ClearMap.Utils.HierarchicalDict as hdict
##############################################################################
# Cell shape detection
##############################################################################
[docs]def detect_shape(source, seeds, threshold = None, verbose = False):
"""Detect object shapes by generatng a labeled image from seeds.
Arguments
---------
source : array, str or Source
Source image.
seeds : array, str or Source
Cell centers as point coordinates.
threshold : float or None
Threshold to determine mask for watershed, pixel below this are
treated as background. If None, the seeds are expanded indefinately.
verbose :bool
If True, print progress info.
Returns
-------
shapes : array
Labeled image, where each label indicates a object.
"""
if verbose:
timer = tmr.Timer();
hdict.pprint(head='Shape detection', threshold=threshold)
source = io.as_source(source).array;
seeds = io.as_source(seeds);
if threshold is None:
mask = None;
else:
mask = source > threshold;
peaks = vox.voxelize(seeds, shape=source.shape, weights=np.arange(1, seeds.shape[0]+1)).array;
shapes = skimage.morphology.watershed(-source, peaks, mask=mask);
#shapes = watershed_ift(-source.astype('uint16'), peaks);
#shapes[numpy.logical_not(mask)] = 0;
if verbose:
timer.print_elapsed_time('Shape detection');
return shapes
[docs]def find_size(label, max_label = None, verbose = False):
"""Find size given object shapes as a labled image
Arguments
---------
label : array, str or Source
Labeled image in which each object has its own label.
max_label : int or None
Maximal label to include, if None use all label.
verbose : bool
Print progress info.
Returns
-------
sizes : array
Measured intensities
"""
if verbose:
timer = tmr.Timer();
hdict.pprint(head='Size detection:', max_label=max_label);
label = io.as_source(label);
if max_label is None:
max_label = int(label.max());
sizes = scipy.ndimage.measurements.sum(np.ones(label.shape, dtype=bool), labels=label, index=np.arange(1, max_label + 1));
if verbose:
timer.print_elapsed_time(head='Size detection');
return sizes
[docs]def find_intensity(source, label, max_label = None, method = 'sum', verbose = False):
"""Find integrated intensity given object shapes as labled image.
Arguments
---------
source : array, str, or Source
Source to measure intensities from.
label : array, str, or Source
Labeled image with a separate label for each object.
max_label : int or None
Maximal label to include. If None use all.
method : {'sum', 'mean', 'max', 'min'}
Method to use to measure the intensities in each object's area.
verbose : bool
If True, print progress information.
Returns
-------
intensities : array
Measured intensities.
"""
if verbose:
timer = tmr.Timer();
hdict.pprint(head='Intensity detection:', max_label=max_label, method = method);
source = io.as_source(source).array;
label = io.as_source(label);
if max_label is None:
max_label = label.max();
if method.lower() == 'sum':
measure = scipy.ndimage.measurements.sum
elif method.lower() == 'mean':
measure= scipy.ndimage.measurements.mean
elif method.lower() == 'max':
measure = scipy.ndimage.measurements.maximum
elif method.lower() == 'min':
measure = scipy.ndimage.measurements.minimum
else:
raise RuntimeError('Unkown method %r!' % (method,));
intensities = measure(label, labels=label, index=np.arange(1, max_label + 1));
if verbose:
timer.print_elapsed_time(head='Intensity detection');
return intensities