Skip to content
Snippets Groups Projects
Unverified Commit 5a488591 authored by Eleftherios Zisis's avatar Eleftherios Zisis Committed by GitHub
Browse files

Add new features total_width, total_height and total_depth (#974)

parent 819e5ee7
Branches
Tags v3.1.0
No related merge requests found
......@@ -3,6 +3,8 @@
*.pyc
*~
.coverage
.coverage.*
coverage.xml
*venv*
*egg-info*
.eggs
......@@ -16,3 +18,5 @@ dist/*
.ipynb_checkpoints
.tox
pip-wheel-metadata
morphology-2D.html
morphology-3D.html
Changelog
=========
Version 3.1.0
-------------
- Add morphology features total_width, total_height and total_depth
Version 3.0.2
-------------
- Fix 'raw' mode in ``neurom stats``.
......
......@@ -55,6 +55,7 @@ from neurom.core.dataformat import COLS
from neurom.core.types import NeuriteType
from neurom.features import feature, NameSpace, neurite as nf
feature = partial(feature, namespace=NameSpace.NEURON)
......@@ -294,3 +295,39 @@ def sholl_frequency(morph, neurite_type=NeuriteType.all, step_size=10, bins=None
bins = np.arange(min_soma_edge, min_soma_edge + max_radii, step_size)
return sholl_crossings(morph, morph.soma.center, bins, neurite_type)
def _extent_along_axis(morph, axis, neurite_type):
"""Returns the total extent of the morpholog neurites.
The morphology is filtered by neurite type and the extent is calculated
along the coordinate axis direction (e.g. COLS.X).
"""
it_points = (
p
for n in iter_neurites(morph, filt=is_type(neurite_type))
for p in n.points[:, axis]
)
try:
return abs(np.ptp(np.fromiter(it_points, dtype=np.float32)))
except ValueError:
# a ValueError is thrown when there are no points passed to ptp
return 0.0
@feature(shape=())
def total_width(morph, neurite_type=NeuriteType.all):
"""Extent of morphology along axis x."""
return _extent_along_axis(morph, axis=COLS.X, neurite_type=neurite_type)
@feature(shape=())
def total_height(morph, neurite_type=NeuriteType.all):
"""Extent of morphology along axis y."""
return _extent_along_axis(morph, axis=COLS.Y, neurite_type=neurite_type)
@feature(shape=())
def total_depth(morph, neurite_type=NeuriteType.all):
"""Extent of morphology along axis z."""
return _extent_along_axis(morph, axis=COLS.Z, neurite_type=neurite_type)
......@@ -756,3 +756,56 @@ def test_principal_direction_extents():
346.83281498399697]
p = features.get('principal_direction_extents', m)
assert_allclose(p, p_ref, rtol=1e-6)
def test_total_width():
assert_allclose(
features.get('total_width', NRN),
105.0758
)
assert_allclose(
features.get('total_width', NRN, neurite_type=nm.AXON),
33.25306
)
assert_allclose(
features.get('total_width', NRN, neurite_type=nm.BASAL_DENDRITE),
104.57807
)
def test_total_height():
assert_allclose(
features.get('total_height', NRN),
106.11643
)
assert_allclose(
features.get('total_height', NRN, neurite_type=nm.AXON),
57.60017
)
assert_allclose(
features.get('total_height', NRN, neurite_type=nm.BASAL_DENDRITE),
48.516262
)
def test_total_depth():
assert_allclose(
features.get('total_depth', NRN),
54.204086
)
assert_allclose(
features.get('total_depth', NRN, neurite_type=nm.AXON),
49.70138
)
assert_allclose(
features.get('total_depth', NRN, neurite_type=nm.BASAL_DENDRITE),
51.64143
)
......@@ -278,3 +278,55 @@ def test_sholl_analysis_custom():
""")
assert (list(morphology.sholl_crossings(morph_C, center, radii=radii)) ==
[2, 2, 2, 2, 2, 2, 10, 10])
def test_extent_along_axis():
morph = load_swc("""
1 1 0 0 0 1. -1
2 3 0 -60 0 1. 1
3 3 80 0 2 1. 2
4 4 0 60 3 1. 1
5 4 -80 0. 0 1. 4
""")
assert_almost_equal(morphology._extent_along_axis(morph, 0, NeuriteType.all), 160.0)
assert_almost_equal(morphology._extent_along_axis(morph, 1, NeuriteType.all), 120.0)
assert_almost_equal(morphology._extent_along_axis(morph, 2, NeuriteType.all), 3.0)
def test_total_width():
morph = load_swc("""
1 1 0 0 0 1. -1
2 3 0 -60 0 1. 1
3 3 80 0 2 1. 2
4 4 0 60 3 1. 1
5 4 -80 0. 0 1. 4
""")
assert_almost_equal(morphology.total_width(morph, neurite_type=NeuriteType.axon), 0.0)
assert_almost_equal(morphology.total_width(morph, neurite_type=NeuriteType.basal_dendrite), 80.0)
assert_almost_equal(morphology.total_width(morph, neurite_type=NeuriteType.apical_dendrite), 80.0)
def test_total_height():
morph = load_swc("""
1 1 0 0 0 1. -1
2 3 0 -60 0 1. 1
3 3 80 0 2 1. 2
4 4 0 60 3 1. 1
5 4 -80 0. 0 1. 4
""")
assert_almost_equal(morphology.total_height(morph, neurite_type=NeuriteType.axon), 0.0)
assert_almost_equal(morphology.total_height(morph, neurite_type=NeuriteType.basal_dendrite), 60.0)
assert_almost_equal(morphology.total_height(morph, neurite_type=NeuriteType.apical_dendrite), 60.0)
def test_total_depth():
morph = load_swc("""
1 1 0 0 0 1. -1
2 3 0 -60 0 1. 1
3 3 80 0 2 1. 2
4 4 0 60 3 1. 1
5 4 -80 0. 0 1. 4
""")
assert_almost_equal(morphology.total_depth(morph, neurite_type=NeuriteType.axon), 0.0)
assert_almost_equal(morphology.total_depth(morph, neurite_type=NeuriteType.basal_dendrite), 2.0)
assert_almost_equal(morphology.total_depth(morph, neurite_type=NeuriteType.apical_dendrite), 3.0)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment