Skip to content

Commit 14d4fe9

Browse files
Update vesicle pool widget WIP
1 parent 9b94807 commit 14d4fe9

File tree

4 files changed

+34
-27
lines changed

4 files changed

+34
-27
lines changed

synapse_net/tools/base_widget.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from superqt import QCollapsible
1212

1313
try:
14-
from napari_skimage_regionprops import add_table
14+
from napari_skimage_regionprops import add_table, get_table
1515
except ImportError:
16-
add_table = None
16+
add_table, get_table = None, None
1717

1818

1919
class BaseWidget(QWidget):
@@ -317,11 +317,21 @@ def _save_table(self, save_path, data):
317317

318318
def _add_properties_and_table(self, layer, table_data, save_path=""):
319319
if layer.properties:
320-
layer.properties = layer.properties.update(table_data)
320+
layer.properties.update(table_data)
321321
else:
322322
layer.properties = table_data
323+
323324
if add_table is not None:
324-
add_table(layer, self.viewer)
325+
table = get_table(layer, self.viewer)
326+
if table is None:
327+
add_table(layer, self.viewer)
328+
else:
329+
# FIXME updating the table does not yet work
330+
table.update_content()
331+
# table_dict = table_data.to_dict()
332+
# table_dict["index"] = table_dict["label"]
333+
# table.set_content(table_dict)
334+
325335
# Save table to file if save path is provided.
326336
if save_path != "":
327337
file_path = self._save_table(self.save_path.text(), table_data)

synapse_net/tools/distance_measure_widget.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ def __init__(self):
4545
def _to_table_data(self, distances, seg_ids, endpoints1=None, endpoints2=None):
4646
assert len(distances) == len(seg_ids), f"{distances.shape}, {seg_ids.shape}"
4747
if seg_ids.ndim == 2:
48-
table_data = {"label_id1": seg_ids[:, 0], "label_id2": seg_ids[:, 1], "distance": distances}
48+
table_data = {"label1": seg_ids[:, 0], "label2": seg_ids[:, 1], "distance": distances}
4949
else:
50-
table_data = {"label_id": seg_ids, "distance": distances}
50+
table_data = {"label": seg_ids, "distance": distances}
5151
if endpoints1 is not None:
5252
axis_names = "zyx" if endpoints1.shape[1] == 3 else "yx"
5353
table_data.update({f"begin-{ax}": endpoints1[:, i] for i, ax in enumerate(axis_names)})

synapse_net/tools/morphology_widget.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def _to_table_data(self, coords, radii, props):
121121
# Define columns based on dimension (2D or 3D)
122122
col_names = ["x", "y"] if coords.shape[1] == 2 else ["x", "y", "z"]
123123
table_data = {
124-
"label_id": [prop.label for prop in props],
124+
"label": [prop.label for prop in props],
125125
**{col: coords[:, i] for i, col in enumerate(col_names)},
126126
"radius": radii,
127127
"intensity_max": [prop.intensity_max for prop in props],

synapse_net/tools/vesicle_pool_widget.py

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99

1010
from .base_widget import BaseWidget
1111

12-
try:
13-
from napari_skimage_regionprops import add_table
14-
except ImportError:
15-
add_table = None
16-
1712
# This will fail if we have more than 8 pools.
1813
COLORMAP = ["red", "blue", "yellow", "cyan", "purple", "magenta", "orange", "green"]
1914

@@ -107,9 +102,8 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, pool_layer_
107102
pool_name (str): Name for the pooled group to be assigned.
108103
query (dict): Query parameters.
109104
"""
110-
111-
distance_ids = distances.get("label_id", [])
112-
morphology_ids = morphology.get("label_id", [])
105+
distance_ids = distances.get("label", [])
106+
morphology_ids = morphology.get("label", [])
113107

114108
# Ensure that IDs are identical.
115109
if set(distance_ids) != set(morphology_ids):
@@ -120,11 +114,11 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, pool_layer_
120114
# TODO: select the dataframes more dynamically depending on the criterion defined by the user.
121115
distances = pd.DataFrame(distances)
122116
morphology = pd.DataFrame(morphology)
123-
merged_df = morphology.merge(distances, left_on="label_id", right_on="label_id", suffixes=("_morph", "_dist"))
117+
merged_df = morphology.merge(distances, left_on="label", right_on="label", suffixes=("_morph", "_dist"))
124118

125119
# Assign the vesicles to the current pool by filtering the mergeddataframe based on the query.
126120
filtered_df = self._parse_query(query, merged_df)
127-
pool_vesicle_ids = filtered_df.label_id.values.tolist()
121+
pool_vesicle_ids = filtered_df.label.values.tolist()
128122

129123
# Check if this layer was already created in a previous pool assignment.
130124
if pool_layer_name in self.viewer.layers:
@@ -140,7 +134,7 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, pool_layer_
140134

141135
# Combine the vesicle ids corresponding to the previous assignment with the
142136
# assignment for the new / current pool.
143-
old_pool_ids = pool_properties.label_id.values.tolist()
137+
old_pool_ids = pool_properties.label.values.tolist()
144138
pool_assignments = sorted(pool_vesicle_ids + old_pool_ids)
145139

146140
# Get a map for each vesicle id to its pool.
@@ -161,7 +155,14 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, pool_layer_
161155
vesicle_pools[~np.isin(vesicle_pools, pool_assignments)] = 0
162156

163157
# Create the pool properties.
164-
pool_properties = merged_df[merged_df.label_id.isin(pool_assignments)]
158+
pool_properties = merged_df[merged_df.label.isin(pool_assignments)]
159+
# Remove columns that are not relevant for measurements.
160+
keep_columns = [
161+
col for col in pool_properties.columns
162+
if col not in ("x", "y", "z", "begin-x", "begin-y", "begin-z", "end-x", "end-y", "end-z")
163+
]
164+
pool_properties = pool_properties[keep_columns].reset_index()
165+
# Add a colun for the pool.
165166
pool_properties.insert(1, "pool", pool_values)
166167

167168
# Create the colormap to group the pools in the layer rendering.
@@ -170,26 +171,25 @@ def _compute_vesicle_pool(self, segmentation, distances, morphology, pool_layer_
170171
# To avoid this the user has to specify the pool color (not yet implemented, see next todo).
171172
pool_names = np.unique(pool_values).tolist()
172173
# TODO: add setting so that users can over-ride the color for a pool.
173-
# TODO: provide a default color (how?) to avoid the warning
174174
pool_colors = {pname: COLORMAP[pool_names.index(pname)] for pname in pool_names}
175175
vesicle_colors = {
176176
label_id: pool_colors[pname] for label_id, pname
177-
in zip(pool_properties.label_id.values, pool_properties.pool.values)
177+
in zip(pool_properties.label.values, pool_properties.pool.values)
178178
}
179+
vesicle_colors[None] = "gray"
179180

180181
# TODO print some messages
181182
# Add or replace the pool layer and properties.
182183
if pool_layer_name in self.viewer.layers:
183184
# message about added or over-ridden pool, including number of vesicles in pool
184185
pool_layer = self.viewer.layers[pool_layer_name]
185186
pool_layer.data = vesicle_pools
186-
pool_layer.color_map = vesicle_colors
187+
pool_layer.colormap = vesicle_colors
187188
else:
188189
# message about new pool, including number of vesicles in pool
189190
pool_layer = self.viewer.add_labels(vesicle_pools, name=pool_layer_name, colormap=vesicle_colors)
190191

191-
# TODO add the save path
192-
self._add_properties_and_table(pool_layer, pool_properties, save_path="")
192+
self._add_properties_and_table(pool_layer, pool_properties, save_path=self.save_path.text())
193193
pool_layer.refresh()
194194

195195
def _parse_query(self, query: str, data: pd.DataFrame) -> pd.DataFrame:
@@ -220,8 +220,5 @@ def _create_settings_widget(self):
220220
self.save_path, layout = self._add_path_param(name="Save Table", select_type="file", value="")
221221
setting_values.layout().addLayout(layout)
222222

223-
self.voxel_size_param, layout = self._add_float_param("voxel_size", 0.0, min_val=0.0, max_val=100.0)
224-
setting_values.layout().addLayout(layout)
225-
226223
settings = self._make_collapsible(widget=setting_values, title="Advanced Settings")
227224
return settings

0 commit comments

Comments
 (0)