Ejemplo n.º 1
0
def has_no_dangling_branch(neuron):
    """Check if the neuron has dangling neurites.

    Are considered dangling

    - dendrites whose first point is too far from the soma center
    - axons whose first point is too far from the soma center AND from
      any point belonging to a dendrite

    Arguments:
        neuron(Neuron): The neuron object to test

    Returns:
        CheckResult with a list of all first segments of dangling neurites
    """
    if len(neuron.soma.points) == 0:
        raise NeuroMError(
            'Can\'t check for dangling neurites if there is no soma')
    soma_center = neuron.soma.points[:, COLS.XYZ].mean(axis=0)
    recentered_soma = neuron.soma.points[:, COLS.XYZ] - soma_center
    radius = np.linalg.norm(recentered_soma, axis=1)
    soma_max_radius = radius.max()

    dendritic_points = np.array(
        list(
            chain.from_iterable(n.points for n in iter_neurites(neuron)
                                if n.type != NeuriteType.axon)))

    def is_dangling(neurite):
        """Is the neurite dangling ?."""
        starting_point = neurite.points[0][COLS.XYZ]

        if np.linalg.norm(starting_point -
                          soma_center) - soma_max_radius <= 12.:
            return False

        if neurite.type != NeuriteType.axon:
            return True

        distance_to_dendrites = np.linalg.norm(dendritic_points[:, COLS.XYZ] -
                                               starting_point,
                                               axis=1)
        return np.all(
            distance_to_dendrites >= 2 * dendritic_points[:, COLS.R] + 2)

    bad_ids = [(n.root_node.id, [n.root_node.points[0]])
               for n in iter_neurites(neuron) if is_dangling(n)]
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 2
0
def has_no_jumps(neuron, max_distance=30.0, axis='z'):
    """Check if there are jumps (large movements in the `axis`).

    Arguments:
        neuron(Neuron): The neuron object to test
        max_distance(float): value above which consecutive z-values are
        considered a jump
        axis(str): one of x/y/z, which axis to check for jumps

    Returns:
        CheckResult with result list of ids of bad sections
    """
    bad_ids = []
    axis = {
        'x': COLS.X,
        'y': COLS.Y,
        'z': COLS.Z,
    }[axis.lower()]
    for neurite in iter_neurites(neuron):
        section_segment = ((sec, seg) for sec in iter_sections(neurite)
                           for seg in iter_segments(sec))
        for sec, (p0, p1) in islice(section_segment, 1,
                                    None):  # Skip neurite root segment
            if max_distance < abs(p0[axis] - p1[axis]):
                bad_ids.append((sec.id, [p0, p1]))
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 3
0
def partition_asymmetries(neurites, neurite_type=NeuriteType.all, variant='branch-order'):
    """Partition asymmetry at bifurcation points of a collection of neurites.

    Variant: length is a different definition, as the absolute difference in
    downstream path lenghts, relative to the total neurite path length
    """
    if variant not in {'branch-order', 'length'}:
        raise ValueError('Please provide a valid variant for partition asymmetry,\
                         found %s' % variant)

    if variant == 'branch-order':
        return map(bifurcationfunc.partition_asymmetry,
                   iter_sections(neurites,
                                 iterator_type=Section.ibifurcation_point,
                                 neurite_filter=is_type(neurite_type)))

    asymmetries = list()
    for neurite in iter_neurites(neurites, filt=is_type(neurite_type)):
        neurite_length = total_length_per_neurite(neurite)[0]
        for section in iter_sections(neurite,
                                     iterator_type=Section.ibifurcation_point,
                                     neurite_filter=is_type(neurite_type)):
            pathlength_diff = abs(sectionfunc.downstream_pathlength(section.children[0]) -
                                  sectionfunc.downstream_pathlength(section.children[1]))
            asymmetries.append(pathlength_diff / neurite_length)
    return asymmetries
Ejemplo n.º 4
0
def plot_neuron3d(ax,
                  nrn,
                  neurite_type=NeuriteType.all,
                  diameter_scale=_DIAMETER_SCALE,
                  linewidth=_LINEWIDTH,
                  color=None,
                  alpha=_ALPHA):
    """Generates a figure of the neuron, that contains a soma and a list of trees.

    Args:
        ax(matplotlib axes): on what to plot
        nrn(neuron): neuron to be plotted
        neurite_type(NeuriteType): an optional filter on the neurite type
        diameter_scale(float): Scale factor multiplied with segment diameters before plotting
        linewidth(float): all segments are plotted with this width, but only if diameter_scale=None
        color(str or None): Color of plotted values, None corresponds to default choice
        alpha(float): Transparency of plotted values
    """
    plot_soma3d(ax, nrn.soma, color=color, alpha=alpha)

    for neurite in iter_neurites(nrn, filt=tree_type_checker(neurite_type)):
        plot_tree3d(ax,
                    neurite,
                    diameter_scale=diameter_scale,
                    linewidth=linewidth,
                    color=color,
                    alpha=alpha)

    ax.set_title(nrn.name)
Ejemplo n.º 5
0
def test_iter_neurites_filter_mapping():
    n = [
        n for n in iter_neurites(POP,
                                 mapfun=lambda n: len(n.points),
                                 filt=lambda n: len(n.points) > 250)
    ]

    ref = [500, 500, 500]
    assert n == ref
Ejemplo n.º 6
0
def principal_direction_extents(neurites, neurite_type=NeuriteType.all, direction=0):
    """Principal direction extent of neurites in neurons."""
    def _pde(neurite):
        """Get the PDE of a single neurite."""
        # Get the X, Y,Z coordinates of the points in each section
        points = neurite.points[:, :3]
        return morphmath.principal_direction_extent(points)[direction]

    return [_pde(neurite) for neurite in iter_neurites(neurites, filt=is_type(neurite_type))]
Ejemplo n.º 7
0
def has_no_root_node_jumps(neuron, radius_multiplier=2):
    """Check that the neurites have no root node jumps.

    Their first point not should not be further than `radius_multiplier * soma radius` from the
    soma center
    """
    bad_ids = []
    for neurite in iter_neurites(neuron):
        p0 = neurite.root_node.points[0, COLS.XYZ]
        distance = np.linalg.norm(p0 - neuron.soma.center)
        if distance > radius_multiplier * neuron.soma.radius:
            bad_ids.append((neurite.root_node.id, [p0]))
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 8
0
def segment_radial_distances(neurites, neurite_type=NeuriteType.all, origin=None):
    """Returns the list of distances between all segment mid points and origin."""
    def _radial_distances(sec, pos):
        """List of distances between the mid point of each segment and pos."""
        mid_pts = 0.5 * (sec.points[:-1, COLS.XYZ] + sec.points[1:, COLS.XYZ])
        return np.linalg.norm(mid_pts - pos[COLS.XYZ], axis=1)

    dist = []
    for n in iter_neurites(neurites, filt=is_type(neurite_type)):
        pos = n.root_node.points[0] if origin is None else origin
        dist.extend([s for ss in n.iter_sections() for s in _radial_distances(ss, pos)])

    return dist
Ejemplo n.º 9
0
def section_radial_distances(neurites, neurite_type=NeuriteType.all, origin=None,
                             iterator_type=Section.ipreorder):
    """Section radial distances in a collection of neurites.

    The iterator_type can be used to select only terminal sections (ileaf)
    or only bifurcations (ibifurcation_point).
    """
    dist = []
    for n in iter_neurites(neurites, filt=is_type(neurite_type)):
        pos = n.root_node.points[0] if origin is None else origin
        dist.extend(sectionfunc.section_radial_distance(s, pos)
                    for s in iter_sections(n,
                                           iterator_type=iterator_type))
    return dist
Ejemplo n.º 10
0
def plot_neuron(ax,
                nrn,
                neurite_type=NeuriteType.all,
                plane='xy',
                soma_outline=True,
                diameter_scale=_DIAMETER_SCALE,
                linewidth=_LINEWIDTH,
                color=None,
                alpha=_ALPHA,
                realistic_diameters=False):
    """Plots a 2D figure of the neuron, that contains a soma and the neurites.

    Args:
        ax(matplotlib axes): on what to plot
        neurite_type(NeuriteType|tuple): an optional filter on the neurite type
        nrn(neuron): neuron to be plotted
        soma_outline(bool): should the soma be drawn as an outline
        plane(str): Any pair of 'xyz'
        diameter_scale(float): Scale factor multiplied with segment diameters before plotting
        linewidth(float): all segments are plotted with this width, but only if diameter_scale=None
        color(str or None): Color of plotted values, None corresponds to default choice
        alpha(float): Transparency of plotted values
        realistic_diameters(bool): scale linewidths with axis data coordinates
    """
    plot_soma(ax,
              nrn.soma,
              plane=plane,
              soma_outline=soma_outline,
              linewidth=linewidth,
              color=color,
              alpha=alpha)

    for neurite in iter_neurites(nrn, filt=tree_type_checker(neurite_type)):
        plot_tree(ax,
                  neurite,
                  plane=plane,
                  diameter_scale=diameter_scale,
                  linewidth=linewidth,
                  color=color,
                  alpha=alpha,
                  realistic_diameters=realistic_diameters)

    ax.set_title(nrn.name)
    ax.set_xlabel(plane[0])
    ax.set_ylabel(plane[1])
Ejemplo n.º 11
0
def sholl_crossings(neurites, center, radii, neurite_filter=None):
    """Calculate crossings of neurites.

    This function can also be used with a list aa neurites, as follow:

        secs = (sec for sec in nm.iter_sections(neuron) if complex_filter(sec))
        sholl = nm.features.neuronfunc.sholl_crossings(secs,
                                                       center=neuron.soma.center,
                                                       radii=np.arange(0, 1000, 100))

    Args:
        neurites(list): morphology on which to perform Sholl analysis, or list of neurites
        center(Point): center point
        radii(iterable of floats): radii for which crossings will be counted

    Returns:
        Array of same length as radii, with a count of the number of crossings
        for the respective radius
    """
    def _count_crossings(neurite, radius):
        """Used to count_crossings of segments in neurite with radius."""
        r2 = radius**2
        count = 0
        for start, end in iter_segments(neurite):
            start_dist2, end_dist2 = (morphmath.point_dist2(center, start),
                                      morphmath.point_dist2(center, end))

            count += int(start_dist2 <= r2 <= end_dist2
                         or end_dist2 <= r2 <= start_dist2)

        return count

    return np.array([
        sum(
            _count_crossings(neurite, r)
            for neurite in iter_neurites(neurites, filt=neurite_filter))
        for r in radii
    ])
Ejemplo n.º 12
0
def neurite_volume_density(neurites, neurite_type=NeuriteType.all):
    """Get the volume density per neurite.

    The volume density is defined as the ratio of the neurite volume and
    the volume of the neurite's enclosing convex hull

    TODO: the convex hull fails on some morphologies, it may be good to instead use
        bounding_box to compute the neurite enclosing volume

    .. note:: Returns `np.nan` if the convex hull computation fails.
    """
    def vol_density(neurite):
        """Volume density of a single neurite."""
        try:
            volume = convex_hull(neurite).volume
        except scipy.spatial.qhull.QhullError:
            L.exception('Failure to compute neurite volume using the convex hull. '
                        'Feature `neurite_volume_density` will return `np.nan`.\n')
            return np.nan

        return neurite.volume / volume

    return list(vol_density(n)
                for n in iter_neurites(neurites, filt=is_type(neurite_type)))
Ejemplo n.º 13
0
def total_area_per_neurite(neurites, neurite_type=NeuriteType.all):
    """Surface area in a collection of neurites.

    The area is defined as the sum of the area of the sections.
    """
    return [neurite.area for neurite in iter_neurites(neurites, filt=is_type(neurite_type))]
Ejemplo n.º 14
0
def total_volume_per_neurite(neurites, neurite_type=NeuriteType.all):
    """Get the volume per neurite in a collection."""
    return list(sum(s.volume for s in n.iter_sections())
                for n in iter_neurites(neurites, filt=is_type(neurite_type)))
Ejemplo n.º 15
0
def total_length_per_neurite(neurites, neurite_type=NeuriteType.all):
    """Get the path length per neurite in a collection."""
    return list(sum(s.length for s in n.iter_sections())
                for n in iter_neurites(neurites, filt=is_type(neurite_type)))
Ejemplo n.º 16
0
def terminal_path_lengths_per_neurite(neurites, neurite_type=NeuriteType.all):
    """Get the path lengths to each terminal point per neurite in a collection."""
    return list(sectionfunc.section_path_length(s)
                for n in iter_neurites(neurites, filt=is_type(neurite_type))
                for s in iter_sections(n, iterator_type=Section.ileaf))
Ejemplo n.º 17
0
def number_of_sections_per_neurite(neurites, neurite_type=NeuriteType.all):
    """Get the number of sections per neurite in a collection of neurites."""
    return list(sum(1 for _ in n.iter_sections())
                for n in iter_neurites(neurites, filt=is_type(neurite_type)))
Ejemplo n.º 18
0
def test_iter_neurites_filter():

    for ntyp in nm.NEURITE_TYPES:
        a = [n for n in POP.neurites if n.type == ntyp]
        b = [n for n in iter_neurites(POP, filt=lambda n: n.type == ntyp)]
        assert a == b
Ejemplo n.º 19
0
def test_iter_neurites_mapping():

    n = [n for n in iter_neurites(POP, mapfun=lambda n: len(n.points))]
    ref = [211, 211, 211, 211, 211, 211, 211, 211, 211, 500, 500, 500]
    assert n == ref
Ejemplo n.º 20
0
def n_neurites(neurites, neurite_type=NeuriteType.all):
    """Number of neurites in a collection of neurites."""
    return sum(1 for _ in iter_neurites(neurites, filt=is_type(neurite_type)))
Ejemplo n.º 21
0
def test_iter_neurites_nrn_order():
    actual = list(
        iter_neurites(REVERSED_NEURITES, neurite_order=NeuriteIter.NRN))
    expected = list(reversed(list(iter_neurites(REVERSED_NEURITES))))
    assert actual == expected
Ejemplo n.º 22
0
 def _fun(neurites, neurite_type=NeuriteType.all):
     """Wrap neurite function from outer scope and map into list."""
     return list(
         func(n)
         for n in iter_neurites(neurites,
                                filt=tree_type_checker(neurite_type)))
Ejemplo n.º 23
0
def test_iter_neurites_default():
    assert list(POP.neurites) == [n for n in iter_neurites(POP)]