From 90b02a30b410cb883c28e15885ef445cce89a63e Mon Sep 17 00:00:00 2001 From: Ziwei Huang Date: Tue, 25 Nov 2025 12:28:49 +0100 Subject: [PATCH 1/2] fix: ntype remapping yields multiple soma node --- skeliner/post.py | 9 +++++++++ tests/test_post.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/skeliner/post.py b/skeliner/post.py index f17c302..1346be3 100644 --- a/skeliner/post.py +++ b/skeliner/post.py @@ -100,6 +100,11 @@ def _remap_ntype( mapped[new_idx] = ntype[old_idx] if new_len: mapped[0] = 1 + # keep soma label unique (some remaps move old node 0 away from index 0) + dupes = (mapped == 1) + dupes[0] = False + if np.any(dupes): + mapped[dupes] = 3 return mapped @@ -708,6 +713,10 @@ def reroot( if set_soma_ntype and ntype is not None: ntype[0] = 1 + if len(ntype) > 1: + dupes = (ntype == 1) + dupes[0] = False + ntype[dupes] = 3 new_skel = Skeleton( soma=new_soma, diff --git a/tests/test_post.py b/tests/test_post.py index 94b3050..4b3099b 100644 --- a/tests/test_post.py +++ b/tests/test_post.py @@ -101,6 +101,7 @@ def test_reroot_updates_soma_and_ntype(): s.soma.axes[0], s.radii["median"][0] ) # radius equals selected column assert s.ntype[0] == 1 + assert int(np.sum(s.ntype == 1)) == 1 def test_reroot_node2verts_vert2node_consistency(): @@ -125,3 +126,30 @@ def test_reroot_node2verts_vert2node_consistency(): assert s.vert2node[v] == i # Soma verts now come from the new node 0's membership assert set(s.soma.verts.tolist()) == set(s.node2verts[0].tolist()) + + +def test_detect_soma_remaps_ntype_once(): + nodes = np.array([[0, 0, 0], [0, 0, 5], [0, 5, 0]], float) + edges = np.array([[0, 1], [1, 2]], np.int64) + radii = {"median": np.array([1.0, 4.0, 1.5])} + skel = Skeleton( + soma=Soma.from_sphere(nodes[0], radii["median"][0], verts=None), + nodes=nodes, + radii=radii, + edges=edges, + ntype=np.array([1, 3, 3], np.int8), + ) + + s = post.detect_soma( + skel, + radius_key="median", + soma_radius_percentile_threshold=90.0, + soma_radius_distance_factor=4.0, + soma_min_nodes=1, + verbose=False, + mesh_vertices=None, + ) + + assert np.allclose(s.nodes[0], nodes[1]) # new soma promoted + assert s.ntype[0] == 1 + assert int(np.sum(s.ntype == 1)) == 1 From 0d63d685598da1a150af474b3ac9e15730408551 Mon Sep 17 00:00:00 2001 From: Ziwei Huang Date: Tue, 25 Nov 2025 12:30:55 +0100 Subject: [PATCH 2/2] bump: v0.2.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 69d8ad1..3674781 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "skeliner" -version = "0.2.3" +version = "0.2.4" description = "A lightweight neuromorphological mesh skeletonizer." authors = [] requires-python = ">=3.10.0"