def iter_neurites(obj, mapfun=None, filt=None, neurite_order=NeuriteIter.FileOrder): """Iterator to a neurite, neuron or neuron population. Applies optional neurite filter and mapping functions. Arguments: obj: a neurite, neuron or neuron population. mapfun: optional neurite mapping function. filt: optional neurite filter function. neurite_order (NeuriteIter): order upon which neurites should be iterated - NeuriteIter.FileOrder: order of appearance in the file - NeuriteIter.NRN: NRN simulator order: soma -> axon -> basal -> apical Examples: Get the number of points in each neurite in a neuron population >>> from neurom.core import iter_neurites >>> n_points = [n for n in iter_neurites(pop, lambda x : len(x.points))] Get the number of points in each axon in a neuron population >>> import neurom as nm >>> from neurom.core import iter_neurites >>> filter = lambda n : n.type == nm.AXON >>> mapping = lambda n : len(n.points) >>> n_points = [n for n in iter_neurites(pop, mapping, filter)] """ neurites = ((obj,) if isinstance(obj, Neurite) else obj.neurites if hasattr(obj, 'neurites') else obj) if neurite_order == NeuriteIter.NRN: last_position = max(NRN_ORDER.values()) + 1 neurites = sorted(neurites, key=lambda neurite: NRN_ORDER.get(neurite.type, last_position)) neurite_iter = iter(neurites) if filt is None else filter(filt, neurites) return neurite_iter if mapfun is None else map(mapfun, neurite_iter)
def iter_neurites(obj, mapfun=None, filt=None): '''Iterator to a neurite, neuron or neuron population Applies optional neurite filter and mapping functions. Parameters: obj: a neurite, neuron or neuron population. mapfun: optional neurite mapping function. filt: optional neurite filter function. Examples: Get the number of points in each neurite in a neuron population >>> from neurom.core import iter_neurites >>> n_points = [n for n in iter_neurites(pop, lambda x : len(x.points))] Get the number of points in each axon in a neuron population >>> import neurom as nm >>> from neurom.core import iter_neurites >>> filter = lambda n : n.type == nm.AXON >>> mapping = lambda n : len(n.points) >>> n_points = [n for n in iter_neurites(pop, mapping, filter)] ''' neurites = ((obj,) if isinstance(obj, Neurite) else obj.neurites if hasattr(obj, 'neurites') else obj) neurite_iter = iter(neurites) if filt is None else filter(filt, neurites) return neurite_iter if mapfun is None else map(mapfun, neurite_iter)
def iter_neurites(obj, mapfun=None, filt=None): '''Iterator to a neurite, neuron or neuron population Applies optional neurite filter and mapping functions. Parameters: obj: a neurite, neuron or neuron population. mapfun: optional neurite mapping function. filt: optional neurite filter function. Examples: Get the number of points in each neurite in a neuron population >>> from neurom.core import iter_neurites >>> n_points = [n for n in iter_neurites(pop, lambda x : len(x.points))] Get the number of points in each axon in a neuron population >>> import neurom as nm >>> from neurom.core import iter_neurites >>> filter = lambda n : n.type == nm.AXON >>> mapping = lambda n : len(n.points) >>> n_points = [n for n in iter_neurites(pop, mapping, filter)] ''' neurites = ((obj, ) if isinstance(obj, Neurite) else obj.neurites if hasattr(obj, 'neurites') else obj) neurite_iter = iter(neurites) if filt is None else filter(filt, neurites) return neurite_iter if mapfun is None else map(mapfun, neurite_iter)
def test_iter_sections_filter(): for ntyp in nm.NEURITE_TYPES: a = [s for n in filter(lambda nn: nn.type == ntyp, POP.neurites) for s in n.iter_sections()] b = [n for n in core.iter_sections(POP, neurite_filter=lambda n: n.type == ntyp)] assert_sequence_equal(a, b)
def test_iter_sections_filter(): for ntyp in nm.NEURITE_TYPES: a = [s.id for n in filter(lambda nn: nn.type == ntyp, POP.neurites) for s in n.iter_sections()] b = [n.id for n in core.iter_sections(POP, neurite_filter=lambda n: n.type == ntyp)] assert_sequence_equal(a, b)
def iforking_point(self, iter_mode=ipreorder): """Iterator to forking points. Returns a tree object. Arguments: tree: the tree over which to iterate iter_mode: iteration mode. Default: ipreorder. """ return filter(Tree.is_forking_point, iter_mode(self))
def get_morph_files(directory): '''Get a list of all morphology files in a directory Returns: list with all files with extensions '.swc' , 'h5' or '.asc' (case insensitive) ''' lsdir = (os.path.join(directory, m) for m in os.listdir(directory)) return list(filter(_is_morphology_file, lsdir))
def iforking_point(self, iter_mode=ipreorder): '''Iterator to forking points. Returns a tree object. Parameters: tree: the tree over which to iterate iter_mode: iteration mode. Default: ipreorder. ''' return filter(Tree.is_forking_point, iter_mode(self))
def _filepath(self, name): """ File path to `name` morphology file. """ if self.file_ext is None: candidates = glob.glob(os.path.join(self.directory, name + ".*")) try: return next(filter(_is_morphology_file, candidates)) except StopIteration: raise NeuroMError("Can not find morphology file for '%s' " % name) else: return os.path.join(self.directory, name + self.file_ext)
def iter_neurites(obj, mapfun=None, filt=None, neurite_order=NeuriteIter.FileOrder): '''Iterator to a neurite, neuron or neuron population Applies optional neurite filter and mapping functions. Parameters: obj: a neurite, neuron or neuron population. mapfun: optional neurite mapping function. filt: optional neurite filter function. neurite_order (NeuriteIter): order upon which neurites should be iterated - NeuriteIter.FileOrder: order of appearance in the file - NeuriteIter.NRN: NRN simulator order: soma -> axon -> basal -> apical Examples: Get the number of points in each neurite in a neuron population >>> from neurom.core import iter_neurites >>> n_points = [n for n in iter_neurites(pop, lambda x : len(x.points))] Get the number of points in each axon in a neuron population >>> import neurom as nm >>> from neurom.core import iter_neurites >>> filter = lambda n : n.type == nm.AXON >>> mapping = lambda n : len(n.points) >>> n_points = [n for n in iter_neurites(pop, mapping, filter)] ''' neurites = ((obj,) if isinstance(obj, Neurite) else obj.neurites if hasattr(obj, 'neurites') else obj) if neurite_order == NeuriteIter.NRN: last_position = max(NRN_ORDER.values()) + 1 neurites = sorted(neurites, key=lambda neurite: NRN_ORDER.get(neurite.type, last_position)) neurite_iter = iter(neurites) if filt is None else filter(filt, neurites) return neurite_iter if mapfun is None else map(mapfun, neurite_iter)
def ileaf(self): '''Iterator to all leaves of a tree''' return filter(Tree.is_leaf, self.ipreorder())
def is_back_tracking(neurite): ''' Check if a neurite process backtracks to a previous node. Back-tracking takes place when a daughter of a branching process goes back and either overlaps with a previous point, or lies inside the cylindrical volume of the latter. Args: neurite(Neurite): neurite to operate on Returns: True Under the following scenaria: 1. A segment endpoint falls back and overlaps with a previous segment's point 2. The geometry of a segment overlaps with a previous one in the section ''' def pair(segs): ''' Pairs the input list into triplets''' return zip(segs, segs[1:]) def coords(node): ''' Returns the first three values of the tree that correspond to the x, y, z coordinates''' return node[COLS.XYZ] def max_radius(seg): ''' Returns maximum radius from the two segment endpoints''' return max(seg[0][COLS.R], seg[1][COLS.R]) def is_not_zero_seg(seg): ''' Returns True if segment has zero length''' return not np.allclose(coords(seg[0]), coords(seg[1])) def is_in_the_same_verse(seg1, seg2): ''' Checks if the vectors face the same direction. This is true if their dot product is greater than zero. ''' v1 = coords(seg2[1]) - coords(seg2[0]) v2 = coords(seg1[1]) - coords(seg1[0]) return np.dot(v1, v2) >= 0 def is_seg2_within_seg1_radius(dist, seg1, seg2): ''' Checks whether the orthogonal distance from the point at the end of seg1 to seg2 segment body is smaller than the sum of their radii ''' return dist <= max_radius(seg1) + max_radius(seg2) def is_seg1_overlapping_with_seg2(seg1, seg2): '''Checks if a segment is in proximity of another one upstream''' # get the coordinates of seg2 (from the origin) s1 = coords(seg2[0]) s2 = coords(seg2[1]) # vector of the center of seg2 (from the origin) C = 0.5 * (s1 + s2) # endpoint of seg1 (from the origin) P = coords(seg1[1]) # vector from the center C of seg2 to the endpoint P of seg1 CP = P - C # vector of seg2 S1S2 = s2 - s1 # projection of CP upon seg2 prj = mm.vector_projection(CP, S1S2) # check if the distance of the orthogonal complement of CP projection on S1S2 # (vertical distance from P to seg2) is smaller than the sum of the radii. (overlap) # If not exit early, because there is no way that backtracking can feasible if not is_seg2_within_seg1_radius(np.linalg.norm(CP - prj), seg1, seg2): return False # projection lies within the length of the cylinder. Check if the distance between # the center C of seg2 and the projection of the end point of seg1, P is smaller than # half of the others length plus a 5% tolerance return np.linalg.norm(prj) < 0.55 * np.linalg.norm(S1S2) def is_inside_cylinder(seg1, seg2): ''' Checks if seg2 approximately lies within a cylindrical volume of seg1. Two conditions must be satisfied: 1. The two segments are not facing the same direction (seg2 comes back to seg1) 2. seg2 is overlaping with seg1 ''' return not is_in_the_same_verse(seg1, seg2) and is_seg1_overlapping_with_seg2(seg1, seg2) # filter out single segment sections section_itr = (snode for snode in neurite.iter_sections() if snode.points.shape[0] > 2) for snode in section_itr: # group each section's points intro triplets segment_pairs = list(filter(is_not_zero_seg, pair(snode.points))) # filter out zero length segments for i, seg1 in enumerate(segment_pairs[1:]): # check if the end point of the segment lies within the previous # ones in the current sectionmake for seg2 in segment_pairs[0: i + 1]: if is_inside_cylinder(seg1, seg2): return True return False
def is_back_tracking(neurite): ''' Check if a neurite process backtracks to a previous node. Back-tracking takes place when a daughter of a branching process goes back and either overlaps with a previous point, or lies inside the cylindrical volume of the latter. Args: neurite(Neurite): neurite to operate on Returns: True Under the following scenaria: 1. A segment endpoint falls back and overlaps with a previous segment's point 2. The geometry of a segment overlaps with a previous one in the section ''' def pair(segs): ''' Pairs the input list into triplets''' return zip(segs, segs[1:]) def coords(node): ''' Returns the first three values of the tree that correspond to the x, y, z coordinates''' return node[COLS.XYZ] def max_radius(seg): ''' Returns maximum radius from the two segment endpoints''' return max(seg[0][COLS.R], seg[1][COLS.R]) def is_not_zero_seg(seg): ''' Returns True if segment has zero length''' return not np.allclose(coords(seg[0]), coords(seg[1])) def is_in_the_same_verse(seg1, seg2): ''' Checks if the vectors face the same direction. This is true if their dot product is greater than zero. ''' v1 = coords(seg2[1]) - coords(seg2[0]) v2 = coords(seg1[1]) - coords(seg1[0]) return np.dot(v1, v2) >= 0 def is_seg2_within_seg1_radius(dist, seg1, seg2): ''' Checks whether the orthogonal distance from the point at the end of seg1 to seg2 segment body is smaller than the sum of their radii ''' return dist <= max_radius(seg1) + max_radius(seg2) def is_seg1_overlapping_with_seg2(seg1, seg2): '''Checks if a segment is in proximity of another one upstream''' # get the coordinates of seg2 (from the origin) s1 = coords(seg2[0]) s2 = coords(seg2[1]) # vector of the center of seg2 (from the origin) C = 0.5 * (s1 + s2) # endpoint of seg1 (from the origin) P = coords(seg1[1]) # vector from the center C of seg2 to the endpoint P of seg1 CP = P - C # vector of seg2 S1S2 = s2 - s1 # projection of CP upon seg2 prj = mm.vector_projection(CP, S1S2) # check if the distance of the orthogonal complement of CP projection on S1S2 # (vertical distance from P to seg2) is smaller than the sum of the radii. (overlap) # If not exit early, because there is no way that backtracking can feasible if not is_seg2_within_seg1_radius(np.linalg.norm(CP - prj), seg1, seg2): return False # projection lies within the length of the cylinder. Check if the distance between # the center C of seg2 and the projection of the end point of seg1, P is smaller than # half of the others length plus a 5% tolerance return np.linalg.norm(prj) < 0.55 * np.linalg.norm(S1S2) def is_inside_cylinder(seg1, seg2): ''' Checks if seg2 approximately lies within a cylindrical volume of seg1. Two conditions must be satisfied: 1. The two segments are not facing the same direction (seg2 comes back to seg1) 2. seg2 is overlaping with seg1 ''' return not is_in_the_same_verse( seg1, seg2) and is_seg1_overlapping_with_seg2(seg1, seg2) # filter out single segment sections section_itr = (snode for snode in neurite.iter_sections() if snode.points.shape[0] > 2) for snode in section_itr: # group each section's points intro triplets segment_pairs = list(filter(is_not_zero_seg, pair(snode.points))) # filter out zero length segments for i, seg1 in enumerate(segment_pairs[1:]): # check if the end point of the segment lies within the previous # ones in the current sectionmake for seg2 in segment_pairs[0:i + 1]: if is_inside_cylinder(seg1, seg2): return True return False
def ileaf(self): """Iterator to all leaves of a tree.""" return filter(Tree.is_leaf, self.ipreorder())