コード例 #1
0
ファイル: celegans.py プロジェクト: yooerzf/brainrender
    def get_neuron_color(self, neuron, colorby="type"):
        """
            Get a neuron's RGB color. Colors can be assigned based on different criteria
            like the neuron's type or by individual neuron etc...

            :param neuron: str, nueron name
            :param colorby: str, metadata attribute to use for coloring
            :returns: rgb values of color
        """
        try:  # make this work if called by a Scene class
            cs = self.atlas
        except:
            cs = self

        allowed = ["neuron", "individual", "ind", "pair", "class", "type"]

        if colorby not in allowed:
            raise ValueError(
                f"color by key should be one of {allowed} not {colorby}")

        if colorby == "type":
            color = cs.neurons_metadata.loc[cs.neurons_metadata.neuron ==
                                            neuron]["type_color"].values[0]
            color = ImageColor.getrgb(color)
        elif (colorby == "individual" or colorby == "ind"
              or colorby == "neuron"):
            color = get_random_colors()
        else:
            raise NotImplementedError

        return color
コード例 #2
0
    def get_streamlines(self, sl_file, *args, colorby=None, color_each=False,  **kwargs):
        """
        Render streamline data downloaded from https://neuroinformatics.nl/HBP/allen-connectivity-viewer/streamline-downloader.html

        :param sl_file: path to JSON file with streamliens data [or list of files]
        :param colorby: str,  criteria for how to color the streamline data (Default value = None)
        :param color_each: bool, if True, the streamlines for each injection is colored differently (Default value = False)
        :param *args:
        :param **kwargs:

        """
        color = None
        if not color_each:
            if colorby is not None:
                try:
                    color = self.structure_tree.get_structures_by_acronym([colorby])[0]['rgb_triplet']
                    if "color" in kwargs.keys():
                        del kwargs["color"]
                except:
                    raise ValueError("Could not extract color for region: {}".format(colorby))
        else:
            if colorby is not None:
                color = kwargs.pop("color", None)
                try:
                    get_n_shades_of(color, 1)
                except:
                    raise ValueError("Invalide color argument: {}".format(color))

        if not isinstance(sl_file, (list, tuple)):
            sl_file = [sl_file]

        actors = []
        if isinstance(sl_file[0], (str, pd.DataFrame)): # we have a list of files to add
            for slf in tqdm(sl_file):
                if not color_each:
                    if color is not None:
                        if isinstance(slf, str):
                            streamlines = parse_streamline(filepath=slf, *args, color=color, **kwargs)
                        else:
                            streamlines = parse_streamline(data=slf, *args, color=color, **kwargs)
                    else:
                        if isinstance(slf, str):
                            streamlines = parse_streamline(filepath=slf, *args, **kwargs)
                        else:
                            streamlines = parse_streamline(data=slf,  *args, **kwargs)
                else:
                    if color is not None:
                        col = get_n_shades_of(color, 1)[0]
                    else:
                        col = get_random_colors(n_colors=1)
                    if isinstance(slf, str):
                        streamlines = parse_streamline(filepath=slf, color=col, *args, **kwargs)
                    else:
                        streamlines = parse_streamline(data= slf, color=col, *args, **kwargs)
                actors.extend(streamlines)
        else:
            raise ValueError("unrecognized argument sl_file: {}".format(sl_file))

        return actors
コード例 #3
0
def get_cells_colors_from_metadata(color_by_metadata, coords_df, color):
    """
        Get color of each cell given some metadata entry

        :param color_by_metadata: str, column name with metadata info
        :param coords_df: dataframe with cell coordinates and metadata
    """

    if color_by_metadata not in coords_df.columns:
        raise ValueError(
            'Color_by_metadata argument should be the name of one of the columns of "coords"'
        )

    # Get a map from metadata values to colors
    vals = list(coords_df[color_by_metadata].values)
    if len(vals) == 0:
        raise ValueError(
            f"Cant color by {color_by_metadata} as no values were found")
    if not isinstance(color,
                      dict):  # The user didn't pass a lookup, generate random
        base_cols = get_random_colors(n_colors=len(set(vals)))
        cols_lookup = {v: c for v, c in zip(set(vals), base_cols)}
    else:
        try:
            for val in list(set(vals)):
                color[val]
        except KeyError:
            raise ValueError(
                'While using "color_by_metadata" with a dictionary of colors passed'
                +
                ' to "color", not every metadata value was assigned a color in the dictionary'
                + " please make sure that the color dictionary is complete")
        else:
            cols_lookup = color

    # Use the map to get a color for each cell
    color = [cols_lookup[v] for v in vals]

    return color
コード例 #4
0
ファイル: aba_utils.py プロジェクト: dhtc/brainrender
def parse_neurons_colors(neurons, color):
    """
        Prepares the color info to render neurons

        :param neurons: str, list, dict. File(s) with neurons data or list of rendered neurons.
        :param color: default None. Can be:
                - None: each neuron is given a random color
                - color: rbg, hex etc. If a single color is passed all neurons will have that color
                - cmap: str with name of a colormap: neurons are colored based on their sequential order and cmap
                - dict: a dictionary specifying a color for soma, dendrites and axon actors, will be the same for all neurons
                - list: a list of length = number of neurons with either a single color for each neuron
                        or a dictionary of colors for each neuron
    """

    N = len(neurons)
    colors = dict(
        soma=None,
        axon=None,
        dendrites=None,
    )

    # If no color is passed, get random colors
    if color is None:
        cols = get_random_colors(N)
        if not isinstance(cols, list):
            cols = [cols]
        colors = dict(
            soma=cols,
            axon=cols,
            dendrites=cols,
        )
    else:
        if isinstance(color, str):
            # Deal with a a cmap being passed
            if color in _mapscales_cmaps:
                cols = [
                    colorMap(n, name=color, vmin=-2, vmax=N + 2)
                    for n in np.arange(N)
                ]
                colors = dict(
                    soma=cols.copy(),
                    axon=cols.copy(),
                    dendrites=cols.copy(),
                )

            else:
                # Deal with a single color being passed
                cols = [getColor(color) for n in np.arange(N)]
                colors = dict(
                    soma=cols.copy(),
                    axon=cols.copy(),
                    dendrites=cols.copy(),
                )
        elif isinstance(color, dict):
            # Deal with a dictionary with color for each component
            if "soma" not in color.keys():
                raise ValueError(
                    f"When passing a dictionary as color argument, \
                                            soma should be one fo the keys: {color}"
                )
            dendrites_color = color.pop("dendrites", color["soma"])
            axon_color = color.pop("axon", color["soma"])

            colors = dict(
                soma=[color["soma"] for n in np.arange(N)],
                axon=[axon_color for n in np.arange(N)],
                dendrites=[dendrites_color for n in np.arange(N)],
            )

        elif isinstance(color, (list, tuple)):
            # Check that the list content makes sense
            if len(color) != N:
                raise ValueError(
                    "When passing a list of color arguments, the list length" +
                    f" ({len(color)}) should match the number of neurons ({N})."
                )
            if len(set([type(c) for c in color])) > 1:
                raise ValueError(
                    "When passing a list of color arguments, all list elements"
                    + " should have the same type (e.g. str or dict)")

            if isinstance(color[0], dict):
                # Deal with a list of dictionaries
                soma_colors, dendrites_colors, axon_colors = [], [], []

                for col in color:
                    if "soma" not in col.keys():
                        raise ValueError(
                            f"When passing a dictionary as col argument, \
                                                    soma should be one fo the keys: {col}"
                        )
                    dendrites_colors.append(col.pop("dendrites", col["soma"]))
                    axon_colors.append(col.pop("axon", col["soma"]))
                    soma_colors.append(col["soma"])

                colors = dict(
                    soma=soma_colors,
                    axon=axon_colors,
                    dendrites=dendrites_colors,
                )

            else:
                if isinstance(color, tuple):
                    color = [color]
                # Deal with a list of colors
                colors = dict(
                    soma=color.copy(),
                    axon=color.copy(),
                    dendrites=color.copy(),
                )
        else:
            raise ValueError(
                f"Color argument passed is not valid. Should be a \
                                    str, dict, list or None, not {type(color)}:{color}"
            )

    # Check colors, if everything went well we should have N colors per entry
    for k, v in colors.items():
        if len(v) != N:
            raise ValueError(
                f"Something went wrong while preparing colors. Not all \
                            entries have right length. We got: {colors}")

    return colors
コード例 #5
0
	def add_image(self, image_file_path, color=None, alpha=None,
				  obj_file_path=None, voxel_size=1, orientation="saggital",
				  invert_axes=None, extension=".obj", step_size=2,
				  keep_obj_file=True, overwrite='use', smooth=True):

		"""
		Loads a 3d image and processes it to extract mesh coordinates. Mesh coordinates are extracted with
		a fast marching algorithm and saved to a .obj file. This file is then used to render the mesh.

		:param image_file_path: str
		:param color: str (Default value = None)
		:param alpha: int (Default value = None)
		:param obj_file_path: str (Default value = None)
		:param voxel_size: float (Default value = 1)
		:param orientation: str (Default value = "saggital")
		:param invert_axes: tuple (Default value = None)
		:param extension: str (Default value = ".obj")
		:param step_size: int (Default value = 2)
		:param keep_obj_file: bool (Default value = True)
		:param overwrite: str (Default value = 'use')
		:param overwrite: if a (Default value = 'use')
		:param smooth: bool (Default value = True)

		"""

		# Check args
		if color is None: color = get_random_colors() # get a random color

		if alpha is None:
			alpha = brainrender.DEFAULT_STRUCTURE_ALPHA

		if obj_file_path is None:
			obj_file_path = os.path.splitext(image_file_path)[0] + extension

		if os.path.exists(obj_file_path):
			if overwrite == "use":
				print("Found a .obj file that matches your input data. Rendering that instead.")
				print("If you would like to change this behaviour, change the 'overwrite' argument.")
			elif overwrite == "overwrite":
				print("Found a .obj file that matches your input data. Overriding it.")
				print("If you would like to change this behaviour, change the 'overwrite' argument.")
				# Process the image and save as .obj file
				image_to_surface(image_file_path, obj_file_path, voxel_size=voxel_size,
								orientation=orientation, invert_axes=invert_axes,
								step_size=step_size)
			elif overwrite == "catch":
				raise FileExistsError("The .obj file exists alread, to overwrite change the 'overwrite' argument.")
			else:
				raise ValueError("Unrecognized value for argument overwrite: {}".format(overwrite))
		else:
			print(f"Converting file: {image_file_path} to surface")
			image_to_surface(image_file_path, obj_file_path,
							 voxel_size=voxel_size,
							 orientation=orientation, invert_axes=invert_axes,
							 step_size=step_size)


		# render obj file, smooth and clean up.
		actor = self.add_from_file(obj_file_path, c=color, alpha=alpha)

		if smooth:
			actors_funcs.smooth_actor(actor)

		if not keep_obj_file:
			os.remove(obj_file_path)
コード例 #6
0
def edit_neurons(neurons, **kwargs):
    """
		Modify neurons actors after they have been created, at render time.
		neurons should be a list of dictionaries with soma, dendrite and axon actors of each neuron.

	:param neurons: list of dictionaries with vtk actors for each neuron
	:param **kwargs: 

	"""
    soma_color, axon_color, dendrites_color = None, None, None
    for neuron in neurons:
        if "random_color" in kwargs:
            if kwargs["random_color"]:
                if not isinstance(kwargs["random_color"], str):
                    color = get_random_colors(n_colors=1)
                else:  # random_color is a colormap
                    color = colorMap(np.random.randint(1000),
                                     name=kwargs["random_color"],
                                     vmin=0,
                                     vmax=1000)
                axon_color = soma_color = dendrites_color = color
        elif "color_neurites" in kwargs:
            soma_color = neuron["soma"].color()
            if not kwargs["color_neurites"]:
                axon_color = dendrites_color = soma_color
            else:
                if not "axon_color" in kwargs:
                    # print("no axon color provided, using somacolor")
                    axon_color = soma_color
                else:
                    axon_color = kwargs["axon_color"]

                if not "dendrites_color" in kwargs:
                    # print("no dendrites color provided, using somacolor")
                    dendrites_color = soma_color
                else:
                    dendrites_color = kwargs["dendrites_color"]
        elif "soma_color" in kwargs:
            if check_colors(kwargs["soma_color"]):
                soma_color = kwargs["soma_color"]
            else:
                print("Invalid soma color provided")
                soma_color = neuron["soma"].color()
        elif "axon_color" in kwargs:
            if check_colors(kwargs["axon_color"]):
                axon_color = kwargs["axon_color"]
            else:
                print("Invalid axon color provided")
                axon_color = neuron["axon"].color()
        elif "dendrites_color" in kwargs:
            if check_colors(kwargs["dendrites_color"]):
                dendrites_color = kwargs["dendrites_color"]
            else:
                print("Invalid dendrites color provided")
                dendrites_color = neuron["dendrites"].color()

        if soma_color is not None:
            neuron["soma"].color(soma_color)
        if axon_color is not None:
            neuron["axon"].color(axon_color)
        if dendrites_color is not None:
            neuron["dendrites"].color(dendrites_color)

        if "mirror" in kwargs:
            if "mirror_coord" in kwargs:
                mcoord = kwargs["mirror_coord"]
            else:
                raise ValueError("Need to pass the mirror point coordinate")

            # mirror X positoin
            for name, actor in neuron.items():
                if "only_soma" in kwargs:
                    if kwargs["only_soma"] and name != "soma": continue

                # get mesh points coords and shift them to other hemisphere
                if isinstance(actor, list):
                    continue
                coords = actor.points()
                shifted_coords = [[c[0], c[1], mcoord + (mcoord - c[2])]
                                  for c in coords]
                actor.points(shifted_coords)

                neuron[name] = actor.mirror(axis='n')

    return neurons
コード例 #7
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 isinstance(neuron, dict):
                self.alleninfo = None
                soma_region = self.scene.get_structure_from_coordinates(
                    get_coords(neuron['soma']))
            else:
                self.alleninfo = None
                soma_region = None
        elif soma_region is None:
            self.alleninfo = None
            if soma is not None:
                soma_region = self.scene.get_structure_from_coordinates(
                    get_coords(soma))
            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
コード例 #8
0
    def get_neurons(self, neurons, color=None, display_axon=True, display_dendrites=True,
                alpha=1, neurite_radius=None):
        """
        Gets rendered morphological data of neurons reconstructions downloaded from the
        Mouse Light project at Janelia (or other sources). 
        Accepts neurons argument as:
            - file(s) with morphological data
            - vtkplotter mesh actor(s) of entire neurons reconstructions
            - dictionary or list of dictionary with actors for different neuron parts

        :param neurons: str, list, dict. File(s) with neurons data or list of rendered neurons.
        :param display_axon, display_dendrites: if set to False the corresponding neurite is not rendered
        :param color: default None. Can be:
                - None: each neuron is given a random color
                - color: rbg, hex etc. If a single color is passed all neurons will have that color
                - cmap: str with name of a colormap: neurons are colored based on their sequential order and cmap
                - dict: a dictionary specifying a color for soma, dendrites and axon actors, will be the same for all neurons
                - list: a list of length = number of neurons with either a single color for each neuron
                        or a dictionary of colors for each neuron
        :param alpha: float in range 0,1. Neurons transparency
        :param neurite_radius: float > 0 , radius of tube actor representing neurites
        """

        if not isinstance(neurons, (list, tuple)):
            neurons = [neurons]

        # ------------------------------ Prepare colors ------------------------------ #
        N = len(neurons)
        colors = dict(
            soma = None,
            axon = None,
            dendrites = None,
        )

        # If no color is passed, get random colors
        if color is None:
            cols = get_random_colors(N)
            colors = dict(
                soma = cols.copy(),
                axon = cols.copy(),
                dendrites = cols.copy(),)
        else:
            if isinstance(color, str):
                # Deal with a a cmap being passed
                if color in _mapscales_cmaps:
                    cols = [colorMap(n, name=color, vmin=-2, vmax=N+2) for n in np.arange(N)]
                    colors = dict(
                        soma = cols.copy(),
                        axon = cols.copy(),
                        dendrites = cols.copy(),)

                else:
                    # Deal with a single color being passed
                    cols = [getColor(color) for n in np.arange(N)]
                    colors = dict(
                        soma = cols.copy(),
                        axon = cols.copy(),
                        dendrites = cols.copy(),)
            elif isinstance(color, dict):
                # Deal with a dictionary with color for each component
                if not 'soma' in color.keys():
                    raise ValueError(f"When passing a dictionary as color argument, \
                                                soma should be one fo the keys: {color}")
                dendrites_color = color.pop('dendrites', color['soma'])
                axon_color = color.pop('axon', color['soma'])

                colors = dict(
                        soma = [color['soma'] for n in np.arange(N)],
                        axon = [axon_color for n in np.arange(N)],
                        dendrites = [dendrites_color for n in np.arange(N)],)
                        
            elif isinstance(color, (list, tuple)):
                # Check that the list content makes sense
                if len(color) != N:
                    raise ValueError(f"When passing a list of color arguments, the list length"+
                                f" ({len(color)}) should match the number of neurons ({N}).")
                if len(set([type(c) for c in color])) > 1:
                    raise ValueError(f"When passing a list of color arguments, all list elements"+
                                " should have the same type (e.g. str or dict)")

                if isinstance(color[0], dict):
                    # Deal with a list of dictionaries
                    soma_colors, dendrites_colors, axon_colors = [], [], []

                    for col in colors:
                        if not 'soma' in col.keys():
                            raise ValueError(f"When passing a dictionary as col argument, \
                                                        soma should be one fo the keys: {col}")
                        dendrites_colors.append(col.pop('dendrites', col['soma']))
                        axon_colors.append(col.pop('axon', col['soma']))
                        soma_colors.append(col['soma'])

                    colors = dict(
                        soma = soma_colors,
                        axon = axon_colors,
                        dendrites = dendrites_colors,)

                else:
                    # Deal with a list of colors
                    colors = dict(
                        soma = color.copy(),
                        axon = color.copy(),
                        dendrites = color.copy(),)
            else:
                raise ValueError(f"Color argument passed is not valid. Should be a \
                                        str, dict, list or None, not {type(color)}:{color}")

        # Check colors, if everything went well we should have N colors per entry
        for k,v in colors.items():
            if len(v) != N:
                raise ValueError(f"Something went wrong while preparing colors. Not all \
                                entries have right length. We got: {colors}")



        # ---------------------------------- Render ---------------------------------- #
        _neurons_actors = []
        for neuron in neurons:
            neuron_actors = {'soma':None, 'dendrites':None, 'axon': None}
            
            # Deal with neuron as filepath
            if isinstance(neuron, str):
                if os.path.isfile(neuron):
                    if neuron.endswith('.swc'):
                        neuron_actors, _ = get_neuron_actors_with_morphapi(swcfile=neuron, neurite_radius=neurite_radius)
                    else:
                        raise NotImplementedError('Currently we can only parse morphological reconstructions from swc files')
                else:
                    raise ValueError(f"Passed neruon {neuron} is not a valid input. Maybe the file doesn't exist?")
            
            # Deal with neuron as single actor
            elif isinstance(neuron, Actor):
                # A single actor was passed, maybe it's the entire neuron
                neuron_actors['soma'] = neuron # store it as soma anyway
                pass

            # Deal with neuron as dictionary of actor
            elif isinstance(neuron, dict):
                neuron_actors['soma'] = neuron.pop('soma', None)
                neuron_actors['axon'] = neuron.pop('axon', None)

                # Get dendrites actors
                if 'apical_dendrites' in neuron.keys() or 'basal_dendrites' in neuron.keys():
                    if 'apical_dendrites' not in neuron.keys():
                        neuron_actors['dendrites'] = neuron['basal_dendrites']
                    elif 'basal_dendrites' not in neuron.keys():
                        neuron_actors['dendrites'] = neuron['apical_dendrites']
                    else:
                        neuron_ctors['dendrites'] = merge(neuron['apical_dendrites'], neuron['basal_dendrites'])
                else:
                    neuron_actors['dendrites'] = neuron.pop('dendrites', None)
            
            # Deal with neuron as instance of Neuron from morphapi
            elif isinstance(neuron, Neuron):
                neuron_actors, _ = get_neuron_actors_with_morphapi(neuron=neuron)                
            # Deal with other inputs
            else:
                raise ValueError(f"Passed neuron {neuron} is not a valid input")

            # Check that we don't have anything weird in neuron_actors
            for key, act in neuron_actors.items():
                if act is not None:
                    if not isinstance(act, Actor):
                        raise ValueError(f"Neuron actor {key} is {act.__type__} but should be a vtkplotter Mesh. Not: {act}")

            if not display_axon:
                neuron_actors['axon'] = None
            if not display_dendrites:
                neuron_actors['dendrites'] = None
            _neurons_actors.append(neuron_actors)

        # Color actors
        for n, neuron in enumerate(_neurons_actors):
            if neuron['axon'] is not None:
                neuron['axon'].c(colors['axon'][n])
            neuron['soma'].c(colors['soma'][n])
            if neuron['dendrites'] is not None:
                neuron['dendrites'].c(colors['dendrites'][n])

        # Return
        if len(_neurons_actors) == 1:
            return _neurons_actors[0], None
        elif not _neurons_actors:
            return None, None
        else:
            return _neurons_actors, None