def __init__(
        self,
        data,
        radius=10,
        color="salmon",
        alpha=1,
        show_injection=True,
        name=None,
    ):
        """
        Turns streamlines data to a mesh.
        :param data: pd.DataFrame with streamlines points data
        :param radius: float. Radius of the Tube mesh used to render streamlines
        :param color: str, name of the color to be used
        :param alpha: float, transparancy
        :param name: str, name of the actor.
        :param show_injection: bool. If true spheres mark the injection sites
        """
        logger.debug(f"Creating a streamlines actor")
        if isinstance(data, (str, Path)):
            data = pd.read_json(data)
        elif not isinstance(data, pd.DataFrame):
            raise TypeError("Input data should be a dataframe")

        self.radius = radius
        mesh = (
            self._make_mesh(data, show_injection=show_injection)
            .c(color)
            .alpha(alpha)
            .clean()
        )

        name = name or "Streamlines"
        Actor.__init__(self, mesh, name=name, br_class="Streamliness")
Exemple #2
0
    def __init__(self,
                 data,
                 name=None,
                 dims=(40, 40, 40),
                 radius=None,
                 **kwargs):
        """
            Creates a Volume actor showing the 3d density of a set 
            of points.

            :param data: np.ndarray, Nx3 array with cell coordinates


            from vedo:
                Generate a density field from a point cloud. Input can also be a set of 3D coordinates.
                Output is a ``Volume``.
                The local neighborhood is specified as the `radius` around each sample position (each voxel).
                The density is expressed as the number of counts in the radius search.

                :param int,list dims: numer of voxels in x, y and z of the output Volume.

        """
        volume = vPoints(data).density(dims=dims, radius=radius,
                                       **kwargs)  # returns a vedo Volume
        Actor.__init__(self, volume, name=name, br_class="density")
Exemple #3
0
    def __init__(self, pos, root, color="powderblue", alpha=1, radius=350):
        """
        Cylinder class creates a cylinder mesh between a given
        point and the brain's surface.

        :param pos: list, np.array of ap, dv, ml coordinates.
            If an actor is passed, get's the center of mass instead
        :param root: brain root Actor or mesh object
        :param color: str, color
        :param alpha: float
        :param radius: float
        """

        # Get pos
        if isinstance(pos, Mesh):
            pos = pos.points().mean(axis=0)
        elif isinstance(pos, Actor):
            pos = pos.center
        logger.debug(f"Creating Cylinder actor at: {pos}")

        # Get point at top of cylinder
        top = pos.copy()
        top[1] = root.bounds()[2] - 500

        # Create mesh and Actor
        mesh = shapes.Cylinder(pos=[top, pos], c=color, r=radius, alpha=alpha)
        Actor.__init__(self, mesh, name="Cylinder", br_class="Cylinder")
Exemple #4
0
    def __init__(self, data, name=None, colors="salmon", alpha=1, radius=20):
        """
            Creates an actor representing multiple points (more efficient than 
            creating many Point instances).

            :param data: np.ndarray, Nx3 array or path to .npy file with coords data
            :param radius: float
            :param color: str, or list of str with color names or hex codes
            :param alpha: float
            :param name: str, actor name
        """
        PointsBase.__init__(self)

        self.radius = radius
        self.colors = colors
        self.alpha = alpha
        self.name = name

        if isinstance(data, np.ndarray):
            mesh = self._from_numpy(data)
        elif isinstance(data, (str, Path)):
            mesh = self._from_file(data)
        else:  # pragma: no cover
            raise TypeError(  # pragma: no cover
                f"Input data should be either a numpy array or a file path, not: {_class_name(data)}"  # pragma: no cover
            )  # pragma: no cover

        Actor.__init__(self, mesh, name=self.name, br_class="Points")
Exemple #5
0
    def __init__(self, *args, ROIs=None, **kwargs):
        self.ROIs = ROIs or [
            (0, self.length),
        ]

        ProbeGeometry.__init__(self, *args, **kwargs)
        Actor.__init__(self, self.get_mesh(), name="Probe", br_class="Probe")
Exemple #6
0
    def __init__(self,
                 data,
                 name=None,
                 dims=(40, 40, 40),
                 radius=None,
                 **kwargs):
        """
        Creates a Volume actor showing the 3d density of a set
        of points.

        :param data: np.ndarray, Nx3 array with cell coordinates


        from vedo:
            Generate a density field from a point cloud. Input can also be a set of 3D coordinates.
            Output is a ``Volume``.
            The local neighborhood is specified as the `radius` around each sample position (each voxel).
            The density is expressed as the number of counts in the radius search.

            :param int,list dims: numer of voxels in x, y and z of the output Volume.

        """
        logger.debug("Creating a PointsDensity actor")

        # flip coordinates on XY axis to match brainrender coordinates system
        # data[:, 2] = -data[:, 2]

        # create volume and then actor
        volume = (vPoints(data).density(dims=dims, radius=radius,
                                        **kwargs).c("Dark2").alpha([0, 0.9
                                                                    ]).mode(1)
                  )  # returns a vedo Volume
        volume.mirror("z")
        Actor.__init__(self, volume, name=name, br_class="density")
Exemple #7
0
    def add_actor(self, *actors, name=None, br_class=None, store=None):
        """
        Add a vtk actor to the scene

        :param actor:
        :param store: a list to store added actors

        """
        # Parse inputs to match a name and br class to each actor
        actors, names, br_classes = parse_add_actors_inputs(
            actors, name, br_class)

        # Add actors to scene
        to_return = []
        for actor, name, br_class in zip(actors, names, br_classes):
            for act in listify(actor):
                if act is None:
                    continue

                try:
                    act = Actor(act, name=name, br_class=br_class)
                except Exception:  # doesn't work for annotations
                    act.name = name
                    act.br_class = br_class
                    act._is_transformed = False

                if store is None:
                    self.actors.append(act)
                else:
                    store.append(act)
                to_return.append(act)

        return return_list_smart(to_return)
Exemple #8
0
    def add(self, *items, names=None, classes=None, **kwargs):
        """
            General method to add Actors to the scene.

            :param items: vedo.Mesh, Actor, (str, Path).   
                    If str/path it should be a path to a .obj or .stl file.
                    Whatever the input it's turned into an instance of Actor
                    before adding it to the scne
                
            :param names: names to be assigned to the Actors
            :param classs: br_classes to be assigned to the Actors
            :param **kwargs: parameters to be passed to the individual 
                loading functions (e.g. to load from file and specify the color)
        """
        names = names or [None for a in items]
        classes = classes or [None for a in items]

        # turn items into Actors
        actors = []
        for item, name, _class in zip(items, listify(names), listify(classes)):
            if item is None:
                continue

            if isinstance(item, (Mesh, Assembly)):
                actors.append(Actor(item, name=name, br_class=_class))

            elif pi.utils._class_name(item) == "vtkCornerAnnotation":
                # Mark text actors differently because they don't behave like
                # other 3d actors
                actors.append(
                    Actor(
                        item,
                        name=name,
                        br_class=_class,
                        is_text=True,
                        **kwargs,
                    ))
            elif pi.utils._class_name(item) == "Volume" and not isinstance(
                    item, Volume):
                actors.append(
                    Volume(item, name=name, br_class=_class, **kwargs))

            elif isinstance(item, Actor):
                actors.append(item)

            elif isinstance(item, (str, Path)):
                mesh = load_mesh_from_file(item, **kwargs)
                name = name or Path(item).name
                _class = _class or "from file"
                actors.append(Actor(mesh, name=name, br_class=_class))

            else:
                raise ValueError(
                    f"Unrecognized argument: {item} [{pi.utils._class_name(item)}]"
                )

        # Add to the lists actors
        self.actors.extend(actors)
        return return_list_smart(actors)
Exemple #9
0
    def __init__(
        self,
        griddata,
        voxel_size=1,
        cmap="bwr",
        min_quantile=None,
        min_value=None,
        name=None,
        br_class=None,
        as_surface=True,
        **volume_kwargs,
    ):
        """
            Takes a 3d numpy array with volumetric data
            and returns an Actor with mesh: vedo.Volume.isosurface or a vedo.Volume.
            BY default the volume is represented as a surface

            To extract the surface:
                The isosurface needs a lower bound threshold, this can be
                either a user defined hard value (min_value) or the value
                corresponding to some percentile of the grid data.

            :param griddata: np.ndarray, 3d array with grid data
            :param voxel_size: int, size of each voxel in microns
            :param min_quantile: float, percentile for threshold
            :param min_value: float, value for threshold
            :param cmap: str, name of colormap to use
            :param as_surface, bool. default True. If True
                a surface mesh is returned instead of the whole volume
            :param volume_kwargs: keyword arguments for vedo's Volume class
        """
        # Create mesh
        color = volume_kwargs.pop("c", "viridis")
        if isinstance(griddata, np.ndarray):
            # create volume from data
            mesh = VedoVolume(
                griddata,
                spacing=[voxel_size, voxel_size, voxel_size],
                c=color,
                **volume_kwargs,
            )
        else:
            mesh = griddata  # assume a vedo Volume was passed

        if as_surface:
            # Get threshold
            if min_quantile is None and min_value is None:
                th = 0
            elif min_value is not None:
                th = min_value
            else:
                th = np.percentile(griddata.ravel(), min_quantile)

            mesh = mesh.legosurface(vmin=th, cmap=cmap)

        Actor.__init__(self,
                       mesh,
                       name=name or "Volume",
                       br_class=br_class or "Volume")
Exemple #10
0
    def get_plane(
        self,
        pos=None,
        norm=None,
        plane=None,
        sx=None,
        sy=None,
        color="lightgray",
        alpha=0.25,
        **kwargs,
    ):
        """
        Returns a plane going through a point at pos, oriented
        orthogonally to the vector norm and of width and height
        sx, sy.

        :param pos: 3-tuple or list with x,y,z, coords of point the plane goes through
        :param norm: 3-tuple with plane's normal vector (optional)
        :param sx, sy: int, width and height of the plane
        :param plane: "sagittal", "horizontal", or "frontal"
        :param color, alpha: plane color and transparency
        """
        axes_pairs = dict(sagittal=(0, 1), horizontal=(2, 0), frontal=(2, 1))

        if pos is None:
            pos = self.root.centerOfMass()

        try:
            norm = norm or self.space.plane_normals[plane]
        except KeyError:  # pragma: no cover
            raise ValueError(  # pragma: no cover
                f"Could not find normals for plane {plane}. Atlas space provides these normals: {self.space.plane_normals}"  # pragma: no cover
            )

        # Get plane width and height
        idx_pair = (
            axes_pairs[plane]
            if plane is not None
            else axes_pairs["horizontal"]
        )

        bounds = self.root.bounds()
        root_bounds = [
            [bounds[0], bounds[1]],
            [bounds[2], bounds[3]],
            [bounds[4], bounds[5]],
        ]

        wh = [float(np.diff(root_bounds[i])) for i in idx_pair]
        if sx is None:
            sx = wh[0]
        if sy is None:
            sy = wh[1]

        # return plane
        return Actor(
            Plane(pos=pos, normal=norm, sx=sx, sy=sy, c=color, alpha=alpha),
            name=f"Plane at {pos} norm: {norm}",
            br_class="plane",
        )
Exemple #11
0
    def __init__(self, data, radius=10, color="salmon", alpha=1, name=None):
        """
            Turns streamlines data to a mesh.
            :param data: pd.DataFrame with streamlines points data
            :param radius: float. Radius of the Tube mesh used to render streamlines
            :param color: str, name of the color to be used
            :param alpha: float, transparancy
            :param name: str, name of the actor.
        """
        if not isinstance(data, pd.DataFrame):
            raise TypeError("Input data should be a dataframe")

        self.radius = radius
        mesh = self._make_mesh(data).c(color).alpha(alpha)

        name = name or "Streamlines"
        Actor.__init__(self, mesh, name=name, br_class="Streamliness")
Exemple #12
0
 def __init__(self,
              pos,
              radius=100,
              color="blackboard",
              alpha=1,
              res=25,
              name=None):
     """
         Creates an actor representing a single point
         :param pos: list or np.ndarray with coordinates
         :param radius: float
         :param color: str,
         :param alpha: float
         :param res: int, resolution of mesh
         :param name: str, actor name
     """
     mesh = Sphere(pos=pos, r=radius, c=color, alpha=alpha, res=res)
     name = name or "Point"
     Actor.__init__(self, mesh, name=name, br_class="Point")
Exemple #13
0
    def get_region(self, *regions, alpha=1, color=None):
        """
        Get brain regions meshes as Actors
        :param regions: str with names of brain regions in the atlas
        :param alpha: float
        :param color: str
        """
        if not regions:
            return None

        _color = color
        actors = []
        for region in regions:
            if (
                region not in self.lookup_df.acronym.values
                and region not in self.lookup_df["id"].values
            ):
                print(
                    f"The region {region} doesn't seem to belong to the atlas being used: {self.atlas_name}. Skipping"
                )
                continue

            # Get mesh
            obj_file = str(self.meshfile_from_structure(region))
            mesh = load_mesh_from_file(obj_file, color=color, alpha=alpha)

            # Get color
            if color is None:
                color = [
                    x / 255
                    for x in self._get_from_structure(region, "rgb_triplet")
                ]

            # Make actor
            actor = Actor(mesh, name=region, br_class="brain region")
            actor.c(color).alpha(alpha)
            actors.append(actor)

            # reset color to input
            color = _color

        return return_list_smart(actors)
Exemple #14
0
    def __init__(
        self,
        neuron,
        color=None,
        alpha=1,
        neurite_radius=8,
        soma_radius=15,
        name=None,
    ):
        """
        Creates an Actor representing a single neuron's morphology
        :param neuron: path to .swc file, Mesh, Actor or Neuron from morphapi.morphology
        :param alpha: float
        :param color: str,
        :param neuron_radius: float, radius of axon/dendrites
        :param soma_radius: float, radius of soma
        :param name: str, actor name
        """
        logger.debug(f"Creating a Neuron actor")
        if color is None:
            color = "blackboard"
        alpha = alpha
        self.neurite_radius = neurite_radius
        self.soma_radius = soma_radius
        self.name = None

        if isinstance(neuron, (str, Path)):
            mesh = self._from_file(neuron)
        elif isinstance(neuron, (Mesh)):
            mesh = neuron
        elif isinstance(neuron, Actor):
            mesh = neuron.mesh
        elif isinstance(neuron, MorphoNeuron):
            mesh = self._from_morphapi_neuron(neuron)
        else:
            raise ValueError(
                f'Argument "neuron" is not in a recognized format: {_class_name(neuron)}'
            )

        Actor.__init__(self, mesh, name=self.name, br_class="Neuron")
        self.mesh.c(color).alpha(alpha)
Exemple #15
0
def ruler(p1, p2, unit_scale=1, units=None, s=50):
    """ 
        Creates a ruler showing the distance between two points.
        The ruler is composed of a line between the points and 
        a text indicating the distance.

        :param p1: list, np.ndarray with coordinates of first point
        :param p2: list, np.ndarray with coordinates of second point
        :param unit_scale: float. To scale the units (e.g. show mm instead of µm)
        :param units: str, name of unit (e.g. 'mm')
        :param s: float size of text

    """
    actors = []

    # Make two line segments
    midpoint = np.array([(x + y) / 2 for x, y in zip(p1, p2)])
    gap1 = ((midpoint - p1) * 0.8) + p1
    gap2 = ((midpoint - p2) * 0.8) + p2

    actors.append(Line(p1, gap1, lw=200))
    actors.append(Line(gap2, p2, lw=200))

    # Add label
    if units is None:  # pragma: no cover
        units = ""  # pragma: no cover
    dist = mag(p2 - p1) * unit_scale
    label = precision(dist, 3) + " " + units
    lbl = Text(label, pos=midpoint, s=s + 100, justify="center")
    lbl.SetOrientation([0, 0, 180])
    actors.append(lbl)

    # Add spheres add end
    actors.append(Sphere(p1, r=s, c=[0.3, 0.3, 0.3]))
    actors.append(Sphere(p2, r=s, c=[0.3, 0.3, 0.3]))

    act = Actor(merge(*actors), name="Ruler", br_class="Ruler")
    act.c((0.3, 0.3, 0.3)).alpha(1).lw(2)
    return act
Exemple #16
0
def test_neuron():

    s = Scene(title="BR")

    neuron = s.add(Neuron("tests/files/neuron1.swc"))
    s.add(Neuron(Actor(neuron.mesh)))
    s.add(Neuron(neuron.mesh))
    Neuron(Sphere())

    with pytest.raises(ValueError):
        Neuron(1)

    with pytest.raises(FileExistsError):
        Neuron("tests/files/neuronsfsfs.swc")
    with pytest.raises(NotImplementedError):
        Neuron("tests/files/random_cells.h5")

    del s