26
26
import anndata as ad
27
27
import dask .array as da
28
28
import numpy as np
29
+ import pandas as pd
29
30
import zarr
31
+ from anndata .experimental import write_elem
30
32
from cellpose import models
31
33
from cellpose .core import use_gpu
32
34
33
35
import fractal_tasks_core
34
36
from fractal_tasks_core .lib_pyramid_creation import build_pyramid
37
+ from fractal_tasks_core .lib_regions_of_interest import (
38
+ array_to_bounding_box_table ,
39
+ )
35
40
from fractal_tasks_core .lib_regions_of_interest import (
36
41
convert_ROI_table_to_indices ,
37
42
)
43
+ from fractal_tasks_core .lib_remove_FOV_overlaps import (
44
+ get_overlapping_pairs_3D ,
45
+ )
38
46
from fractal_tasks_core .lib_zattrs_utils import extract_zyx_pixel_sizes
39
47
from fractal_tasks_core .lib_zattrs_utils import rescale_datasets
40
48
@@ -121,6 +129,7 @@ def cellpose_segmentation(
121
129
flow_threshold : float = 0.4 ,
122
130
model_type : str = "nuclei" ,
123
131
ROI_table_name : str = "FOV_ROI_table" ,
132
+ bounding_box_ROI_table_name : str = None ,
124
133
) -> Dict [str , Any ]:
125
134
"""
126
135
Example inputs:
@@ -136,8 +145,8 @@ def cellpose_segmentation(
136
145
# Set input path
137
146
if len (input_paths ) > 1 :
138
147
raise NotImplementedError
139
- in_path = input_paths [0 ]
140
- zarrurl = (in_path .parent . resolve () / component ).as_posix () + "/"
148
+ in_path = input_paths [0 ]. parent
149
+ zarrurl = (in_path .resolve () / component ).as_posix () + "/"
141
150
logger .info (zarrurl )
142
151
143
152
# Read useful parameters from metadata
@@ -166,6 +175,9 @@ def cellpose_segmentation(
166
175
f"{ zarrurl } .zattrs" , level = 0
167
176
)
168
177
178
+ actual_res_pxl_sizes_zyx = extract_zyx_pixel_sizes (
179
+ f"{ zarrurl } .zattrs" , level = labeling_level
180
+ )
169
181
# Create list of indices for 3D FOVs spanning the entire Z direction
170
182
list_indices = convert_ROI_table_to_indices (
171
183
ROI_table ,
@@ -308,6 +320,10 @@ def cellpose_segmentation(
308
320
309
321
# Iterate over ROIs
310
322
num_ROIs = len (list_indices )
323
+
324
+ if bounding_box_ROI_table_name :
325
+ bbox_dataframe_list = []
326
+
311
327
logger .info (f"[{ well_id } ] Now starting loop over { num_ROIs } ROIs" )
312
328
for i_ROI , indices in enumerate (list_indices ):
313
329
# Define region
@@ -353,6 +369,20 @@ def cellpose_segmentation(
353
369
f"but dtype={ label_dtype } "
354
370
)
355
371
372
+ if bounding_box_ROI_table_name :
373
+
374
+ bbox_df = array_to_bounding_box_table (
375
+ fov_mask , actual_res_pxl_sizes_zyx
376
+ )
377
+
378
+ bbox_dataframe_list .append (bbox_df )
379
+
380
+ overlap_list = []
381
+ for df in bbox_dataframe_list :
382
+ overlap_list .append (
383
+ get_overlapping_pairs_3D (df , full_res_pxl_sizes_zyx )
384
+ )
385
+
356
386
# Compute and store 0-th level to disk
357
387
da .array (fov_mask ).to_zarr (
358
388
url = mask_zarr ,
@@ -378,6 +408,23 @@ def cellpose_segmentation(
378
408
379
409
logger .info (f"[{ well_id } ] End building pyramids, exit" )
380
410
411
+ if bounding_box_ROI_table_name :
412
+ logger .info (f"[{ well_id } ] Writing bounding box table, exit" )
413
+ # Concatenate all FOV dataframes
414
+ df_well = pd .concat (bbox_dataframe_list , axis = 0 , ignore_index = True )
415
+ df_well .index = df_well .index .astype (str )
416
+ # Convert all to float (warning: some would be int, in principle)
417
+ bbox_dtype = np .float32
418
+ df_well = df_well .astype (bbox_dtype )
419
+ # Convert to anndata
420
+ bbox_table = ad .AnnData (df_well , dtype = bbox_dtype )
421
+ # Write to zarr group
422
+ group_tables = zarr .group (f"{ in_path } /{ component } /tables/" )
423
+ write_elem (group_tables , bounding_box_ROI_table_name , bbox_table )
424
+ logger .info (
425
+ f"[{ in_path } /{ component } /tables/{ bounding_box_ROI_table_name } "
426
+ )
427
+
381
428
return {}
382
429
383
430
@@ -402,6 +449,7 @@ class TaskArguments(BaseModel):
402
449
flow_threshold : float = 0.4
403
450
model_type : str = "nuclei"
404
451
ROI_table_name : str = "FOV_ROI_table"
452
+ bounding_box_ROI_table_name : Optional [str ] = None
405
453
406
454
run_fractal_task (
407
455
task_function = cellpose_segmentation , TaskArgsModel = TaskArguments
0 commit comments