def _inputsort(obj): import dolfin u = None mesh = None if not utils.isSequence(obj): obj = [obj] for ob in obj: inputtype = str(type(ob)) #printc('inputtype is', inputtype, c=2) if "vtk" in inputtype: # skip vtk objects, will be added later continue if "dolfin" in inputtype or "ufl" in inputtype: if "MeshFunction" in inputtype: mesh = ob.mesh() if ob.dim() > 0: printc('MeshFunction of dim>0 not supported.', c=1) printc('Try e.g.: MeshFunction("size_t", mesh, 0)', c=1, italic=1) printc('instead of MeshFunction("size_t", mesh, 1)', c=1, strike=1) else: #printc(ob.dim(), mesh.num_cells(), len(mesh.coordinates()), len(ob.array())) V = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.Function(V) v2d = dolfin.vertex_to_dof_map(V) u.vector()[v2d] = ob.array() elif "Function" in inputtype or "Expression" in inputtype: u = ob elif "Mesh" in inputtype: mesh = ob elif "algebra" in inputtype: mesh = ob.ufl_domain() #print('algebra', ob.ufl_domain()) if "str" in inputtype: mesh = dolfin.Mesh(ob) if u and not mesh and hasattr(u, "function_space"): V = u.function_space() if V: mesh = V.mesh() if u and not mesh and hasattr(u, "mesh"): mesh = u.mesh() #printc('------------------------------------') #printc('mesh.topology dim=', mesh.topology().dim()) #printc('mesh.geometry dim=', mesh.geometry().dim()) #if u: printc('u.value_rank()', u.value_rank()) #if u and u.value_rank(): printc('u.value_dimension()', u.value_dimension(0)) # axis=0 ##if u: printc('u.value_shape()', u.value_shape()) return (mesh, u)
def cylinder(pos=[0, 0, 0], r=1, height=1, axis=[0, 0, 1], c='teal', wire=0, alpha=1, legend=None, texture=None, res=24): ''' Build a cylinder of specified height and radius r, centered at pos. If pos is a list of 2 points, e.g. pos=[v1,v2], build a cylinder with base centered at v1 and top at v2. [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/gyroscope1.py) [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/turing.py) ''' if utils.isSequence(pos[0]): # assume user is passing pos=[base, top] base = np.array(pos[0]) top = np.array(pos[1]) pos = (base + top) / 2 height = np.linalg.norm(top - base) axis = top - base axis = utils.norm(axis) else: axis = utils.norm(axis) base = pos - axis * height / 2 top = pos + axis * height / 2 cyl = vtk.vtkCylinderSource() cyl.SetResolution(res) cyl.SetRadius(r) cyl.SetHeight(height) cyl.Update() theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) t = vtk.vtkTransform() t.PostMultiply() t.RotateX(90) # put it along Z t.RotateY(theta * 57.3) t.RotateZ(phi * 57.3) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(cyl.GetOutput()) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c, alpha, wire, legend=legend, texture=texture) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) actor.base = base actor.top = top return actor
def _inputsort_dolfinx(obj): # dolfinx import dolfin u = None mesh = None if not utils.isSequence(obj): obj = [obj] for ob in obj: inputtype = str(type(ob)) #print('inputtype is', inputtype) if "vtk" in inputtype: # skip vtk objects, will be added later continue if "dolfin" in inputtype or "ufl" in inputtype: if "MeshFunction" in inputtype: mesh = ob.mesh # dolfin 2019.2 if ob.dim > 0: print('MeshFunction of dim>0 not supported.') print('Try e.g.: MeshFunction("size_t", mesh, 0)') print('instead of MeshFunction("size_t", mesh, 1)') else: #print(ob.dim, mesh.num_cells, len(mesh.coordinates, len(ob.array())) V = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.Function(V) v2d = dolfin.vertex_to_dof_map(V) u.vector[v2d] = ob.array elif "Function" in inputtype or "Expression" in inputtype: u = ob mesh = ob.function_space.mesh elif "Mesh" in inputtype: mesh = ob elif "algebra" in inputtype: mesh = ob.ufl_domain #print('algebra', ob.ufl_domain) if "str" in inputtype: mesh = dolfin.Mesh(ob) if u and not mesh and hasattr(u, "function_space"): V = u.function_space if V: mesh = V.mesh if u and not mesh and hasattr(u, "mesh"): mesh = u.function_space.mesh print('------------------------------------') print('mesh.topology dim=', mesh.topology.dim) print('mesh.geometry dim=', mesh.geometry.dim) if u: print('u.value_rank', u.value_rank) if u and u.value_rank: print('u.value_dimension', u.value_dimension(0)) # axis=0 if u: print('u.value_shape', u.value_shape()) return (mesh, u)
def importWindow(fileinput): """Import a whole scene from a Numpy file. Return ``Plotter`` instance.""" from vtkplotter import Plotter data = np.load(fileinput, allow_pickle=True, encoding="latin1").flatten()[0] if 'renderPointsAsSpheres' in data.keys(): settings.renderPointsAsSpheres = data['renderPointsAsSpheres'] if 'renderLinesAsTubes' in data.keys(): settings.renderLinesAsTubes = data['renderLinesAsTubes'] if 'hiddenLineRemoval' in data.keys(): settings.hiddenLineRemoval = data['hiddenLineRemoval'] if 'visibleGridEdges' in data.keys(): settings.visibleGridEdges = data['visibleGridEdges'] if 'interactorStyle' in data.keys(): settings.interactorStyle = data['interactorStyle'] if 'useParallelProjection' in data.keys(): settings.useParallelProjection = data['useParallelProjection'] axes = data.pop('axes', 4) title = data.pop('title', '') backgrcol = data.pop('backgrcol', "blackboard") vp = Plotter( #size=data['size'], # not necessarily a good idea to set it #shape=data['shape'], axes=axes, title=title, bg=backgrcol, ) vp.xtitle = data.pop('xtitle', 'x') vp.ytitle = data.pop('ytitle', 'y') vp.ztitle = data.pop('ztitle', 'z') if 'objects' in data.keys(): objs = loadNumpy(data['objects']) if not utils.isSequence(objs): objs = [objs] else: colors.printc("Trying to import a that was not exported.", c=1) colors.printc(" -> try to load a single object with load().", c=1) return loadNumpy(fileinput) vp.actors = objs # if vp.shape==(1,1): # vp.actors = loadNumpy(data['objects']) # else: # print(objs, ) # for a in objs: # for ar in a.renderedAt: # print(vp.shape, [a], ar ) # vp.show(a, at=ar) return vp
def line(p0, p1=None, lw=1, tube=False, dotted=False, c='r', alpha=1., legend=None): '''Build the line segment between points p0 and p1. if p0 is a list of points returns the line connecting them. if tube=True, lines are rendered as tubes of radius lw ''' #detect if user is passing a list of points: if vu.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline poly = vtk.vtkPolyData() for i in range(len(p0)): p = p0[i] ppoints.InsertPoint(i, p[0], p[1], p[2]) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) lineSource.Update() poly = lineSource.GetOutput() if tube: tuf = vtk.vtkTubeFilter() tuf.SetNumberOfSides(12) #tuf.CappingOn() vu.setInput(tuf, poly) tuf.SetRadius(lw) tuf.Update() poly = tuf.GetOutput() actor = vu.makeActor(poly, c, alpha, legend=legend) actor.GetProperty().SetInterpolationToPhong() else: actor = vu.makeActor(poly, c, alpha, legend=legend) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xf0f0) actor.GetProperty().SetLineStippleRepeatFactor(1) setattr(actor, 'base', np.array(p0)) setattr(actor, 'top', np.array(p1)) return actor
def points(plist, r=4, c='k', alpha=1, legend=None): ''' Build a point ``Actor`` for a list of points. :param r: point radius. :type r: float :param c: color name, number, or list of [R,G,B] colors of same length as plist. :type c: int, str, list :param float alpha: transparency in range [0,1]. .. hint:: Example: `lorenz.py <https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/lorenz.py>`_ .. image:: https://user-images.githubusercontent.com/32848391/46818115-be7a6380-cd80-11e8-8ffb-60af2631bf71.png ''' n = len(plist) if n == 0: return None elif n == 3: # assume plist is in the format [all_x, all_y, all_z] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], plist[2])) elif n == 2: # assume plist is in the format [all_x, all_y, 0] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], [0] * len(plist[0]))) if utils.isSequence(c) and utils.isSequence(c[0]) and len(c[0]) == 3: return _colorPoints(plist, c, r, alpha, legend) n = len(plist) # refresh src = vtk.vtkPointSource() src.SetNumberOfPoints(n) src.Update() pd = src.GetOutput() if n == 1: # passing just one point pd.GetPoints().SetPoint(0, [0, 0, 0]) else: pd.GetPoints().SetData(numpy_to_vtk(plist, deep=True)) actor = Actor(pd, c, alpha, legend=legend) actor.GetProperty().SetPointSize(r) if n == 1: actor.SetPosition(plist[0]) return actor
def medianSmooth(self, neighbours=(2, 2, 2)): """Median filter that replaces each pixel with the median value from a rectangular neighborhood around that pixel. """ imgm = vtk.vtkImageMedian3D() imgm.SetInputData(self.imagedata()) if utils.isSequence(neighbours): imgm.SetKernelSize(neighbours[0], neighbours[1], neighbours[2]) else: imgm.SetKernelSize(neighbours, neighbours, neighbours) imgm.Update() return self._update(imgm.GetOutput())
def points(self, pts=None, transformed=True, copy=False): """ Set/Get the vertex coordinates of the mesh. Argument can be an index, a set of indices or a complete new set of points to update the mesh. :param bool transformed: if `False` ignore any previous transformation applied to the mesh. :param bool copy: if `False` return the reference to the points so that they can be modified in place, otherwise a copy is built. """ if pts is None: ### getter vpts = self._ugrid.GetPoints() if vpts: if copy: return np.array(vtk_to_numpy(vpts.GetData())) else: return vtk_to_numpy(vpts.GetData()) else: return np.array([]) elif (utils.isSequence(pts) and not utils.isSequence(pts[0])) or isinstance( pts, (int, np.integer)): #passing a list of indices or a single index return vtk_to_numpy( self.polydata(transformed).GetPoints().GetData())[pts] else: ### setter if len(pts) == 3 and len(pts[0]) != 3: # assume plist is in the format [all_x, all_y, all_z] pts = np.stack((pts[0], pts[1], pts[2]), axis=1) vpts = self._ugrid.GetPoints() vpts.SetData(numpy_to_vtk(np.ascontiguousarray(pts), deep=True)) self._ugrid.GetPoints().Modified() # reset mesh to identity matrix position/rotation: self.PokeMatrix(vtk.vtkMatrix4x4()) return self
def importWindow(fileinput): """Import a whole scene from a Numpy file. Return ``Plotter`` instance.""" import numpy as np from vtkplotter import Plotter data = np.load(fileinput, allow_pickle=True)[0] if 'renderPointsAsSpheres' in data.keys(): settings.renderPointsAsSpheres = data['renderPointsAsSpheres'] if 'renderLinesAsTubes' in data.keys(): settings.renderLinesAsTubes = data['renderLinesAsTubes'] if 'hiddenLineRemoval' in data.keys(): settings.hiddenLineRemoval = data['hiddenLineRemoval'] if 'visibleGridEdges' in data.keys(): settings.visibleGridEdges = data['visibleGridEdges'] if 'interactorStyle' in data.keys(): settings.interactorStyle = data['interactorStyle'] if 'useParallelProjection' in data.keys(): settings.useParallelProjection = data['useParallelProjection'] pos = data.pop('position', (0, 0)) axes = data.pop('axes', 4) title = data.pop('title', '') backgrcol = data.pop('backgrcol', "blackboard") vp = Plotter( pos=pos, #size=data['size'], # not necessarily a good idea to set it #shape=data['shape'], axes=axes, title=title, bg=backgrcol, ) vp.xtitle = data.pop('xtitle', 'x') vp.ytitle = data.pop('ytitle', 'y') vp.ztitle = data.pop('ztitle', 'z') objs = loadNumpy(data['objects']) if not utils.isSequence(objs): objs = [objs] vp.actors = objs # if vp.shape==(1,1): # vp.actors = loadNumpy(data['objects']) # else: # print(objs, ) # for a in objs: # for ar in a.renderedAt: # print(vp.shape, [a], ar ) # vp.show(a, at=ar) return vp
def gaussianSmooth(self, sigma=(2, 2, 2), radius=None): """Performs a convolution of the input Volume with a gaussian. :param float,list sigma: standard deviation(s) in voxel units. A list can be given to smooth in the three direction differently. :param float,list radius: radius factor(s) determine how far out the gaussian kernel will go before being clamped to zero. A list can be given too. """ gsf = vtk.vtkImageGaussianSmooth() gsf.SetDimensionality(3) gsf.SetInputData(self.imagedata()) if utils.isSequence(sigma): gsf.SetStandardDeviations(sigma) else: gsf.SetStandardDeviation(sigma) if radius is not None: if utils.isSequence(radius): gsf.SetRadiusFactors(radius) else: gsf.SetRadiusFactor(radius) gsf.Update() return self._update(gsf.GetOutput())
def add(self, actors): """Append input object to the internal list of actors to be shown. :return: returns input actor for possible concatenation. """ if utils.isSequence(actors): for a in actors: if a not in self.actors: self.actors.append(a) return None else: self.actors.append(actors) return actors
def Cylinder( pos=(0, 0, 0), r=1, height=1, axis=(0, 0, 1), c="teal", alpha=1, res=24): """ Build a cylinder of specified height and radius `r`, centered at `pos`. If `pos` is a list of 2 Points, e.g. `pos=[v1,v2]`, build a cylinder with base centered at `v1` and top at `v2`. |Cylinder| """ if utils.isSequence(pos[0]): # assume user is passing pos=[base, top] base = np.array(pos[0]) top = np.array(pos[1]) pos = (base + top) / 2 height = np.linalg.norm(top - base) axis = top - base axis = utils.versor(axis) else: axis = utils.versor(axis) base = pos - axis * height / 2 top = pos + axis * height / 2 cyl = vtk.vtkCylinderSource() cyl.SetResolution(res) cyl.SetRadius(r) cyl.SetHeight(height) cyl.Update() theta = np.arccos(axis[2]) phi = np.arctan2(axis[1], axis[0]) t = vtk.vtkTransform() t.PostMultiply() t.RotateX(90) # put it along Z t.RotateY(np.rad2deg(theta)) t.RotateZ(np.rad2deg(phi)) tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(cyl.GetOutput()) tf.SetTransform(t) tf.Update() pd = tf.GetOutput() actor = Actor(pd, c, alpha) actor.GetProperty().SetInterpolationToPhong() actor.SetPosition(pos) actor.base = base + pos actor.top = top + pos settings.collectable_actors.append(actor) return actor
def showInset(self, *actors, **options): #pos=3, size=0.1, c='r', draggable=True): """Add a draggable inset space into a renderer. :param pos: icon position in the range [1-4] indicating one of the 4 corners, or it can be a tuple (x,y) as a fraction of the renderer size. :param float size: size of the square inset. :param bool draggable: if True the subrenderer space can be dragged around. .. hint:: |inset| |inset.py|_ """ pos = options.pop("pos", None) size = options.pop("size", 0.1) c = options.pop("c", 'r') draggable = options.pop("draggable", True) if not self.renderer: colors.printc( "~lightningWarning: Use showInset() after first rendering the scene.", c=3) save_int = self.interactive self.show(interactive=0) self.interactive = save_int widget = vtk.vtkOrientationMarkerWidget() r, g, b = colors.getColor(c) widget.SetOutlineColor(r, g, b) if len(actors) == 1: widget.SetOrientationMarker(actors[0]) else: widget.SetOrientationMarker(Assembly(utils.flatten(actors))) widget.SetInteractor(self.interactor) if utils.isSequence(pos): widget.SetViewport(pos[0] - size, pos[1] - size, pos[0] + size, pos[1] + size) else: if pos < 2: widget.SetViewport(0, 1 - 2 * size, size * 2, 1) elif pos == 2: widget.SetViewport(1 - 2 * size, 1 - 2 * size, 1, 1) elif pos == 3: widget.SetViewport(0, 0, size * 2, size * 2) elif pos == 4: widget.SetViewport(1 - 2 * size, 0, 1, size * 2) widget.EnabledOn() widget.SetInteractive(draggable) self.widgets.append(widget) for a in actors: if a in self.actors: self.actors.remove(a) return widget
def points(plist, c='k', r=4, alpha=1, legend=None): ''' Build a vtkActor for a list of points. c can be a list of [R,G,B] colors of same length as plist [**Example**](https://github.com/marcomusy/vtkplotter/blob/master/examples/basic/lorenz.py) ![lorenz](https://user-images.githubusercontent.com/32848391/46818115-be7a6380-cd80-11e8-8ffb-60af2631bf71.png) ''' n = len(plist) if n == 0: return None elif n == 3: # assume plist is in the format [all_x, all_y, all_z] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], plist[2])) elif n == 2: # assume plist is in the format [all_x, all_y, 0] if utils.isSequence(plist[0]) and len(plist[0]) > 3: plist = list(zip(plist[0], plist[1], [0] * len(plist[0]))) if utils.isSequence(c) and utils.isSequence(c[0]) and len(c[0]) == 3: return _colorPoints(plist, c, r, alpha, legend) n = len(plist) # refresh src = vtk.vtkPointSource() src.SetNumberOfPoints(n) src.Update() pd = src.GetOutput() if n == 1: # passing just one point pd.GetPoints().SetPoint(0, [0, 0, 0]) else: pd.GetPoints().SetData(numpy_to_vtk(plist, deep=True)) actor = Actor(pd, c, alpha, legend=legend) actor.GetProperty().SetPointSize(r) if n == 1: actor.SetPosition(plist[0]) return actor
def isosurface(self, threshold=True, connectivity=False): """Return an ``Mesh`` isosurface extracted from the ``Volume`` object. :param threshold: value or list of values to draw the isosurface(s) :type threshold: float, list :param bool connectivity: if True only keeps the largest portion of the polydata |isosurfaces| |isosurfaces.py|_ """ scrange = self._imagedata.GetScalarRange() cf = vtk.vtkContourFilter() cf.SetInputData(self._imagedata) cf.UseScalarTreeOn() cf.ComputeScalarsOn() cf.ComputeNormalsOn() if utils.isSequence(threshold): cf.SetNumberOfContours(len(threshold)) for i, t in enumerate(threshold): cf.SetValue(i, t) cf.Update() else: if threshold is True: threshold = (2 * scrange[0] + scrange[1]) / 3.0 print('automatic threshold set to ' + utils.precision(threshold, 3), end=' ') print('in [' + utils.precision(scrange[0], 3) + ', ' + utils.precision(scrange[1], 3) + ']') cf.SetValue(0, threshold) cf.Update() clp = vtk.vtkCleanPolyData() clp.SetInputConnection(cf.GetOutputPort()) clp.Update() poly = clp.GetOutput() if connectivity: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetExtractionModeToLargestRegion() conn.SetInputData(poly) conn.Update() poly = conn.GetOutput() a = Mesh(poly, c=None).phong() a._mapper.SetScalarRange(scrange[0], scrange[1]) return a
def __init__(self, obj=None): vtk.vtkImageActor.__init__(self) ActorBase.__init__(self) if utils.isSequence(obj) and len(obj): iac = vtk.vtkImageAppendComponents() for i in range(3): #arr = np.flip(np.flip(array[:,:,i], 0), 0).ravel() arr = np.flip(obj[:, :, i], 0).ravel() varb = numpy_to_vtk(arr, deep=True, array_type=vtk.VTK_UNSIGNED_CHAR) imgb = vtk.vtkImageData() imgb.SetDimensions(obj.shape[1], obj.shape[0], 1) imgb.GetPointData().SetScalars(varb) iac.AddInputData(0, imgb) iac.Update() img = iac.GetOutput() self.SetInputData(img) elif isinstance(obj, vtk.vtkImageData): self.SetInputData(obj) img = obj elif isinstance(obj, str): if ".png" in obj: picr = vtk.vtkPNGReader() elif ".jpg" in obj or ".jpeg" in obj: picr = vtk.vtkJPEGReader() elif ".bmp" in obj: picr = vtk.vtkBMPReader() elif ".tif" in obj: picr = vtk.vtkTIFFReader() else: colors.printc("Cannot understand picture format", obj, c=1) picr.SetFileName(obj) picr.Update() img = picr.GetOutput() self.SetInputData(img) else: img = vtk.vtkImageData() self.SetInputData(img) self._imagedata = img self._mapper = self.GetMapper()
def MeshLines(*inputobj, **options): """ Build the line segments between two lists of points `startPoints` and `endPoints`. `startPoints` can be also passed in the form ``[[point1, point2], ...]``. A dolfin ``Mesh`` that was deformed/modified by a function can be passed together as inputs. :param float scale: apply a rescaling factor to the length """ scale = options.pop("scale", 1) lw = options.pop("lw", 1) c = options.pop("c", 'grey') alpha = options.pop("alpha", 1) mesh, u = _inputsort(inputobj) if not mesh: return None if hasattr(mesh, "coordinates"): startPoints = mesh.coordinates() else: startPoints = mesh.geometry.points u_values = _compute_uvalues(u, mesh) if not utils.isSequence(u_values[0]): printc("~times Error: cannot show Lines for 1D scalar values!", c=1) raise RuntimeError() endPoints = startPoints + u_values if u_values.shape[1] == 2: # u_values is 2D u_values = np.insert(u_values, 2, 0, axis=1) # make it 3d startPoints = np.insert(startPoints, 2, 0, axis=1) # make it 3d endPoints = np.insert(endPoints, 2, 0, axis=1) # make it 3d actor = shapes.Lines(startPoints, endPoints, scale=scale, lw=lw, c=c, alpha=alpha) actor.mesh = mesh actor.u = u actor.u_values = u_values return actor
def color(self, col): """Assign a color or a set of colors to a volume along the range of the scalar value. A single constant color can also be assigned. Any matplotlib color map name is also accepted, e.g. ``volume.color('jet')``. E.g.: say that your voxel scalar runs from -3 to 6, and you want -3 to show red and 1.5 violet and 6 green, then just set: ``volume.color(['red', 'violet', 'green'])`` """ smin, smax = self._imagedata.GetScalarRange() volumeProperty = self.GetProperty() ctf = vtk.vtkColorTransferFunction() self._color = col if utils.isSequence(col): for i, ci in enumerate(col): r, g, b = colors.getColor(ci) xalpha = smin + (smax - smin) * i / (len(col) - 1) ctf.AddRGBPoint(xalpha, r, g, b) #colors.printc('\tcolor at', round(xalpha, 1), # '\tset to', colors.getColorName((r, g, b)), c='b', bold=0) elif isinstance(col, str): if col in colors.colors.keys() or col in colors.color_nicks.keys(): r, g, b = colors.getColor(col) ctf.AddRGBPoint(smin, r, g, b) # constant color ctf.AddRGBPoint(smax, r, g, b) elif colors._mapscales: for x in np.linspace(smin, smax, num=64, endpoint=True): r, g, b = colors.colorMap(x, name=col, vmin=smin, vmax=smax) ctf.AddRGBPoint(x, r, g, b) elif isinstance(col, int): r, g, b = colors.getColor(col) ctf.AddRGBPoint(smin, r, g, b) # constant color ctf.AddRGBPoint(smax, r, g, b) else: colors.printc("volume.color(): unknown input type:", col, c=1) volumeProperty.SetColor(ctf) volumeProperty.SetInterpolationTypeToLinear() #volumeProperty.SetInterpolationTypeToNearest() return self
def alphaGradient(self, alphaGrad): """ Assign a set of tranparencies to a volume's gradient along the range of the scalar value. A single constant value can also be assigned. The gradient function is used to decrease the opacity in the "flat" regions of the volume while maintaining the opacity at the boundaries between material types. The gradient is measured as the amount by which the intensity changes over unit distance. The format for alphaGrad is the same as for method ``volume.alpha()``. |read_vti| |read_vti.py|_ """ self._alphaGrad = alphaGrad volumeProperty = self.GetProperty() if alphaGrad is None: volumeProperty.DisableGradientOpacityOn() return self else: volumeProperty.DisableGradientOpacityOff() #smin, smax = self._imagedata.GetScalarRange() smin, smax = 0, 255 gotf = volumeProperty.GetGradientOpacity() if utils.isSequence(alphaGrad): alphaGrad = np.array(alphaGrad) if len(alphaGrad.shape ) == 1: # user passing a flat list e.g. (0.0, 0.3, 0.9, 1) for i, al in enumerate(alphaGrad): xalpha = smin + (smax - smin) * i / (len(alphaGrad) - 1) # Create transfer mapping scalar value to gradient opacity gotf.AddPoint(xalpha, al) elif len(alphaGrad.shape) == 2: # user passing [(x0,alpha0), ...] gotf.AddPoint(smin, alphaGrad[0][1]) for xalpha, al in alphaGrad: # Create transfer mapping scalar value to opacity gotf.AddPoint(xalpha, al) gotf.AddPoint(smax, alphaGrad[-1][1]) #colors.printc("alphaGrad at", round(xalpha, 1), "\tset to", al, c="b", bold=0) else: gotf.AddPoint(smin, alphaGrad) # constant alphaGrad gotf.AddPoint(smax, alphaGrad) return self
def MeshArrows(*inputobj, **options): """ Build arrows representing displacements. :param float s: cross-section size of the arrow :param float rescale: apply a rescaling factor to the length """ s = options.pop("s", None) scale = options.pop("scale", 1) c = options.pop("c", "gray") alpha = options.pop("alpha", 1) res = options.pop("res", 12) mesh, u = _inputsort(inputobj) if not mesh: return None if hasattr(mesh, "coordinates"): startPoints = mesh.coordinates() else: startPoints = mesh.geometry.points u_values = _compute_uvalues(u, mesh) if not utils.isSequence(u_values[0]): printc("~times Error: cannot show Arrows for 1D scalar values!", c=1) raise RuntimeError() endPoints = startPoints + u_values if u_values.shape[1] == 2: # u_values is 2D u_values = np.insert(u_values, 2, 0, axis=1) # make it 3d startPoints = np.insert(startPoints, 2, 0, axis=1) # make it 3d endPoints = np.insert(endPoints, 2, 0, axis=1) # make it 3d actor = shapes.Arrows(startPoints, endPoints, s=s, scale=scale, alpha=alpha, res=res) actor.color(c) actor.mesh = mesh actor.u = u actor.u_values = u_values return actor
def line(p0, p1=None, lw=1, c='r', alpha=1, dotted=False, legend=None): ''' Build the line segment between points `p0` and `p1`. If `p0` is a list of points returns the line connecting them. :param lw: line width. :param c: color name, number, or list of [R,G,B] colors. :type c: int, str, list :param float alpha: transparency in range [0,1]. :param bool dotted: draw a dotted line ''' # detect if user is passing a list of points: if utils.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline dim = len((p0[0])) if dim == 2: for i in range(len(p0)): p = p0[i] ppoints.InsertPoint(i, p[0], p[1], 0) else: ppoints.SetData(numpy_to_vtk(p0, deep=True)) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly = vtk.vtkPolyData() poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) lineSource.Update() poly = lineSource.GetOutput() actor = Actor(poly, c, alpha, legend=legend) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xf0f0) actor.GetProperty().SetLineStippleRepeatFactor(1) actor.base = np.array(p0) actor.top = np.array(p1) return actor
def clear(self, actors=()): """Delete specified list of actors, by default delete all.""" if not utils.isSequence(actors): actors = [actors] if len(actors): for a in actors: self.removeActor(a) else: settings.collectable_actors = [] self.actors = [] for a in self.getActors(): self.renderer.RemoveActor(a) for s in self.sliders: s.EnabledOff() for b in self.buttons: self.renderer.RemoveActor(b) for w in self.widgets: w.EnabledOff() for c in self.scalarbars: self.renderer.RemoveActor(c)
def alpha(self, alpha): """ Assign a set of tranparencies along the range of the scalar value. A single constant value can also be assigned. E.g.: say alpha=(0.0, 0.3, 0.9, 1) and the scalar range goes from -10 to 150. Then all tets with a value close to -10 will be completely transparent, tets at 1/4 of the range will get an alpha equal to 0.3 and voxels with value close to 150 will be completely opaque. As a second option one can set explicit (x, alpha_x) pairs to define the transfer function. E.g.: say alpha=[(-5, 0), (35, 0.4) (123,0.9)] and the scalar range goes from -10 to 150. Then all tets below -5 will be completely transparent, tets with a scalar value of 35 will get an opacity of 40% and above 123 alpha is set to 90%. """ smin, smax = self._ugrid.GetScalarRange() otf = self.GetProperty().GetScalarOpacity() otf.RemoveAllPoints() self._alpha = alpha if utils.isSequence(alpha): alpha = np.array(alpha) if len(alpha.shape ) == 1: # user passing a flat list e.g. (0.0, 0.3, 0.9, 1) for i, al in enumerate(alpha): xalpha = smin + (smax - smin) * i / (len(alpha) - 1) # Create transfer mapping scalar value to opacity otf.AddPoint(xalpha, al) elif len(alpha.shape) == 2: # user passing [(x0,alpha0), ...] otf.AddPoint(smin, alpha[0][1]) for xalpha, al in alpha: # Create transfer mapping scalar value to opacity otf.AddPoint(xalpha, al) otf.AddPoint(smax, alpha[-1][1]) #colors.printc("alpha at", round(xalpha, 1), "\tset to", al) else: otf.AddPoint(smin, alpha) # constant alpha otf.AddPoint(smax, alpha) return self
def _parse(self, objs, t, duration): if t is None: if self._lastT: t = self._lastT else: t = 0.0 if duration is None: if self._lastDuration: duration = self._lastDuration else: duration = 0.0 if objs is None: if self._lastActs: objs = self._lastActs else: printc('Need to specify actors!', c=1) raise RuntimeError objs2 = objs if utils.isSequence(objs): objs2 = objs else: objs2 = [objs] #quantize time steps and duration t = int(t / self.timeResolution + 0.5) * self.timeResolution nsteps = int(duration / self.timeResolution + 0.5) duration = nsteps * self.timeResolution rng = np.linspace(t, t + duration, nsteps + 1) self._lastT = t self._lastDuration = duration self._lastActs = objs2 for a in objs2: if a not in self.actors: self.actors.append(a) return objs2, t, duration, rng
def _buildugrid(self, points, cells): if len(points) == 0: return None if not utils.isSequence(points[0]): return None ug = vtk.vtkUnstructuredGrid() sourcePoints = vtk.vtkPoints() varr = numpy_to_vtk(np.ascontiguousarray(points), deep=True) sourcePoints.SetData(varr) ug.SetPoints(sourcePoints) sourceTets = vtk.vtkCellArray() for f in cells: ele = vtk.vtkTetra() pid = ele.GetPointIds() for i, fi in enumerate(f): pid.SetId(i, fi) sourceTets.InsertNextCell(ele) ug.SetCells(vtk.VTK_TETRA, sourceTets) return ug
def append(self, volumes, axis='z', preserveExtents=False): """ Take the components from multiple inputs and merges them into one output. Except for the append axis, all inputs must have the same extent. All inputs must have the same number of scalar components. The output has the same origin and spacing as the first input. The origin and spacing of all other inputs are ignored. All inputs must have the same scalar type. :param int,str axis: axis expanded to hold the multiple images. :param bool preserveExtents: if True, the extent of the inputs is used to place the image in the output. The whole extent of the output is the union of the input whole extents. Any portion of the output not covered by the inputs is set to zero. The origin and spacing is taken from the first input. .. code-block:: python from vtkplotter import load, datadir vol = load(datadir+'embryo.tif') vol.append(vol, axis='x').show() """ ima = vtk.vtkImageAppend() ima.SetInputData(self.imagedata()) if not utils.isSequence(volumes): volumes = [volumes] for volume in volumes: if isinstance(volume, vtk.vtkImageData): ima.AddInputData(volume) else: ima.AddInputData(volume.imagedata()) ima.SetPreserveExtents(preserveExtents) if axis == "x": axis = 0 elif axis == "y": axis = 1 elif axis == "z": axis = 2 ima.SetAppendAxis(axis) ima.Update() return self._update(ima.GetOutput())
def delaunay3D(mesh, alphaPar=0, tol=None, boundary=False): """Create 3D Delaunay triangulation of input points.""" deln = vtk.vtkDelaunay3D() if utils.isSequence(mesh): pd = vtk.vtkPolyData() vpts = vtk.vtkPoints() vpts.SetData(numpy_to_vtk(np.ascontiguousarray(mesh), deep=True)) pd.SetPoints(vpts) deln.SetInputData(pd) else: deln.SetInputData(mesh.GetMapper().GetInput()) deln.SetAlpha(alphaPar) deln.AlphaTetsOn() deln.AlphaTrisOff() deln.AlphaLinesOff() deln.AlphaVertsOff() if tol: deln.SetTolerance(tol) deln.SetBoundingTriangulation(boundary) deln.Update() m = TetMesh(deln.GetOutput()) return m
def addIcon(iconActor, pos=3, size=0.08): """Add an inset icon mesh into the renderer. :param pos: icon position in the range [1-4] indicating one of the 4 corners, or it can be a tuple (x,y) as a fraction of the renderer size. :param float size: size of the icon space. .. hint:: |icon| |icon.py|_ """ vp = settings.plotter_instance if not vp.renderer: colors.printc( "~lightningWarning: Use addIcon() after first rendering the scene.", c=3) save_int = vp.interactive vp.show(interactive=0) vp.interactive = save_int widget = vtk.vtkOrientationMarkerWidget() widget.SetOrientationMarker(iconActor) widget.SetInteractor(vp.interactor) if utils.isSequence(pos): widget.SetViewport(pos[0] - size, pos[1] - size, pos[0] + size, pos[1] + size) else: if pos < 2: widget.SetViewport(0, 1 - 2 * size, size * 2, 1) elif pos == 2: widget.SetViewport(1 - 2 * size, 1 - 2 * size, 1, 1) elif pos == 3: widget.SetViewport(0, 0, size * 2, size * 2) elif pos == 4: widget.SetViewport(1 - 2 * size, 0, 1, size * 2) widget.EnabledOn() widget.InteractiveOff() vp.widgets.append(widget) if iconActor in vp.actors: vp.actors.remove(iconActor) return widget
def line(p0, p1=None, lw=1, dotted=False, c='r', alpha=1, legend=None): ''' Build the line segment between points p0 and p1. If p0 is a list of points returns the line connecting them. ''' # detect if user is passing a list of points: if utils.isSequence(p0[0]): ppoints = vtk.vtkPoints() # Generate the polyline dim = len((p0[0])) if dim == 2: for i in range(len(p0)): p = p0[i] ppoints.InsertPoint(i, p[0], p[1], 0) else: ppoints.SetData(numpy_to_vtk(p0, deep=True)) lines = vtk.vtkCellArray() # Create the polyline. lines.InsertNextCell(len(p0)) for i in range(len(p0)): lines.InsertCellPoint(i) poly = vtk.vtkPolyData() poly.SetPoints(ppoints) poly.SetLines(lines) else: # or just 2 points to link lineSource = vtk.vtkLineSource() lineSource.SetPoint1(p0) lineSource.SetPoint2(p1) lineSource.Update() poly = lineSource.GetOutput() actor = Actor(poly, c, alpha, legend=legend) actor.GetProperty().SetLineWidth(lw) if dotted: actor.GetProperty().SetLineStipplePattern(0xf0f0) actor.GetProperty().SetLineStippleRepeatFactor(1) actor.base = np.array(p0) actor.top = np.array(p1) return actor
def MeshArrows(*inputobj, **options): """ Build arrows representing displacements. :param float s: cross-section size of the arrow :param float rescale: apply a rescaling factor to the length """ s = options.pop("s", None) scale = options.pop("scale", 1) c = options.pop("c", "gray") alpha = options.pop("alpha", 1) res = options.pop("res", 12) mesh, u = _inputsort(inputobj) startPoints = mesh.coordinates() u_values = np.array([u(p) for p in mesh.coordinates()]) if not utils.isSequence(u_values[0]): printc("~times Error: cannot show Arrows for 1D scalar values!", c=1) exit() endPoints = mesh.coordinates() + u_values if u_values.shape[1] == 2: # u_values is 2D u_values = np.insert(u_values, 2, 0, axis=1) # make it 3d startPoints = np.insert(startPoints, 2, 0, axis=1) # make it 3d endPoints = np.insert(endPoints, 2, 0, axis=1) # make it 3d actor = shapes.Arrows(startPoints, endPoints, s=s, scale=scale, c=c, alpha=alpha, res=res) actor.mesh = mesh actor.u = u actor.u_values = u_values return actor