Skip to content

Commit

Permalink
Convert more neurite features
Browse files Browse the repository at this point in the history
  • Loading branch information
eleftherioszisis committed Feb 28, 2022
1 parent f380c7c commit 15782a9
Show file tree
Hide file tree
Showing 2 changed files with 584 additions and 100 deletions.
108 changes: 63 additions & 45 deletions neurom/features/neurite.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,23 @@ def section_bif_lengths(neurite, section_type=NeuriteType.all):


@feature(shape=(...,))
def section_branch_orders(neurite):
def section_branch_orders(neurite, section_type=NeuriteType.all):
"""Section branch orders."""
return _map_sections(sf.branch_order, neurite)
return _map_sections(sf.branch_order, neurite, section_type=section_type)


@feature(shape=(...,))
def section_bif_branch_orders(neurite):
def section_bif_branch_orders(neurite, section_type=NeuriteType.all):
"""Bifurcation section branch orders."""
return _map_sections(sf.branch_order, neurite, Section.ibifurcation_point)
return _map_sections(
sf.branch_order, neurite, Section.ibifurcation_point, section_type=section_type
)


@feature(shape=(...,))
def section_term_branch_orders(neurite):
def section_term_branch_orders(neurite, section_type=NeuriteType.all):
"""Termination section branch orders."""
return _map_sections(sf.branch_order, neurite, Section.ileaf)
return _map_sections(sf.branch_order, neurite, Section.ileaf, section_type=section_type)


@feature(shape=(...,))
Expand Down Expand Up @@ -275,7 +277,7 @@ def _seg_taper_rates(sec):


@feature(shape=(...,))
def section_taper_rates(neurite):
def section_taper_rates(neurite, section_type=NeuriteType.all):
"""Diameter taper rates of the sections from root to tip.
Taper rate is defined here as the linear fit along a section.
Expand All @@ -287,25 +289,29 @@ def _sec_taper_rate(sec):
path_distances = np.cumsum(interval_lengths(sec.points, prepend_zero=True))
return np.polynomial.polynomial.polyfit(path_distances, 2 * sec.points[:, COLS.R], 1)[1]

return _map_sections(_sec_taper_rate, neurite)
return _map_sections(_sec_taper_rate, neurite, section_type=section_type)


@feature(shape=(...,))
def segment_meander_angles(neurite):
def segment_meander_angles(neurite, section_type=NeuriteType.all):
"""Inter-segment opening angles in a section."""
return list(chain.from_iterable(_map_sections(sf.section_meander_angles, neurite)))
return list(
chain.from_iterable(
_map_sections(sf.section_meander_angles, neurite, section_type=section_type)
)
)


@feature(shape=(..., 3))
def segment_midpoints(neurite):
def segment_midpoints(neurite, section_type=NeuriteType.all):
"""Return a list of segment mid-points."""

def _seg_midpoint(sec):
"""Return the mid-points of segments in a section."""
pts = sec.points[:, COLS.XYZ]
return np.divide(np.add(pts[:-1], pts[1:]), 2.0)

return _map_segments(_seg_midpoint, neurite)
return _map_segments(_seg_midpoint, neurite, section_type=section_type)


@feature(shape=(...,))
Expand All @@ -327,33 +333,37 @@ def _get_pathlength(section):


@feature(shape=(...,))
def segment_radial_distances(neurite, origin=None):
def segment_radial_distances(neurite, origin=None, section_type=NeuriteType.all):
"""Returns the list of distances between all segment mid points and origin."""

def _radial_distances(sec, pos):
def _radial_distances(sec):
"""List of distances between the mid point of each segment and pos."""
mid_pts = 0.5 * (sec.points[:-1, COLS.XYZ] + sec.points[1:, COLS.XYZ])
return np.linalg.norm(mid_pts - pos[COLS.XYZ], axis=1)

pos = neurite.root_node.points[0] if origin is None else origin
# return [s for ss in n.iter_sections() for s in _radial_distances(ss, pos)]
return [d for s in Section.ipreorder(neurite.root_node) for d in _radial_distances(s, pos)]

return _map_segments(_radial_distances, neurite, section_type=section_type)

@feature(shape=(...,))
def local_bifurcation_angles(neurite):
def local_bifurcation_angles(neurite, section_type=NeuriteType.all):
"""Get a list of local bf angles."""
return _map_sections(bf.local_bifurcation_angle,
neurite,
iterator_type=Section.ibifurcation_point)
return _map_sections(
bf.local_bifurcation_angle,
neurite,
iterator_type=Section.ibifurcation_point,
section_type=section_type,
)


@feature(shape=(...,))
def remote_bifurcation_angles(neurite):
def remote_bifurcation_angles(neurite, section_type=NeuriteType.all):
"""Get a list of remote bf angles."""
return _map_sections(bf.remote_bifurcation_angle,
neurite,
iterator_type=Section.ibifurcation_point)
return _map_sections(
bf.remote_bifurcation_angle,
neurite,
iterator_type=Section.ibifurcation_point,
section_type=section_type,
)


@feature(shape=(...,))
Expand Down Expand Up @@ -397,51 +407,57 @@ def partition_asymmetry_length(neurite, method='petilla'):


@feature(shape=(...,))
def bifurcation_partitions(neurite):
def bifurcation_partitions(neurite, section_type=NeuriteType.all):
"""Partition at bf points."""
return _map_sections(bf.bifurcation_partition,
neurite,
Section.ibifurcation_point)
return _map_sections(
bf.bifurcation_partition, neurite, Section.ibifurcation_point, section_type=section_type
)


@feature(shape=(...,))
def sibling_ratios(neurite, method='first'):
def sibling_ratios(neurite, method='first', section_type=NeuriteType.all):
"""Sibling ratios at bf points.
The sibling ratio is the ratio between the diameters of the
smallest and the largest child. It is a real number between
0 and 1. Method argument allows one to consider mean diameters
along the child section instead of diameter of the first point.
"""
return _map_sections(partial(bf.sibling_ratio, method=method),
neurite,
Section.ibifurcation_point)
return _map_sections(
partial(bf.sibling_ratio, method=method),
neurite,
Section.ibifurcation_point,
section_type=section_type,
)


@feature(shape=(..., 2))
def partition_pairs(neurite):
def partition_pairs(neurite, section_type=NeuriteType.all):
"""Partition pairs at bf points.
Partition pair is defined as the number of bifurcations at the two
daughters of the bifurcating section
"""
return _map_sections(bf.partition_pair,
neurite,
Section.ibifurcation_point)
return _map_sections(
bf.partition_pair, neurite, Section.ibifurcation_point, section_type=section_type
)


@feature(shape=(...,))
def diameter_power_relations(neurite, method='first'):
def diameter_power_relations(neurite, method='first', section_type=NeuriteType.all):
"""Calculate the diameter power relation at a bf point.
Diameter power relation is defined in https://www.ncbi.nlm.nih.gov/pubmed/18568015
This quantity gives an indication of how far the branching is from
the Rall ratio (when =1).
"""
return _map_sections(partial(bf.diameter_power_relation, method=method),
neurite,
Section.ibifurcation_point)
return _map_sections(
partial(bf.diameter_power_relation, method=method),
neurite,
Section.ibifurcation_point,
section_type=section_type,
)


@feature(shape=(...,))
Expand All @@ -467,9 +483,11 @@ def section_term_radial_distances(neurite, origin=None, section_type=NeuriteType


@feature(shape=(...,))
def section_bif_radial_distances(neurite, origin=None):
def section_bif_radial_distances(neurite, origin=None, section_type=NeuriteType.all):
"""Get the radial distances of the bf sections."""
return section_radial_distances(neurite, origin, Section.ibifurcation_point)
return section_radial_distances(
neurite, origin, Section.ibifurcation_point, section_type=section_type
)


@feature(shape=(...,))
Expand Down Expand Up @@ -547,6 +565,6 @@ def principal_direction_extents(neurite, direction=0):


@feature(shape=(...,))
def section_strahler_orders(neurite):
def section_strahler_orders(neurite, section_type=NeuriteType.all):
"""Inter-segment opening angles in a section."""
return _map_sections(sf.strahler_order, neurite)
return _map_sections(sf.strahler_order, neurite, section_type=section_type)
Loading

0 comments on commit 15782a9

Please sign in to comment.