def test_mut_copy_ctor(): simple = Morphology(os.path.join(_path, "simple.swc")) assert_equal([sec.id for sec in simple.iter()], [0, 1, 2, 3, 4, 5]) copy = Morphology(simple) copy.append_root_section( PointLevel([[1, 2, 3], [4, 5, 6]], [2, 2], [20, 20]), SectionType.axon) # test that first object has not been mutated assert_equal([sec.id for sec in simple.iter()], [0, 1, 2, 3, 4, 5]) assert_equal([sec.id for sec in copy.iter()], [0, 1, 2, 3, 4, 5, 6])
def fix_non_zero_segments(neuron, zero_length=_ZERO_LENGTH): '''Return a neuron with zero length segments removed Sections composed of a single zero length segment are deleted, where zero is parametrized by zero_length Args: neuron (str|pathlib.Path|morphio.Morphology|morphio.mut.Morphology): input neuron zero_length (float): smallest length of a segment Returns: a fixed morphio.mut.Morphology ''' neuron = Morphology(neuron) to_be_deleted = list() for section in neuron.iter(): points = section.points distances = np.linalg.norm(np.diff(points, axis=0), axis=1) distances[distances < zero_length] = 0 indices = np.append(0, np.nonzero(distances)[0] + 1) if len(indices) != len(points): section.points = section.points[indices] section.diameters = section.diameters[indices] if len(indices) < 2: to_be_deleted.append(section) for section in to_be_deleted: neuron.delete_section(section) return neuron
def test_sanitize(): m = Morphology() section = m.append_root_section( PointLevel([[1, 0, 0], [2, 0, 0]], [2, 2], [20, 20]), SectionType.axon) section.append_section(PointLevel([[2, 0, 0], [3, 0, 0]], [2, 2], [20, 20])) with captured_output() as (_, err): with ostream_redirect(stdout=True, stderr=True): m.sanitize() assert_equal(len(list(m.iter())), 1) assert_equal( err.getvalue().strip(), 'Warning: section 1 is the only child of section: 0\nIt will be merged ' 'with the parent section') # Checking that sanitize() issues a warning on missing duplicate m = Morphology() section = m.append_root_section( PointLevel([[1, 0, 0], [2, 0, 0]], [2, 2], [20, 20]), SectionType.axon) section.append_section(PointLevel([[2, 0, 0], [3, 0, 0]], [2, 2], [20, 20])) with captured_output() as (_, err): with ostream_redirect(): section.append_section( PointLevel([[2, 1, 0], [2, 0, 0]], [2, 2], [20, 20])) with captured_output() as (_, err): with ostream_redirect(): m.sanitize() assert_equal( err.getvalue().strip(), 'Warning: while appending section: 2 to parent: 0\nThe section first point should be parent section last point: \n : X Y Z Diameter\nparent last point :[2.000000, 0.000000, 0.000000, 2.000000]\nchild first point :[2.000000, 1.000000, 0.000000, 2.000000]' )
def test_iterators(): assert_array_equal( [sec.id for sec in SIMPLE.section(5).iter(IterType.upstream)], [5, 3]) assert_array_equal( [sec.id for sec in SIMPLE.section(0).iter(IterType.depth_first)], [0, 1, 2]) assert_array_equal( [sec.id for sec in SIMPLE.section(0).iter(IterType.breadth_first)], [0, 1, 2]) assert_array_equal([sec.id for sec in SIMPLE.iter()], [0, 1, 2, 3, 4, 5]) assert_array_equal([sec.id for sec in SIMPLE.iter(IterType.depth_first)], [0, 1, 2, 3, 4, 5]) assert_array_equal([sec.id for sec in SIMPLE.iter(IterType.breadth_first)], [0, 3, 1, 2, 4, 5]) neuron = Morphology(os.path.join(_path, "iterators.asc")) root = neuron.root_sections[0] assert_array_equal( [section.id for section in root.iter(IterType.depth_first)], [0, 1, 2, 3, 4, 5, 6]) assert_array_equal( [section.id for section in root.iter(IterType.breadth_first)], [0, 1, 4, 2, 3, 5, 6]) assert_array_equal( [section.id for section in neuron.iter(IterType.breadth_first)], [0, 7, 1, 4, 8, 9, 2, 3, 5, 6])
def fix_non_zero_segments(neuron): '''Return a neuron with zero length segments removed Sections composed of a single zero length segment are deleted Args: neuron (str|pathlib.Path|morphio.Morphology|morphio.mut.Morphology): input neuron Returns: a fixed morphio.mut.Morphology ''' neuron = Morphology(neuron) to_be_deleted = list() for section in neuron.iter(): points = section.points distances = np.linalg.norm(np.diff(points, axis=0), axis=1) indices = np.append(0, np.nonzero(distances)[0] + 1) if len(indices) != len(points): section.points = section.points[indices] section.diameters = section.diameters[indices] if len(indices) < 2: to_be_deleted.append(section) for section in to_be_deleted: neuron.delete_section(section) return neuron
def sanitize(input_neuron, output_path): '''Sanitize one morphology. - ensures it can be loaded with MorphIO - raises if the morphology has no soma or of invalid format - removes unifurcations - set negative diameters to zero - raises if the morphology has a neurite whose type changes along the way - removes segments with near zero lengths (shorter than 1e-4) Args: input_neuron (str|pathlib.Path|morphio.Morphology|morphio.mut.Morphology): input neuron output_path (str|pathlib.Path): output name ''' neuron = Morphology(input_neuron) if neuron.soma.type == SomaType.SOMA_UNDEFINED: # pylint: disable=no-member raise CorruptedMorphology( '{} has an invalid or no soma'.format(input_neuron)) neuron.remove_unifurcations() for section in neuron.iter(): section.diameters = np.clip(section.diameters, 0, None) for root in neuron.root_sections: # pylint: disable=not-an-iterable for section in root.iter(): if section.type != root.type: raise CorruptedMorphology( f'{input_neuron} has a neurite whose type changes along ' 'the way\n' f'Child section (id: {section.id}) has a different type ' f'({section.type}) than its parent (id: ' f'{section.parent.id}) (type: {section.parent.type})') fix_non_zero_segments(neuron).write(str(output_path))
def test_equality(): set_ignored_warning([Warning.wrong_duplicate, Warning.only_child], True) filename = joinp(DATA, 'simple2.asc') neuron_ref = Morphology(filename) ok_(not diff(neuron_ref, neuron_ref)) ok_(not diff(neuron_ref, filename)) ok_(not diff(neuron_ref, neuron_ref.as_immutable())) def mundane_section(neuron): '''Not a root section, not a leaf section''' return neuron.root_sections[0].children[0] a = Morphology(joinp(DATA, 'simple2.asc')) mundane_section(a).type = SectionType.apical_dendrite result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, 'Section(id=1, points=[(0 5 0),..., (-6 5 0)]) and Section(id=1, points=[(0 5 0),..., (-6 5 0)]) have different section types') a = Morphology(joinp(DATA, 'simple2.asc')) mundane_section(a).points = [[0,0,0], [0,0,0], [0,0,1]] result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, '\n'.join(['Attributes Section.points of:', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'Section(id=1, points=[(0 0 0),..., (0 0 1)])', 'have the same shape but different values'])) a = Morphology(joinp(DATA, 'simple2.asc')) mundane_section(a).diameters = [0,0,0] result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, '\n'.join(['Attributes Section.diameters of:', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'have the same shape but different values'])) a = Morphology(joinp(DATA, 'simple2.asc')) for section in a.iter(): section.perimeters = [1] * len(section.points) result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, '\n'.join(['Attributes Section.perimeters of:', 'Section(id=0, points=[(0 0 0),..., (0 5 0)])', 'Section(id=0, points=[(0 0 0),..., (0 5 0)])', 'have different shapes: (0,) vs (2,)'])) a = Morphology(joinp(DATA, 'simple2.asc')) mundane_section(a).append_section(PointLevel([[-6, 5, 0], [4, 5, 6]], [2, 3])) result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, 'Section(id=1, points=[(0 5 0),..., (-6 5 0)]) and Section(id=1, points=[(0 5 0),..., (-6 5 0)]) have different a different number of children') a = Morphology(joinp(DATA, 'simple2.asc')) a.delete_section(a.root_sections[0]) result = diff(neuron_ref, a) ok_(result) assert_equal(result.info, 'Both morphologies have different a different number of root sections') result = diff(joinp(DATA, 'single_child.asc'), joinp(DATA, 'not_single_child.asc')) ok_(not result) set_ignored_warning([Warning.wrong_duplicate, Warning.only_child], False)
def test_equality(): set_ignored_warning([Warning.wrong_duplicate, Warning.only_child], True) filename = DATA / 'simple2.asc' neuron_ref = Morphology(filename) assert not diff(neuron_ref, neuron_ref) assert not diff(neuron_ref, filename) assert not diff(neuron_ref, neuron_ref.as_immutable()) def mundane_section(neuron): '''Not a root section, not a leaf section''' return neuron.root_sections[0].children[0] a = Morphology(DATA / 'simple2.asc') mundane_section(a).type = SectionType.apical_dendrite result = diff(neuron_ref, a) assert result assert result.info == 'Section(id=1, points=[(0 5 0),..., (-6 5 0)]) and Section(id=1, points=[(0 5 0),..., (-6 5 0)]) have different section types' a = Morphology(DATA / 'simple2.asc') mundane_section(a).points = [[0,0,0], [0,0,0], [0,0,1]] result = diff(neuron_ref, a) assert result assert (result.info == '\n'.join(['Attributes Section.points of:', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'Section(id=1, points=[(0 0 0),..., (0 0 1)])', 'have the same shape but different values', 'Vector points differs at index 0: [0. 5. 0.] != [0. 0. 0.]'])) a = Morphology(DATA / 'simple2.asc') mundane_section(a).diameters = [0,0,0] result = diff(neuron_ref, a) assert result assert (result.info == '\n'.join(['Attributes Section.diameters of:', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'Section(id=1, points=[(0 5 0),..., (-6 5 0)])', 'have the same shape but different values', 'Vector diameters differs at index 0: 3.0 != 0.0'])) a = Morphology(DATA / 'simple2.asc') for section in a.iter(): section.perimeters = [1] * len(section.points) result = diff(neuron_ref, a) assert result assert (result.info == '\n'.join(['Attributes Section.perimeters of:', 'Section(id=0, points=[(0 0 0),..., (0 5 0)])', 'Section(id=0, points=[(0 0 0),..., (0 5 0)])', 'have different shapes: (0,) vs (2,)'])) a = Morphology(DATA / 'simple2.asc') mundane_section(a).append_section(PointLevel([[-6, 5, 0], [4, 5, 6]], [2, 3])) result = diff(neuron_ref, a) assert result assert result.info == 'Section(id=1, points=[(0 5 0),..., (-6 5 0)]) and Section(id=1, points=[(0 5 0),..., (-6 5 0)]) have a different number of children' a = Morphology(DATA / 'simple2.asc') a.delete_section(a.root_sections[0]) result = diff(neuron_ref, a) assert result assert result.info == 'Both morphologies have a different number of root sections' result = diff(DATA / 'single_child.asc', DATA / 'not_single_child.asc') if parse_version(get_distribution("morphio").version) < parse_version("3"): assert not result else: assert result set_ignored_warning([Warning.wrong_duplicate, Warning.only_child], False)