def toMesh(self, fill=True, shrink=1.0): """ Build a polygonal Mesh from the current TetMesh. If fill=True, the interior traingular faces of all the tets are created. In this case setting a `shrink` value slightly smaller than 1.0 can avoid flickering due to adjacent faces. If fill=False, only the boundary triangles are generated. """ gf = vtk.vtkGeometryFilter() if fill: sf = vtk.vtkShrinkFilter() sf.SetInputData(self._ugrid) sf.SetShrinkFactor(shrink) sf.Update() gf.SetInputData(sf.GetOutput()) gf.Update() else: gf.SetInputData(self._ugrid) gf.Update() poly = gf.GetOutput() msh = Mesh(poly).flat() msh.scalarbar = self.scalarbar lut = utils.ctf2lut(self) msh._mapper.SetLookupTable(lut) if self.useCells: msh._mapper.SetScalarModeToUseCellData() else: msh._mapper.SetScalarModeToUsePointData() # msh._mapper.SetScalarRange(msh._mapper.GetScalarRange()) # print(msh._mapper.GetScalarRange(), lut.GetRange()) # msh._mapper.SetScalarRange() # msh.selectCellArray('chem_0') return msh
def slicePlane(self, origin=(0, 0, 0), normal=(1, 1, 1)): """Extract the slice along a given plane position and normal. |slicePlane| |slicePlane.py|_ """ reslice = vtk.vtkImageReslice() reslice.SetInputData(self._imagedata) reslice.SetOutputDimensionality(2) newaxis = utils.versor(normal) pos = np.array(origin) initaxis = (0, 0, 1) crossvec = np.cross(initaxis, newaxis) angle = np.arccos(np.dot(initaxis, newaxis)) T = vtk.vtkTransform() T.PostMultiply() T.RotateWXYZ(np.rad2deg(angle), crossvec) T.Translate(pos) M = T.GetMatrix() reslice.SetResliceAxes(M) reslice.SetInterpolationModeToLinear() reslice.Update() vslice = vtk.vtkImageDataGeometryFilter() vslice.SetInputData(reslice.GetOutput()) vslice.Update() msh = Mesh(vslice.GetOutput()) msh.SetOrientation(T.GetOrientation()) msh.SetPosition(pos) return msh
def loadDolfin(filename, exterior=False): """Reads a `Fenics/Dolfin` file format (.xml or .xdmf). Return an ``Mesh(vtkActor)`` object.""" import sys if sys.version_info[0] < 3: return _loadDolfin_old(filename) import dolfin if filename.lower().endswith('.xdmf'): f = dolfin.XDMFFile(filename) m = dolfin.Mesh() f.read(m) else: m = dolfin.Mesh(filename) bm = dolfin.BoundaryMesh(m, "exterior") if exterior: poly = utils.buildPolyData(bm.points(), bm.cells(), fast=True) else: polyb = utils.buildPolyData(bm.points(), bm.cells(), fast=True) polym = utils.buildPolyData(m.points(), m.cells(), fast=True) app = vtk.vtkAppendPolyData() app.AddInputData(polym) app.AddInputData(polyb) app.Update() poly = app.GetOutput() return Mesh(poly).lw(0.1)
def loadNeutral(filename): """Reads a `Neutral` tetrahedral file format. Return an ``Mesh(vtkActor)`` object.""" f = open(filename, "r") lines = f.readlines() f.close() ncoords = int(lines[0]) coords = [] for i in range(1, ncoords + 1): x, y, z = lines[i].split() coords.append([float(x), float(y), float(z)]) ntets = int(lines[ncoords + 1]) idolf_tets = [] for i in range(ncoords + 2, ncoords + ntets + 2): text = lines[i].split() v0, v1, v2, v3 = int(text[1])-1, int(text[2])-1, int(text[3])-1, int(text[4])-1 # p0, p1, p2, p3 = np.array(coords[v1]), np.array(coords[v0]), coords[v3], coords[v2] # d10 = p1-p0 # d21 = p2-p1 # dc = np.cross(d10, d21) # print(np.dot(dc,p3-p0)) idolf_tets.append([v0, v1, v2, v3]) poly = utils.buildPolyData(coords, idolf_tets) return Mesh(poly)
def isosurface(self, threshold=True): """Return a ``Mesh`` isosurface. :param float,list threshold: value or list of values to draw the isosurface(s) """ if not self._ugrid.GetPointData().GetScalars(): self.mapCellsToPoints() scrange = self._ugrid.GetPointData().GetScalars().GetRange() cf = vtk.vtkContourFilter() #vtk.vtkContourGrid() cf.SetInputData(self._ugrid) 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.SetInputData(cf.GetOutput()) clp.Update() msh = Mesh(clp.GetOutput(), c=None).phong() msh._mapper.SetLookupTable(utils.ctf2lut(self)) return msh
def loadGmesh(filename): """Reads a `gmesh` file format. Return an ``Mesh(vtkActor)`` object.""" f = open(filename, "r") lines = f.readlines() f.close() nnodes = 0 index_nodes = 0 for i, line in enumerate(lines): if "$Nodes" in line: index_nodes = i + 1 nnodes = int(lines[index_nodes]) break node_coords = [] for i in range(index_nodes + 1, index_nodes + 1 + nnodes): cn = lines[i].split() node_coords.append([float(cn[1]), float(cn[2]), float(cn[3])]) nelements = 0 index_elements = 0 for i, line in enumerate(lines): if "$Elements" in line: index_elements = i + 1 nelements = int(lines[index_elements]) break elements = [] for i in range(index_elements + 1, index_elements + 1 + nelements): ele = lines[i].split() elements.append([int(ele[-3]), int(ele[-2]), int(ele[-1])]) poly = utils.buildPolyData(node_coords, elements, indexOffset=1) return Mesh(poly)
def loadGeoJSON(filename): """Load GeoJSON files.""" if filename.endswith('.gz'): filename = gunzip(filename) jr = vtk.vtkGeoJSONReader() jr.SetFileName(filename) jr.Update() return Mesh(jr.GetOutput())
def ySlice(self, j): """Extract the slice at index `j` of volume along y-axis.""" vslice = vtk.vtkImageDataGeometryFilter() vslice.SetInputData(self.imagedata()) nx, ny, nz = self.imagedata().GetDimensions() if j > ny - 1: j = ny - 1 vslice.SetExtent(0, nx, j, j, 0, nz) vslice.Update() return Mesh(vslice.GetOutput())
def xSlice(self, i): """Extract the slice at index `i` of volume along x-axis.""" vslice = vtk.vtkImageDataGeometryFilter() vslice.SetInputData(self.imagedata()) nx, ny, nz = self.imagedata().GetDimensions() if i > nx - 1: i = nx - 1 vslice.SetExtent(i, i, 0, ny, 0, nz) vslice.Update() return Mesh(vslice.GetOutput())
def zSlice(self, k): """Extract the slice at index `i` of volume along z-axis.""" vslice = vtk.vtkImageDataGeometryFilter() vslice.SetInputData(self.imagedata()) nx, ny, nz = self.imagedata().GetDimensions() if k > nz - 1: k = nz - 1 vslice.SetExtent(0, nx, 0, ny, k, k) vslice.Update() return Mesh(vslice.GetOutput())
def toPoints(self): """Extract all image voxels as points. This function takes an input ``Volume`` and creates an ``Mesh`` that contains the points and the point attributes. See example script: |vol2points.py|_ """ v2p = vtk.vtkImageToPoints() v2p.SetInputData(self.imagedata()) v2p.Update() mpts = Mesh(v2p.GetOutput()) return mpts
def __init__(self, *inputobj, **options): c = options.pop("c", None) alpha = options.pop("alpha", 1) exterior = options.pop("exterior", False) fast = options.pop("fast", False) computeNormals = options.pop("computeNormals", False) mesh, u = _inputsort(inputobj) if not mesh: return if exterior: import dolfin meshc = dolfin.BoundaryMesh(mesh, 'exterior') else: meshc = mesh if hasattr(mesh, "coordinates"): coords = mesh.coordinates() else: coords = mesh.geometry.points poly = utils.buildPolyData(coords, meshc.cells(), fast=fast, tetras=True) Mesh.__init__( self, poly, c=c, alpha=alpha, computeNormals=computeNormals, ) self.mesh = mesh # holds a dolfin Mesh obj self.u = u # holds a dolfin function_data # holds the actual values of u on the mesh self.u_values = _compute_uvalues(u, mesh)
def loadPDB(filename, bondScale=1, hydrogenBondScale=1, coilWidth=0.3, helixWidth=1.3): """Reads a molecule Protein Data Bank file.""" rr = vtk.vtkPDBReader() rr.SetFileName('1btn.pdb') rr.SetBScale(bondScale) rr.SetHBScale(hydrogenBondScale) rr.Update() prf = vtk.vtkProteinRibbonFilter() prf.SetCoilWidth(coilWidth) prf.SetHelixWidth(helixWidth) prf.SetInputData(rr.GetOutput()) prf.Update() return Mesh(prf.GetOutput())
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 _loadDolfin_old(filename, exterior='dummy'): import xml.etree.ElementTree as et if filename.endswith(".gz"): import gzip inF = gzip.open(filename, "rb") outF = open("/tmp/filename.xml", "wb") outF.write(inF.read()) outF.close() inF.close() tree = et.parse("/tmp/filename.xml") else: tree = et.parse(filename) coords, connectivity = [], [] for mesh in tree.getroot(): for elem in mesh: for e in elem.findall("vertex"): x = float(e.get("x")) y = float(e.get("y")) ez = e.get("z") if ez is None: coords.append([x, y]) else: z = float(ez) coords.append([x, y, z]) tets = elem.findall("tetrahedron") if not len(tets): tris = elem.findall("triangle") for e in tris: v0 = int(e.get("v0")) v1 = int(e.get("v1")) v2 = int(e.get("v2")) connectivity.append([v0, v1, v2]) else: for e in tets: v0 = int(e.get("v0")) v1 = int(e.get("v1")) v2 = int(e.get("v2")) v3 = int(e.get("v3")) connectivity.append([v0, v1, v2, v3]) poly = utils.buildPolyData(coords, connectivity) return Mesh(poly)
def legosurface(self, vmin=None, vmax=None, invert=False, cmap='afmhot_r'): """ Represent a ``Volume`` as lego blocks (voxels). By default colors correspond to the volume's scalar. Returns an ``Mesh``. :param float vmin: the lower threshold, voxels below this value are not shown. :param float vmax: the upper threshold, voxels above this value are not shown. :param str cmap: color mapping of the scalar associated to the voxels. |legosurface| |legosurface.py|_ """ dataset = vtk.vtkImplicitDataSet() dataset.SetDataSet(self._imagedata) window = vtk.vtkImplicitWindowFunction() window.SetImplicitFunction(dataset) srng = list(self._imagedata.GetScalarRange()) if vmin is not None: srng[0] = vmin if vmax is not None: srng[1] = vmax tol = 0.00001*(srng[1]-srng[0]) srng[0] -= tol srng[1] += tol window.SetWindowRange(srng) extract = vtk.vtkExtractGeometry() extract.SetInputData(self._imagedata) extract.SetImplicitFunction(window) extract.SetExtractInside(invert) extract.ExtractBoundaryCellsOff() extract.Update() gf = vtk.vtkGeometryFilter() gf.SetInputData(extract.GetOutput()) gf.Update() a = Mesh(gf.GetOutput()).lw(0.1).flat() scalars = a.getPointArray() if scalars is None: print("Error in legosurface(): no scalars found!") return a a.pointColors(scalars, vmin=srng[0], vmax=srng[1], cmap=cmap) a.mapPointsToCells() return a
def geometry(obj, extent=None): """ Apply the ``vtkGeometryFilter``. This is a general-purpose filter to extract geometry (and associated data) from any type of dataset. This filter also may be used to convert any type of data to polygonal type. The conversion process may be less than satisfactory for some 3D datasets. For example, this filter will extract the outer surface of a volume or structured grid dataset. Returns a ``Mesh`` object. :param list extent: set a `[xmin,xmax, ymin,ymax, zmin,zmax]` bounding box to clip data. """ from vtkplotter.mesh import Mesh gf = vtk.vtkGeometryFilter() gf.SetInputData(obj) if extent is not None: gf.SetExtent(extent) gf.Update() return Mesh(gf.GetOutput())
def slice(self, origin=(0, 0, 0), normal=(1, 0, 0)): """Return a 2D slice of the mesh by a plane passing through origin and assigned normal.""" strn = str(normal) if strn == "x": normal = (1, 0, 0) elif strn == "y": normal = (0, 1, 0) elif strn == "z": normal = (0, 0, 1) elif strn == "-x": normal = (-1, 0, 0) elif strn == "-y": normal = (0, -1, 0) elif strn == "-z": normal = (0, 0, -1) plane = vtk.vtkPlane() plane.SetOrigin(origin) plane.SetNormal(normal) cc = vtk.vtkCutter() cc.SetInputData(self._ugrid) cc.SetCutFunction(plane) cc.Update() msh = Mesh(cc.GetOutput()).flat().lighting('ambient') msh._mapper.SetLookupTable(utils.ctf2lut(self)) return msh
def loadOFF(filename): """Read OFF file format.""" f = open(filename, "r") lines = f.readlines() f.close() vertices = [] faces = [] NumberOfVertices = None i = -1 for text in lines: if len(text) == 0: continue if text == '\n': continue if "#" in text: continue if "OFF" in text: continue ts = text.split() n = len(ts) if not NumberOfVertices and n > 1: NumberOfVertices, NumberOfFaces = int(ts[0]), int(ts[1]) continue i += 1 if i < NumberOfVertices and n == 3: x, y, z = float(ts[0]), float(ts[1]), float(ts[2]) vertices.append([x, y, z]) ids = [] if NumberOfVertices <= i < (NumberOfVertices + NumberOfFaces + 1) and n > 2: ids += [int(xx) for xx in ts[1:]] faces.append(ids) return Mesh(utils.buildPolyData(vertices, faces))
def loadPCD(filename): """Return a ``Mesh`` made of only vertex points from `Point Cloud` file format. Return an ``Mesh(vtkActor)`` object.""" f = open(filename, "r") lines = f.readlines() f.close() start = False pts = [] N, expN = 0, 0 for text in lines: if start: if N >= expN: break l = text.split() pts.append([float(l[0]), float(l[1]), float(l[2])]) N += 1 if not start and "POINTS" in text: expN = int(text.split()[1]) if not start and "DATA ascii" in text: start = True if expN != N: colors.printc("~!? Mismatch in pcd file", expN, len(pts), c="red") poly = utils.buildPolyData(pts) return Mesh(poly).pointSize(4)
def hexHistogram( xvalues, yvalues, xtitle="", ytitle="", ztitle="", bins=12, norm=1, fill=True, c=None, cmap="terrain_r", alpha=1, ): """ Build a hexagonal histogram from a list of x and y values. :param bool bins: nr of bins for the smaller range in x or y. :param float norm: sets a scaling factor for the z axis (freq. axis). :param bool fill: draw solid hexagons. :param str cmap: color map name for elevation. |histoHexagonal| |histoHexagonal.py|_ """ if xtitle: from vtkplotter import settings settings.xtitle = xtitle if ytitle: from vtkplotter import settings settings.ytitle = ytitle if ztitle: from vtkplotter import settings settings.ztitle = ztitle xmin, xmax = np.min(xvalues), np.max(xvalues) ymin, ymax = np.min(yvalues), np.max(yvalues) dx, dy = xmax - xmin, ymax - ymin if xmax - xmin < ymax - ymin: n = bins m = np.rint(dy / dx * n / 1.2 + 0.5).astype(int) else: m = bins n = np.rint(dx / dy * m * 1.2 + 0.5).astype(int) src = vtk.vtkPointSource() src.SetNumberOfPoints(len(xvalues)) src.Update() pointsPolydata = src.GetOutput() #values = list(zip(xvalues, yvalues)) values = np.stack((xvalues, yvalues), axis=1) zs = [[0.0]] * len(values) values = np.append(values, zs, axis=1) pointsPolydata.GetPoints().SetData(numpy_to_vtk(values, deep=True)) cloud = Mesh(pointsPolydata) col = None if c is not None: col = colors.getColor(c) hexs, binmax = [], 0 ki, kj = 1.33, 1.12 r = 0.47 / n * 1.2 * dx for i in range(n + 3): for j in range(m + 2): cyl = vtk.vtkCylinderSource() cyl.SetResolution(6) cyl.CappingOn() cyl.SetRadius(0.5) cyl.SetHeight(0.1) cyl.Update() t = vtk.vtkTransform() if not i % 2: p = (i / ki, j / kj, 0) else: p = (i / ki, j / kj + 0.45, 0) q = (p[0] / n * 1.2 * dx + xmin, p[1] / m * dy + ymin, 0) ids = cloud.closestPoint(q, radius=r, returnIds=True) ne = len(ids) if fill: t.Translate(p[0], p[1], ne / 2) t.Scale(1, 1, ne * 10) else: t.Translate(p[0], p[1], ne) t.RotateX(90) # put it along Z tf = vtk.vtkTransformPolyDataFilter() tf.SetInputData(cyl.GetOutput()) tf.SetTransform(t) tf.Update() if c is None: col = i h = Mesh(tf.GetOutput(), c=col, alpha=alpha).flat() h.GetProperty().SetSpecular(0) h.GetProperty().SetDiffuse(1) h.PickableOff() hexs.append(h) if ne > binmax: binmax = ne if cmap is not None: for h in hexs: z = h.GetBounds()[5] col = colors.colorMap(z, cmap, 0, binmax) h.color(col) asse = Assembly(hexs) asse.SetScale(1.2 / n * dx, 1 / m * dy, norm / binmax * (dx + dy) / 4) asse.SetPosition(xmin, ymin, 0) return asse
def _np_dump(obj): '''dump a vtkplotter obj to a numpy dictionary''' adict = dict() def fillcommon(obj, adict): adict['filename'] = obj.filename adict['legend'] = obj.legend() adict['time'] = obj.time() adict['rendered_at'] = obj.renderedAt adict['position'] = obj.pos() m = np.eye(4) vm = obj.getTransform().GetMatrix() for i in [0, 1, 2, 3]: for j in [0, 1, 2, 3]: m[i,j] = vm.GetElement(i, j) adict['transform'] = m minv = np.eye(4) vm.Invert() for i in [0, 1, 2, 3]: for j in [0, 1, 2, 3]: minv[i,j] = vm.GetElement(i, j) adict['transform_inverse'] = minv if hasattr(obj, 'GetProperty'): # assembly doesn't prp = obj.GetProperty() adict['ambient'] = prp.GetAmbient() adict['diffuse'] = prp.GetDiffuse() def _doactor(obj, adict): adict['points'] = obj.points(transformed=0).astype(np.float32) poly = obj.polydata() adict['cells'] = None adict['lines'] = None if poly.GetNumberOfCells(): try: adict['cells'] = np.array(obj.faces(), dtype=np.uint32) except ValueError: adict['cells'] = obj.faces() if poly.GetNumberOfLines(): adict['lines'] = vtk_to_numpy(poly.GetLines().GetData()).astype(np.uint32) fillcommon(obj, adict) adict['pointdata'] = [] adict['celldata'] = [] adict['activedata'] = None if poly.GetCellData().GetScalars(): adict['activedata'] = ['celldata', poly.GetCellData().GetScalars().GetName()] if poly.GetPointData().GetScalars(): adict['activedata'] = ['pointdata', poly.GetPointData().GetScalars().GetName()] for iname in obj.getArrayNames()['PointData']: adict['pointdata'].append([obj.getPointArray(iname), iname]) for iname in obj.getArrayNames()['CellData']: adict['celldata'].append([obj.getCellArray(iname), iname]) prp = obj.GetProperty() adict['alpha'] = prp.GetOpacity() adict['representation'] = prp.GetRepresentation() adict['texture'] = None adict['pointsize'] = prp.GetPointSize() if prp.GetEdgeVisibility(): adict['linewidth'] = prp.GetLineWidth() if hasattr(prp, 'GetLineColor'): adict['linecolor'] = prp.GetLineColor() else: adict['linewidth'] = 0 adict['linecolor'] = 0 adict['specular'] = prp.GetSpecular() adict['specularpower'] = prp.GetSpecularPower() adict['specularcolor'] = prp.GetSpecularColor() adict['shading'] = prp.GetInterpolation() adict['color'] = prp.GetColor() adict['backColor'] = None if obj.GetBackfaceProperty(): adict['backColor'] = obj.GetBackfaceProperty().GetColor() ############################ adict['type'] = 'unknown' if isinstance(obj, Mesh): adict['type'] = 'mesh' _doactor(obj, adict) elif isinstance(obj, Assembly): adict['type'] = 'assembly' adict['actors'] = [] for a in obj.getMeshes(): assdict = dict() if not isinstance(a, Mesh): #normal vtkActor b = Mesh(a) # promote it to a Actor pra = vtk.vtkProperty() pra.DeepCopy(a.GetProperty()) b.SetProperty(pra) a = b _doactor(a, assdict) adict['actors'].append(assdict) fillcommon(obj, adict) elif isinstance(obj, Picture): adict['type'] = 'image' arr = vtk_to_numpy(obj.inputdata().GetPointData().GetScalars()) adict['array'] = arr adict['shape'] = obj.inputdata().GetDimensions() fillcommon(obj, adict) #print('image', arr, arr.shape, obj.inputdata().GetDimensions()) elif isinstance(obj, Volume): adict['type'] = 'volume' imgdata = obj.inputdata() arr = vtk_to_numpy(imgdata.GetPointData().GetScalars()) adict['array'] = arr.reshape(imgdata.GetDimensions()) adict['mode'] = obj.mode() adict['jittering'] = obj.mapper().GetUseJittering() prp = obj.GetProperty() ctf = prp.GetRGBTransferFunction() otf = prp.GetScalarOpacity() gotf = prp.GetGradientOpacity() smin, smax = ctf.GetRange() xs = np.linspace(smin, smax, num=100, endpoint=True) cols, als, algrs = [], [], [] for x in xs: cols.append(ctf.GetColor(x)) als.append(otf.GetValue(x)) if gotf: algrs.append(gotf.GetValue(x)) adict['color'] = cols adict['alpha'] = als adict['alphagrad'] = algrs fillcommon(obj, adict) return adict
def _buildactor(d): #print('_buildactor', d) vertices = d['points'] if not len(vertices): return None cells = None lines = None keys = d.keys() if 'cells' in keys: cells = d['cells'] if 'lines' in keys: lines = d['lines'] poly = utils.buildPolyData(vertices, cells, lines) act = Mesh(poly) loadcommon(act, d) act.mapper().ScalarVisibilityOff() if 'celldata' in keys: for csc, cscname in d['celldata']: act.addCellScalars(csc, cscname) if 'normal' not in cscname.lower(): act.getCellArray(cscname) # activate if 'pointdata' in keys: for psc, pscname in d['pointdata']: act.addPointScalars(psc, pscname) if 'normal' not in pscname.lower(): act.getPointArray(pscname) # activate prp = act.GetProperty() if 'specular' in keys: prp.SetSpecular(d['specular']) if 'specularpower' in keys: prp.SetSpecularPower(d['specularpower']) if 'specularcolor' in keys: prp.SetSpecularColor(d['specularcolor']) if 'shading' in keys: prp.SetInterpolation(d['shading']) if 'alpha' in keys: prp.SetOpacity(d['alpha']) if 'opacity' in keys: prp.SetOpacity(d['opacity']) # synonym if 'pointsize' in keys and d['pointsize']: prp.SetPointSize(d['pointsize']) if 'texture' in keys and d['texture']: act.texture(d['texture']) if 'linewidth' in keys and d['linewidth']: act.lineWidth(d['linewidth']) if 'linecolor' in keys and d['linecolor']: act.lineColor(d['linecolor']) if 'representation' in keys: prp.SetRepresentation(d['representation']) if 'color' in keys and d['color']: act.color(d['color']) if 'backColor' in keys and d['backColor']: act.backColor(d['backColor']) if 'activedata' in keys and d['activedata'] is not None: act.mapper().ScalarVisibilityOn() if d['activedata'][0] == 'celldata': poly.GetCellData().SetActiveScalars(d['activedata'][1]) if d['activedata'][0] == 'pointdata': poly.GetPointData().SetActiveScalars(d['activedata'][1]) return act
def fxy( z="sin(3*x)*log(x-y)/3", x=(0, 3), y=(0, 3), zlimits=(None, None), showNan=True, zlevels=10, c="b", bc="aqua", alpha=1, texture="paper", res=(100, 100), ): """ Build a surface representing the function :math:`f(x,y)` specified as a string or as a reference to an external function. :param float x: x range of values. :param float y: y range of values. :param float zlimits: limit the z range of the independent variable. :param int zlevels: will draw the specified number of z-levels contour lines. :param bool showNan: show where the function does not exist as red points. :param list res: resolution in x and y. |fxy| |fxy.py|_ Function is: :math:`f(x,y)=\sin(3x) \cdot \log(x-y)/3` in range :math:`x=[0,3], y=[0,3]`. """ if isinstance(z, str): try: z = z.replace("math.", "").replace("np.", "") namespace = locals() code = "from math import*\ndef zfunc(x,y): return " + z exec(code, namespace) z = namespace["zfunc"] except: colors.printc("Syntax Error in fxy()", c=1) return None ps = vtk.vtkPlaneSource() ps.SetResolution(res[0], res[1]) ps.SetNormal([0, 0, 1]) ps.Update() poly = ps.GetOutput() dx = x[1] - x[0] dy = y[1] - y[0] todel, nans = [], [] for i in range(poly.GetNumberOfPoints()): px, py, _ = poly.GetPoint(i) xv = (px + 0.5) * dx + x[0] yv = (py + 0.5) * dy + y[0] try: zv = z(xv, yv) except: zv = 0 todel.append(i) nans.append([xv, yv, 0]) poly.GetPoints().SetPoint(i, [xv, yv, zv]) if len(todel): cellIds = vtk.vtkIdList() poly.BuildLinks() for i in todel: poly.GetPointCells(i, cellIds) for j in range(cellIds.GetNumberOfIds()): poly.DeleteCell(cellIds.GetId(j)) # flag cell poly.RemoveDeletedCells() cl = vtk.vtkCleanPolyData() cl.SetInputData(poly) cl.Update() poly = cl.GetOutput() if not poly.GetNumberOfPoints(): colors.printc("Function is not real in the domain", c=1) return None if zlimits[0]: tmpact1 = Mesh(poly) a = tmpact1.cutWithPlane((0, 0, zlimits[0]), (0, 0, 1)) poly = a.polydata() if zlimits[1]: tmpact2 = Mesh(poly) a = tmpact2.cutWithPlane((0, 0, zlimits[1]), (0, 0, -1)) poly = a.polydata() if c is None: elev = vtk.vtkElevationFilter() elev.SetInputData(poly) elev.Update() poly = elev.GetOutput() mesh = Mesh(poly, c, alpha).computeNormals().lighting("plastic") if c is None: mesh.getPointArray("Elevation") if bc: mesh.bc(bc) mesh.texture(texture) acts = [mesh] if zlevels: elevation = vtk.vtkElevationFilter() elevation.SetInputData(poly) bounds = poly.GetBounds() elevation.SetLowPoint(0, 0, bounds[4]) elevation.SetHighPoint(0, 0, bounds[5]) elevation.Update() bcf = vtk.vtkBandedPolyDataContourFilter() bcf.SetInputData(elevation.GetOutput()) bcf.SetScalarModeToValue() bcf.GenerateContourEdgesOn() bcf.GenerateValues(zlevels, elevation.GetScalarRange()) bcf.Update() zpoly = bcf.GetContourEdgesOutput() zbandsact = Mesh(zpoly, "k", alpha).lw(0.5) acts.append(zbandsact) if showNan and len(todel): bb = mesh.GetBounds() if bb[4] <= 0 and bb[5] >= 0: zm = 0.0 else: zm = (bb[4] + bb[5]) / 2 nans = np.array(nans) + [0, 0, zm] nansact = shapes.Points(nans, r=2, c="red", alpha=alpha) nansact.GetProperty().RenderPointsAsSpheresOff() acts.append(nansact) if len(acts) > 1: return Assembly(acts) else: return mesh
def polarPlot( rphi, title="", r1=0, r2=1, lpos=1, lsize=0.03, c="blue", bc="k", alpha=1, lw=3, deg=False, vmax=None, fill=True, spline=True, smooth=0, showPoints=True, showDisc=True, showLines=True, showAngles=True, ): """ Polar/radar plot by splining a set of points in polar coordinates. Input is a list of polar angles and radii. :param str title: histogram title :param int bins: number of bins in phi :param float r1: inner radius :param float r2: outer radius :param float lsize: label size :param c: color of the line :param bc: color of the frame and labels :param alpha: alpha of the frame :param int lw: line width in pixels :param bool deg: input array is in degrees :param bool fill: fill convex area with solid color :param bool spline: interpolate the set of input points :param bool showPoints: show data points :param bool showDisc: show the outer ring axis :param bool showLines: show lines to the origin :param bool showAngles: show angular values |polarPlot| |polarPlot.py|_ """ if len(rphi) == 2: #rphi = list(zip(rphi[0], rphi[1])) rphi = np.stack((rphi[0], rphi[1]), axis=1) rphi = np.array(rphi) thetas = rphi[:, 0] radii = rphi[:, 1] k = 180 / np.pi if deg: thetas = np.array(thetas) / k vals = [] for v in thetas: # normalize range t = np.arctan2(np.sin(v), np.cos(v)) if t < 0: t += 2 * np.pi vals.append(t) thetas = np.array(vals) if vmax is None: vmax = np.max(radii) angles = [] labs = [] points = [] for i in range(len(thetas)): t = thetas[i] r = (radii[i]) / vmax * r2 + r1 ct, st = np.cos(t), np.sin(t) points.append([r * ct, r * st, 0]) p0 = points[0] points.append(p0) r2e = r1 + r2 if spline: lines = shapes.KSpline(points, closed=True) else: lines = shapes.Line(points) lines.c(c).lw(lw).alpha(alpha) points.pop() ptsact = None if showPoints: ptsact = shapes.Points(points).c(c).alpha(alpha) filling = None if fill: faces = [] coords = [[0, 0, 0]] + lines.points().tolist() for i in range(1, lines.N()): faces.append([0, i, i + 1]) filling = Mesh([coords, faces]).c(c).alpha(alpha) back = None if showDisc: back = shapes.Disc(r1=r2e, r2=r2e * 1.01, c=bc, res=1, resphi=360) back.z(-0.01).lighting(diffuse=0, ambient=1).alpha(alpha) ti = None if title: ti = shapes.Text(title, (0, 0, 0), s=lsize * 2, depth=0, justify="top-center") ti.pos(0, -r2e * 1.15, 0.01) rays = [] if showDisc: rgap = 0.05 for t in np.linspace(0, 2 * np.pi, num=8, endpoint=False): ct, st = np.cos(t), np.sin(t) if showLines: l = shapes.Line((0, 0, -0.01), (r2e * ct * 1.03, r2e * st * 1.03, -0.01)) rays.append(l) elif showAngles: # just the ticks l = shapes.Line( (r2e * ct * 0.98, r2e * st * 0.98, -0.01), (r2e * ct * 1.03, r2e * st * 1.03, -0.01), ) if showAngles: if 0 <= t < np.pi / 2: ju = "bottom-left" elif t == np.pi / 2: ju = "bottom-center" elif np.pi / 2 < t <= np.pi: ju = "bottom-right" elif np.pi < t < np.pi * 3 / 2: ju = "top-right" elif t == np.pi * 3 / 2: ju = "top-center" else: ju = "top-left" a = shapes.Text(int(t * k), pos=(0, 0, 0), s=lsize, depth=0, justify=ju) a.pos(r2e * ct * (1 + rgap), r2e * st * (1 + rgap), -0.01) angles.append(a) mrg = merge(back, angles, rays, labs, ti) if mrg: mrg.color(bc).alpha(alpha).lighting(diffuse=0, ambient=1) rh = Assembly([lines, ptsact, filling] + [mrg]) rh.base = np.array([0, 0, 0]) rh.top = np.array([0, 0, 1]) return rh
def trimesh2vtk(inputobj, alphaPerCell=False): """ Convert ``Trimesh`` object to ``Mesh(vtkActor)`` or ``Assembly`` object. """ if isSequence(inputobj): vms = [] for ob in inputobj: vms.append(trimesh2vtk(ob)) return vms # print('trimesh2vtk inputobj', type(inputobj)) inputobj_type = str(type(inputobj)) if "Trimesh" in inputobj_type or "primitives" in inputobj_type: from vtkplotter import Mesh faces = inputobj.faces poly = buildPolyData(inputobj.vertices, faces) tact = Mesh(poly) if inputobj.visual.kind == "face": trim_c = inputobj.visual.face_colors else: trim_c = inputobj.visual.vertex_colors if isSequence(trim_c): if isSequence(trim_c[0]): sameColor = len(np.unique(trim_c, axis=0)) < 2 # all vtxs have same color trim_c = trim_c/255 if sameColor: tact.c(trim_c[0, [0,1,2]]).alpha(trim_c[0, 3]) else: if inputobj.visual.kind == "face": tact.cellColors(trim_c[:, [0,1,2]], mode='colors', alpha=trim_c[:,3], alphaPerCell=alphaPerCell) else: tact.pointColors(trim_c[:, [0,1,2]], mode='colors', alpha=trim_c[3]) return tact elif "PointCloud" in inputobj_type: from vtkplotter.shapes import Points trim_cc, trim_al = "black", 1 if hasattr(inputobj, "vertices_color"): trim_c = inputobj.vertices_color if len(trim_c): trim_cc = trim_c[:, [0, 1, 2]] / 255 trim_al = trim_c[:, 3] / 255 trim_al = np.sum(trim_al) / len(trim_al) # just the average return Points(inputobj.vertices, r=8, c=trim_cc, alpha=trim_al) elif "path" in inputobj_type: from vtkplotter.shapes import Line from vtkplotter.assembly import Assembly lines = [] for e in inputobj.entities: # print('trimesh entity', e.to_dict()) l = Line(inputobj.vertices[e.points], c="k", lw=2) lines.append(l) return Assembly(lines) return None
'AA0271': 'forestgreen', 'AA0623': 'red', 'AA0635': 'red', 'AA0649': 'red', 'AA0898': 'red' } # Load MOp annotation im = io.imread('C://Users/maithamn/Downloads/MOpul_Binary_528.tif') im += np.flip(im, axis=2) verts, faces, normals, values = marching_cubes_lewiner(im, spacing=(25, 25, 25), step_size=2) MOp_region = Mesh([verts, faces], c=(144, 0, 255), alpha=.25) cells_base_dir = './cells/cell_jsons/' IDs = [ 'C57BL_6J', 'Ntsr1-Cre_GN220', 'Sim1-Cre_KJ18', 'Tlx3-Cre_PL56', 'Nr5a1-Cre', 'Cux2-IRES-Cre', 'Rbp4-Cre_KL100' ] # {'cells':[],'streamlines':[],'name':''} figs = [{ 'cells': ['18453_3456_x24161_y6646'], 'streamlines': [], 'name': '18453_3456_x24161_y6646' }, {
def _load_file(filename, c, alpha, threshold, spacing, unpack): fl = filename.lower() ################################################################# other formats: if fl.endswith(".xml") or fl.endswith(".xml.gz") or fl.endswith(".xdmf"): # Fenics tetrahedral file actor = loadDolfin(filename) elif fl.endswith(".neutral") or fl.endswith(".neu"): # neutral tetrahedral file actor = loadNeutral(filename) elif fl.endswith(".gmsh"): # gmesh file actor = loadGmesh(filename) elif fl.endswith(".pcd"): # PCL point-cloud format actor = loadPCD(filename) actor.GetProperty().SetPointSize(2) elif fl.endswith(".off"): actor = loadOFF(filename) elif fl.endswith(".3ds"): # 3ds format actor = load3DS(filename) elif fl.endswith(".wrl"): importer = vtk.vtkVRMLImporter() importer.SetFileName(filename) importer.Read() importer.Update() actors = importer.GetRenderer().GetActors() #vtkActorCollection actors.InitTraversal() wacts = [] for i in range(actors.GetNumberOfItems()): act = actors.GetNextActor() wacts.append(act) actor = Assembly(wacts) ################################################################# volumetric: elif fl.endswith(".tif") or fl.endswith(".slc") or fl.endswith(".vti") \ or fl.endswith(".mhd") or fl.endswith(".nrrd") or fl.endswith(".nii") \ or fl.endswith(".dem"): img = loadImageData(filename, spacing) if threshold is False: if c is None and alpha == 1: c = ['b','lb','lg','y','r'] # good for blackboard background alpha = (0.0, 0.0, 0.2, 0.4, 0.8, 1) actor = Volume(img) else: actor = Volume(img).isosurface(threshold=threshold) actor.color(c).alpha(alpha) ################################################################# 2D images: elif fl.endswith(".png") or fl.endswith(".jpg") or fl.endswith(".bmp") or fl.endswith(".jpeg"): if ".png" in fl: picr = vtk.vtkPNGReader() elif ".jpg" in fl or ".jpeg" in fl: picr = vtk.vtkJPEGReader() elif ".bmp" in fl: picr = vtk.vtkBMPReader() picr.SetFileName(filename) picr.Update() actor = Picture() # object derived from vtk.vtkImageActor() actor.SetInputData(picr.GetOutput()) if alpha is None: alpha = 1 actor.SetOpacity(alpha) ################################################################# multiblock: elif fl.endswith(".vtm") or fl.endswith(".vtmb"): read = vtk.vtkXMLMultiBlockDataReader() read.SetFileName(filename) read.Update() mb = read.GetOutput() if unpack: acts = [] for i in range(mb.GetNumberOfBlocks()): b = mb.GetBlock(i) if isinstance(b, (vtk.vtkPolyData, vtk.vtkUnstructuredGrid, vtk.vtkStructuredGrid, vtk.vtkRectilinearGrid)): acts.append(Mesh(b, c=c, alpha=alpha)) if isinstance(b, vtk.vtkImageData): acts.append(Volume(b)) return acts else: return mb ################################################################# numpy: elif fl.endswith(".npy"): acts = loadNumpy(filename) if unpack is False: return Assembly(acts) return acts elif fl.endswith(".geojson") or fl.endswith(".geojson.gz"): return loadGeoJSON(fl) elif fl.endswith(".pvd"): return loadPVD(fl) elif fl.endswith(".pdb"): return loadPDB(fl) ################################################################# polygonal mesh: else: if fl.endswith(".vtk"): # read all legacy vtk types #output can be: # PolyData, StructuredGrid, StructuredPoints, UnstructuredGrid, RectilinearGrid reader = vtk.vtkDataSetReader() reader.ReadAllScalarsOn() reader.ReadAllVectorsOn() reader.ReadAllTensorsOn() reader.ReadAllFieldsOn() reader.ReadAllNormalsOn() reader.ReadAllColorScalarsOn() elif fl.endswith(".ply"): reader = vtk.vtkPLYReader() elif fl.endswith(".obj"): reader = vtk.vtkOBJReader() elif fl.endswith(".stl"): reader = vtk.vtkSTLReader() elif fl.endswith(".byu") or fl.endswith(".g"): reader = vtk.vtkBYUReader() elif fl.endswith(".foam"): # OpenFoam reader = vtk.vtkOpenFOAMReader() elif fl.endswith(".pvd"): reader = vtk.vtkXMLGenericDataObjectReader() elif fl.endswith(".vtp"): reader = vtk.vtkXMLPolyDataReader() elif fl.endswith(".vts"): reader = vtk.vtkXMLStructuredGridReader() elif fl.endswith(".vtu"): reader = vtk.vtkXMLUnstructuredGridReader() elif fl.endswith(".vtr"): reader = vtk.vtkXMLRectilinearGridReader() elif fl.endswith(".pvtk"): reader = vtk.vtkPDataSetReader() elif fl.endswith(".pvtr"): reader = vtk.vtkXMLPRectilinearGridReader() elif fl.endswith("pvtu"): reader = vtk.vtkXMLPUnstructuredGridReader() elif fl.endswith(".txt") or fl.endswith(".xyz"): reader = vtk.vtkParticleReader() # (format is x, y, z, scalar) elif fl.endswith(".facet"): reader = vtk.vtkFacetReader() else: return None reader.SetFileName(filename) reader.Update() routput = reader.GetOutput() if not routput: colors.printc("~noentry Unable to load", filename, c=1) return None actor = Mesh(routput, c, alpha) if fl.endswith(".txt") or fl.endswith(".xyz"): actor.GetProperty().SetPointSize(4) actor.filename = filename return actor
def importWindow(fileinput, mtlFile=None, texturePath=None): """Import a whole scene from a Numpy or OBJ wavefront file. Return ``Plotter`` instance. :param str mtlFile: MTL file for OBJ wavefront files. :param str texturePath: path of the texture files directory. """ from vtkplotter import Plotter if '.npy' in fileinput: 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') #print(data.keys()) # print(data['objects']) # exit() 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 elif '.obj' in fileinput.lower(): vp = Plotter() importer = vtk.vtkOBJImporter() importer.SetFileName(fileinput) if mtlFile is not False: if mtlFile is None: mtlFile = fileinput.replace('.obj', '.mtl').replace('.OBJ', '.MTL') importer.SetFileNameMTL(mtlFile) if texturePath is not False: if texturePath is None: texturePath = fileinput.replace('.obj', '.txt').replace('.OBJ', '.TXT') importer.SetTexturePath(texturePath) importer.SetRenderWindow(vp.window) importer.Update() actors = vp.renderer.GetActors() actors.InitTraversal() for i in range(actors.GetNumberOfItems()): vactor = actors.GetNextActor() act = Mesh(vactor) act_tu = vactor.GetTexture() if act_tu: act_tu.InterpolateOn() act.texture(act_tu) vp.actors.append( act ) return vp