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)
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", )
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)
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
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)
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