diff --git a/tests/test_extract_input.py b/tests/test_extract_input.py index f9eb0d5d..0618cced 100644 --- a/tests/test_extract_input.py +++ b/tests/test_extract_input.py @@ -49,13 +49,18 @@ def test_trunk_distr(): assert_equal(trunkAP, target_trunkAPIC) def test_diameter_extract(): - assert_equal(extract_input.from_diameter.model(NEU), - {'basal': {'Rall_ratio': 0.6666666666666666, - 'siblings_ratio': 1.0, - 'taper': [0.24000000000000005, 0.1], - 'term': [2.0, 2.0], - 'trunk': [3.9], - 'trunk_taper': [0.3000000000000001]}}) + res = extract_input.from_diameter.model(NEU) + assert_equal(set(res.keys()), {'basal'}) + expected = {'Rall_ratio': 1.5, + 'siblings_ratio': 1.0, + 'taper': [0.24, 0.1], + 'term': [2.0, 2.0], + 'trunk': [3.9], + 'trunk_taper': [0.30]} + + assert_equal(res['basal'].keys(), expected.keys()) + for key in expected.keys(): + assert_array_almost_equal(res['basal'][key], expected[key]) class NeuromJSON(json.JSONEncoder): diff --git a/tns/extract_input/from_diameter.py b/tns/extract_input/from_diameter.py index 21f6aa96..0ef7e646 100644 --- a/tns/extract_input/from_diameter.py +++ b/tns/extract_input/from_diameter.py @@ -9,8 +9,9 @@ from neurom.morphmath import segment_length, segment_radius from tns.morphio_utils import NEUROM_TYPE_TO_STR +from tns.utils import _check -default_model = {'Rall_ratio': 2. / 3., +default_model = {'Rall_ratio': 3. / 2., 'siblings_ratio': 1.} @@ -26,7 +27,9 @@ def section_mean_taper(s): def terminal_diam(tree): """Returns the model for the terminations""" - term_diam = [2. * t.points[-1, 3] for t in Tree.ileaf(next(tree.iter_sections()))] + mean_diam = np.mean(tree.points[:, 3]) + term_diam = [2. * t.points[-1, 3] for t in Tree.ileaf(next(tree.iter_sections())) + if t.points[-1, 3] < 1.2 * mean_diam] return term_diam @@ -46,71 +49,34 @@ def section_trunk_taper(tree): return section_mean_taper(next(tree.iter_sections())) -def model(neuron): - """Measures the statistical properties of a neuron's - diameters and outputs a diameter_model""" - +def model(input_object): + """Measures the statistical properties of an input_object's + diameters and outputs a diameter_model + Input can be a population of neurons, or a single neuron. + """ values = {} - for neurite_type in set(tree.type for tree in neuron.neurites): - taper = [section_taper(tree) for tree in iter_neurites(neuron, - filt=is_type(neurite_type))] - trunk_taper = np.array([section_trunk_taper(tree) - for tree in iter_neurites(neuron, - filt=is_type(neurite_type))]) + for neurite_type in set(tree.type for tree in input_object.neurites): + + neurites = list(iter_neurites(input_object, filt=is_type(neurite_type))) + + taper = [section_taper(tree) for tree in neurites] + trunk_taper = np.array([section_trunk_taper(tree) for tree in neurites]) taper_c = np.array(list(chain(*taper))) # Keep only positive, non-zero taper rates - taper_c = taper_c[np.where(taper_c > 0)[0]] - trunk_taper = trunk_taper[np.where(trunk_taper > 0.0)[0]] - - term_diam = [terminal_diam(tree) - for tree in iter_neurites(neuron, filt=is_type(neurite_type))] - trunk_diam = [2. * np.max(get('segment_radii', tree)) - for tree in iter_neurites(neuron, filt=is_type(neurite_type))] + taper_c = taper_c[np.where(taper_c > 0.00001)[0]] + trunk_taper = trunk_taper[np.where(trunk_taper >= 0.0)[0]] + term_diam = [terminal_diam(tree) for tree in neurites] + trunk_diam = [2. * np.max(get('segment_radii', tree)) for tree in neurites] key = NEUROM_TYPE_TO_STR[neurite_type] + values[key] = {"taper": taper_c, - "term": [c for c in chain(*term_diam)], - "trunk": trunk_diam, - "trunk_taper": trunk_taper} + "term": [c for c in chain(*term_diam)], + "trunk": trunk_diam, + "trunk_taper": trunk_taper} + _check(values[key]) values[key].update(default_model) return values - - -def get_taper(neurons, neurite_type): - '''get taper''' - return [section_taper(tree) for tree in iter_neurites(neurons, filt=is_type(neurite_type))] - - -def get_term_diam(neurons, neurite_type): - '''get term''' - return [terminal_diam(tree) - for tree in iter_neurites(neurons, filt=is_type(neurite_type))] - - -def population_model(neurons): - """Measures the statistical properties of a neuron's - diameters and outputs a diameter_model""" - - values = {} - - types_to_process = {tree.type.value: tree.type for tree in neurons.neurites} - - for typee in types_to_process: - - neurite_type = types_to_process[typee] - - values[typee - 1] = { - "taper": [c for c in chain(*get_taper(neurons, neurite_type))], - "term": [c for c in chain(*get_term_diam(neurons, neurite_type))], - "trunk": [ - 2. * np.max(get('segment_radii', tree)) - for tree in iter_neurites(neurons, filt=is_type(neurite_type)) - ] - } - - values[typee - 1].update(default_model) - - return values diff --git a/tns/generate/soma.py b/tns/generate/soma.py index ab8a26ad..24e802c9 100644 --- a/tns/generate/soma.py +++ b/tns/generate/soma.py @@ -6,7 +6,7 @@ import numpy as np from tns.morphmath.utils import norm - +from tns.utils import TNSError L = logging.getLogger() @@ -103,9 +103,6 @@ def interpolate(self, points3D, interpolation=10): """ from scipy.spatial import ConvexHull # pylint: disable=no-name-in-module - class TNSError(Exception): - '''Raises TNS error''' - interpolation = np.max([3, interpolation]) # soma must have at least 3 points if len(points3D) >= interpolation: diff --git a/tns/utils.py b/tns/utils.py new file mode 100644 index 00000000..865caf99 --- /dev/null +++ b/tns/utils.py @@ -0,0 +1,13 @@ +"""TNS utils used by multiple tools""" + + +class TNSError(Exception): + '''Raises TNS error''' + + +def _check(data): + """Checks if data in dictionary are empty. + """ + for key, val in data.items(): + if len(val) == 0: + raise TNSError('Empty distrib for diameter key: {}'.format(key)) diff --git a/tns/version.py b/tns/version.py index f6067f56..8e556764 100644 --- a/tns/version.py +++ b/tns/version.py @@ -1,2 +1,2 @@ """ tns version """ -VERSION = "1.0.6" +VERSION = "1.0.7.dev0"