1111from .base_widget import BaseWidget
1212from synaptic_reconstruction .imod .to_imod import convert_segmentation_to_spheres
1313from synaptic_reconstruction .morphology import compute_object_morphology
14- from synaptic_reconstruction .tools .util import _save_table
15-
16- try :
17- from napari_skimage_regionprops import add_table
18- except ImportError :
19- add_table = None
2014
2115
2216class MorphologyWidget (BaseWidget ):
@@ -125,51 +119,19 @@ def _to_table_data(self, coords, radii, props):
125119 assert len (coords ) == len (radii ), f"Shape mismatch: { coords .shape } , { radii .shape } "
126120
127121 # Define columns based on dimension (2D or 3D)
128- col_names = ['x' , 'y' ] if coords .shape [1 ] == 2 else ['x' , 'y' , 'z' ]
122+ col_names = ["x" , "y" ] if coords .shape [1 ] == 2 else ["x" , "y" , "z" ]
129123 table_data = {
130- ' label_id' : [prop .label for prop in props ],
124+ " label_id" : [prop .label for prop in props ],
131125 ** {col : coords [:, i ] for i , col in enumerate (col_names )},
132- ' radius' : radii ,
133- ' intensity_max' : [prop .intensity_max for prop in props ],
134- ' intensity_mean' : [prop .intensity_mean for prop in props ],
135- ' intensity_min' : [prop .intensity_min for prop in props ],
136- ' intensity_std' : [prop .intensity_std for prop in props ],
126+ " radius" : radii ,
127+ " intensity_max" : [prop .intensity_max for prop in props ],
128+ " intensity_mean" : [prop .intensity_mean for prop in props ],
129+ " intensity_min" : [prop .intensity_min for prop in props ],
130+ " intensity_std" : [prop .intensity_std for prop in props ],
137131 }
138132
139133 return pd .DataFrame (table_data )
140134
141- def _add_table (self , coords , radii , props , name = "Shapes Layer" ):
142- """
143- Add a Shapes layer and table data to the Napari viewer.
144-
145- Args:
146- viewer (napari.Viewer): The Napari viewer instance.
147- coords (np.ndarray): Array of 2D or 3D coordinates.
148- radii (np.ndarray): Array of radii corresponding to the coordinates.
149- props (list): List of properties containing intensity statistics.
150- name (str): Name of the Shapes layer.
151- save_path (str): Path to save the table data, if provided.
152- """
153- # Create table data
154- table_data = self ._to_table_data (coords , radii , props )
155-
156- # Add the shapes layer
157- layer = self ._get_layer_selector_layer (self .image_selector_name1 )
158- if layer .properties :
159- layer .properties = layer .properties .update (table_data )
160- else :
161- layer .properties = table_data
162-
163- if add_table is not None :
164- add_table (layer , self .viewer )
165-
166- # Save the table to a file if a save path is provided
167- if self .save_path .text ():
168- table_data .to_csv (self .save_path , index = False )
169- print (f"INFO: Added table and saved file to { self .save_path } ." )
170- else :
171- print ("INFO: Table added to viewer." )
172-
173135 def on_measure_vesicle_morphology (self ):
174136 segmentation = self ._get_layer_selector_data (self .image_selector_name1 )
175137 image = self ._get_layer_selector_data (self .image_selector_name )
@@ -180,23 +142,22 @@ def on_measure_vesicle_morphology(self):
180142 show_info ("INFO: Please choose an image." )
181143 return
182144
183- # get metadata from layer if available
145+ # Get the resolution / voxel size.
184146 metadata = self ._get_layer_selector_data (self .image_selector_name , return_metadata = True )
185- resolution = metadata .get ("voxel_size" , None )
186- if resolution is not None :
187- resolution = [v for v in resolution .values ()]
188- # if user input is present override metadata
189- if self .voxel_size_param .value () != 0.0 : # changed from default
190- resolution = segmentation .ndim * [self .voxel_size_param .value ()]
147+ resolution = self ._handle_resolution (metadata , self .voxel_size_param , segmentation .ndim )
191148
149+ # Compute the mophology parameter.
192150 props = regionprops (label_image = segmentation , intensity_image = image )
193-
194151 coords , radii = convert_segmentation_to_spheres (
195152 segmentation = segmentation ,
196153 resolution = resolution ,
197154 props = props ,
198155 )
199- self ._add_table (coords , radii , props , name = "Vesicle Morphology" )
156+
157+ # Create table data and add the properties and table to the layer.
158+ table_data = self ._to_table_data (coords , radii , props )
159+ layer = self ._get_layer_selector_layer (self .image_selector_name1 )
160+ self ._add_properties_and_table (layer , table_data , self .save_path .text ())
200161
201162 def on_measure_structure_morphology (self ):
202163 """
@@ -213,30 +174,12 @@ def on_measure_structure_morphology(self):
213174 if resolution is not None :
214175 resolution = [v for v in resolution .values ()]
215176 morphology = compute_object_morphology (
216- object_ = segmentation , structure_name = self .image_selector_name1 ,
217- resolution = resolution
218- )
219-
220- self ._add_table_structure (morphology )
177+ object_ = segmentation , structure_name = self .image_selector_name1 , resolution = resolution
178+ )
221179
222- def _add_table_structure ( self , morphology ):
180+ # Add the properties to the layer and add/save the table.
223181 layer = self ._get_layer_selector_layer (self .image_selector_name1 )
224- # Add properties to layer for add_table function
225- if layer .properties :
226- layer .properties = layer .properties .update (morphology )
227- else :
228- layer .properties = morphology
229-
230- # Add a table layer to the Napari viewer
231- if add_table is not None :
232- add_table (layer , self .viewer )
233-
234- # Save table to file if save path is provided
235- if self .save_path .text () != "" :
236- file_path = _save_table (self .save_path .text (), morphology )
237- show_info (f"INFO: Added table and saved file to { file_path } ." )
238- else :
239- print ("INFO: Table added to viewer." )
182+ self ._add_properties_and_table (layer , morphology , self .save_path .text ())
240183
241184 def _create_settings_widget (self ):
242185 setting_values = QWidget ()
0 commit comments