def get_common_bounding_box(neurons): '''Returns the bounding box that wraps all neurons''' common_bbox = geom.bounding_box(neurons[0]) for neuron in neurons[1:]: bbox = geom.bounding_box(neuron) common_bbox[0] = np.min(np.vstack([common_bbox[0], bbox[0]]), axis=0) common_bbox[1] = np.max(np.vstack([common_bbox[1], bbox[1]]), axis=0) return common_bbox
def sholl_frequency(nrn, neurite_type=NeuriteType.all, bins=10): """Perform Sholl frequency calculations on a population of neurites. Args: nrn(morph): nrn or population neurite_type(NeuriteType): which neurites to operate on bins(iterable of floats|int): binning to use for the Sholl radii. If ``int`` is used then \ it sets the number of bins in the interval between min and max radii of ``nrn``. Note: Given a neuron, the soma center is used for the concentric circles, which range from the soma radii, and the maximum radial distance in steps of `step_size`. When a population is given, the concentric circles range from the smallest soma radius to the largest radial neurite distance. Finally, each segment of the neuron is tested, so a neurite that bends back on itself, and crosses the same Sholl radius will get counted as having crossed multiple times. """ nrns = neuron_population(nrn) if isinstance(bins, int): min_soma_edge = min(neuron.soma.radius for neuron in nrns) max_radii = np.max([np.abs(bounding_box(neuron)) for neuron in nrns]) bins = np.linspace(min_soma_edge, max_radii, bins) return sum( sholl_crossings(neuron, neuron.soma.center, bins, is_type( neurite_type)) for neuron in nrns)
def plot(neuron, result, inline=False): '''Plot the neuron, the cut plane and the cut leaves. Args: neuron (Neuron): the neuron to be plotted result (dict): the cut plane object in dictionary form inline (bool): if True, plot as an interactive plot (for example in a Jupyter notebook) ''' try: from plotly_helper.neuron_viewer import NeuronBuilder from plotly_helper.object_creator import scatter from plotly_helper.shapes import line except ImportError as e: raise ImportError( 'neuror[plotly] is not installed.' ' Please install it by doing: pip install neuror[plotly]') from e bbox = geom.bounding_box(neuron) plane = result['cut-plane'] for display_plane, idx in [('xz', 0), ('yz', 1), ('3d', None)]: builder = NeuronBuilder(neuron, display_plane, inline=inline, line_width=4, title='{}'.format(neuron.name)) if idx is not None: if plane['a'] == 0 and plane['b'] == 0: builder.helper.add_shapes([ line(bbox[0][idx], -plane['d'], bbox[1][idx], -plane['d'], width=4) ]) builder.helper.add_data({'a': scatter(result['cut-leaves'][:, [idx, 2]], showlegend=False, width=5)}) else: builder.helper.add_data({'a': scatter(result['cut-leaves'], width=2)}) builder.plot()
def neuron3d(nrn, new_fig=True, new_axes=True, subplot=False, **kwargs): ''' Generates a figure of the neuron, that contains a soma and a list of trees. Parameters: neuron: Neuron \ neurom.Neuron object diameter: boolean If True the diameter, scaled with diameter_scale factor, \ will define the width of the tree lines. \ If False use linewidth to select the width of the tree lines. \ Default value is True. diameter_scale: float \ Defines the scale factor that will be multiplied \ with the diameter to define the width of the tree line. \ Default value is 1. ''' # Initialization of matplotlib figure and axes. fig, ax = common.get_figure(new_fig=new_fig, new_axes=new_axes, subplot=subplot, params={'projection': '3d'}) white_space = get_default('white_space', **kwargs) kwargs['new_fig'] = False kwargs['subplot'] = subplot kwargs['new_axes'] = False kwargs['title'] = kwargs.get('title', nrn.name) kwargs['final'] = False soma3d(nrn.soma, **kwargs) boundaries = [[], [], []] for temp_tree in nrn.neurites: bounding_box = geom.bounding_box(temp_tree) boundaries[0].append([bounding_box[0][getattr(COLS, 'X')], bounding_box[1][getattr(COLS, 'X')]]) boundaries[1].append([bounding_box[0][getattr(COLS, 'Y')], bounding_box[1][getattr(COLS, 'Y')]]) boundaries[2].append([bounding_box[0][getattr(COLS, 'Z')], bounding_box[1][getattr(COLS, 'Z')]]) tree3d(temp_tree, **kwargs) if len(boundaries[0]) > 0: kwargs['xlim'] = kwargs.get('xlim', [np.min(boundaries[0]) - white_space, np.max(boundaries[0]) + white_space]) if len(boundaries[1]) > 0: kwargs['ylim'] = kwargs.get('ylim', [np.min(boundaries[1]) - white_space, np.max(boundaries[1]) + white_space]) if len(boundaries[2]) > 0: kwargs['zlim'] = kwargs.get('zlim', [np.min(boundaries[2]) - white_space, np.max(boundaries[2]) + white_space]) return common.plot_style(fig=fig, ax=ax, **kwargs)
def bounding_box(neurite): '''Get a neurite's X,Y,Z bounding box''' if is_new_style(neurite): if isinstance(neurite, Section): neurite = Neurite(neurite) return geom.bounding_box(neurite) else: return get_bounding_box(neurite)
def _update_3d_datalim(ax, obj): '''unlike w/ 2d Axes, the dataLim isn't set by collections, so it has to be updated manually''' min_bounding_box, max_bounding_box = geom.bounding_box(obj) xy_bounds = np.vstack((min_bounding_box[:COLS.Z], max_bounding_box[:COLS.Z])) ax.xy_dataLim.update_from_data_xy(xy_bounds, ignore=False) z_bounds = np.vstack(((min_bounding_box[COLS.Z], min_bounding_box[COLS.Z]), (max_bounding_box[COLS.Z], max_bounding_box[COLS.Z]))) ax.zz_dataLim.update_from_data_xy(z_bounds, ignore=False)
def test_bounding_box(): pts = np.array([[-1, -2, -3, -999], [1, 2, 3, 1000], [-100, 5, 33, 42], [42, 55, 12, -3]]) obj = PointObj() obj.points = pts nt.assert_true( np.alltrue(geom.bounding_box(obj) == [[-100, -2, -3], [42, 55, 33]]))
def plot_soma(ax, soma, plane='xy', soma_outline=True, linewidth=_LINEWIDTH, color=None, alpha=_ALPHA): '''Generates a 2d figure of the soma. Args: ax(matplotlib axes): on what to plot soma(neurom.core.Soma): plotted soma 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 ''' plane0, plane1 = _plane2col(plane) color = _get_color(color, tree_type=NeuriteType.soma) if isinstance(soma, SomaCylinders): plane0, plane1 = _plane2col(plane) for start, end in zip(soma.points, soma.points[1:]): common.project_cylinder_onto_2d(ax, (plane0, plane1), start=start[COLS.XYZ], end=end[COLS.XYZ], start_radius=start[COLS.R], end_radius=end[COLS.R], color=color, alpha=alpha) else: if soma_outline: ax.add_artist( Circle(soma.center[[plane0, plane1]], soma.radius, color=color, alpha=alpha)) else: plane0, plane1 = _plane2col(plane) points = [(p[plane0], p[plane1]) for p in soma.iter()] if points: points.append(points[0]) # close the loop ax.plot(points, color=color, alpha=alpha, linewidth=linewidth) ax.set_xlabel(plane[0]) ax.set_ylabel(plane[1]) bounding_box = geom.bounding_box(soma) ax.dataLim.update_from_data_xy(np.vstack( ([bounding_box[0][plane0], bounding_box[0][plane1]], [bounding_box[1][plane0], bounding_box[1][plane1]])), ignore=False)
def test_bounding_box(): pts = np.array([[-1, -2, -3, -999], [1, 2, 3, 1000], [-100, 5, 33, 42], [42, 55, 12, -3]]) obj = PointObj() obj.points = pts nt.assert_true(np.alltrue(geom.bounding_box(obj) == [[-100, -2, -3], [42, 55, 33]]))
def plot_soma(ax, soma, plane='xy', soma_outline=True, linewidth=_LINEWIDTH, color=None, alpha=_ALPHA): '''Generates a 2d figure of the soma. Args: ax(matplotlib axes): on what to plot soma(neurom.core.Soma): plotted soma 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 ''' plane0, plane1 = _plane2col(plane) color = _get_color(color, tree_type=NeuriteType.soma) if isinstance(soma, SomaCylinders): plane0, plane1 = _plane2col(plane) for start, end in zip(soma.points, soma.points[1:]): common.project_cylinder_onto_2d(ax, (plane0, plane1), start=start[COLS.XYZ], end=end[COLS.XYZ], start_radius=start[COLS.R], end_radius=end[COLS.R], color=color, alpha=alpha) else: if soma_outline: ax.add_artist(Circle(soma.center[[plane0, plane1]], soma.radius, color=color, alpha=alpha)) else: plane0, plane1 = _plane2col(plane) points = [(p[plane0], p[plane1]) for p in soma.iter()] if points: points.append(points[0]) # close the loop ax.plot(points, color=color, alpha=alpha, linewidth=linewidth) ax.set_xlabel(plane[0]) ax.set_ylabel(plane[1]) bounding_box = geom.bounding_box(soma) ax.dataLim.update_from_data_xy(np.vstack(([bounding_box[0][plane0], bounding_box[0][plane1]], [bounding_box[1][plane0], bounding_box[1][plane1]])), ignore=False)
def sholl_frequency(nrn, neurite_type=NeuriteType.all, step_size=10): """Perform Sholl frequency calculations on a population of neurites. Args: nrn(morph): nrn or population neurite_type(NeuriteType): which neurites to operate on step_size(float): step size between Sholl radii Note: Given a neuron, the soma center is used for the concentric circles, which range from the soma radii, and the maximum radial distance in steps of `step_size`. When a population is given, the concentric circles range from the smallest soma radius to the largest radial neurite distance. Finally, each segment of the neuron is tested, so a neurite that bends back on itself, and crosses the same Sholl radius will get counted as having crossed multiple times. """ nrns = neuron_population(nrn) neurite_filter = is_type(neurite_type) min_soma_edge = float('Inf') max_radii = 0 neurites_list = [] for neuron in nrns: neurites_list.extend(((neurites, neuron.soma.center) for neurites in neuron.neurites if neurite_filter(neurites))) min_soma_edge = min(min_soma_edge, neuron.soma.radius) max_radii = max(max_radii, np.max(np.abs(bounding_box(neuron)))) radii = np.arange(min_soma_edge, max_radii + step_size, step_size) ret = np.zeros_like(radii) for neurites, center in neurites_list: ret += sholl_crossings(neurites, center, radii) return ret
def test_bounding_box_neurite(): nrt = NRN.neurites[0] ref = np.array([[-33.25305769, -57.600172, 0.], [0., 0., 49.70137991]]) nt.assert_true(np.allclose(geom.bounding_box(nrt), ref))
def test_bounding_box_neuron(): ref = np.array([[-40.32853516, -57.600172 , 0.], [ 64.74726272, 48.51626225, 54.20408797]]) nt.assert_true(np.allclose(geom.bounding_box(NRN), ref))
def test_bounding_box_soma(): ref = np.array([[0., 0., 0.], [0.1, 0.2, 0.]]) nt.assert_true(np.allclose(geom.bounding_box(NRN.soma), ref))
def tree(tr, plane='xy', new_fig=True, subplot=False, **kwargs): ''' Generates a 2d figure of the tree's segments. \ If the tree contains one single point the plot will be empty \ since no segments can be constructed. Parameters: tr: Tree \ neurom.Tree object plane: str \ Accepted values: Any pair of of xyz \ Default value is 'xy'.treecolor diameter: boolean If True the diameter, scaled with diameter_scale factor, \ will define the width of the tree lines. \ If False use linewidth to select the width of the tree lines. \ Default value is True. diameter_scale: float \ Defines the scale factor that will be multiplied \ with the diameter to define the width of the tree line. \ Default value is 1. white_space: float \ Defines the white space around \ the boundary box of the morphology. \ Default value is 1. ''' if plane not in ('xy', 'yx', 'xz', 'zx', 'yz', 'zy'): return None, 'No such plane found! Please select one of: xy, xz, yx, yz, zx, zy.' # Initialization of matplotlib figure and axes. fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot) # Data needed for the viewer: x,y,z,r bounding_box = geom.bounding_box(tr) white_space = get_default('white_space', **kwargs) def _seg_2d(seg): '''2d coordinates needed for the plotting of a segment''' horz = getattr(COLS, plane[0].capitalize()) vert = getattr(COLS, plane[1].capitalize()) parent_point = seg[0] child_point = seg[1] horz1 = parent_point[horz] horz2 = child_point[horz] vert1 = parent_point[vert] vert2 = child_point[vert] return ((horz1, vert1), (horz2, vert2)) segs = map_segments(tr, _seg_2d) linewidth = get_default('linewidth', **kwargs) # Definition of the linewidth according to diameter, if diameter is True. if get_default('diameter', **kwargs): scale = get_default('diameter_scale', **kwargs) # TODO: This was originally a numpy array. Did it have to be one? linewidth = [2 * r * scale for r in map_segments(tr, segment_radius)] if len(linewidth) == 0: linewidth = get_default('linewidth', **kwargs) # Plot the collection of lines. collection = LineCollection(segs, color=common.get_color(get_default('treecolor', **kwargs), tr.type), linewidth=linewidth, alpha=get_default('alpha', **kwargs)) ax.add_collection(collection) kwargs['title'] = kwargs.get('title', 'Tree view') kwargs['xlabel'] = kwargs.get('xlabel', plane[0]) kwargs['ylabel'] = kwargs.get('ylabel', plane[1]) kwargs['xlim'] = kwargs.get('xlim', [bounding_box[0][getattr(COLS, plane[0].capitalize())] - white_space, bounding_box[1][getattr(COLS, plane[0].capitalize())] + white_space]) kwargs['ylim'] = kwargs.get('ylim', [bounding_box[0][getattr(COLS, plane[1].capitalize())] - white_space, bounding_box[1][getattr(COLS, plane[1].capitalize())] + white_space]) return common.plot_style(fig=fig, ax=ax, **kwargs)
def test_bounding_box_neuron(): ref = np.array([[-40.32853516, -57.600172, 0.], [64.74726272, 48.51626225, 54.20408797]]) assert np.allclose(geom.bounding_box(NRN), ref)
print( 'Number of bifurcation points:', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point))) # Number of bifurcation points for apical dendrites print( 'Number of bifurcation points (apical dendrites):', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point, neurite_filter=tree_type_checker( nm.APICAL_DENDRITE)))) # Maximum branch order print('Maximum branch order:', max(sectionfunc.branch_order(s) for s in nm.iter_sections(nrn))) # Neuron's bounding box # Note: does not account for soma radius print('Bounding box ((min x, y, z), (max x, y, z))', geom.bounding_box(nrn)) #with open(os.curdir + '/exp14_17 Pos_R1_7 M-exported-000.swc', 'r') as f, open(os.curdir + '/new_scw.scw', 'w') as ff: # lines = f.readlines() # # for i, line in enumerate(lines): # row = line.split(' ') # # if i > 5: # row[-2] = '1.0' # # ff.write(' '.join(row))
def test_bounding_box_neurite(): nrt = SIMPLE.neurites[0] ref = np.array([[-5., 0., 0.], [ 6., 5., 0.]]) np.testing.assert_allclose(geom.bounding_box(nrt), ref)
def set_neuron(filename): '''Globally loads the neuron''' global NEURON, FIGURE, BBOX # pylint: disable=global-statement NEURON = load_neuron(filename) FIGURE = NeuronBuilder(NEURON, '3d').get_figure() BBOX = bounding_box(NEURON)
np.std(seg_taper_rate), ', min=', np.min(seg_taper_rate), ', max=', np.max(seg_taper_rate), sep='') # Number of bifurcation points. print( 'Number of bifurcation points:', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point))) # Number of bifurcation points for apical dendrites print( 'Number of bifurcation points (apical dendrites):', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point, neurite_filter=tree_type_checker( nm.APICAL_DENDRITE)))) # Maximum branch order print('Maximum branch order:', max(sectionfunc.branch_order(s) for s in nm.iter_sections(nrn))) # Neuron's bounding box # Note: does not account for soma radius print('Bounding box ((min x, y, z), (max x, y, z))', geom.bounding_box(nrn))
def test_bounding_box_soma(): ref = np.array([[0., 0., 0.], [0.1, 0.2, 0.]]) assert np.allclose(geom.bounding_box(NRN.soma), ref)
def neuron(nrn, plane='xy', new_fig=True, subplot=False, **kwargs): ''' Generates a 2d figure of the neuron, \ that contains a soma and a list of trees. Parameters: neuron: Neuron \ neurom.Neuron object plane: str \ Accepted values: Any pair of of xyz \ Default value is 'xy'.treecolor diameter: boolean If True the diameter, scaled with diameter_scale factor, \ will define the width of the tree lines. \ If False use linewidth to select the width of the tree lines. \ Default value is True. diameter_scale: float \ Defines the scale factor that will be multiplied \ with the diameter to define the width of the tree line. \ Default value is 1. ''' if plane not in ('xy', 'yx', 'xz', 'zx', 'yz', 'zy'): return None, 'No such plane found! Please select one of: xy, xz, yx, yz, zx, zy.' # Initialization of matplotlib figure and axes. fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot) kwargs['new_fig'] = False kwargs['subplot'] = subplot kwargs['final'] = False white_space = get_default('white_space', **kwargs) soma(nrn.soma, plane=plane, **kwargs) kwargs['title'] = kwargs.get('title', nrn.name) kwargs['xlabel'] = kwargs.get('xlabel', plane[0]) kwargs['ylabel'] = kwargs.get('ylabel', plane[1]) h = [] v = [] for temp_tree in nrn.neurites: bounding_box = geom.bounding_box(temp_tree) h.append([bounding_box[0][getattr(COLS, plane[0].capitalize())], bounding_box[1][getattr(COLS, plane[0].capitalize())]]) v.append([bounding_box[0][getattr(COLS, plane[1].capitalize())], bounding_box[1][getattr(COLS, plane[1].capitalize())]]) tree(temp_tree, plane=plane, **kwargs) if h: kwargs['xlim'] = kwargs.get('xlim', [np.min(h) - white_space, np.max(h) + white_space]) if v: kwargs['ylim'] = kwargs.get('ylim', [np.min(v) - white_space, np.max(v) + white_space]) return common.plot_style(fig=fig, ax=ax, **kwargs)
def tree3d(tr, new_fig=True, new_axes=True, subplot=False, **kwargs): ''' 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. Parameters: tr: Tree \ neurom.Tree object diameter: boolean \ If True the diameter, scaled with diameter_scale factor, \ will define the width of the tree lines. \ If False use linewidth to select the width of the tree lines. \ Default value is True. diameter_scale: float \ Defines the scale factor that will be multiplied \ with the diameter to define the width of the tree line. \ Default value is 1. white_space: float \ Defines the white space around \ the boundary box of the morphology. \ Default value is 1. ''' from mpl_toolkits.mplot3d.art3d import Line3DCollection # Initialization of matplotlib figure and axes. fig, ax = common.get_figure(new_fig=new_fig, new_axes=new_axes, subplot=subplot, params={'projection': '3d'}) # Data needed for the viewer: x,y,z,r bounding_box = geom.bounding_box(tr) def _seg_3d(seg): '''2d coordinates needed for the plotting of a segment''' horz = getattr(COLS, 'X') vert = getattr(COLS, 'Y') depth = getattr(COLS, 'Z') parent_point = seg[0] child_point = seg[1] horz1 = parent_point[horz] horz2 = child_point[horz] vert1 = parent_point[vert] vert2 = child_point[vert] depth1 = parent_point[depth] depth2 = child_point[depth] return ((horz1, vert1, depth1), (horz2, vert2, depth2)) segs = map_segments(tr, _seg_3d) linewidth = get_default('linewidth', **kwargs) # Definition of the linewidth according to diameter, if diameter is True. if get_default('diameter', **kwargs): # TODO: This was originally a numpy array. Did it have to be one? scale = get_default('diameter_scale', **kwargs) linewidth = [2 * r * scale for r in map_segments(tr, segment_radius)] if len(linewidth) == 0: linewidth = get_default('linewidth', **kwargs) # Plot the collection of lines. collection = Line3DCollection(segs, color=common.get_color(get_default('treecolor', **kwargs), tr.type), linewidth=linewidth, alpha=get_default('alpha', **kwargs)) ax.add_collection3d(collection) kwargs['title'] = kwargs.get('title', 'Tree 3d-view') kwargs['xlabel'] = kwargs.get('xlabel', 'X') kwargs['ylabel'] = kwargs.get('ylabel', 'Y') kwargs['zlabel'] = kwargs.get('zlabel', 'Z') kwargs['xlim'] = kwargs.get('xlim', [bounding_box[0][0] - get_default('white_space', **kwargs), bounding_box[1][0] + get_default('white_space', **kwargs)]) kwargs['ylim'] = kwargs.get('ylim', [bounding_box[0][1] - get_default('white_space', **kwargs), bounding_box[1][1] + get_default('white_space', **kwargs)]) kwargs['zlim'] = kwargs.get('zlim', [bounding_box[0][2] - get_default('white_space', **kwargs), bounding_box[1][2] + get_default('white_space', **kwargs)]) return common.plot_style(fig=fig, ax=ax, **kwargs)
for ttype in NEURITES: ttt = ttype seg_taper_rate = [mm.segment_taper_rate(s) for s in nm.iter_segments(nrn, neurite_filter=tree_type_checker(ttt))] print('Segment taper rate (', ttype, '):\n mean=', np.mean(seg_taper_rate), ', std=', np.std(seg_taper_rate), ', min=', np.min(seg_taper_rate), ', max=', np.max(seg_taper_rate), sep='') # Number of bifurcation points. print('Number of bifurcation points:', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point))) # Number of bifurcation points for apical dendrites print('Number of bifurcation points (apical dendrites):', sum(1 for _ in nm.iter_sections(nrn, iterator_type=Tree.ibifurcation_point, neurite_filter=tree_type_checker(nm.APICAL_DENDRITE)))) # Maximum branch order print('Maximum branch order:', max(sectionfunc.branch_order(s) for s in nm.iter_sections(nrn))) # Neuron's bounding box # Note: does not account for soma radius print('Bounding box ((min x, y, z), (max x, y, z))', geom.bounding_box(nrn))