99from tqdm import tqdm
1010
1111from .file_utils import read_image_data
12+ from .segmentation .postprocessing import _compute_table
1213
1314
1415def _measure_volume_and_surface (mask , resolution ):
@@ -25,35 +26,26 @@ def _measure_volume_and_surface(mask, resolution):
2526 return volume , surface
2627
2728
28- # Could also support s3 directly?
29- def compute_object_measures (
30- image_path : str ,
31- segmentation_path : str ,
32- segmentation_table_path : str ,
33- output_table_path : str ,
34- image_key : Optional [str ] = None ,
35- segmentation_key : Optional [str ] = None ,
29+ def compute_object_measures_impl (
30+ image : np .typing .ArrayLike ,
31+ segmentation : np .typing .ArrayLike ,
3632 n_threads : Optional [int ] = None ,
3733 resolution : float = 0.38 ,
38- ):
39- """
34+ table : Optional [pd .DataFrame ] = None ,
35+ ) -> pd .DataFrame :
36+ """Compute simple intensity and morphology measures for each segmented cell in a segmentation.
37+
38+ See `compute_object_measures` for details.
4039
4140 Args:
42- image_path:
43- segmentation_path:
44- segmentation_table_path:
45- output_table_path:
46- image_key:
47- segmentation_key:
48- n_threads:
49- resolution:
41+ image: The image data.
42+ segmentation: The segmentation.
43+ n_threads: The number of threads to use for computation.
44+ resolution: The resolution / voxel size of the data.
45+ table: The segmentation table. Will be computed on the fly if it is not given.
5046 """
51- # First, we load the pre-computed segmentation table from MoBIE.
52- table = pd .read_csv (segmentation_table_path , sep = "\t " )
53-
54- # Then, open the volumes.
55- image = read_image_data (image_path , image_key )
56- segmentation = read_image_data (segmentation_path , segmentation_key )
47+ if table is None :
48+ table = _compute_table (segmentation , resolution )
5749
5850 def intensity_measures (seg_id ):
5951 # Get the bounding box.
@@ -107,4 +99,44 @@ def intensity_measures(seg_id):
10799 # Create the result table and save it.
108100 keys = measures [0 ].keys ()
109101 measures = pd .DataFrame ({k : [measure [k ] for measure in measures ] for k in keys })
102+ return measures
103+
104+
105+ # Could also support s3 directly?
106+ def compute_object_measures (
107+ image_path : str ,
108+ segmentation_path : str ,
109+ segmentation_table_path : str ,
110+ output_table_path : str ,
111+ image_key : Optional [str ] = None ,
112+ segmentation_key : Optional [str ] = None ,
113+ n_threads : Optional [int ] = None ,
114+ resolution : float = 0.38 ,
115+ ) -> None :
116+ """Compute simple intensity and morphology measures for each segmented cell in a segmentation.
117+
118+ This computes the mean, standard deviation, minimum, maximum, median and
119+ 5th, 10th, 25th, 75th, 90th and 95th percentile of the intensity image
120+ per cell, as well as the volume and surface.
121+
122+ Args:
123+ image_path: The filepath to the image data. Either a tif or hdf5/zarr/n5 file.
124+ segmentation_path: The filepath to the segmentation data. Either a tif or hdf5/zarr/n5 file.
125+ segmentation_table_path: The path to the segmentation table in MoBIE format.
126+ output_table_path: The path for saving the segmentation with intensity measures.
127+ image_key: The key (= internal path) for the image data. Not needed fir tif.
128+ segmentation_key: The key (= internal path) for the segmentation data. Not needed for tif.
129+ n_threads: The number of threads to use for computation.
130+ resolution: The resolution / voxel size of the data.
131+ """
132+ # First, we load the pre-computed segmentation table from MoBIE.
133+ table = pd .read_csv (segmentation_table_path , sep = "\t " )
134+
135+ # Then, open the volumes.
136+ image = read_image_data (image_path , image_key )
137+ segmentation = read_image_data (segmentation_path , segmentation_key )
138+
139+ measures = compute_object_measures_impl (
140+ image , segmentation , n_threads , resolution , table = table
141+ )
110142 measures .to_csv (output_table_path , sep = "\t " , index = False )
0 commit comments