Exemplo n.º 1
0
	def render_neuron(self, neuron, neuron_number, neuron_name):
		"""
		This function takes care of rendering a single neuron.

		:param neuron: dictionary with neurons data
		:param neuron_number: number of neuron being rendered
		:param neuron_name: name of the neuron, used to load/save the .vtk files with the rendered neuron.

		"""
		# Prepare variables for rendering
		soma_color, axon_color, dendrites_color, soma_region =  self._render_neuron_get_params(neuron_number, neuron=neuron)
		
		# create soma actor
		neuron_actors = None
		if USE_MORPHOLOGY_CACHE:
			params = dict(
					force_to_hemisphere = self.force_to_hemisphere,
					neurite_radius = self.neurite_radius,
				)
			neuron_actors = self._load_cached_neuron(neuron_name, params)
			if neuron_actors is not None:
				# Color the loaded neuron
				for component, color in zip(['soma', 'dendrites', 'axon'], [soma_color, dendrites_color, axon_color]):
					if component in list(neuron_actors.keys()):
						neuron_actors[component].color(color)
				return neuron_actors, {'soma':soma_region, 'dendrites':None, 'axons':None}

		if not USE_MORPHOLOGY_CACHE or neuron_actors is None:
			print("Parsing neuron: " + neuron_name)
			neuron_actors = {}

			self.soma_coords = get_coords(neuron["soma"], mirror=self.mirror_coord, mirror_ax=self.mirror_ax)
			neuron_actors['soma'] = shapes.Sphere(pos=self.soma_coords, c=soma_color, r=SOMA_RADIUS)

			# Draw dendrites and axons
			if self.render_neurites:
				if self.is_json:
					neuron_actors['dendrites'], dendrites_regions = self.neurites_parser(pd.DataFrame(neuron["dendrite"]), dendrites_color)
					neuron_actors['axon'], axon_regions = self.neurites_parser(pd.DataFrame(neuron["axon"]), axon_color)
				else:
					neuron_actors['dendrites'], dendrites_regions = self.neurites_parser_swc(pd.DataFrame(neuron["dendrite"]), dendrites_color)
					neuron_actors['axon'], axon_regions = self.neurites_parser_swc(pd.DataFrame(neuron["axon"]), axon_color)
			else:
				neuron_actors['dendrites'], dendrites_regions = [], None
				neuron_actors['axon'], axon_regions = [], None

			self.decimate_neuron_actors(neuron_actors)
			self.smooth_neurons(neuron_actors)

			# force to hemisphere
			if self.force_to_hemisphere is not None:
					neuron_actors = self.mirror_neuron(neuron_actors)

			if USE_MORPHOLOGY_CACHE:
				self._cache_neuron(neuron_actors, neuron_name, params)

			return neuron_actors, {'soma':soma_region, 'dendrites':dendrites_regions, 'axon':axon_regions}
Exemplo n.º 2
0
    def parse_neurons_swc_allen(self, morphology, color='blackboard', alpha=1):
        """
		SWC parser for Allen neuron's morphology data, they're a bit different from the Mouse Light SWC

		:param morphology: data with morphology
		:param neuron_number: int, number of the neuron being rendered.

		"""
        # Create soma actor
        radius = 1
        neuron_actors = [
            shapes.Sphere(pos=get_coords(morphology.soma)[::-1],
                          c=color,
                          r=radius * 3)
        ]

        # loop over trees
        for tree in morphology._tree_list:

            tree = pd.DataFrame(tree)
            branching_points = [
                t.id for i, t in tree.iterrows()
                if len(t.children) > 2 and t.id < len(tree)
            ]

            branch_starts = []
            for bp in branching_points:
                branch_starts.extend(tree.iloc[bp].children)

            for bp in branch_starts:
                parent = tree.iloc[tree.iloc[bp].parent]
                branch = [(parent.x, parent.y, parent.z)]
                point = tree.iloc[bp]

                while True:
                    branch.append((point.x, point.y, point.z))

                    if not point.children:
                        break
                    else:
                        try:
                            point = tree.iloc[point.children[0]]
                        except:
                            break

                # Create actor
                neuron_actors.append(
                    shapes.Tube(branch, r=radius, c='red', alpha=1, res=24))

        actor = merge(*neuron_actors)
        actor.color(color)
        actor.alpha(alpha)
        return actor
Exemplo n.º 3
0
	def neurites_parser_swc(self, neurites, color):
		"""
		Parses neuron's  neurites when the data are provided as .swc

		:param neurites: datafarme with neurites samples 
		:param color: color for vtk actor

		"""
		coords = [self.soma_coords]
		coords.extend([get_coords(sample, mirror=self.mirror_coord, mirror_ax=self.mirror_ax) for i, sample in neurites.iterrows()])
		lines = shapes.Spheres(coords, r=38, c=color, res=4)
		regions = []
		return lines, regions
Exemplo n.º 4
0
    def parse_neurons_swc_allen(self, morphology, neuron_number):
        """
		SWC parser for Allen neuron's morphology data, they're a bit different from the Mouse Light SWC

		:param morphology: data with morphology
		:param neuron_number: int, number of the neuron being rendered.

		"""
        # Get params
        neurite_radius = self._get_neurites_radius()
        soma_color, axon_color, dendrites_color, soma_region =  \
         self._render_neuron_get_params(neuron_number, soma=morphology.soma)

        # Create soma actor
        neuron_actors, regions = {
            "soma": None,
            "axon": [],
            "dendrites": []
        }, {
            'soma': soma_region,
            'dendrites': [],
            'axon': []
        }
        neuron_actors['soma'] = Sphere(pos=get_coords(morphology.soma)[::-1],
                                       c=soma_color,
                                       r=SOMA_RADIUS)

        # loop over trees
        if self.render_neurites:
            for tree in morphology._tree_list:
                tree = pd.DataFrame(tree)

                # get node numbers in t
                # get the first non soma node
                first_node_type = tree.loc[
                    tree.type != morphology.SOMA].type.values[0]

                # get the branch type
                if first_node_type == morphology.AXON:
                    neurite = "axon"
                    color = axon_color
                else:
                    neurite = "dendrites"
                    color = dendrites_color

                # Get all the points that make the branch
                branch_points = [[x, y, z] for x, y, z in zip(
                    tree.x.values, tree.y.values, tree.z.values)]

                # Create actor
                neuron_actors[neurite].append(\
                 shapes.Tube(branch_points, r=neurite_radius,
                   c=color, alpha=1, res=NEURON_RESOLUTION))

            # merge actors' meshes to make rendering faster
            for neurite, color in zip(["axon", "dendrites"],
                                      [axon_color, dendrites_color]):
                if neuron_actors[neurite]:
                    neuron_actors[neurite] = merge(*neuron_actors[neurite])
                    neuron_actors[neurite].color(color)

        self.decimate_neuron_actors(neuron_actors)
        self.smooth_neurons(neuron_actors)

        # force to hemisphere
        if self.force_to_hemisphere is not None:
            neuron_actors = self.mirror_neuron(neuron_actors)

        # Check output
        if not neuron_actors["axon"]: neuron_actors["axon"] = None
        if not neuron_actors["dendrites"]: neuron_actors["dendrites"] = None

        return neuron_actors, regions
Exemplo n.º 5
0
    def neurites_parser(self, neurites, color):
        """
		Given a dataframe with all the samples for some neurites, create "Tube" actors that render each neurite segment.	
		----------------------------------------------------------------
		This function works by first identifyingt the branching points of a neurite structure. Then each segment between either two branchin points
		or between a branching point and a terminal is modelled as a Tube. This minimizes the number of actors needed to represent the neurites
		while stil accurately modelling the neuron.
		
		Known issue: the axon initial segment is missing from renderings.

		:param neurites: dataframe with each sample for the neurites
		:param color: color to be assigned to the Tube actor

		
		"""
        neurite_radius = self._get_neurites_radius()

        # get branching points
        try:
            parent_counts = neurites["parentNumber"].value_counts()
        except:
            if len(neurites) == 0:
                print("Couldn't find neurites data")
                return [], []
            else:
                raise ValueError(
                    "Something went wrong while rendering neurites:\n{}".
                    format(neurites))
        branching_points = parent_counts.loc[parent_counts > 1]

        # loop over each branching point
        actors = []
        for idx, bp in branching_points.iteritems():
            # get neurites after the branching point
            bp = neurites.loc[neurites.sampleNumber == idx]
            post_bp = neurites.loc[neurites.parentNumber == idx]

            # loop on each branch after the branching point
            for bi, branch in post_bp.iterrows():
                if bi == 0:
                    branch_points = [
                        self.soma_coords,
                        get_coords(bp,
                                   mirror=self.mirror_coord,
                                   mirror_ax=self.mirror_ax),
                        get_coords(branch,
                                   mirror=self.mirror_coord,
                                   mirror_ax=self.mirror_ax)
                    ]  # this list stores all the samples that  are part of a branch
                else:
                    branch_points = [
                        get_coords(bp,
                                   mirror=self.mirror_coord,
                                   mirror_ax=self.mirror_ax),
                        get_coords(branch,
                                   mirror=self.mirror_coord,
                                   mirror_ax=self.mirror_ax)
                    ]

                # loop over all following points along the branch, until you meet either a terminal or another branching point. store the points
                idx = branch.sampleNumber
                while True:
                    nxt = neurites.loc[neurites.parentNumber == idx]
                    if len(nxt) != 1:
                        break
                    else:
                        branch_points.append(
                            get_coords(nxt,
                                       mirror=self.mirror_coord,
                                       mirror_ax=self.mirror_ax))
                        idx += 1

                # if the branch is too short for a tube, create a sphere instead
                if len(
                        branch_points
                ) < 2:  # plot either a line between two branch_points or  a spheere
                    actors.append(Sphere(branch_points[0], c="g", r=100))
                    continue

                # create tube actor
                actors.append(
                    shapes.Tube(branch_points,
                                r=neurite_radius,
                                c=color,
                                alpha=1,
                                res=NEURON_RESOLUTION))

        # merge actors' meshes to make rendering faster
        merged = merge(*actors)
        if merged is None:
            return None, None
        merged.color(color)

        # get regions the neurites go through
        regions = []
        if "allenId" in neurites.columns:
            for rid in set(neurites.allenId.values):
                try:
                    region = self.alleninfo.loc[self.alleninfo.allenId ==
                                                rid].acronym.values[0]
                    regions.append(
                        self.scene.get_structure_parent(region)['acronym'])
                except:
                    pass

        return merged, regions
Exemplo n.º 6
0
    def _render_neuron_get_params(self,
                                  neuron_number,
                                  neuron=None,
                                  soma_region=None,
                                  soma=None):
        """
		Makes sure that all the parameters to specify how neurons should be rendered. 

		:param neuron_number: number of the neuron being rendered
		:param neuron: neuron's metadata (Default value = None)
		:param soma_region: str with the acronym of the region the soma is in (Default value = None)
		:param soma: list with XYZ coordinates of the neuron's soma. (Default value = None)

		"""
        # Define colors of different components
        if not self.color_by_region:
            if self.random_color:
                if not isinstance(self.random_color, str):
                    color = get_random_colors(n_colors=1)
                else:  # random_color is a colormap
                    color = colorMap(neuron_number,
                                     name=self.random_color,
                                     vmin=0,
                                     vmax=self.n_neurons)
                axon_color = soma_color = dendrites_color = color
            else:
                if self.soma_color is None:
                    soma_color = get_random_colors(n_colors=1)

                if not self.color_neurites:
                    axon_color = dendrites_color = soma_color = self.soma_color
                else:
                    soma_color = self.soma_color
                    if self.axon_color is None:
                        axon_color = soma_color
                    else:
                        axon_color = self.axon_color
                    if self.dendrites_color is None:
                        dendrites_color = soma_color
                    else:
                        dendrites_color = self.dendrites_color

            # check that the colors make sense
            if not check_colors([soma_color, axon_color, dendrites_color]):
                raise ValueError(
                    "The colors chosen are not valid: soma - {}, dendrites {}, axon {}"
                    .format(soma_color, dendrites_color, axon_color))

            # check if we have lists of colors or single colors
            if isinstance(soma_color, list):
                if isinstance(soma_color[0], str) or isinstance(
                        soma_color[0], list):
                    soma_color = soma_color[neuron_number]
            if isinstance(dendrites_color, list):
                if isinstance(dendrites_color[0], str) or isinstance(
                        dendrites_color[0], list):
                    dendrites_color = dendrites_color[neuron_number]
            if isinstance(axon_color, list):
                if isinstance(axon_color[0], str) or isinstance(
                        axon_color[0], list):
                    axon_color = axon_color[neuron_number]

        # get allen info: it containes the allenID of each brain region
        # each sample has the corresponding allen ID so we can recontruct in which brain region it is
        if neuron is not None:
            if 'allenInformation' in list(neuron.keys()):
                self.alleninfo = pd.DataFrame(
                    neuron['allenInformation']
                )  # get brain structure in which is the soma
                soma_region = self.scene.get_structure_parent(
                    self.alleninfo.loc[
                        self.alleninfo.allenId == neuron['soma']
                        ['allenId']].acronym.values[0])['acronym']
            else:
                self.alleninfo = None
                soma_region = self.scene.get_structure_from_coordinates(
                    get_coords(neuron['soma']))
                if soma_region is not None:
                    soma_region = soma_region['acronym']
        elif soma_region is None:
            self.alleninfo = None
            if soma is not None:
                soma_region = self.scene.get_structure_from_coordinates(
                    get_coords(soma))
                if soma_region is not None:
                    soma_region = soma_region['acronym']
            else:
                raise ValueError(
                    "You need to pass either a neuron, or a soma region or a soma"
                )
        else:
            self.alleninfo = None

        if soma_region is not None:
            soma_region = self.scene.get_structure_parent(
                soma_region)['acronym']
        else:
            soma_region = "root"

        if self.color_by_region:
            try:
                region_color = self.scene.structure_tree.get_structures_by_acronym(
                    [soma_region])[0]['rgb_triplet']
            except:
                print(
                    "could not find default color for region: {}. Using random color instead"
                    .format(soma_region))
                region_color = get_random_colors(n_colors=1)

            axon_color = soma_color = dendrites_color = region_color

        return soma_color, axon_color, dendrites_color, soma_region