Source code for bmtk.tests.simulator.bionet.test_morphology

import os
import pytest
import numpy as np
from collections import namedtuple
try:
    from neuron import h
except ModuleNotFoundError:
    pytest.importorskip("neuron")

from .conftest import *

from bmtk.simulator.bionet.nrn import load_neuron_modules
from bmtk.simulator.bionet.morphology import Morphology


RORB_SWC_PATH = os.path.join(MORPH_DIR, 'rorb_480169178_morphology.swc')

try:
    load_neuron_modules(mechanisms_dir='components/mechanisms', templates_dir='.')
    has_mechanism = True
except AttributeError as ae:
    has_mechanism = False


[docs] def load_hobj(): # load_neuron_modules(mechanisms_dir='components/mechanisms', templates_dir='.') # load_templates(os.path.join(bionet_dir, 'default_templates')) hobj = h.Biophys1(RORB_SWC_PATH) return hobj
[docs] def fix_axon_peri(hobj): """Replace reconstructed axon with a stub""" for sec in hobj.axon: h.delete_section(sec=sec) h.execute('create axon[2]', hobj) for sec in hobj.axon: sec.L = 30 sec.diam = 1 hobj.axonal.append(sec=sec) hobj.all.append(sec=sec) # need to remove this comment hobj.axon[0].connect(hobj.soma[0], 0.5, 0) hobj.axon[1].connect(hobj.axon[0], 1, 0) h.define_shape()
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_base(): hobj = load_hobj() morph = Morphology(hobj) assert(morph.nseg == 87) assert(len(morph.seg_props.type) == 87) assert(len(morph.seg_props.area) == 87) assert(len(morph.seg_props.x) == 87) assert(len(morph.seg_props.dist) == 87) assert(len(morph.seg_props.length) == 87) assert(morph.seg_props.type[0] == 1 and morph.seg_props.type[1] == 2) assert(np.isclose(morph.seg_props.area[0], 425.756, atol=1.0e-2)) assert(morph.seg_props.x[0] == 0.5) assert(np.isclose(morph.seg_props.dist[0], 5.82, atol=1.0e-2)) assert(np.isclose(morph.seg_props.length[0], 11.64, atol=1.0e-2)) assert(isinstance(morph.seg_coords.p0, np.ndarray) and morph.seg_coords.p0.shape == (3, 87)) assert(isinstance(morph.seg_coords.p0, np.ndarray) and morph.seg_coords.p1.shape == (3, 87)) assert(isinstance(morph.seg_coords.p0, np.ndarray) and morph.seg_coords.p05.shape == (3, 87)) assert(np.allclose(morph.seg_coords.p0[:, 0], [-5.82, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p05[:, 0], [0.0, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p1[:, 0], [5.82, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p0[:, 86], [-22.21, -18.18, -1.89], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p05[:, 86], [-38.98, -12.29, -4.19], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p1[:, 86], [-51.45, 0.740, -6.35], atol=1.0e-2))
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_seg_props_cache(): # Check ability to cache segment props hobj = load_hobj() morph1 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) hobj = load_hobj() morph2 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) morph3 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=False) hobj = load_hobj() for sec in hobj.axon: h.delete_section(sec=sec) morph4 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) # morph1 and morph2 have different hobj but should share the same SegmentProps sp1 = morph1.seg_props assert(id(sp1) == id(morph1.seg_props) == id(morph2.seg_props)) assert(id(morph1.segments[0]) != id(morph2.segments[0])) # morph3 explicity did not cache seg_props assert(id(morph2) != id(morph3)) # morph4 has the same morphology_file, but not the same number of segments since axon with removed assert (id(morph1) != id(morph4))
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_full(): hobj = load_hobj() fix_axon_peri(hobj) morph = Morphology(hobj) morph.set_segment_dl(20.0) morph = morph.move_and_rotate( soma_coords=[100.0, -100.0, 0.0], rotation_angles=[90.0, 180.0, 0.0] ) assert(len(morph.seg_props.type) == 206) assert(len(morph.seg_props.area) == 206) assert(len(morph.seg_props.x) == 206) assert(len(morph.seg_props.dist) == 206) assert(len(morph.seg_props.length) == 206) assert(morph.seg_props.type[0] == 1 and morph.seg_props.type[1] == 3 and morph.seg_props.type[-1] == 2) assert(np.isclose(morph.seg_props.area[0], 425.756, atol=1.0e-2)) assert(morph.seg_props.x[0] == 0.5) assert(np.isclose(morph.seg_props.dist[0], 5.82, atol=1.0e-2)) assert(np.isclose(morph.seg_props.length[0], 11.64, atol=1.0e-2)) assert(isinstance(morph.seg_coords.p0, np.ndarray) and morph.seg_coords.p0.shape == (3, 206)) assert(isinstance(morph.seg_coords.p1, np.ndarray) and morph.seg_coords.p1.shape == (3, 206)) assert(isinstance(morph.seg_coords.p05, np.ndarray) and morph.seg_coords.p05.shape == (3, 206)) assert(np.allclose(morph.seg_coords.p0[:, 0], [103.48, -95.83, 2.08], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p05[:, 0], [100.0, -100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p1[:, 0], [96.51, -104.16, -2.08], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p0[:, -1], [93.00, -120.74858452, 20.50896093], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p05[:, -1], [89.51, -131.12281575, 30.76346789], atol=1.0e-2)) assert(np.allclose(morph.seg_coords.p1[:, -1], [86.01, -141.49, 41.01], atol=1.0e-2))
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_multicell(): hobj = load_hobj() fix_axon_peri(hobj) morph = Morphology(hobj) morph.set_segment_dl(20.0) morph1 = morph.move_and_rotate( soma_coords=[0.0, 100.0, 0.0], rotation_angles=[0.0, 0.0, 0.0] ) morph2 = morph.move_and_rotate( soma_coords=[50.0, -50.0, 300.6789], rotation_angles=[-90.0, 0.0, 90.0] ) assert(len(morph1.seg_props.type) == len(morph2.seg_props.type) == 206) assert(len(morph1.seg_props.area) == 206) assert(len(morph1.seg_props.x) == 206) assert(len(morph1.seg_props.dist) == 206) assert(len(morph1.seg_props.length) == 206) assert(morph1.seg_props.type[0] == 1 and morph1.seg_props.type[1] == 3 and morph1.seg_props.type[-1] == 2) assert(np.isclose(morph1.seg_props.area[0], 425.756, atol=1.0e-2)) assert(morph1.seg_props.x[0] == 0.5) assert(np.isclose(morph1.seg_props.dist[0], 5.82, atol=1.0e-2)) assert(np.isclose(morph1.seg_props.length[0], 11.64, atol=1.0e-2)) assert(isinstance(morph1.seg_coords.p0, np.ndarray) and morph1.seg_coords.p0.shape == (3, 206)) assert(isinstance(morph1.seg_coords.p0, np.ndarray) and morph1.seg_coords.p1.shape == (3, 206)) assert(isinstance(morph1.seg_coords.p0, np.ndarray) and morph1.seg_coords.p05.shape == (3, 206)) assert(np.allclose(morph1.seg_coords.p0[:, 0], [-5.82, 100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p05[:, 0], [0.0, 100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p1[:, 0], [5.82, 100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p0[:, -1], [11.68, 127.63, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p05[:, -1], [17.52, 141.44, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p1[:, -1], [23.36, 155.26, 0.0], atol=1.0e-2)) assert(isinstance(morph2.seg_coords.p0, np.ndarray) and morph2.seg_coords.p0.shape == (3, 206)) assert(isinstance(morph2.seg_coords.p0, np.ndarray) and morph2.seg_coords.p1.shape == (3, 206)) assert(isinstance(morph2.seg_coords.p0, np.ndarray) and morph2.seg_coords.p05.shape == (3, 206)) assert(np.allclose(morph2.seg_coords.p0[:, 0], [52.60793758495786, -47.66851250016918, 305.3306848207208], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, 0], [49.999927071351536, -50.00006519796841, 300.67876991698654], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, 0], [47.391916557745205, -52.33161789576764, 296.02685501325226], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p0[:, -1], [20.06251275325579, -49.132177777673576, 302.41037925570913], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, -1], [5.093809548685826, -48.69823418216671, 303.27618369633956], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, -1], [-9.87490156483996, -48.26429035737874, 304.1419885944318], atol=1.0e-2))
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_find_sections(): hobj = load_hobj() fix_axon_peri(hobj) morph = Morphology(hobj) morph.set_segment_dl(20.0) morph = morph.move_and_rotate( soma_coords=[100.0, -100.0, 0.0], rotation_angles=[90.0, 180.0, 0.0] ) secs, _ = morph.find_sections(section_names=['dend', 'apic', 'soma', 'axon'], distance_range=[0.0, 1.0e20]) assert(len(secs) == morph.nseg) secs, _ = morph.find_sections(section_names=('dend', 'apic', 'soma', 'axon'), distance_range=(0.0, 1.0e20)) assert(len(secs) == morph.nseg) secs, sec_probs = morph.find_sections(section_names=['dend', 'apic'], distance_range=[150.0, 200.0]) assert(np.isclose(np.sum(sec_probs), 1.0, atol=1.0e-3)) for sec in secs: assert(morph.seg_props.type[sec] in [3, 4]) assert(10.0 <= morph.seg_props.dist1[sec] and morph.seg_props.dist0[sec] <= 200.0) secs, sec_probs = morph.find_sections(section_names=['axon'], distance_range=[0.0, 10.0e20]) for sec in secs: assert (morph.seg_props.type[sec] == 2) secs, sec_probs = morph.find_sections(section_names=['soma'], distance_range=[300.0, 500.0]) assert(len(secs) == 0) assert(len(sec_probs) == 0) secs, sec_probs = morph.find_sections(section_names=['soma'], distance_range=[0.0, 100.0]) assert(len(secs) == 1 and sec_probs[0] == 1.0)
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') @pytest.mark.skip(reason='no longer using get_target_segments() method in new Morphology') def test_get_target_segments(): hobj = load_hobj() fix_axon_peri(hobj) morph = Morphology(hobj) morph.set_segment_dl(20.0) morph = morph.move_and_rotate( soma_coords=[100.0, -100.0, 0.0], rotation_angles=[90.0, 180.0, 0.0] ) EdgeType = namedtuple('EdgeType', ['target_sections', 'target_distance']) edge_type = EdgeType(target_sections=('dend', 'apic', 'soma', 'axon'), target_distance=(0.0, 1.0e20)) secs, _ = morph.get_target_segments(edge_type=edge_type) assert(len(secs) == morph.nseg) # Check to see if it's cached secs, _ = morph.get_target_segments(edge_type=edge_type) assert(len(secs) == morph.nseg) secs, sec_probs = morph.get_target_segments(EdgeType(target_sections=('dend', 'apic'), target_distance=(150.0, 200.0))) assert(np.isclose(np.sum(sec_probs), 1.0, atol=1.0e-3)) for sec in secs: assert(morph.seg_prop['type'][sec] in [3, 4]) assert(10.0 <= morph.seg_prop['dist1'][sec] and morph.seg_prop['dist0'][sec] <= 200.0)
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_get_swc_id(): hobj = load_hobj() fix_axon_peri(hobj) morph = Morphology(hobj, swc_path=RORB_SWC_PATH) morph.set_segment_dl(20.0) # check soma has swc id == 1 assert(morph.get_swc_id(0, 0.0)[0] == 1) assert(morph.get_swc_id(0, 0.5)[0] == 1) assert(morph.get_swc_id(0, 0.5)[0] == 1) # check dend assert(morph.get_swc_id(1, 0.0)[0] == 2) assert(morph.get_swc_id(1, 0.0001)[0] == 2) assert(morph.get_swc_id(1, 1.0) == (19.0, 0.0)) assert(morph.get_swc_id(2, 0.0) == (20.0, 0.0)) # check apic assert(morph.get_swc_id(40, 0.0) == (3436, 0.0)) assert(morph.get_swc_id(41, 0.0) == (964, 0.0)) assert(morph.get_swc_id(85, 0.0) == (2824, 0.0)) assert(morph.get_swc_id(85, 1.0) == (2857, 0.0)) # check axon assert(morph.get_swc_id(86, 0.0) == (3495, 0.0)) assert(morph.get_swc_id(86, 1.0) == (3508, 0.0)) for sec_id, sec_type in zip(morph.seg_props.sec_id, morph.seg_props.type): swc_id, _ = morph.get_swc_id(sec_id, 0.0) if swc_id != -1: assert(morph.swc_map[morph.swc_map['id'] == swc_id]['type'].values[0] == sec_type)
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_remove_secs(): # if you don't cut off the axon the second segment should be the axon hobj = load_hobj() morph = Morphology(hobj, swc_path=RORB_SWC_PATH) assert(len(morph.segments) == 87) assert(len(morph.sections) == 87) assert(len(morph.seg_props.sec_id) == 87) assert(morph.seg_props.sec_id[1] == 1) assert(morph.seg_props.type[1] == 2) assert(morph.seg_props.type[0] != 2) assert(morph.seg_props.type[2] != 2) # In the given swc file the last 14 ids are assigned to the axon assert(morph.get_swc_id(1, 0.0) == (3495, 0.0)) assert(morph.get_swc_id(1, 1.0) == (3508, 0.0)) for sec_x in np.linspace(0.0, 1.0, num=13, endpoint=False): assert(3495 <= morph.get_swc_id(1, sec_x)[0] < 3508) # remove the axon hobj = load_hobj() for sec in hobj.axon: h.delete_section(sec=sec) morph = Morphology(hobj, swc_path=RORB_SWC_PATH) assert(len(morph.seg_props.sec_id) == 86) assert(len(morph.segments) == 86) assert(len(morph.sections) == 86) assert(2 not in morph.seg_props.type) assert(set(morph.seg_props.type) == {1, 3, 4}) axon_swc_ids = morph.swc_map[morph.swc_map['type'] == 2]['id'].values for sec_id in morph.seg_props.sec_id: for sec_x in np.linspace(0.0, 1.0, num=10, endpoint=True): swc_id, _ = morph.get_swc_id(sec_id, sec_x=sec_x) assert(sec_id not in axon_swc_ids) # remove apical and basal dendrites hobj = load_hobj() for sec in hobj.all: if 'apic' in sec.name() or 'dend' in sec.name(): h.delete_section(sec=sec) morph = Morphology(hobj, swc_path=RORB_SWC_PATH) assert(len(morph.segments) == 2) assert(len(morph.sections) == 2) assert(len(morph.seg_props.sec_id) == 2) for sec_id in morph.seg_props.sec_id: for sec_x in np.linspace(0.0, 1.0, num=10, endpoint=True): swc_id, _ = morph.get_swc_id(sec_id, sec_x=sec_x) assert(morph.swc_map[morph.swc_map['id'] == swc_id]['type'].values[0] in [1, 2])
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_move_and_rotate(): hobj = load_hobj() # fix_axon_peri(hobj) morph1 = Morphology(hobj) morph2 = morph1.move_and_rotate( soma_coords=[100.0, -100.0, 0.0], rotation_angles=[90.0, 180.0, 0.0], inplace=False ) # Make sure inplace=False updating morph1 doesn't affect morph2 assert(np.allclose(morph1.seg_coords.p0[:, 0], [-5.82, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p05[:, 0], [0.0, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p1[:, 0], [5.82, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p0[:, 86], [-22.21, -18.18, -1.89], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p05[:, 86], [-38.98, -12.29, -4.19], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p1[:, 86], [-51.45, 0.740, -6.35], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p0[:, 0], [103.48, -95.83, 2.08], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, 0], [100.0, -100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, 0], [96.51, -104.16, -2.08], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p0[:, -1], [114.81, -76.95, -8.79], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, -1], [126.68, -68.81, 1.87], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, -1], [135.88, -66.87, 17.42], atol=1.0e-2)) # Make sure inplace=True updating morph1 doesn't affect morph2 morph1.move_and_rotate( soma_coords=[10.0, 10.0, 10.0], rotation_angles=[0.0, 0.0, 0.0], inplace=True ) assert(np.allclose(morph1.seg_coords.p0[:, 0], [4.17966715, 10.0, 10.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p05[:, 0], [10.0, 10.0, 10.0], atol=1.0e-2)) assert(np.allclose(morph1.seg_coords.p1[:, 0], [15.82, 10.0, 10.0], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p0[:, 0], [103.48, -95.83, 2.08], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, 0], [100.0, -100.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, 0], [96.51, -104.16, -2.08], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p0[:, -1], [114.81, -76.95, -8.79], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, -1], [126.68, -68.81, 1.87], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p1[:, -1], [135.88, -66.87, 17.42], atol=1.0e-2))
[docs] @pytest.mark.skipif(not has_mechanism, reason='Mechanisms has not been compiled, run nrnivmodl mechanisms.') @pytest.mark.skipif(not nrn_installed, reason='NEURON is not installed') def test_move_and_rotate_cached(): hobj = load_hobj() morph1 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) morph2 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) # initially morph1 and morph2 share the same SegmentCoords object, make sure after a move_and_rotate is done # the two morphology has different coordinates assert(morph1.seg_coords == morph2.seg_coords) morph2.move_and_rotate( soma_coords=[10.0, 10.0, 10.0], rotation_angles=[100.0, 100.0, 100.0], inplace=True ) assert(morph1.seg_coords != morph2.seg_coords) assert(np.allclose(morph1.seg_coords.p05[:, 0], [0.0, 0.0, 0.0], atol=1.0e-2)) assert(np.allclose(morph2.seg_coords.p05[:, 0], [10.0, 10.0, 10.0], atol=1.0e-2))
[docs] def check_lazy_loading(): hobj = load_hobj() morph1 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=True) hobj = load_hobj() morph2 = Morphology.load(hobj, morphology_file=RORB_SWC_PATH, cache_seg_props=False) print(len(morph2.seg_props.x)) print(len(morph1.seg_props.x)) print(id(morph1.seg_props) == id(morph2.seg_props))
# morph1.seg_props if __name__ == '__main__': # test_base() # test_seg_props_cache() # test_full() # test_multicell() # test_find_sections() # test_get_target_segments() # test_get_swc_id() # test_remove_secs() # check_lazy_loading() # test_move_and_rotate() test_move_and_rotate_cached()