Ejemplo n.º 1
0
    def _get_structure_mesh(self, acronym, **kwargs):
        """
        Fetches the mesh for a brain region from the atlas.

        :param acronym: string, acronym of brain region
        :param **kwargs:

        """
        if self.structures is None:
            print("No atlas was loaded, use self.get_brain first")
            return None

        if acronym not in self.region_acronyms and acronym != "root":
            raise ValueError(
                f"Acronym {acronym} not in available regions: {self.structures}"
            )

        # Get obj file path
        if acronym != "root":
            mesh_format = self.mesh_format
        else:
            mesh_format = "vtk"
        obj_path = os.path.join(self.meshes_folder,
                                "{}.{}".format(acronym, mesh_format))

        # Load
        if self._check_obj_file(acronym, obj_path):
            mesh = load_mesh_from_file(obj_path, **kwargs)
            return mesh
        else:
            mesh = self.download_and_write_mesh(acronym, obj_path)
            return None
Ejemplo n.º 2
0
    def add_from_file(self, *filepaths, **kwargs):
        """
        Add data to the scene by loading them from a file. Should handle .obj, .vtk and .nii files.

        :param filepaths: path to the file. Can pass as many arguments as needed
        :param **kwargs:

        """
        actors = []
        for filepath in filepaths:
            actor = load_mesh_from_file(filepath, **kwargs)
            name = Path(filepath).name
            act = self.add_actor(actor, name=name, br_class=name)
            actors.append(act)
        return return_list_smart(actors)
Ejemplo n.º 3
0
    def _get_structure_mesh(self, acronym,   **kwargs):
        """
        Fetches the mesh for a brain region from the Allen Brain Atlas SDK.

        :param acronym: string, acronym of brain region
        :param **kwargs:

        """
        structure = self.structure_tree.get_structures_by_acronym([acronym])[0]
        obj_path = os.path.join(self.mouse_meshes, "{}.obj".format(acronym))

        if self._check_obj_file(structure, obj_path):
            mesh = load_mesh_from_file(obj_path, **kwargs)
            return mesh
        else:
            return None
Ejemplo n.º 4
0
	def add_from_file(self, *filepaths, **kwargs):
		"""
		Add data to the scene by loading them from a file. Should handle .obj, .vtk and .nii files.

		:param filepaths: path to the file. Can pass as many arguments as needed
		:param **kwargs:

		"""
		actors = []
		for filepath in filepaths:
			actor = load_mesh_from_file(filepath, **kwargs)
			self.actors['others'].append(actor)
			actors.append(actor)
			
		if len(actors) == 1:
			return actors[0]
		elif len(actors) > 1:
			return actors
		else:
			return None
Ejemplo n.º 5
0
    def get_neurons(self, neurons, alpha=1, as_skeleton=False, colorby="type"):
        """
            Renders neurons and adds returns to the scene. 

            :param neurons: list of names of neurons
            :param alpha: float in range 0,1 -  neurons transparency
            :param as_skeleton: bool (Default value = False), if True neurons are rendered as skeletons 
                                otherwise as a full mesh showing the whole morphology
            :param colorby: str, criteria to use to color the neurons. Accepts values like type, individual etc. 
        """
        neurons = self._check_neuron_argument(neurons)

        actors, store = [], {}
        for neuron in neurons:
            if neuron not in self.neurons_names:
                print(f"Neuron {neuron} not included in dataset")
            else:
                color = self.get_neuron_color(neuron, colorby=colorby)

                if as_skeleton:  # reconstruct skeleton from json
                    actor = self._parse_neuron_skeleton(neuron)

                else:  # load as .obj file
                    try:
                        neuron_file = [
                            f for f in self.neurons_files if neuron in f
                        ][0]
                    except:
                        print(f"Could not find .obj file for neuron {neuron}")
                        continue

                    actor = load_mesh_from_file(neuron_file)

                if actor is not None:
                    # Refine actor's look
                    actor.alpha(alpha).c(color)

            actors.append(actor)
            store[neuron] = (actor, as_skeleton)

        return actors, store
Ejemplo n.º 6
0
    def add_neurons(self, neurons, alpha=1, as_skeleton=False, colorby='type'):   
        """
            THIS METHODS GETS CALLED BY SCENE, self referes to the instance of Scene not to this class.
            Renders neurons and adds them to the scene. 

            :param neurons: list of names of neurons
            :param alpha: float in range 0,1 -  neurons transparency
            :param as_skeleton: bool (Default value = False), if True neurons are rendered as skeletons 
                                otherwise as a full mesh showing the whole morphology
            :param colorby: str, criteria to use to color the neurons. Accepts values like type, individual etc. 
        """
        neurons = self.atlas._check_neuron_argument(neurons)

        for neuron in neurons:
            if neuron not in self.atlas.neurons_names:
                print(f"Neuron {neuron} not included in dataset")
            else:
                color = self.atlas.get_neuron_color(neuron, colorby=colorby)

                if as_skeleton: # reconstruct skeleton from json
                    actor = self.atlas._parse_neuron_skeleton(neuron)


                else: # load as .obj file
                    try:
                        neuron_file = [f for f in self.atlas.neurons_files if neuron in f][0]
                    except:
                        print(f"Could not find .obj file for neuron {neuron}")
                        continue

                    actor = load_mesh_from_file(neuron_file)

                if actor is not None:
                    # Refine actor's look
                    actor.alpha(alpha).c(color)

                    # Add to scene
                    self.actors['neurons'].append(actor)
                    self.store[neuron] = (actor, as_skeleton) # repurpusing the region's actors store for hosting neurons as dict
Ejemplo n.º 7
0
    def get_brain_regions(
        self,
        brain_regions,
        add_labels=False,
        colors=None,
        use_original_color=True,
        alpha=None,
        hemisphere=None,
        verbose=False,
        **kwargs,
    ):
        """
                Gets brain regions meshes for rendering
                Many parameters can be passed to specify how the regions should be rendered.
                To treat a subset of the rendered regions, specify which regions are VIP. 
                Use the kwargs to specify more detailes on how the regins should be rendered (e.g. wireframe look)

                :param brain_regions: str list of acronyms of brain regions
                :param colors: str, color of rendered brian regions (Default value = None)
                :param use_original_color: bool, if True, the allen's default color for the region is used.  (Default value = False)
                :param alpha: float, transparency of the rendered brain regions (Default value = None)
                :param hemisphere: str (Default value = None)
                :param add_labels: bool (default False). If true a label is added to each regions' actor. The label is visible when hovering the mouse over the actor
                :param **kwargs: used to determine a bunch of thigs, including the look and location of lables from scene.add_labels
            """
        # Parse arguments
        if alpha is None:
            alpha = brainrender.DEFAULT_STRUCTURE_ALPHA

        # check that we have a list
        if not isinstance(brain_regions, list):
            brain_regions = [brain_regions]

        # check the colors input is correct
        if colors is not None:
            if isinstance(colors, (list, tuple)):
                if not len(colors) == len(brain_regions):
                    raise ValueError(
                        "when passing colors as a list, the number of colors must match the number of brain regions"
                    )
                for col in colors:
                    if not check_colors(col):
                        raise ValueError(
                            "Invalide colors in input: {}".format(col))
            else:
                if not check_colors(colors):
                    raise ValueError(
                        "Invalide colors in input: {}".format(colors))
                colors = [colors for i in range(len(brain_regions))]

        # loop over all brain regions
        actors = {}
        for i, region in enumerate(brain_regions):
            if verbose:
                print("Rendering: ({})".format(region))

            # get the structure and check if we need to download the object file
            if region not in self.lookup_df.acronym.values:
                print(
                    f"The region {region} doesn't seem to belong to the atlas being used: {self.atlas_name}. Skipping"
                )
                continue

            # Get path to .obj file
            obj_file = str(self.meshfile_from_structure(region))

            # check which color to assign to the brain region
            if use_original_color:
                color = [
                    x / 255
                    for x in self._get_from_structure(region, "rgb_triplet")
                ]
            else:
                if colors is None:
                    color = brainrender.DEFAULT_STRUCTURE_COLOR
                elif isinstance(colors, list):
                    color = colors[i]
                else:
                    color = colors

            # Load the object file as a mesh and store the actor
            if hemisphere is not None:
                if (hemisphere.lower() == "left"
                        or hemisphere.lower() == "right"):
                    obj = self.get_region_unilateral(region,
                                                     hemisphere=hemisphere,
                                                     color=color,
                                                     alpha=alpha)
                else:
                    raise ValueError(
                        f"Invalid hemisphere argument: {hemisphere}")
            else:
                obj = load_mesh_from_file(obj_file, color=color, alpha=alpha)

            if obj is not None:
                actors_funcs.edit_actor(obj, **kwargs)
                actors[region] = obj
            else:
                print(
                    f"Something went wrong while loading mesh data for {region}, skipping."
                )

        return actors
Ejemplo n.º 8
0
 def _get_structure_mesh(self, acronym, **kwargs):
     obj_path = self._get_from_structure(acronym, "mesh_filename")
     return load_mesh_from_file(obj_path, **kwargs)
Ejemplo n.º 9
0
    def get_neurons_synapses(
        self,
        scene_store,
        neurons,
        alpha=1,
        pre=False,
        post=False,
        colorby="synapse_type",
        draw_patches=False,
        draw_arrows=True,
    ):
        """
            THIS METHODS GETS CALLED BY SCENE, self referes to the instance of Scene not to this class.
            Renders neurons and adds them to the scene. 

            :param neurons: list of names of neurons
            :param alpha: float in range 0,1 -  neurons transparency
            :param pre: bool, if True the presynaptic sites of each neuron are rendered
            :param post: bool, if True the postsynaptic sites on each neuron are rendered
            :param colorby: str, criteria to use to color the neurons.
                             Accepts values like synapse_type, type, individual etc. 
            :param draw_patches: bool, default True. If true dark patches are used to show the location of post synapses
            :param draw_arrows: bool, default True. If true arrows are used to show the location of post synapses
        """

        col_names = ["x", "z", "y"]
        # used to correctly position synapses on .obj files

        neurons = self._check_neuron_argument(neurons)

        spheres_data, actors = [], []
        for neuron in neurons:
            if pre:
                if colorby == "synapse_type":
                    color = self.pre_synapses_color
                else:
                    color = self.get_neuron_color(neuron, colorby=colorby)

                data = self.synapses_data.loc[self.synapses_data.pre == neuron]
                if not len(data):
                    print(f"No pre- synapses found for neuron {neuron}")
                else:
                    data = data[["x", "y", "z"]]
                    data["y"] = -data["y"]

                    spheres_data.append((
                        data,
                        dict(
                            color=color,
                            verbose=False,
                            alpha=alpha,
                            radius=self.synapses_radius,
                            res=24,
                            col_names=col_names,
                        ),
                    ))

            if post:
                if colorby == "synapse_type":
                    color = self.post_synapses_color
                else:
                    color = self.get_neuron_color(neuron, colorby=colorby)

                rows = [
                    i for i, row in self.synapses_data.iterrows()
                    if neuron in row.posts
                ]
                data = self.synapses_data.iloc[rows]

                if not len(data):
                    print(f"No post- synapses found for neuron {neuron}")
                else:
                    data = data[["x", "y", "z"]]
                    data["y"] = -data["y"]
                    """
                        Post synaptic locations are shown as darkening of patches
                        of a neuron's mesh and or as a 3d arrow point toward the neuron.
                    """

                    spheres_data.append((
                        data,
                        dict(
                            color="black",
                            verbose=False,
                            alpha=0,
                            radius=self.synapses_radius * 4,
                            res=24,
                            col_names=col_names,
                        ),
                    ))

                    # Get mesh points for neuron the synapses belong to
                    if neuron not in scene_store.keys():
                        neuron_file = [
                            f for f in self.neurons_files if neuron in f
                        ][0]
                        neuron_act = load_mesh_from_file(neuron_file, c=color)
                    else:
                        neuron_act, as_skeleton = scene_store[neuron]

                    # Draw post synapses as dark patches
                    if draw_patches:
                        if as_skeleton:
                            print(
                                "Can't display post synapses as dark spots when neron is rendered in skeleton mode"
                            )
                        else:
                            # Get faces that are inside the synapses spheres and color them darker
                            raise NotImplementedError("This needs some fixing")

                            # neuron_points = neuron_act.cellCenters()
                            # inside_points = spheres.insidePoints(
                            #     neuron_points, returnIds=True
                            # )

                            # n_cells = neuron_act.polydata().GetNumberOfCells()
                            # scals = np.zeros((n_cells))
                            # scals[inside_points] = 1

                            # colors = [
                            #     neuron_act.c()
                            #     if s == 0
                            #     else getColor("blackboard")
                            #     for s in scals
                            # ]
                            # neuron_act.cellIndividualColors(colors)

                    # Draw post synapses as arrow
                    if draw_arrows:
                        points1 = [[x, y, z] for x, y, z in zip(
                            data[col_names[0]].values,
                            data[col_names[1]].values,
                            data[col_names[2]].values,
                        )]

                        points2 = [neuron_act.closestPoint(p) for p in points1]

                        #  shift point1 to make arrows longer
                        def dist(p1, p2):
                            return math.sqrt((p1[0] - p2[0])**2 +
                                             (p1[1] - p2[1])**2 +
                                             (p1[2] - p2[2])**2)

                        def get_point(p1, p2, d, u):
                            alpha = (1 / d) * u
                            x = (1 - alpha) * p1[0] + alpha * p2[0]
                            y = (1 - alpha) * p1[1] + alpha * p2[1]
                            z = (1 - alpha) * p1[2] + alpha * p2[2]
                            return [x, y, z]

                        dists = [
                            dist(p1, p2) for p1, p2 in zip(points1, points2)
                        ]
                        points0 = [
                            get_point(p1, p2, d, -0.5)
                            for p1, p2, d in zip(points1, points2, dists)
                        ]

                        arrows = Arrows(points0,
                                        endPoints=points2,
                                        c=color,
                                        s=4)

                        # ! aasduaisdbasiudbuia
                        actors.append(arrows)
        return spheres_data, actors