1- import  os 
2- 
31import  napari 
42import  napari .layers 
53import  numpy  as  np 
119from  .base_widget  import  BaseWidget 
1210from  .. import  distance_measurements 
1311
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- 
3512
3613class  DistanceMeasureWidget (BaseWidget ):
3714    def  __init__ (self ):
@@ -68,47 +45,33 @@ def __init__(self):
6845    def  _to_table_data (self , distances , seg_ids , endpoints1 = None , endpoints2 = None ):
6946        assert  len (distances ) ==  len (seg_ids ), f"{ distances .shape }  , { seg_ids .shape }  " 
7047        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 }
7249        else :
73-             table_data  =  {"label " : seg_ids , "distance" : distances }
50+             table_data  =  {"label_id " : seg_ids , "distance" : distances }
7451        if  endpoints1  is  not   None :
7552            axis_names  =  "zyx"  if  endpoints1 .shape [1 ] ==  3  else  "yx" 
7653            table_data .update ({f"begin-{ ax }  " : endpoints1 [:, i ] for  i , ax  in  enumerate (axis_names )})
7754            table_data .update ({f"end-{ ax }  " : endpoints2 [:, i ] for  i , ax  in  enumerate (axis_names )})
7855        return  pd .DataFrame (table_data )
7956
80-     def  _add_lines_and_table (self , lines , properties ,  table_data , name ):
57+     def  _add_lines_and_table (self , lines , table_data , name ):
8158        line_layer  =  self .viewer .add_shapes (
8259            lines ,
8360            name = name ,
8461            shape_type = "line" ,
8562            edge_width = 2 ,
8663            edge_color = "red" ,
8764            blending = "additive" ,
88-             properties = properties ,
8965        )
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 ())
10067
10168    def  on_measure_seg_to_object (self ):
10269        segmentation  =  self ._get_layer_selector_data (self .image_selector_name1 )
10370        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. 
10573        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 )
11275
11376        (distances ,
11477         endpoints1 ,
@@ -117,28 +80,23 @@ def on_measure_seg_to_object(self):
11780            segmentation = segmentation , segmented_object = object_data , distance_type = "boundary" ,
11881            resolution = resolution 
11982        )
120-         lines , properties  =  distance_measurements .create_object_distance_lines (
83+         lines , _  =  distance_measurements .create_object_distance_lines (
12184            distances = distances ,
12285            endpoints1 = endpoints1 ,
12386            endpoints2 = endpoints2 ,
12487            seg_ids = seg_ids ,
12588        )
12689        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" )
12891
12992    def  on_measure_pairwise (self ):
13093        segmentation  =  self ._get_layer_selector_data (self .image_selector_name1 )
13194        if  segmentation  is  None :
13295            show_info ("Please choose a segmentation." )
13396            return 
134-          # get metadata from layer if available 
97+ 
13598        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 )
142100
143101        (distances ,
144102         endpoints1 ,
@@ -153,7 +111,7 @@ def on_measure_pairwise(self):
153111            distances = properties ["distance" ],
154112            seg_ids = np .concatenate ([properties ["id_a" ][:, None ], properties ["id_b" ][:, None ]], axis = 1 )
155113        )
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" )
157115
158116    def  _create_settings_widget (self ):
159117        setting_values  =  QWidget ()
0 commit comments