@@ -28,11 +28,9 @@ def __init__(self):
28
28
29
29
self .image_selector_name = "Distances to Structure"
30
30
self .image_selector_name1 = "Vesicles Segmentation"
31
- self .image_selector_name2 = "Vesicles Morphology"
32
31
# # Create the image selection dropdown.
33
32
self .image_selector_widget = self ._create_layer_selector (self .image_selector_name , layer_type = "Shapes" )
34
33
self .segmentation1_selector_widget = self ._create_layer_selector (self .image_selector_name1 , layer_type = "Labels" )
35
- self .image_selector_widget2 = self ._create_layer_selector (self .image_selector_name2 , layer_type = "Shapes" )
36
34
37
35
# Create new layer name
38
36
self .new_layer_name_param , new_layer_name_layout = self ._add_string_param (
@@ -62,25 +60,20 @@ def __init__(self):
62
60
63
61
# Add the widgets to the layout.
64
62
layout .addWidget (self .image_selector_widget )
65
- layout .addWidget (self .image_selector_widget2 )
66
63
layout .addWidget (self .segmentation1_selector_widget )
67
64
layout .addLayout (query_layout )
68
65
layout .addLayout (new_layer_name_layout )
69
66
layout .addLayout (pooled_group_name_layout )
70
- # layout.addWidget(self.settings)
71
67
layout .addWidget (self .measure_button1 )
72
- # layout.addWidget(self.measure_button2)
73
68
74
69
self .setLayout (layout )
75
70
76
71
def on_pool_vesicles (self ):
77
72
distances_layer = self ._get_layer_selector_layer (self .image_selector_name )
78
73
distances = distances_layer .properties
79
74
segmentation = self ._get_layer_selector_data (self .image_selector_name1 )
80
- morphology_layer = self ._get_layer_selector_layer (self .image_selector_name2 )
75
+ morphology_layer = self ._get_layer_selector_layer (self .image_selector_name1 )
81
76
morphology = morphology_layer .properties
82
- print ("distances" , distances )
83
- print ("morphology" , morphology )
84
77
85
78
if segmentation is None :
86
79
show_info ("INFO: Please choose a segmentation." )
@@ -99,25 +92,12 @@ def on_pool_vesicles(self):
99
92
show_info ("INFO: Please enter a pooled group name." )
100
93
return
101
94
pooled_group_name = self .pooled_group_name_param .text ()
102
-
103
- # Get distances layer
104
- # distance_layer_name = # query.get("distance_layer_name", None)
105
- # if distance_layer_name in self.viewer.layers:
106
- # distances = self._get_layer_selector_data(self.image_selector_name1, return_metadata=True)
95
+
107
96
if distances is None :
108
97
show_info ("INFO: Distances layer could not be found or has no values." )
109
98
return
110
99
vesicle_pool = self ._compute_vesicle_pool (segmentation , distances , morphology , new_layer_name , pooled_group_name , query )
111
100
112
- # # get metadata from layer if available
113
- # metadata = self._get_layer_selector_data(self.image_selector_name1, return_metadata=True)
114
- # resolution = metadata.get("voxel_size", None)
115
- # if resolution is not None:
116
- # resolution = [v for v in resolution.values()]
117
- # # if user input is present override metadata
118
- # if self.voxel_size_param.value() != 0.0: # changed from default
119
- # resolution = segmentation.ndim * [self.voxel_size_param.value()]
120
-
121
101
def _compute_vesicle_pool (self , segmentation , distances , morphology , new_layer_name , pooled_group_name , query ):
122
102
"""
123
103
Compute a vesicle pool based on the provided query parameters.
@@ -128,7 +108,7 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, new_layer_n
128
108
morphology (dict): Properties from the morphology layer.
129
109
new_layer_name (str): Name for the new layer to be created.
130
110
pooled_group_name (str): Name for the pooled group to be assigned.
131
- query (dict): Query parameters with keys "min_radius" and "max_distance" .
111
+ query (dict): Query parameters.
132
112
133
113
Returns:
134
114
dict: Updated properties for the new vesicle pool.
@@ -147,73 +127,63 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, new_layer_n
147
127
148
128
# Merge dataframes on the 'id' column
149
129
merged_df = morphology .merge (distances , left_on = "label_id" , right_on = "id" , suffixes = ("_morph" , "_dist" ))
150
- # Filter rows based on query parameters
130
+
151
131
# Apply the query string to filter the data
152
132
filtered_df = self ._parse_query (query , merged_df )
153
133
154
134
# Extract valid vesicle IDs
155
135
valid_vesicle_ids = filtered_df ["label_id" ].tolist ()
156
136
157
- # Debugging output
158
- for _ , row in filtered_df .iterrows ():
159
- print (f"Vesicle { row ['label_id' ]} : Passed (Radius: { row ['radius' ]} , Distance: { row ['distance' ]} )" )
160
-
161
- # Update segmentation layer with valid vesicles
162
137
new_layer_data = np .zeros (segmentation .shape , dtype = np .uint8 )
138
+ pool_id = 1
139
+ layer = None
140
+
141
+ # check if group already exists
142
+ if new_layer_name in self .viewer .layers :
143
+ layer = self .viewer .layers [new_layer_name ]
144
+ if pooled_group_name not in layer .properties ["pool" ]:
145
+ new_layer_data = layer .data
146
+ pool_id = len (np .unique (layer .properties ["pool" ])) + 1
147
+ # compute vesicles with new pool_id and properties
163
148
for vesicle_id in valid_vesicle_ids :
164
- new_layer_data [segmentation == vesicle_id ] = 1 # Highlight pooled vesicles
165
-
166
- # Create a new layer in the viewer
167
- self .viewer .add_labels (
168
- new_layer_data ,
169
- name = new_layer_name ,
170
- properties = {
171
- "id" : valid_vesicle_ids ,
172
- "radius" : filtered_df ["radius" ].tolist (),
173
- "distance" : filtered_df ["distance" ].tolist (),
174
- },
175
- )
176
- show_info (f"Vesicle pool created with { len (valid_vesicle_ids )} vesicles." )
149
+ new_layer_data [segmentation == vesicle_id ] = pool_id
150
+ new_properties = {
151
+ "id" : valid_vesicle_ids ,
152
+ "radius" : filtered_df ["radius" ].tolist (),
153
+ "distance" : filtered_df ["distance" ].tolist (),
154
+ "pool" : [pooled_group_name ] * len (valid_vesicle_ids )
155
+ }
156
+ if new_layer_name in self .viewer .layers :
157
+ layer = self .viewer .layers [new_layer_name ]
158
+ # override current vesicles with new pooled vesicles
159
+ if pooled_group_name in layer .properties ["pool" ]:
160
+ layer .data = new_layer_data
161
+ layer .properties = new_properties
162
+ show_info (f"Vesicle pool '{ pooled_group_name } ' overriden with { len (valid_vesicle_ids )} vesicles." )
163
+ else :
164
+ # add new vesicles and pool to existing layer
165
+ current_properties = pd .DataFrame (layer .properties )
166
+ new_properties = pd .DataFrame (new_properties )
167
+ merged = pd .concat ([current_properties , new_properties ], ignore_index = True )
168
+ layer .data = new_layer_data
169
+ layer .properties = merged
170
+ show_info (f"Vesicle pool '{ pooled_group_name } ' updated with { len (valid_vesicle_ids )} vesicles." )
171
+ else :
172
+ # Create a new layer in the viewer
173
+ self .viewer .add_labels (
174
+ new_layer_data ,
175
+ name = new_layer_name ,
176
+ properties = new_properties
177
+ )
178
+ show_info (f"Added new layer '{ new_layer_name } ' with { len (valid_vesicle_ids )} vesicles in group '{ pooled_group_name } '." )
179
+ if add_table is not None :
180
+ add_table (self .viewer .layers [new_layer_name ], self .viewer )
177
181
return {
178
182
"id" : valid_vesicle_ids ,
179
183
"radius" : filtered_df ["radius" ].tolist (),
180
184
"distance" : filtered_df ["distance" ].tolist (),
181
185
}
182
186
183
- # # Filter vesicles based on the query
184
- # valid_vesicles = []
185
- # for i in distances_ids:
186
- # distance = distances.get("distance", [])[i]
187
- # radius = morphology.get("radius", [])[i]
188
- # if radius >= min_radius and distance <= max_distance:
189
- # print(f"Vesicle {i}: Passed (Radius: {radius}, Distance: {distance})")
190
- # valid_vesicles.append(i)
191
- # else:
192
- # print(f"Vesicle {i}: Failed (Radius: {radius}, Distance: {distance})")
193
-
194
- # Create pooled properties
195
- # pooled_properties = {
196
- # "id": [i for i in valid_vesicles],
197
- # "radius": [morphology["radius"][i] for i in valid_vesicles],
198
- # "distance": [distances["distance"][i] for i in valid_vesicles],
199
- # }
200
- # print("pooled_properties", pooled_properties)
201
- # print("np.unique(segmenation)", np.unique(segmentation))
202
-
203
- # # Create a new layer in the viewer
204
- # new_layer_data = np.zeros(segmentation.shape, dtype=np.uint8)
205
- # for vesicle_id in valid_vesicles:
206
- # new_layer_data[segmentation == vesicle_id] = 1
207
-
208
- # self.viewer.add_labels(
209
- # new_layer_data,
210
- # name=new_layer_name,
211
- # properties=pooled_properties,
212
- # )
213
-
214
- # show_info(f"INFO: Created pooled vesicle layer '{new_layer_name}' with {len(valid_vesicles)} vesicles.")
215
- # return pooled_properties
216
-
217
187
def _parse_query (self , query , data ):
218
188
"""
219
189
Parse and apply a query string to filter data.
0 commit comments