Healing fragmented skeletons¶
Reconstructed skeletons are often broken into several disconnected fragments. Healing means finding the shortest set of new edges that stitches those fragments back into a single rooted tree.
heal_skeleton does the whole job: it finds the
minimal-length bridges between connected components and regenerates the parent
vector. The two halves are also available on their own —
stitch_fragments returns just the bridging
edges, so you can inspect or filter them, and
reroot_rewire turns any edited edge set back
into a rooted forest, whether the edges came from stitch_fragments or from
somewhere else entirely.
import navis_fastcore as fastcore
new_parent_ids = fastcore.heal_skeleton(node_ids, parent_ids, coords)
Two options are worth knowing about:
max_distcaps how long a single new edge may be. Gaps wider than that are left alone, so the result can still be fragmented — which is usually what you want, as bridging a huge gap is more likely to be wrong than right.use_radiustakes node radii into account when measuring distances, which prefers connecting fragments of similar calibre over merely nearby ones. Pass a float rather thanTrueto weight how much influence radius gets. Note thatmax_distis then measured in that augmented space too.
API¶
navis_fastcore.heal_skeleton(node_ids, parent_ids, coords, method='ALL', max_dist=None, min_size=None, mask=None, radius=None, use_radius=False, threads=None)
¶
Heal a fragmented skeleton by reconnecting its fragments.
Rust re-implementation of the core of navis.heal_skeleton: it finds the
minimal-length set of bridges between the skeleton's connected components
(see :func:stitch_fragments) and regenerates a single rooted tree.
| PARAMETER | DESCRIPTION |
|---|---|
node_ids
|
TYPE:
|
parent_ids
|
TYPE:
|
coords
|
TYPE:
|
method
|
TYPE:
|
max_dist
|
TYPE:
|
min_size
|
TYPE:
|
mask
|
TYPE:
|
radius
|
TYPE:
|
use_radius
|
|
threads
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
new_parent_ids
|
New parent IDs, in the same order as
TYPE:
|
Examples:
>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(4)
>>> parent_ids = np.array([-1, 0, -1, 2]) # two fragments
>>> coords = np.array([[0, 0, 0], [1, 0, 0], [10, 0, 0], [11, 0, 0]], dtype=float)
>>> fastcore.heal_skeleton(node_ids, parent_ids, coords)
array([-1, 0, 1, 2])
navis_fastcore.stitch_fragments(node_ids, parent_ids, coords, mask=None, max_dist=None, radius=None, use_radius=False, threads=None)
¶
Find minimal-length edges to reconnect a fragmented skeleton.
This is the low-level primitive behind :func:heal_skeleton: given a
skeleton that consists of several disconnected fragments (connected
components), it returns the set of new edges that would connect those
fragments into a single tree while minimising the total added length. It
does not modify the skeleton.
| PARAMETER | DESCRIPTION |
|---|---|
node_ids
|
TYPE:
|
parent_ids
|
TYPE:
|
coords
|
TYPE:
|
mask
|
TYPE:
|
max_dist
|
TYPE:
|
radius
|
TYPE:
|
use_radius
|
|
threads
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
edges
|
Pairs of node IDs to connect. At most
TYPE:
|
distances
|
Euclidean length of each new edge. If
TYPE:
|
Examples:
>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(4)
>>> # Two fragments: {0, 1} and {2, 3}
>>> parent_ids = np.array([-1, 0, -1, 2])
>>> coords = np.array([[0, 0, 0], [1, 0, 0], [10, 0, 0], [11, 0, 0]], dtype=float)
>>> edges, dists = fastcore.stitch_fragments(node_ids, parent_ids, coords)
>>> edges
array([[1, 2]])
>>> dists
array([9.], dtype=float32)
navis_fastcore.reroot_rewire(node_ids, parent_ids, new_edges, root=None)
¶
Regenerate the parent array after adding a set of undirected edges.
Takes an edited edge set — the skeleton's own child→parent edges plus
new_edges — and orients all of it away from a root, which is what turns a bag
of edges back into a rooted forest. This is step 2 of
:func:heal_skeleton, exposed on its own for callers who choose their own
edges rather than taking the minimal bridges from
:func:stitch_fragments.
| PARAMETER | DESCRIPTION |
|---|---|
node_ids
|
TYPE:
|
parent_ids
|
TYPE:
|
new_edges
|
TYPE:
|
root
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
new_parent_ids
|
New parent IDs, aligned with
TYPE:
|
Notes
Not the same as navis_fastcore.reroot, which re-roots an unchanged
forest by reversing only the edges between each new root and the old one, and
leaves components nobody named byte-identical. This one re-orients everything,
because after an edge set changes there is no "unchanged" to preserve. Use
reroot to move a root; use this when the edges themselves moved.
Examples:
>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(4)
>>> parent_ids = np.array([-1, 0, -1, 2]) # two fragments
>>> fastcore.reroot_rewire(node_ids, parent_ids, [(1, 2)])
array([-1, 0, 1, 2])
Rooting the joined skeleton at node 3 instead: