1
- import os
2
-
3
1
import napari
4
2
import napari .layers
5
3
import numpy as np
11
9
from .base_widget import BaseWidget
12
10
from .. import distance_measurements
13
11
14
- try :
15
- from napari_skimage_regionprops import add_table
16
- except ImportError :
17
- add_table = None
18
-
19
-
20
- def _save_distance_table (save_path , data ):
21
- ext = os .path .splitext (save_path )[1 ]
22
- if ext == "" : # No file extension given, By default we save to CSV.
23
- file_path = f"{ save_path } .csv"
24
- data .to_csv (file_path , index = False )
25
- elif ext == ".csv" : # Extension was specified as csv
26
- file_path = save_path
27
- data .to_csv (file_path , index = False )
28
- elif ext == ".xlsx" : # We also support excel.
29
- file_path = save_path
30
- data .to_excel (file_path , index = False )
31
- else :
32
- raise ValueError ("Invalid extension for table: {ext}. We support .csv or .xlsx." )
33
- return file_path
34
-
35
12
36
13
class DistanceMeasureWidget (BaseWidget ):
37
14
def __init__ (self ):
@@ -68,47 +45,33 @@ def __init__(self):
68
45
def _to_table_data (self , distances , seg_ids , endpoints1 = None , endpoints2 = None ):
69
46
assert len (distances ) == len (seg_ids ), f"{ distances .shape } , { seg_ids .shape } "
70
47
if seg_ids .ndim == 2 :
71
- table_data = {"label1 " : seg_ids [:, 0 ], "label2 " : seg_ids [:, 1 ], "distance" : distances }
48
+ table_data = {"label_id1 " : seg_ids [:, 0 ], "label_id2 " : seg_ids [:, 1 ], "distance" : distances }
72
49
else :
73
- table_data = {"label " : seg_ids , "distance" : distances }
50
+ table_data = {"label_id " : seg_ids , "distance" : distances }
74
51
if endpoints1 is not None :
75
52
axis_names = "zyx" if endpoints1 .shape [1 ] == 3 else "yx"
76
53
table_data .update ({f"begin-{ ax } " : endpoints1 [:, i ] for i , ax in enumerate (axis_names )})
77
54
table_data .update ({f"end-{ ax } " : endpoints2 [:, i ] for i , ax in enumerate (axis_names )})
78
55
return pd .DataFrame (table_data )
79
56
80
- def _add_lines_and_table (self , lines , properties , table_data , name ):
57
+ def _add_lines_and_table (self , lines , table_data , name ):
81
58
line_layer = self .viewer .add_shapes (
82
59
lines ,
83
60
name = name ,
84
61
shape_type = "line" ,
85
62
edge_width = 2 ,
86
63
edge_color = "red" ,
87
64
blending = "additive" ,
88
- properties = properties ,
89
65
)
90
- if add_table is not None :
91
- add_table (line_layer , self .viewer )
92
-
93
- if self .save_path .text () != "" :
94
- file_path = _save_distance_table (self .save_path .text (), table_data )
95
-
96
- if self .save_path .text () != "" :
97
- show_info (f"Added distance lines and saved file to { file_path } ." )
98
- else :
99
- show_info ("Added distance lines." )
66
+ self ._add_properties_and_table (line_layer , table_data , self .save_path .text ())
100
67
101
68
def on_measure_seg_to_object (self ):
102
69
segmentation = self ._get_layer_selector_data (self .image_selector_name1 )
103
70
object_data = self ._get_layer_selector_data (self .image_selector_name2 )
104
- # get metadata from layer if available
71
+
72
+ # Get the resolution / voxel size.
105
73
metadata = self ._get_layer_selector_data (self .image_selector_name1 , return_metadata = True )
106
- resolution = metadata .get ("voxel_size" , None )
107
- if resolution is not None :
108
- resolution = [v for v in resolution .values ()]
109
- # if user input is present override metadata
110
- if self .voxel_size_param .value () != 0.0 : # changed from default
111
- resolution = segmentation .ndim * [self .voxel_size_param .value ()]
74
+ resolution = self ._handle_resolution (metadata , self .voxel_size_param , segmentation .ndim )
112
75
113
76
(distances ,
114
77
endpoints1 ,
@@ -117,28 +80,23 @@ def on_measure_seg_to_object(self):
117
80
segmentation = segmentation , segmented_object = object_data , distance_type = "boundary" ,
118
81
resolution = resolution
119
82
)
120
- lines , properties = distance_measurements .create_object_distance_lines (
83
+ lines , _ = distance_measurements .create_object_distance_lines (
121
84
distances = distances ,
122
85
endpoints1 = endpoints1 ,
123
86
endpoints2 = endpoints2 ,
124
87
seg_ids = seg_ids ,
125
88
)
126
89
table_data = self ._to_table_data (distances , seg_ids , endpoints1 , endpoints2 )
127
- self ._add_lines_and_table (lines , properties , table_data , name = "distances" )
90
+ self ._add_lines_and_table (lines , table_data , name = "distances" )
128
91
129
92
def on_measure_pairwise (self ):
130
93
segmentation = self ._get_layer_selector_data (self .image_selector_name1 )
131
94
if segmentation is None :
132
95
show_info ("Please choose a segmentation." )
133
96
return
134
- # get metadata from layer if available
97
+
135
98
metadata = self ._get_layer_selector_data (self .image_selector_name1 , return_metadata = True )
136
- resolution = metadata .get ("voxel_size" , None )
137
- if resolution is not None :
138
- resolution = [v for v in resolution .values ()]
139
- # if user input is present override metadata
140
- if self .voxel_size_param .value () != 0.0 : # changed from default
141
- resolution = segmentation .ndim * [self .voxel_size_param .value ()]
99
+ resolution = self ._handle_resolution (metadata , self .voxel_size_param , segmentation .ndim )
142
100
143
101
(distances ,
144
102
endpoints1 ,
@@ -153,7 +111,7 @@ def on_measure_pairwise(self):
153
111
distances = properties ["distance" ],
154
112
seg_ids = np .concatenate ([properties ["id_a" ][:, None ], properties ["id_b" ][:, None ]], axis = 1 )
155
113
)
156
- self ._add_lines_and_table (lines , properties , table_data , name = "pairwise-distances" )
114
+ self ._add_lines_and_table (lines , table_data , name = "pairwise-distances" )
157
115
158
116
def _create_settings_widget (self ):
159
117
setting_values = QWidget ()
0 commit comments