1
1
import os
2
2
import multiprocessing as mp
3
- from typing import Dict , List , Optional , Tuple
3
+ from typing import Dict , List , Optional , Tuple , Union
4
4
5
5
import numpy as np
6
6
18
18
skfmm = None
19
19
20
20
21
- def compute_geodesic_distances (segmentation , distance_to , resolution = None , unsigned = True ):
21
+ def compute_geodesic_distances (
22
+ segmentation : np .ndarray ,
23
+ distance_to : np .ndarray ,
24
+ resolution : Optional [Union [int , float , Tuple [int , int , int ]]] = None ,
25
+ unsigned : bool = True ,
26
+ ) -> np .ndarray :
27
+ """Compute the geodesic distances between a segmentation and a distance target.
28
+
29
+ This function require scikit-fmm to be installed.
30
+
31
+ Args:
32
+ segmentation: The binary segmentation.
33
+ distance_to: The binary distance target.
34
+ resolution: The voxel size of the data, used to scale the distances.
35
+ unsigned: Whether to return the unsigned or signed distances.
36
+
37
+ Returns:
38
+ Array with the geodesic distance values.
39
+ """
22
40
assert skfmm is not None , "Please install scikit-fmm to use compute_geodesic_distance."
23
41
24
42
invalid = segmentation == 0
@@ -43,14 +61,12 @@ def compute_geodesic_distances(segmentation, distance_to, resolution=None, unsig
43
61
return distances
44
62
45
63
46
- # TODO update this
47
64
def _compute_centroid_distances (segmentation , resolution , n_neighbors ):
48
- # TODO enable eccentricity centers instead
49
65
props = regionprops (segmentation )
50
66
centroids = np .array ([prop .centroid for prop in props ])
51
67
if resolution is not None :
52
- pass # TODO scale the centroids
53
-
68
+ scale_factor = np . array ( resolution )[:, None ]
69
+ centroids *= scale_factor
54
70
pair_distances = pairwise_distances (centroids )
55
71
return pair_distances
56
72
@@ -313,11 +329,13 @@ def create_pairwise_distance_lines(
313
329
endpoints1: One set of distance end points.
314
330
endpoints2: The other set of distance end points.
315
331
seg_ids: The segmentation pair corresponding to each distance.
316
- n_neighbors: ...
317
- pairs: ...
318
- bb: ....
319
- scale: ...
320
- remove_duplicates: ...
332
+ n_neighbors: The number of nearest neighbors to take into consideration
333
+ for creating the distance lines.
334
+ pairs: Optional list of ids to use for creating the distance lines.
335
+ bb: Bounding box for restricing the distance line creation.
336
+ scale: Scale factor for resizing the distance lines.
337
+ Use this if the corresponding segmentations were downscaled for visualization.
338
+ remove_duplicates: Remove duplicate id pairs from the distance lines.
321
339
322
340
Returns:
323
341
The lines for plotting in napari.
@@ -386,8 +404,10 @@ def create_object_distance_lines(
386
404
endpoints1: One set of distance end points.
387
405
endpoints2: The other set of distance end points.
388
406
seg_ids: The segmentation ids corresponding to each distance.
389
- max_distance: ...
390
- scale: ...
407
+ max_distance: Maximal distance for drawing the distance line.
408
+ filter_seg_ids: Segmentation ids to restrict the distance lines.
409
+ scale: Scale factor for resizing the distance lines.
410
+ Use this if the corresponding segmentations were downscaled for visualization.
391
411
392
412
Returns:
393
413
The lines for plotting in napari.
@@ -416,13 +436,32 @@ def create_object_distance_lines(
416
436
return lines , properties
417
437
418
438
419
- def keep_direct_distances (segmentation , measurement_path , line_dilation = 0 , scale = None ):
420
- """Filter out all distances that are not direct.
421
- I.e. distances that cross another segmented object.
422
- """
439
+ def keep_direct_distances (
440
+ segmentation : np .ndarray ,
441
+ distances : np .ndarray ,
442
+ endpoints1 : np .ndarray ,
443
+ endpoints2 : np .ndarray ,
444
+ seg_ids : np .ndarray ,
445
+ line_dilation : int = 0 ,
446
+ scale : Optional [Tuple [int , int , int ]] = None ,
447
+ ) -> List [List [int , int ]]:
448
+ """Filter out all distances that are not direct; distances that are occluded by another segmented object.
423
449
424
- distances , ep1 , ep2 , seg_ids = load_distances (measurement_path )
425
- distance_lines , properties = create_object_distance_lines (distances , ep1 , ep2 , seg_ids , scale = scale )
450
+ Args:
451
+ segmentation: The segmentation from which the distances are derived.
452
+ distances: The measurd distances.
453
+ endpoints1: One set of distance end points.
454
+ endpoints2: The other set of distance end points.
455
+ seg_ids: The segmentation ids corresponding to each distance.
456
+ line_dilation: Dilation factor of the distance lines for determining occlusions.
457
+ scale: Scaling factor of the segmentation compared to the distance measurements.
458
+
459
+ Returns:
460
+ The list of id pairs that are kept.
461
+ """
462
+ distance_lines , properties = create_object_distance_lines (
463
+ distances , endpoints1 , endpoints2 , seg_ids , scale = scale
464
+ )
426
465
427
466
ids_a , ids_b = properties ["id_a" ], properties ["id_b" ]
428
467
filtered_ids_a , filtered_ids_b = [], []
@@ -459,10 +498,35 @@ def keep_direct_distances(segmentation, measurement_path, line_dilation=0, scale
459
498
460
499
461
500
def filter_blocked_segmentation_to_object_distances (
462
- segmentation , measurement_path , line_dilation = 0 , scale = None , seg_ids = None , verbose = False ,
463
- ):
464
- distances , ep1 , ep2 , seg_ids = load_distances (measurement_path )
465
- distance_lines , properties = create_object_distance_lines (distances , ep1 , ep2 , seg_ids , scale = scale )
501
+ segmentation : np .ndarray ,
502
+ distances : np .ndarray ,
503
+ endpoints1 : np .ndarray ,
504
+ endpoints2 : np .ndarray ,
505
+ seg_ids : np .ndarray ,
506
+ line_dilation : int = 0 ,
507
+ scale : Optional [Tuple [int , int , int ]] = None ,
508
+ filter_seg_ids : Optional [List [int ]] = None ,
509
+ verbose : bool = False ,
510
+ ) -> List [int ]:
511
+ """Filter out all distances that are not direct; distances that are occluded by another segmented object.
512
+
513
+ Args:
514
+ segmentation: The segmentation from which the distances are derived.
515
+ distances: The measurd distances.
516
+ endpoints1: One set of distance end points.
517
+ endpoints2: The other set of distance end points.
518
+ seg_ids: The segmentation ids corresponding to each distance.
519
+ line_dilation: Dilation factor of the distance lines for determining occlusions.
520
+ scale: Scaling factor of the segmentation compared to the distance measurements.
521
+ filter_seg_ids: Segmentation ids to restrict the distance lines.
522
+ verbose: Whether to print progressbar.
523
+
524
+ Returns:
525
+ The list of id pairs that are kept.
526
+ """
527
+ distance_lines , properties = create_object_distance_lines (
528
+ distances , endpoints1 , endpoints2 , seg_ids , scale = scale
529
+ )
466
530
all_seg_ids = properties ["id" ]
467
531
468
532
filtered_ids = []
0 commit comments