def test_convert_recenter(): with setup_tempdir('test-convert_recenter') as tmp_dir: simple = os.path.join(DATA, 'simple.swc') outname = os.path.join(tmp_dir, 'test.swc') convert(simple, outname, recenter=True) ok_(not diff(simple, outname)) #simple.swc is already centered mut = morphio.Morphology(simple).as_mutable() mut.soma.points = [[1, 1, 1], ] inname = os.path.join(tmp_dir, 'moved.swc') mut.write(inname) convert(inname, outname, recenter=True) simple = morphio.Morphology(simple) centered_morph = morphio.Morphology(outname) ok_(np.all((simple.points - centered_morph.points) == 1))
def test_convert_recenter(tmpdir): simple = DATA / 'simple.swc' outname = Path(tmpdir, 'test.swc') convert(simple, outname, recenter=True) assert not diff(simple, outname) #simple.swc is already centered mut = morphio.Morphology(simple).as_mutable() mut.soma.points = [ [1, 1, 1], ] inname = Path(tmpdir, 'moved.swc') mut.write(inname) convert(inname, outname, recenter=True) simple = morphio.Morphology(simple) centered_morph = morphio.Morphology(outname) assert np.all((simple.points - centered_morph.points) == 1)
def test_convert_sanitize(tmpdir): # needs to have a complex contour soma simple = DATA / 'single_child.asc' outname = Path(tmpdir, 'single_child.swc') with pytest.raises(MorphToolException, match='Use `sanitize` option for converting'): convert(simple, outname, single_point_soma=True) convert(simple, outname, single_point_soma=True, sanitize=True) m = morphio.Morphology(outname) assert len(m.sections) == 1
def test_convert_swc_contour_to_sphere(tmpdir): # needs to have a complex contour soma simple = DATA / 'tkb061126a4_ch0_cc2_h_zk_60x_1.asc' outname = Path(tmpdir, 'test.swc') convert(simple, outname, single_point_soma=True) m = morphio.Morphology(outname) assert 1 == len(m.soma.points) assert 1 == len(m.soma.diameters) #value dumped from NEURON: h.area(0.5, sec=icell.soma[0]) np.testing.assert_approx_equal(m.soma.surface, 476.0504050847511)
def test_neuron_building_consistency__swc(): path = f'{DATA_PATH}/valid/C010398B-P2.CNG.swc' neuron1 = load_neuron(path) neuron2 = load_neuron_from_morphio(path) _assert_neurons_equal(neuron1, neuron2) neuron2 = load_neuron_from_morphio(morphio.Morphology(path)) _assert_neurons_equal(neuron1, neuron2)
def test_convert_swc_contour_to_sphere(): with setup_tempdir('test_convert_swc_contour_to_sphere') as tmp_dir: # needs to have a complex contour soma simple = os.path.join(DATA, 'tkb061126a4_ch0_cc2_h_zk_60x_1.asc') outname = os.path.join(tmp_dir, 'test.swc') convert(simple, outname, single_point_soma=True) m = morphio.Morphology(outname) assert_equal(1, len(m.soma.points)) assert_equal(1, len(m.soma.diameters)) #value dumped from NEURON: h.area(0.5, sec=icell.soma[0]) np.testing.assert_approx_equal(m.soma.surface, 476.0504050847511)
def test_convert_sanitize(): with setup_tempdir('test_convert_sanitize') as tmp_dir: # needs to have a complex contour soma simple = os.path.join(DATA, 'single_child.asc') outname = os.path.join(tmp_dir, 'single_child.swc') with assert_raises(MorphToolException) as obj: convert(simple, outname, single_point_soma=True) assert_equal('Use `sanitize` option for converting', str(obj.exception)) convert(simple, outname, single_point_soma=True, sanitize=True) m = morphio.Morphology(outname) assert_equal(len(m.sections), 1)
def sanitize(input_neuron, output_path): '''Sanitize one morphology. - fixes non zero segments - raises if the morphology has no soma - raises if the morphology has negative diameters Args: input_neuron (str|pathlib.Path|morphio.Morphology|morphio.mut.Morphology): input neuron output_path (str|pathlib.Path): output name ''' neuron = morphio.Morphology(input_neuron) if neuron.soma.type == SomaType.SOMA_UNDEFINED: # pylint: disable=no-member raise CorruptedMorphology('{} has no soma'.format(input_neuron)) if np.any(neuron.diameters < 0): raise CorruptedMorphology('{} negative diameters'.format(input_neuron)) fix_non_zero_segments(neuron).write(str(output_path))
def unravel(filename, window_half_length=DEFAULT_WINDOW_HALF_LENGTH): '''Return an unravelled neuron Segment are unravelled iteratively Each segment direction is replaced by the averaged direction in a sliding window around this segment. And the original segment length is preserved. The start position of the new segment is the end of the latest unravelled segment Args: filename (str): the neuron to unravel window_half_length (int): the number of segments that defines half of the sliding window Returns: a tuple (morphio.mut.Morphology, dict) where first item is the unravelled morphology and the second one is the mapping of each point coordinate before and after unravelling ''' morph = morphio.Morphology(filename) new_morph = morphio.mut.Morphology(morph) # pylint: disable=no-member coord_before = np.empty([0, 3]) coord_after = np.empty([0, 3]) for sec, new_section in zip(morph.iter(), new_morph.iter()): _unravel_section(sec, new_section, window_half_length) coord_before = np.append(coord_before, sec.points, axis=0) coord_after = np.append(coord_after, new_section.points, axis=0) mapping = pd.DataFrame({ 'x0': coord_before[:, 0], 'y0': coord_before[:, 1], 'z0': coord_before[:, 2], 'x1': coord_after[:, 0], 'y1': coord_after[:, 1], 'z1': coord_after[:, 2], }) L.info('Unravel successful for file: %s', filename) return new_morph, mapping
def unravel(filename, window_half_length=None, legacy_behavior=False, use_path_length=True): '''Return an unravelled neuron Segment are unravelled iteratively Each segment direction is replaced by the averaged direction in a sliding window around this segment, preserving the original segment length. The start position of the new segment is the end of the latest unravelled segment Based initially on: DOI: 10.7551/mitpress/9780262013277.001.0001 Section: 9.2 Repair of Neuronal Dendrites Args: filename (str): the neuron to unravel window_half_length (int): path length that defines half of the sliding window legacy_behavior (bool): if yes, when the soma has more than one point, the first point of the soma is appended to the start of each neurite. use_path_length (bool): if False, the argument window_half_length will be recasted to an int and correspond to number of points on each side of the window. Returns: a tuple (morphio.mut.Morphology, dict) where first item is the unravelled morphology and the second one is the mapping of each point coordinate before and after unravelling ''' morph = morphio.Morphology(filename, options=morphio.Option.nrn_order) new_morph = morphio.mut.Morphology(morph, options=morphio.Option.nrn_order) # noqa, pylint: disable=no-member if window_half_length is None: window_half_length = DEFAULT_WINDOW_HALF_LENGTH_PATH \ if use_path_length else DEFAULT_WINDOW_HALF_LENGTH coord_before = np.empty([0, 3]) coord_after = np.empty([0, 3]) for sec, new_section in zip(morph.iter(), new_morph.iter()): if use_path_length: _unravel_section_path_length(new_section, window_half_length, morph.soma, legacy_behavior) else: _unravel_section(new_section, int(window_half_length), morph.soma, legacy_behavior) coord_before = np.append(coord_before, sec.points, axis=0) coord_after = np.append(coord_after, new_section.points, axis=0) if legacy_behavior and len(morph.soma.points) > 1: # pylint: disable=no-member coord_before = np.vstack((morph.soma.points[0], coord_before)) # noqa, pylint: disable=no-member mapping = pd.DataFrame({ 'x0': coord_before[:, 0], 'y0': coord_before[:, 1], 'z0': coord_before[:, 2], 'x1': coord_after[:, 0], 'y1': coord_after[:, 1], 'z1': coord_after[:, 2], }) L.debug('Unravel successful for file: %s', filename) return new_morph, mapping
def _get(self, name, options=None): filepath = os.path.join(self.base_dir, name + self.file_ext) if options is None: return morphio.Morphology(filepath) else: return morphio.Morphology(filepath, options)