Ejemplo n.º 1
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.º 2
0
def has_no_single_children(neuron):
    """Check if the neuron has sections with only one child section."""
    bad_ids = [
        section.id for section in iter_sections(neuron)
        if len(section.children) == 1
    ]
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 3
0
def has_no_narrow_neurite_section(neuron,
                                  neurite_filter,
                                  radius_threshold=0.05,
                                  considered_section_min_length=50):
    """Check if the neuron has dendrites with narrow sections.

    Arguments:
        neuron(Neuron): The neuron object to test
        neurite_filter(callable): filter the neurites by this callable
        radius_threshold(float): radii below this are considered narro
        considered_section_min_length(float): sections with length below
        this are not taken into account

    Returns:
        CheckResult with result. result.info contains the narrow section ids and their
        first point
    """
    considered_sections = (
        sec for sec in iter_sections(neuron, neurite_filter=neurite_filter)
        if sec.length > considered_section_min_length)

    def narrow_section(section):
        """Select narrow sections."""
        return section.points[:, COLS.R].mean() < radius_threshold

    bad_ids = [(section.id, section.points[np.newaxis, 1])
               for section in considered_sections if narrow_section(section)]
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 4
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.º 5
0
def test_iter_section_nrn():
    ref = list(iter_sections(SIMPLE))
    assert len(ref) == 6

    ref = list(
        iter_sections(SIMPLE, neurite_filter=lambda n: n.type == nm.AXON))
    assert len(ref) == 3

    ref = list(
        iter_sections(SIMPLE,
                      neurite_filter=lambda n: n.type == nm.BASAL_DENDRITE))
    assert len(ref) == 3

    ref = list(
        iter_sections(SIMPLE,
                      neurite_filter=lambda n: n.type == nm.APICAL_DENDRITE))
    assert len(ref) == 0
Ejemplo n.º 6
0
def map_segments(func, neurites, neurite_type):
    """Map `func` to all the segments in a collection of neurites.

    `func` accepts a section and returns list of values corresponding to each segment.
    """
    neurite_filter = is_type(neurite_type)
    return [
        s for ss in iter_sections(neurites, neurite_filter=neurite_filter) for s in func(ss)
    ]
Ejemplo n.º 7
0
def partition_pairs(neurites, neurite_type=NeuriteType.all):
    """Partition pairs at bifurcation points of a collection of neurites.

    Partition pair is defined as the number of bifurcations at the two
    daughters of the bifurcating section
    """
    return map(bifurcationfunc.partition_pair,
               iter_sections(neurites,
                             iterator_type=Section.ibifurcation_point,
                             neurite_filter=is_type(neurite_type)))
Ejemplo n.º 8
0
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 iter_sections(POP,
                                   neurite_filter=lambda n: n.type == ntyp)
        ]
        assert a == b
Ejemplo n.º 9
0
def sibling_ratios(neurites, neurite_type=NeuriteType.all, method='first'):
    """Sibling ratios at bifurcation points of a collection of neurites.

    The sibling ratio is the ratio between the diameters of the
    smallest and the largest child. It is a real number between
    0 and 1. Method argument allows one to consider mean diameters
    along the child section instead of diameter of the first point.
    """
    return map(lambda bif_point: bifurcationfunc.sibling_ratio(bif_point, method),
               iter_sections(neurites,
                             iterator_type=Section.ibifurcation_point,
                             neurite_filter=is_type(neurite_type)))
Ejemplo n.º 10
0
def diameter_power_relations(neurites, neurite_type=NeuriteType.all, method='first'):
    """Calculate the diameter power relation at a bifurcation point.

    Diameter power relation is defined in https://www.ncbi.nlm.nih.gov/pubmed/18568015

    This quantity gives an indication of how far the branching is from
    the Rall ratio (when =1).
    """
    return (bifurcationfunc.diameter_power_relation(bif_point, method)
            for bif_point in iter_sections(neurites,
                                           iterator_type=Section.ibifurcation_point,
                                           neurite_filter=is_type(neurite_type)))
Ejemplo n.º 11
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.º 12
0
def segment_path_lengths(neurites, neurite_type=NeuriteType.all):
    """Returns pathlengths between all non-root points and their root point."""
    pathlength = {}
    neurite_filter = is_type(neurite_type)

    def _get_pathlength(section):
        if section.id not in pathlength:
            if section.parent:
                pathlength[section.id] = section.parent.length + _get_pathlength(section.parent)
            else:
                pathlength[section.id] = 0
        return pathlength[section.id]

    result = [_get_pathlength(section) + np.cumsum(sectionfunc.segment_lengths(section))
              for section in iter_sections(neurites, neurite_filter=neurite_filter)]
    return np.hstack(result) if result else np.array([])
Ejemplo n.º 13
0
def section_path_lengths(neurites, neurite_type=NeuriteType.all):
    """Path lengths of a collection of neurites."""
    # Calculates and stores the section lengths in one pass,
    # then queries the lengths in the path length iterations.
    # This avoids repeatedly calculating the lengths of the
    # same sections.
    dist = {}
    neurite_filter = is_type(neurite_type)

    for s in iter_sections(neurites, neurite_filter=neurite_filter):
        dist[s] = s.length

    def pl2(node):
        """Calculate the path length using cached section lengths."""
        return sum(dist[n] for n in node.iupstream())

    return _map_sections(pl2, neurites, neurite_type=neurite_type)
Ejemplo n.º 14
0
def plot_tree3d(ax,
                tree,
                diameter_scale=_DIAMETER_SCALE,
                linewidth=_LINEWIDTH,
                color=None,
                alpha=_ALPHA):
    """Generates a figure of the tree in 3d.

    If the tree contains one single point the plot will be empty \
    since no segments can be constructed.

    Args:
        ax(matplotlib axes): on what to plot
        tree(neurom.core.Section or neurom.core.Neurite): plotted tree
        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
    """
    section_segment_list = [(section, segment)
                            for section in iter_sections(tree)
                            for segment in iter_segments(section)]
    segs = [(seg[0][COLS.XYZ], seg[1][COLS.XYZ])
            for _, seg in section_segment_list]
    colors = [
        _get_color(color, section.type) for section, _ in section_segment_list
    ]

    linewidth = _get_linewidth(tree,
                               diameter_scale=diameter_scale,
                               linewidth=linewidth)

    collection = Line3DCollection(segs,
                                  colors=colors,
                                  linewidth=linewidth,
                                  alpha=alpha)
    ax.add_collection3d(collection)

    _update_3d_datalim(ax, tree)
Ejemplo n.º 15
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.º 16
0
def _map_sections(fun, neurites, neurite_type=NeuriteType.all, iterator_type=Section.ipreorder):
    """Map `fun` to all the sections in a collection of neurites."""
    return map(fun, iter_sections(neurites,
                                  iterator_type=iterator_type,
                                  neurite_filter=is_type(neurite_type)))
Ejemplo n.º 17
0
def test_iter_sections_default():

    ref = [s for n in POP.neurites for s in n.iter_sections()]
    assert (ref == [n for n in iter_sections(POP)])
Ejemplo n.º 18
0
def plot_tree(ax,
              tree,
              plane='xy',
              diameter_scale=_DIAMETER_SCALE,
              linewidth=_LINEWIDTH,
              color=None,
              alpha=_ALPHA,
              realistic_diameters=False):
    """Plots a 2d figure of the tree's segments.

    Args:
        ax(matplotlib axes): on what to plot
        tree(neurom.core.Section or neurom.core.Neurite): plotted tree
        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

    Note:
        If the tree contains one single point the plot will be empty
        since no segments can be constructed.
    """
    plane0, plane1 = _plane2col(plane)

    section_segment_list = [(section, segment)
                            for section in iter_sections(tree)
                            for segment in iter_segments(section)]
    colors = [
        _get_color(color, section.type) for section, _ in section_segment_list
    ]

    if realistic_diameters:

        def _get_rectangle(x, y, linewidth):
            """Draw  a rectangle to represent a secgment."""
            x, y = np.array(x), np.array(y)
            diff = y - x
            angle = np.arctan2(diff[1], diff[0]) % (2 * np.pi)
            return Rectangle(
                x - linewidth /
                2. * np.array([-np.sin(angle), np.cos(angle)]),
                np.linalg.norm(diff), linewidth, np.rad2deg(angle))

        segs = [
            _get_rectangle((seg[0][plane0], seg[0][plane1]),
                           (seg[1][plane0], seg[1][plane1]),
                           2 * segment_radius(seg) * diameter_scale)
            for _, seg in section_segment_list
        ]

        collection = PatchCollection(segs, alpha=alpha, facecolors=colors)

    else:
        segs = [((seg[0][plane0], seg[0][plane1]), (seg[1][plane0],
                                                    seg[1][plane1]))
                for _, seg in section_segment_list]

        linewidth = _get_linewidth(
            tree,
            diameter_scale=diameter_scale,
            linewidth=linewidth,
        )
        collection = LineCollection(segs,
                                    colors=colors,
                                    linewidth=linewidth,
                                    alpha=alpha)

    ax.add_collection(collection)
Ejemplo n.º 19
0
def has_multifurcation(neuron):
    """Check if a section has more than 3 children."""
    bad_ids = [(section.id, section.points[np.newaxis, -1])
               for section in iter_sections(neuron)
               if len(section.children) > 3]
    return CheckResult(len(bad_ids) == 0, bad_ids)
Ejemplo n.º 20
0
def n_segments(neurites, neurite_type=NeuriteType.all):
    """Number of segments in a collection of neurites."""
    return sum(len(s.points) - 1
               for s in iter_sections(neurites, neurite_filter=is_type(neurite_type)))
Ejemplo n.º 21
0
def bifurcation_partitions(neurites, neurite_type=NeuriteType.all):
    """Partition at bifurcation points of a collection of neurites."""
    return map(bifurcationfunc.bifurcation_partition,
               iter_sections(neurites,
                             iterator_type=Section.ibifurcation_point,
                             neurite_filter=is_type(neurite_type)))
Ejemplo n.º 22
0
def n_sections(neurites, neurite_type=NeuriteType.all, iterator_type=Section.ipreorder):
    """Number of sections in a collection of neurites."""
    return sum(1 for _ in iter_sections(neurites,
                                        iterator_type=iterator_type,
                                        neurite_filter=is_type(neurite_type)))
Ejemplo n.º 23
0
def test_iter_sections_default_pop():
    ref = [s.id for n in POP.neurites for s in n.iter_sections()]
    assert ref == [n.id for n in iter_sections(POP)]