Skip to content

Commit bc39941

Browse files
committed
added vesicle pool widget
1 parent c4bbc00 commit bc39941

File tree

2 files changed

+56
-80
lines changed

2 files changed

+56
-80
lines changed

synaptic_reconstruction/tools/morphology_widget.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ def _add_table(self, coords, radii, props, name="Shapes Layer"):
156156
table_data = self._to_table_data(coords, radii, props)
157157

158158
# Add the shapes layer
159-
layer = self._create_shapes_layer(table_data, name)
159+
layer = self._get_layer_selector_layer(self.image_selector_name1)
160+
if layer.properties:
161+
layer.properties = layer.properties.update(table_data)
162+
else:
163+
layer.properties = table_data
160164

161165
if add_table is not None:
162166
add_table(layer, self.viewer)
@@ -217,10 +221,12 @@ def on_measure_structure_morphology(self):
217221
self._add_table_structure(morphology)
218222

219223
def _add_table_structure(self, morphology):
220-
segmentation = self._get_layer_selector_data(self.image_selector_name1)
221-
layer = self.viewer.add_labels(np.zeros(segmentation.shape, dtype=np.uint16), name="Structure Morphology")
224+
layer = self._get_layer_selector_layer(self.image_selector_name1)
222225
# Add properties to layer for add_table function
223-
layer.properties = morphology
226+
if layer.properties:
227+
layer.properties = layer.properties.update(morphology)
228+
else:
229+
layer.properties = morphology
224230

225231
# Add a table layer to the Napari viewer
226232
if add_table is not None:

synaptic_reconstruction/tools/vesicle_pool_widget.py

Lines changed: 46 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ def __init__(self):
2828

2929
self.image_selector_name = "Distances to Structure"
3030
self.image_selector_name1 = "Vesicles Segmentation"
31-
self.image_selector_name2 = "Vesicles Morphology"
3231
# # Create the image selection dropdown.
3332
self.image_selector_widget = self._create_layer_selector(self.image_selector_name, layer_type="Shapes")
3433
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")
3634

3735
# Create new layer name
3836
self.new_layer_name_param, new_layer_name_layout = self._add_string_param(
@@ -62,25 +60,20 @@ def __init__(self):
6260

6361
# Add the widgets to the layout.
6462
layout.addWidget(self.image_selector_widget)
65-
layout.addWidget(self.image_selector_widget2)
6663
layout.addWidget(self.segmentation1_selector_widget)
6764
layout.addLayout(query_layout)
6865
layout.addLayout(new_layer_name_layout)
6966
layout.addLayout(pooled_group_name_layout)
70-
# layout.addWidget(self.settings)
7167
layout.addWidget(self.measure_button1)
72-
# layout.addWidget(self.measure_button2)
7368

7469
self.setLayout(layout)
7570

7671
def on_pool_vesicles(self):
7772
distances_layer = self._get_layer_selector_layer(self.image_selector_name)
7873
distances = distances_layer.properties
7974
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)
8176
morphology = morphology_layer.properties
82-
print("distances", distances)
83-
print("morphology", morphology)
8477

8578
if segmentation is None:
8679
show_info("INFO: Please choose a segmentation.")
@@ -99,25 +92,12 @@ def on_pool_vesicles(self):
9992
show_info("INFO: Please enter a pooled group name.")
10093
return
10194
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+
10796
if distances is None:
10897
show_info("INFO: Distances layer could not be found or has no values.")
10998
return
11099
vesicle_pool = self._compute_vesicle_pool(segmentation, distances, morphology, new_layer_name, pooled_group_name, query)
111100

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-
121101
def _compute_vesicle_pool(self, segmentation, distances, morphology, new_layer_name, pooled_group_name, query):
122102
"""
123103
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
128108
morphology (dict): Properties from the morphology layer.
129109
new_layer_name (str): Name for the new layer to be created.
130110
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.
132112
133113
Returns:
134114
dict: Updated properties for the new vesicle pool.
@@ -147,73 +127,63 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, new_layer_n
147127

148128
# Merge dataframes on the 'id' column
149129
merged_df = morphology.merge(distances, left_on="label_id", right_on="id", suffixes=("_morph", "_dist"))
150-
# Filter rows based on query parameters
130+
151131
# Apply the query string to filter the data
152132
filtered_df = self._parse_query(query, merged_df)
153133

154134
# Extract valid vesicle IDs
155135
valid_vesicle_ids = filtered_df["label_id"].tolist()
156136

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
162137
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
163148
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)
177181
return {
178182
"id": valid_vesicle_ids,
179183
"radius": filtered_df["radius"].tolist(),
180184
"distance": filtered_df["distance"].tolist(),
181185
}
182186

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-
217187
def _parse_query(self, query, data):
218188
"""
219189
Parse and apply a query string to filter data.

0 commit comments

Comments
 (0)