Skip to content

Commit a7c79b0

Browse files
author
anna-grim
committed
bug: merge counting
1 parent 4c57edb commit a7c79b0

File tree

3 files changed

+66
-31
lines changed

3 files changed

+66
-31
lines changed

src/segmentation_skeleton_metrics/skeleton_metric.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
util
2929
)
3030

31-
MERGE_DIST_THRESHOLD = 200
3231
MIN_CNT = 40
3332

3433

@@ -165,9 +164,15 @@ def load_fragments(self, swc_pointer):
165164
use_anisotropy=True,
166165
)
167166
self.fragment_graphs = graph_builder.run(swc_pointer)
167+
self.set_fragment_ids()
168168
else:
169169
self.fragment_graphs = None
170170

171+
def set_fragment_ids(self):
172+
self.fragment_ids = set()
173+
for key in self.fragment_graphs:
174+
self.fragment_ids.add(util.get_segment_id(key))
175+
171176
def label_graphs(self, key, batch_size=64):
172177
"""
173178
Iterates over nodes in "graph" and stores the corresponding label from
@@ -197,7 +202,7 @@ def label_graphs(self, key, batch_size=64):
197202
visited.add(i)
198203

199204
# Check whether to submit batch
200-
is_node_far = self.dist(key, root, j) > 128
205+
is_node_far = self.graphs[key].dist(root, j) > 128
201206
is_batch_full = len(batch) >= batch_size
202207
if is_node_far or is_batch_full:
203208
threads.append(
@@ -482,7 +487,7 @@ def count_merges(self, key, kdtree):
482487
"""
483488
Counts the number of label merges for a given graph key based on
484489
whether the fragment graph corresponding to a label has a node that is
485-
more that MERGE_DIST_THRESHOLD-ums away from the nearest point in
490+
more that 200ums away from the nearest point in
486491
"kdtree".
487492
488493
Parameters
@@ -501,15 +506,15 @@ def count_merges(self, key, kdtree):
501506
nodes = self.graphs[key].nodes_with_label(label)
502507
if len(nodes) > MIN_CNT:
503508
for label in self.label_handler.get_class(label):
504-
if label in self.fragment_graphs:
509+
if label in self.fragment_ids:
505510
self.is_fragment_merge(key, label, kdtree)
506511

507512
def is_fragment_merge(self, key, label, kdtree):
508513
"""
509514
Determines whether fragment corresponding to "label" is falsely merged
510515
to graph corresponding to "key". A fragment is said to be merged if
511-
there is a node in the fragment more than MERGE_DIST_THRESHOLD-ums
512-
away from the nearest point in "kdtree".
516+
there is a node in the fragment more than 200ums away from the nearest
517+
point in "kdtree".
513518
514519
Parameters
515520
----------
@@ -525,8 +530,10 @@ def is_fragment_merge(self, key, label, kdtree):
525530
None
526531
527532
"""
528-
for voxel in self.fragment_graphs[label].voxels:
529-
if kdtree.query(voxel)[0] > MERGE_DIST_THRESHOLD:
533+
fragment_graph = self.find_graph_from_label(label)
534+
for voxel in fragment_graph.voxels:
535+
gt_voxel = util.kdtree_query(kdtree, voxel)
536+
if self.physical_dist(gt_voxel, voxel) > 150:
530537
# Log merge mistake
531538
equiv_label = self.label_handler.get(label)
532539
xyz = img_util.to_physical(voxel, self.anisotropy)
@@ -538,8 +545,13 @@ def is_fragment_merge(self, key, label, kdtree):
538545
swc_util.to_zipped_swc(
539546
self.zip_writer[key], self.fragment_graphs[label]
540547
)
541-
return
548+
break
542549

550+
def find_graph_from_label(self, label):
551+
for key in self.fragment_graphs:
552+
if label == util.get_segment_id(key):
553+
return self.fragment_graphs[key]
554+
543555
def find_label_intersections(self):
544556
"""
545557
Detects merges between ground truth graphs, namely distinct graphs that
@@ -857,10 +869,11 @@ def list_metrics(self):
857869
return metrics
858870

859871
# -- util --
860-
def dist(self, key, i, j):
861-
xyz_i = self.graphs[key].voxels[i]
862-
xyz_j = self.graphs[key].voxels[j]
863-
return distance.euclidean(xyz_i, xyz_j)
872+
def physical_dist(self, voxel_1, voxel_2):
873+
xyz_1 = img_util.to_physical(voxel_1, self.anisotropy)
874+
xyz_2 = img_util.to_physical(voxel_2, self.anisotropy)
875+
return distance.euclidean(xyz_1, xyz_2)
876+
864877

865878
def init_counter(self):
866879
"""

src/segmentation_skeleton_metrics/utils/graph_util.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ def nodes_with_label(self, label):
145145

146146
# --- Computation ---
147147
def dist(self, i, j):
148+
return distance.euclidean(self.voxels[i], self.voxels[j])
149+
150+
def physical_dist(self, i, j):
148151
xyz_i = self.voxels[i] * self.anisotropy
149152
xyz_j = self.voxels[j] * self.anisotropy
150153
return distance.euclidean(xyz_i, xyz_j)
@@ -184,7 +187,7 @@ def run_lengths(self):
184187
def run_length_from(self, root):
185188
run_length = 0
186189
for i, j in nx.dfs_edges(self, source=root):
187-
run_length += self.dist(i, j)
190+
run_length += self.physical_dist(i, j)
188191
return run_length
189192

190193

src/segmentation_skeleton_metrics/utils/util.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,42 @@ def load_valid_labels(path):
242242
return valid_labels
243243

244244

245+
def kdtree_query(kdtree, xyz):
246+
"""
247+
Gets the xyz coordinates of the nearest neighbor of "xyz" from "kdtree".
248+
249+
Parameters
250+
----------
251+
xyz : tuple
252+
xyz coordinate to be queried.
253+
254+
Returns
255+
-------
256+
tuple
257+
xyz coordinate of the nearest neighbor of "xyz".
258+
259+
"""
260+
_, idx = kdtree.query(xyz)
261+
return tuple(kdtree.data[idx])
262+
263+
264+
def sample_once(my_container):
265+
"""
266+
Samples a single element from "my_container".
267+
268+
Parameters
269+
----------
270+
my_container : container
271+
Container to be sampled from.
272+
273+
Returns
274+
-------
275+
sample
276+
277+
"""
278+
return sample(my_container, 1)[0]
279+
280+
245281
def time_writer(t, unit="seconds"):
246282
"""
247283
Converts runtime "t" to its proper unit.
@@ -270,20 +306,3 @@ def time_writer(t, unit="seconds"):
270306
unit = upd_unit[unit]
271307
t, unit = time_writer(t, unit=unit)
272308
return t, unit
273-
274-
275-
def sample_once(my_container):
276-
"""
277-
Samples a single element from "my_container".
278-
279-
Parameters
280-
----------
281-
my_container : container
282-
Container to be sampled from.
283-
284-
Returns
285-
-------
286-
sample
287-
288-
"""
289-
return sample(my_container, 1)[0]

0 commit comments

Comments
 (0)