Skip to content

Segments

For some operations (e.g. plotting) it is useful to break the graph into its linear components. You can do so by simply "breaking" the graph at each branch point, effectively producing linear segments that connect leafs, branch points and roots. Alternatively, you can try to make as few cuts as possible resulting in fewer and longer linear segments.

Breaking neurons into linear components with as few cuts as possible. The alternative would be to introduce a break at node 2 resulting in 3 separate segments. This is the same toy skeleton used in the code examples below.

Generate Segments

Generate linear segments maximizing segment lengths.

PARAMETER DESCRIPTION
node_ids
     Array node IDs.

TYPE: (N, ) array

parent_ids
     Array of parent IDs for each node. Root nodes' parents
     must be -1.

TYPE: (N, ) array

weights
     Array of distances for each child -> parent connection.
     If ``None`` all node-to-node distances are set to 1.

TYPE: (N, ) float32 array DEFAULT: None

RETURNS DESCRIPTION
segments

Segments as list of arrays, sorted from longest to shortest. Each segment starts with a leaf and stops with a branch point or root node.

TYPE: list of arrays

lengths

Length of each segment, measured from its first node to its last: the physical distance between them if weights was given, otherwise the number of edges. Because a segment stops at a branch point, that terminal node's own edge continues into the parent segment and is not counted here - so a single-node segment has length 0.

TYPE: array

Examples:

>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(7)
>>> parent_ids = np.array([-1, 0, 1, 2, 1, 4, 5])
>>> segs, length = fastcore.generate_segments(node_ids, parent_ids)
>>> segs
[array([6, 5, 4, 1, 0]), array([3, 2, 1])]
>>> length
array([4, 2], dtype=int32)

Break neuron into linear segments connecting ends, branches and root.

PARAMETER DESCRIPTION
node_ids
     Array node IDs.

TYPE: (N, ) array

parent_ids
     Array of parent IDs for each node. Root nodes' parents
     must be -1.

TYPE: (N, ) array

RETURNS DESCRIPTION
segments

Segments as list of arrays.

TYPE: list of arrays

Examples:

>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(7)
>>> parent_ids = np.array([-1, 0, 1, 2, 1, 4, 5])
>>> fastcore.break_segments(node_ids, parent_ids)
[array([1, 0]), array([3, 2, 1]), array([6, 5, 4, 1])]

Segment Coordinates

Generate coordinates for linear segments.

This is useful for plotting the skeleton of a neuron.

PARAMETER DESCRIPTION
node_ids
        Array node IDs.

TYPE: (N, ) array

parent_ids
        Array of parent IDs for each node. Root nodes' parents
        must be -1.

TYPE: (N, ) array

coords
        Array of coordinates for each node.

TYPE: (N, 3) array

node_colors
        A color for each node in `node_ids`. If provided, will
        also return a list of colors sorted to match coordinates.

TYPE: (N, ) numpy.ndarray DEFAULT: None

flat
        If True, return the segments as a single array with each
        segment separated by a row of NaNs instead of as a list.
        Plotting backends generally want this form; producing it
        directly is markedly faster than splitting into per-segment
        arrays and concatenating them back together.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
seg_coords

Coordinates per segment. With flat=False (default) a list of arrays. With flat=True a single array in which segments are separated by a row of NaNs; integer coordinates are promoted to float to make room for those.

TYPE: list of arrays | (M, 3) array

colors

If node_colors provided, a copy of it sorted to match seg_coords. With flat=True it is padded to match: the separator rows are NaN for float colors but 0 for integer ones (e.g. uint8 RGB), which keeps the dtype intact. Those rows are never drawn, so the padded colors are only meaningful alongside the returned coordinates.

TYPE: list of colors | (M, ...) array

Examples:

>>> import navis_fastcore as fastcore
>>> import numpy as np
>>> node_ids = np.arange(7)
>>> parent_ids = np.array([-1, 0, 1, 2, 1, 4, 5])
>>> coords = np.random.RandomState(42).rand(7, 3)
>>> fastcore.segment_coords(node_ids, parent_ids, coords)
[array([[0.43194502, 0.29122914, 0.61185289],
       [0.18340451, 0.30424224, 0.52475643],
       [0.83244264, 0.21233911, 0.18182497],
       [0.59865848, 0.15601864, 0.15599452],
       [0.37454012, 0.95071431, 0.73199394]]), array([[0.70807258, 0.02058449, 0.96990985],
       [0.05808361, 0.86617615, 0.60111501],
       [0.59865848, 0.15601864, 0.15599452]])]

The same segments as one NaN-separated array:

>>> fastcore.segment_coords(node_ids, parent_ids, coords, flat=True).shape
(10, 3)