def addScalarBar( self, pos=(0.8, 0.05), title="", titleXOffset=0, titleYOffset=15, titleFontSize=12, nlabels=None, c=None, horizontal=False, useAlpha=True, ): """ Add a 2D scalar bar for the specified obj. .. hint:: |mesh_coloring| |mesh_coloring.py|_ |scalarbars.py|_ """ import vtkplotter.addons as addons self.scalarbar = addons.addScalarBar( self, pos, title, titleXOffset, titleYOffset, titleFontSize, nlabels, c, horizontal, useAlpha, ) return self
def buttonfunc(): global cmap bu.switch() cmap = bu.status() for mesh in visibles: if mesh: mesh.pointColors(cmap=cmap) vp.renderer.RemoveActor(mesh.scalarbar) mesh.scalarbar = addons.addScalarBar(mesh, pos=(0.04, 0.0), horizontal=True, titleFontSize=0) vp.renderer.AddActor(mesh.scalarbar)
def addScalarBar(self, actor=None, c=None, title="", horizontal=False, vmin=None, vmax=None): """Add a 2D scalar bar for the specified actor. If `actor` is ``None`` will add it to the last actor in ``self.actors``. .. hint:: |mesh_bands| |mesh_bands.py|_ """ return addons.addScalarBar(actor, c, title, horizontal, vmin, vmax)
def buttonfunc(): global _cmap_slicer bu.switch() _cmap_slicer = bu.status() for mesh in visibles: if mesh: mesh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: mesh.mapPointsToCells() vp.renderer.RemoveActor(mesh.scalarbar) mesh.scalarbar = addScalarBar(mesh, pos=(0.04, 0.0), horizontal=True, titleFontSize=0) vp.renderer.AddActor(mesh.scalarbar)
def show( self, *actors, **options # at=None, # axes=None, # c=None, # alpha=None, # wire=False, # bc=None, # resetcam=True, # zoom=False, # interactive=None, # rate=None, # viewup="", # azimuth=0, # elevation=0, # roll=0, # interactorStyle=0, # q=False, ): """ Render a list of actors. Allowed input objects are: ``filename``, ``vtkPolyData``, ``vtkActor``, ``vtkActor2D``, ``vtkImageActor``, ``vtkAssembly`` or ``vtkVolume``. If filename is given, its type is guessed based on its extension. Supported formats are: `vtu, vts, vtp, ply, obj, stl, 3ds, xml, neutral, gmsh, pcd, xyz, txt, byu, tif, slc, vti, mhd, png, jpg`. :param int at: number of the renderer to plot to, if more than one exists :param int axes: set the type of axes to be shown - 0, no axes, - 1, draw three gray grid walls - 2, show cartesian axes from (0,0,0) - 3, show positive range of cartesian axes from (0,0,0) - 4, show a triad at bottom left - 5, show a cube at bottom left - 6, mark the corners of the bounding box - 7, draw a simple ruler at the bottom of the window - 8, show the ``vtkCubeAxesActor`` object, - 9, show the bounding box outLine, - 10, show three circles representing the maximum bounding box :param c: surface color, in rgb, hex or name formats :param bc: set a color for the internal surface face :param bool wire: show actor in wireframe representation :param float azimuth/elevation/roll: move camera accordingly :param str viewup: either ['x', 'y', 'z'] or a vector to set vertical direction :param bool resetcam: re-adjust camera position to fit objects :param bool interactive: pause and interact with window (True) or continue execution (False) :param float rate: maximum rate of `show()` in Hertz :param int interactorStyle: set the type of interaction - 0, TrackballCamera - 1, TrackballActor - 2, JoystickCamera - 3, Unicam - 4, Flight - 5, RubberBand3D - 6, RubberBandZoom :param bool q: force program to quit after `show()` command returns. """ if not hasattr(self, 'window'): return at = options.pop("at", None) axes = options.pop("axes", None) c = options.pop("c", None) alpha = options.pop("alpha", None) wire = options.pop("wire", False) bc = options.pop("bc", None) resetcam = options.pop("resetcam", True) zoom = options.pop("zoom", False) interactive = options.pop("interactive", None) rate = options.pop("rate", None) viewup = options.pop("viewup", "") azimuth = options.pop("azimuth", 0) elevation = options.pop("elevation", 0) roll = options.pop("roll", 0) interactorStyle = options.pop("interactorStyle", 0) q = options.pop("q", False) if self.offscreen: interactive = False self.interactive = False def scan(wannabeacts): scannedacts = [] if not utils.isSequence(wannabeacts): wannabeacts = [wannabeacts] for a in wannabeacts: # scan content of list if isinstance(a, vtk.vtkActor): scannedacts.append(a) if hasattr(a, 'trail' ) and a.trail and not a.trail in self.actors: scannedacts.append(a.trail) elif isinstance(a, vtk.vtkAssembly): scannedacts.append(a) if a.trail and not a.trail in self.actors: scannedacts.append(a.trail) elif isinstance(a, vtk.vtkActor2D): if isinstance(a, vtk.vtkCornerAnnotation): for a2 in settings.collectable_actors: if isinstance(a2, vtk.vtkCornerAnnotation): if at in a2.renderedAt: # remove old message self.removeActor(a2) scannedacts.append(a) elif isinstance(a, vtk.vtkImageActor): scannedacts.append(a) elif isinstance(a, vtk.vtkVolume): scannedacts.append(a) elif isinstance(a, vtk.vtkImageData): scannedacts.append(Volume(a)) elif isinstance(a, vtk.vtkPolyData): scannedacts.append(Actor(a, c, alpha, wire, bc)) elif isinstance(a, str): # assume a filepath was given out = vtkio.load(a, c, alpha, wire, bc) if isinstance(out, str): colors.printc("~times File not found:", out, c=1) scannedacts.append(None) else: scannedacts.append(out) elif "dolfin" in str(type(a)): # assume a dolfin.Mesh object from vtkplotter.dolfin import MeshActor out = MeshActor(a, c=c, alpha=alpha, wire=True, bc=bc) scannedacts.append(out) elif a is None: pass elif isinstance(a, vtk.vtkUnstructuredGrid): gf = vtk.vtkGeometryFilter() gf.SetInputData(a) gf.Update() scannedacts.append( Actor(gf.GetOutput(), c, alpha, wire, bc)) elif isinstance(a, vtk.vtkStructuredGrid): gf = vtk.vtkGeometryFilter() gf.SetInputData(a) gf.Update() scannedacts.append( Actor(gf.GetOutput(), c, alpha, wire, bc)) elif isinstance(a, vtk.vtkRectilinearGrid): gf = vtk.vtkRectilinearGridGeometryFilter() gf.SetInputData(a) gf.Update() scannedacts.append( Actor(gf.GetOutput(), c, alpha, wire, bc)) elif isinstance(a, vtk.vtkMultiBlockDataSet): for i in range(a.GetNumberOfBlocks()): b = a.GetBlock(i) if isinstance(b, vtk.vtkPolyData): scannedacts.append(Actor(b, c, alpha, wire, bc)) elif isinstance(b, vtk.vtkImageData): scannedacts.append(Volume(b)) else: colors.printc("~!? Cannot understand input in show():", type(a), c=1) scannedacts.append(None) return scannedacts if len(actors) == 0: actors = None elif len(actors) == 1: actors = actors[0] else: actors = utils.flatten(actors) if actors is not None: self.actors = [] actors2show = scan(actors) for a in actors2show: if a not in self.actors: self.actors.append(a) else: actors2show = scan(self.actors) self.actors = list(actors2show) if axes is not None: self.axes = axes if interactive is not None: self.interactive = interactive if at is None and len(self.renderers) > 1: # in case of multiple renderers a call to show w/o specifing # at which renderer will just render the whole thing and return if self.interactor: if zoom: self.camera.Zoom(zoom) self.interactor.Render() if self.interactive: self.interactor.Start() return if at is None: at = 0 if at < len(self.renderers): self.renderer = self.renderers[at] else: colors.printc("~times Error in show(): wrong renderer index", at, c=1) return if not self.camera: self.camera = self.renderer.GetActiveCamera() self.camera.SetParallelProjection(self.infinity) if self.camThickness: self.camera.SetThickness(self.camThickness) if self.sharecam: for r in self.renderers: r.SetActiveCamera(self.camera) if len(self.renderers) == 1: self.renderer.SetActiveCamera(self.camera) # rendering for ia in actors2show: # add the actors that are not already in scene if ia: if isinstance(ia, vtk.vtkVolume): self.renderer.AddVolume(ia) else: self.renderer.AddActor(ia) if hasattr(ia, 'renderedAt'): ia.renderedAt.add(at) else: colors.printc( "~lightning Warning: Invalid actor in actors list, skip.", c=5) # remove the ones that are not in actors2show for ia in self.getActors(at): if ia not in actors2show: self.renderer.RemoveActor(ia) if hasattr(ia, 'renderedAt'): ia.renderedAt.discard(at) for c in self.scalarbars: self.renderer.RemoveActor(c) if hasattr(c, 'renderedAt'): c.renderedAt.discard(at) if self.axes is not None: addons.addAxes() addons.addLegend() if self.showFrame and len(self.renderers) > 1: addons.addFrame() if resetcam or self.initializedIren == False: self.renderer.ResetCamera() if not self.initializedIren and self.interactor: self.initializedIren = True self.interactor.Initialize() self.interactor.RemoveObservers("CharEvent") if self.verbose and self.interactive: docs.onelinetip() self.initializedPlotter = True if zoom: self.camera.Zoom(zoom) if azimuth: self.camera.Azimuth(azimuth) if elevation: self.camera.Elevation(elevation) if roll: self.camera.Roll(roll) if len(viewup): if viewup == "x": viewup = [1, 0, 0] elif viewup == "y": viewup = [0, 1, 0] elif viewup == "z": viewup = [0, 0, 1] self.camera.Azimuth(60) self.camera.Elevation(30) self.camera.Azimuth(0.01) # otherwise camera gets locked self.camera.SetViewUp(viewup) self.renderer.ResetCameraClippingRange() self.window.Render() scbflag = False for a in self.actors: if (hasattr(a, "scalarbar") and a.scalarbar is not None and utils.isSequence(a.scalarbar)): if len(a.scalarbar) == 5: # addScalarBar s1, s2, s3, s4, s5 = a.scalarbar sb = addons.addScalarBar(a, s1, s2, s3, s4, s5) scbflag = True a.scalarbar = sb # save scalarbar actor elif len(a.scalarbar) == 10: # addScalarBar3D s0, s1, s2, s3, s4, s5, s6, s7, s8 = a.scalarbar sb = addons.addScalarBar3D(a, at, s0, s1, s2, s3, s4, s5, s6, s7, s8) scbflag = True a.scalarbar = sb # save scalarbar actor if scbflag: self.window.Render() if settings.allowInteraction and not self.offscreen: self.allowInteraction() if settings.interactorStyle is not None: interactorStyle = settings.interactorStyle if interactorStyle == 0 or interactorStyle == "TrackballCamera": pass # do nothing elif interactorStyle == 1 or interactorStyle == "TrackballActor": self.interactor.SetInteractorStyle( vtk.vtkInteractorStyleTrackballActor()) elif interactorStyle == 2 or interactorStyle == "JoystickCamera": self.interactor.SetInteractorStyle( vtk.vtkInteractorStyleJoystickCamera()) elif interactorStyle == 3 or interactorStyle == "Unicam": self.interactor.SetInteractorStyle(vtk.vtkInteractorStyleUnicam()) elif interactorStyle == 4 or interactorStyle == "Flight": self.interactor.SetInteractorStyle(vtk.vtkInteractorStyleFlight()) elif interactorStyle == 5 or interactorStyle == "RubberBand3D": self.interactor.SetInteractorStyle( vtk.vtkInteractorStyleRubberBand3D()) elif interactorStyle == 6 or interactorStyle == "RubberBandZoom": self.interactor.SetInteractorStyle( vtk.vtkInteractorStyleRubberBandZoom()) if self.interactor and self.interactive: self.interactor.Start() if rate: if self.clock is None: # set clock and limit rate self._clockt0 = time.time() self.clock = 0.0 else: t = time.time() - self._clockt0 elapsed = t - self.clock mint = 1.0 / rate if elapsed < mint: time.sleep(mint - elapsed) self.clock = time.time() - self._clockt0 if q: # gracefully exit if self.verbose: print("q flag set to True. Exit.") sys.exit(0)
def slicer( volume, alpha=1, cmaps=('gist_ncar_r', "hot_r", "bone_r", "jet", "Spectral_r"), map2cells=False, # buggy clamp=True, useSlider3D=False, size=(850, 700), screensize="auto", title="", bg="white", bg2="lightblue", axes=1, showHisto=True, showIcon=True, draggable=False, verbose=True, ): """ Generate a ``Plotter`` window with slicing planes for the input Volume. Returns the ``Plotter`` object. :param float alpha: transparency of the slicing planes :param list cmaps: list of color maps names to cycle when clicking button :param bool map2cells: scalars are mapped to cells, not intepolated. :param bool clamp: clamp scalar to reduce the effect of tails in color mapping :param bool useSlider3D: show sliders attached along the axes :param list size: rendering window size in pixels :param list screensize: size of the screen can be specified :param str title: window title :param bg: background color :param bg2: background gradient color :param int axes: axis type number :param bool showHisto: show histogram on bottom left :param bool showIcon: show a small 3D rendering icon of the volume :param bool draggable: make the icon draggable """ global _cmap_slicer if verbose: printc("Slicer tool", invert=1, c="m") ################################ vp = Plotter(bg=bg, bg2=bg2, size=size, screensize=screensize, title=title, interactive=False, verbose=verbose) ################################ box = volume.box().wireframe().alpha(0) vp.show(box, viewup="z", axes=axes) if showIcon: vp.showInset(volume, pos=(.85, .85), size=0.15, c='w', draggable=draggable) # inits la, ld = 0.7, 0.3 #ambient, diffuse dims = volume.dimensions() data = volume.getPointArray() rmin, rmax = volume.imagedata().GetScalarRange() sbwidth = 800 if clamp: hdata, edg = np.histogram(data, bins=50) logdata = np.log(hdata + 1) # mean of the logscale plot meanlog = np.sum(np.multiply(edg[:-1], logdata)) / np.sum(logdata) rmax = min(rmax, meanlog + (meanlog - rmin) * 0.9) rmin = max(rmin, meanlog - (rmax - meanlog) * 0.9) if verbose: printc('scalar range clamped to: (' + precision(rmin, 3) + ', ' + precision(rmax, 3) + ')', c='m', bold=0) _cmap_slicer = cmaps[0] visibles = [None, None, None] msh = volume.zSlice(int(dims[2] / 2)) msh.alpha(alpha).lighting('', la, ld, 0) msh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: msh.mapPointsToCells() vp.renderer.AddActor(msh) visibles[2] = msh addScalarBar(msh, pos=(0.04, 0.0), horizontal=True, width=sbwidth, vmin=rmin, vmax=rmax, titleFontSize=0) def sliderfunc_x(widget, event): i = int(widget.GetRepresentation().GetValue()) msh = volume.xSlice(i).alpha(alpha).lighting('', la, ld, 0) msh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: msh.mapPointsToCells() vp.renderer.RemoveActor(visibles[0]) if i and i < dims[0]: vp.renderer.AddActor(msh) visibles[0] = msh def sliderfunc_y(widget, event): i = int(widget.GetRepresentation().GetValue()) msh = volume.ySlice(i).alpha(alpha).lighting('', la, ld, 0) msh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: msh.mapPointsToCells() vp.renderer.RemoveActor(visibles[1]) if i and i < dims[1]: vp.renderer.AddActor(msh) visibles[1] = msh def sliderfunc_z(widget, event): i = int(widget.GetRepresentation().GetValue()) msh = volume.zSlice(i).alpha(alpha).lighting('', la, ld, 0) msh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: msh.mapPointsToCells() vp.renderer.RemoveActor(visibles[2]) if i and i < dims[2]: vp.renderer.AddActor(msh) visibles[2] = msh cx, cy, cz, ch = 'dr', 'dg', 'db', (0.3, 0.3, 0.3) if np.sum(vp.renderer.GetBackground()) < 1.5: cx, cy, cz = 'lr', 'lg', 'lb' ch = (0.8, 0.8, 0.8) if not useSlider3D: vp.addSlider2D(sliderfunc_x, 0, dims[0], title='X', pos=[(0.8, 0.12), (0.95, 0.12)], showValue=False, c=cx) vp.addSlider2D(sliderfunc_y, 0, dims[1], title='Y', pos=[(0.8, 0.08), (0.95, 0.08)], showValue=False, c=cy) vp.addSlider2D(sliderfunc_z, 0, dims[2], title='Z', value=int(dims[2] / 2), pos=[(0.8, 0.04), (0.95, 0.04)], showValue=False, c=cz) else: # 3d sliders attached to the axes bounds bs = box.bounds() vp.addSlider3D( sliderfunc_x, pos1=(bs[0], bs[2], bs[4]), pos2=(bs[1], bs[2], bs[4]), xmin=0, xmax=dims[0], t=box.diagonalSize() / mag(box.xbounds()) * 0.6, c=cx, showValue=False, ) vp.addSlider3D( sliderfunc_y, pos1=(bs[1], bs[2], bs[4]), pos2=(bs[1], bs[3], bs[4]), xmin=0, xmax=dims[1], t=box.diagonalSize() / mag(box.ybounds()) * 0.6, c=cy, showValue=False, ) vp.addSlider3D( sliderfunc_z, pos1=(bs[0], bs[2], bs[4]), pos2=(bs[0], bs[2], bs[5]), xmin=0, xmax=dims[2], value=int(dims[2] / 2), t=box.diagonalSize() / mag(box.zbounds()) * 0.6, c=cz, showValue=False, ) ################# def buttonfunc(): global _cmap_slicer bu.switch() _cmap_slicer = bu.status() for mesh in visibles: if mesh: mesh.pointColors(cmap=_cmap_slicer, vmin=rmin, vmax=rmax) if map2cells: mesh.mapPointsToCells() vp.renderer.RemoveActor(mesh.scalarbar) mesh.scalarbar = addScalarBar(mesh, pos=(0.04, 0.0), horizontal=True, width=sbwidth, vmin=rmin, vmax=rmax, titleFontSize=0) vp.renderer.AddActor(mesh.scalarbar) bu = vp.addButton( buttonfunc, pos=(0.27, 0.005), states=cmaps, c=["db"] * len(cmaps), bc=["lb"] * len(cmaps), # colors of states size=14, bold=True, ) ################# hist = None if showHisto: hist = cornerHistogram(data, s=0.2, bins=25, logscale=1, pos=(0.02, 0.02), c=ch, bg=ch, alpha=0.7) # vp.backgroundRenderer = vtk.vtkRenderer() # vp.backgroundRenderer.SetLayer(1) # vp.backgroundRenderer.InteractiveOff() # actor = histogram(data, logscale=1, alpha=0.8).scale(4/150) # vp.window.AddRenderer(vp.backgroundRenderer) # vp.backgroundRenderer.AddActor(actor) # cam = vtk.vtkCamera() # cam.SetPosition( -10,-10, 40) # #actor.SetPosition(-4,-4, 0) # actor.SetOrigin(-8,-8,0) # cam.SetParallelScale(1) # vp.backgroundRenderer.SetActiveCamera(cam) # vp.backgroundRenderer.ResetCameraClippingRange() comment = None if verbose: comment = Text2D( "Use sliders to slice volume\nClick button to change colormap", font='Montserrat', s=0.8) vp.show(msh, hist, comment, interactive=False) vp.interactive = True if verbose: printc("Press button to cycle through color maps:\n", cmaps, c="m") printc("Use sliders to select the slicing planes.", c="m") return vp