def functional_tet(): grid = test_tetrahedralize() # get cell centroids cells = grid.cells.reshape(-1, 5)[:, 1:] cell_center = grid.points[cells].mean(1) # extract cells below the 0 xy plane mask = cell_center[:, 2] < 0 cell_ind = mask.nonzero()[0] subgrid = grid.ExtractSelectionCells(cell_ind) # plot this subgrid.Plot(scalars=subgrid.quality, stitle='quality', colormap='bwr', flipscalars=True) # advanced plotting plotter = vtki.PlotClass() plotter.SetBackground('w') plotter.AddMesh(subgrid, 'lightgrey', lighting=True) plotter.AddMesh(grid, 'r', 'wireframe') plotter.AddLegend([[' Input Mesh ', 'r'], [' Tesselated Mesh ', 'black']]) plotter.Plot() plotter = vtki.PlotClass() plotter.SetBackground('w') plotter.AddMesh(grid, 'r', 'wireframe') plotter.Plot(autoclose=False) plotter.Plot(autoclose=False, interactive_update=True) for i in range(500): single_cell = grid.ExtractSelectionCells([i]) plotter.AddMesh(single_cell) plotter.Update() plotter.Close()
def PlotAntsPlane(): """ Demonstrate how to create a plot class to plot multiple meshes while adding scalars and text. Plot two ants and airplane """ # load and shrink airplane airplane = vtkInterface.PolyData(planefile) airplane.points /= 10 # pts = airplane.GetNumpyPoints() # gets pointer to array # pts /= 10 # shrink # rotate and translate ant so it is on the plane ant = vtkInterface.PolyData(antfile) ant.RotateX(90) ant.Translate([90, 60, 15]) # Make a copy and add another ant ant_copy = ant.Copy() ant_copy.Translate([30, 0, -10]) # Create plotting object plobj = vtkInterface.PlotClass() plobj.AddMesh(ant, 'r') plobj.AddMesh(ant_copy, 'b') # Add airplane mesh and make the color equal to the Y position plane_scalars = airplane.points[:, 1] plobj.AddMesh(airplane, scalars=plane_scalars, stitle='Plane Y\nLocation') plobj.AddText('Ants and Plane Example') plobj.Plot()
def PlotNodalStress(self, rnum, stype): """ Plots the stresses at each node in the solution. The order of the results corresponds to the sorted node numbering. This algorthim, like ANSYS, computes the node stress by averaging the stress for each element at each node. Due to the discontinunities across elements, stresses will vary based on the element they are evaluated from. Parameters ---------- rnum : interger Result set using zero based indexing. stype : string Stress type from the following list: [Sx Sy Sz Sxy Syz Sxz] Returns ------- None """ stress_types = ['Sx', 'Sy', 'Sz', 'Sxy', 'Syz', 'Sxz', 'Seqv'] if stype not in stress_types: raise Exception('Stress type not in \n' +\ "['Sx', 'Sy', 'Sz', 'Sxy', 'Syz', 'Sxz']") sidx = ['Sx', 'Sy', 'Sz', 'Sxy', 'Syz', 'Sxz'].index(stype) # create a zero array for all nodes stress = np.zeros(self.resultheader['nnod']) # Populate with nodal stress at edge nodes stress[self.edge_node_num_idx] = self.NodalStress(rnum)[:, sidx] stitle = 'Nodal Stress\n{:s}'.format(stype) # Generate plot plobj = vtkInterface.PlotClass() plobj.AddMesh(self.uGrid, scalars=stress, stitle=stitle, no_copy=True, flipscalars=True, interpolatebeforemap=True) text = 'Result {:d} at {:f}'.format(rnum + 1, self.tvalues[rnum]) plobj.AddText(text) cpos = plobj.Plot() # store camera position del plobj return cpos
def SolveKM(): """ Loads and solves a mass and stiffness matrix from an ansys full file """ try: from scipy.sparse import linalg from scipy import sparse except ImportError: print('scipy not installed, aborting') return # load the mass and stiffness matrices full = pyansys.FullReader(pyansys.examples.fullfile) dofref, k, m = full.LoadKM(sort=True) # make symmetric k += sparse.triu(k, 1).T m += sparse.triu(m, 1).T k += sparse.diags(np.random.random(k.shape[0]) / 1E20, shape=k.shape) # Solve w, v = linalg.eigsh(k, k=20, M=m, sigma=1000) # System natural frequencies f = (np.real(w))**0.5 / (2 * np.pi) # %% Plot result # Get the 4th mode shape full_mode_shape = v[:, 3] # x, y, z displacement for each node # reshape and compute the normalized displacement disp = full_mode_shape.reshape((-1, 3)) n = (disp * disp).sum(1)**0.5 n /= n.max() # normalize # load an archive file and create a vtk unstructured grid archive = pyansys.ReadArchive(pyansys.examples.hexarchivefile) grid = archive.ParseVTK() # Fancy plot the displacement plobj = vtkInterface.PlotClass() # add two meshes to the plotting class plobj.AddMesh(grid.Copy(), style='wireframe') plobj.AddMesh(grid, scalars=n, stitle='Normalized\nDisplacement', flipscalars=True) # Update the coordinates by adding the mode shape to the grid plobj.UpdateCoordinates(grid.GetNumpyPoints() + disp / 80, render=False) plobj.AddText('Cantliver Beam 4th Mode Shape at {:.4f}'.format(f[3]), fontsize=30) plobj.Plot()
def PlotPrincipalNodalStress(self, rnum, stype): """ Plot the principal stress at each node in the solution. Parameters ---------- rnum : interger Result set using zero based indexing. stype : string Stress type to plot. S1, S2, S3 principal stresses, SINT stress intensity, and SEQV equivalent stress. Stress type must be a string from the following list: ['S1', 'S2', 'S3', 'SINT', 'SEQV'] Returns ------- cpos : list VTK camera position. """ stress_types = ['S1', 'S2', 'S3', 'SINT', 'SEQV'] if stype not in stress_types: raise Exception('Stress type not in \n' + str(stress_types)) sidx = stress_types.index(stype) # create a zero array for all nodes stress = np.zeros(self.resultheader['nnod']) # Populate with nodal stress at edge nodes pstress = self.PrincipalNodalStress(rnum) stress[self.edge_node_num_idx] = pstress[:, sidx] stitle = 'Nodal Stress\n{:s}'.format(stype) # Generate plot plobj = vtkInterface.PlotClass() plobj.AddMesh(self.grid, scalars=stress, stitle=stitle, flipscalars=True, interpolatebeforemap=True) text = 'Result {:d} at {:f}'.format(rnum + 1, self.tvalues[rnum]) plobj.AddText(text) return plobj.Plot() # store camera position
def test_creatingagifmovie(tmpdir, off_screen=True): if tmpdir: filename = str(tmpdir.mkdir("tmpdir").join('wave.gif')) else: filename = '/tmp/wave.gif' import vtkInterface as vtki import numpy as np x = np.arange(-10, 10, 0.25) y = np.arange(-10, 10, 0.25) x, y = np.meshgrid(x, y) r = np.sqrt(x**2 + y**2) z = np.sin(r) # Create and structured surface grid = vtki.StructuredGrid(x, y, z) # Make copy of points pts = grid.points.copy() # Start a plotter object and set the scalars to the Z height plobj = vtki.PlotClass(off_screen=off_screen) plobj.AddMesh(grid, scalars=z.ravel()) plobj.Plot(autoclose=False) # Open a gif plobj.OpenGif(filename) # Update Z and write a frame for each updated position nframe = 15 for phase in np.linspace(0, 2 * np.pi, nframe + 1)[:nframe]: z = np.sin(r + phase) pts[:, -1] = z.ravel() plobj.UpdateCoordinates(pts) plobj.UpdateScalars(z.ravel()) plobj.WriteFrame() # Close movie and delete object plobj.Close()
def test_docexample_advancedplottingwithnumpy(): import vtkInterface as vtki import numpy as np # Make a grid x, y, z = np.meshgrid(np.linspace(-5, 5, 20), np.linspace(-5, 5, 20), np.linspace(-5, 5, 5)) points = np.empty((x.size, 3)) points[:, 0] = x.ravel('F') points[:, 1] = y.ravel('F') points[:, 2] = z.ravel('F') # Compute a direction for the vector field direction = np.sin(points)**3 # plot using the plotting class plobj = vtki.PlotClass(off_screen=True) plobj.AddArrows(points, direction, 0.5) plobj.SetBackground([0, 0, 0]) # RGB set to black plobj.Plot(autoclose=False) img = plobj.TakeScreenShot() assert np.any(img) plobj.Close()
ipd.SetInput(A.mesh) ipd.Modified() dists = np.zeros((len(coords),)) pts = np.zeros((len(coords), 3)) for ii in xrange(len(coords)): dists[ii] = ipd.EvaluateFunctionAndGetClosestPoint(coords[ii], pts[ii]) # filter_ = np.logical_and(dists > -6, dists < 0) filter_ = dists < 0 #idxs = idxs[~np.isinf(dists)] coords = coords[filter_] vals = vals[filter_] dists = dists[filter_] #coords[idxs] pobj = vi.PlotClass() pobj.AddMesh(A.mesh) pobj.AddPoints(coords, scalars=vals, opacity=1) pobj.Plot() # Find the closest point on mesh to each point tree = cKDTree(A.mesh.points) closest = tree.query(coords, k=1)[1] sumvals = np.zeros(A.mesh.points.shape[0]) for ii in xrange(len(coords)): sumvals[closest[ii]] += vals[ii] dom_vals = np.zeros((3, )) doms = pdata.domain.values
def PlotNodalResult(self, rnum, comp='norm', as_abs=False, label=''): """ Plots a nodal result. Parameters ---------- rnum : int Cumulative result number. Zero based indexing. comp : str, optional Display component to display. Options are 'x', 'y', 'z', and 'norm', corresponding to the x directin, y direction, z direction, and the combined direction (x**2 + y**2 + z**2)**0.5 as_abs : bool, optional Displays the absolute value of the result. label: string, optional Annotation string to add to scalar bar in plot. Returns ------- cpos : list Camera position from vtk render window. """ if not vtkloaded: raise Exception('Cannot plot without VTK') # Load result from file result = self.GetNodalResult(rnum) # Process result if comp == 'x': d = result[:, 0] stitle = 'X {:s}'.format(label) elif comp == 'y': d = result[:, 1] stitle = 'Y {:s}'.format(label) elif comp == 'z': d = result[:, 2] stitle = 'Z {:s}'.format(label) else: # Normalize displacement d = result[:, :3] d = (d * d).sum(1)**0.5 stitle = 'Normalized\n{:s}'.format(label) if as_abs: d = np.abs(d) # Generate plot # text = 'Result {:d} at {:f}'.format(rnum + 1, self.tvalues[rnum]) # setup text ls_table = self.resultheader['ls_table'] freq = self.GetTimeValues()[rnum] text = 'Cumulative Index: {:3d}\n'.format(ls_table[rnum, 2]) text += 'Loadstep: {:3d}\n'.format(ls_table[rnum, 0]) text += 'Substep: {:3d}\n'.format(ls_table[rnum, 1]) # text += 'Harmonic Index: {:3d}\n'.format(hindex) text += 'Frequency: {:10.4f} Hz'.format(freq) plobj = vtkInterface.PlotClass() plobj.AddMesh(self.grid, scalars=d, stitle=stitle, flipscalars=True, interpolatebeforemap=True) plobj.AddText(text, fontsize=20) # return camera position return plobj.Plot()
def PlotCyclicNodalResult( self, rnum, phase=0, comp='norm', as_abs=False, label='', expand=True): """ Plots a nodal result from a cyclic analysis. Parameters ---------- rnum : interger Cumulative result number. Zero based indexing. phase : float, optional Shifts the phase of the solution. comp : string, optional Display component to display. Options are 'x', 'y', 'z', and 'norm', corresponding to the x directin, y direction, z direction, and the combined direction (x**2 + y**2 + z**2)**0.5 as_abs : bool, optional Displays the absolute value of the result. label: string, optional Annotation string to add to scalar bar in plot. expand : bool, optional Expands the solution to a full rotor when True. Enabled by default. When disabled, plots the maximum response of a single sector of the cyclic solution in the component of interest. Returns ------- cpos : list Camera position from vtk render window. """ if 'hindex' not in self.resultheader: raise Exception('Result file does not contain cyclic results') # harmonic index and number of sectors hindex = self.resultheader['hindex'][rnum] nSector = self.resultheader['nSector'] # get the nodal result r = self.GetCyclicNodalResult(rnum) alpha = (2 * np.pi / nSector) if expand: grid = self.rotor d = np.empty((self.rotor.GetNumberOfPoints(), 3)) n = self.sector.GetNumberOfPoints() for i in range(nSector): # adjust the phase of the result sec_sol = np.real(r) * np.cos(i * hindex * alpha + phase) -\ np.imag(r) * np.sin(i * hindex * alpha + phase) # adjust the "direction" of the x and y vectors as they're being # rotated s_x = sec_sol[:, 0] * np.cos(alpha * i + phase) -\ sec_sol[:, 1] * np.sin(alpha * i + phase) s_y = sec_sol[:, 0] * np.sin(alpha * i + phase) +\ sec_sol[:, 1] * np.cos(alpha * i + phase) sec_sol[:, 0] = s_x sec_sol[:, 1] = s_y d[i * n:(i + 1) * n] = sec_sol else: # plot the max response for a single sector grid = self.sector n = np.sum(r * r, 1) # rotate the response based on the angle to maximize the highest # responding node angle = np.angle(n[np.argmax(np.abs(n))]) d = np.real(r) * np.cos(angle + phase) -\ np.imag(r) * np.sin(angle + phase) d = -d # Process result if comp == 'x': d = d[:, 0] stitle = 'X {:s}'.format(label) elif comp == 'y': d = d[:, 1] stitle = 'Y {:s}'.format(label) elif comp == 'z': d = d[:, 2] stitle = 'Z {:s}'.format(label) else: # Normalize displacement d = d[:, :3] d = (d * d).sum(1)**0.5 stitle = 'Normalized\n{:s}'.format(label) if as_abs: d = np.abs(d) # setup text ls_table = self.resultheader['ls_table'] freq = self.GetTimeValues()[rnum] text = 'Cumulative Index: {:3d}\n'.format(ls_table[rnum, 2]) text += 'Loadstep: {:3d}\n'.format(ls_table[rnum, 0]) text += 'Substep: {:3d}\n'.format(ls_table[rnum, 1]) text += 'Harmonic Index: {:3d}\n'.format(hindex) text += 'Frequency: {:10.4f} Hz'.format(freq) # plot plobj = vtkInterface.PlotClass() plobj.AddMesh(grid, scalars=d, stitle=stitle, flipscalars=True, interpolatebeforemap=True) plobj.AddText(text, fontsize=20) plobj.Plot()
def ShowWave(fps=30, frequency=1, wavetime=3, interactive=False): """ Plot a 3D moving wave in a render window. Parameters ---------- fps : int, optional Maximum frames per second to display. Defaults to 30. frequency: float, optional Wave cycles per second. Defaults to 1 wavetime : float, optional The desired total display time in seconds. Defaults to 3 seconds. interactive: bool, optional Allows the user to set the camera position before the start of the wave movement. Default False. """ # camera position cpos = [(6.879481857604187, -32.143727535933195, 23.05622921691103), (-0.2336056403734026, -0.6960083534590372, -0.7226721553894022), (-0.008900669873416645, 0.6018246347860926, 0.7985786667826725)] # Make data X = np.arange(-10, 10, 0.25) Y = np.arange(-10, 10, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) # Create and plot structured grid sgrid = vtkInterface.StructuredGrid(X, Y, Z) # Get pointer to points pts = sgrid.GetNumpyPoints(deep=True) # Start a plotter object and set the scalars to the Z height plobj = vtkInterface.PlotClass() plobj.AddMesh(sgrid, scalars=Z.ravel()) plobj.SetCameraPosition(cpos) plobj.Plot(title='Wave Example', window_size=[800, 600], autoclose=False, interactive=interactive) # Update Z and display a frame for each updated position tdelay = 1. / fps tlast = time.time() tstart = time.time() while time.time() - tstart < wavetime: # get phase from start telap = time.time() - tstart phase = telap * 2 * np.pi * frequency Z = np.sin(R + phase) pts[:, -1] = Z.ravel() # update plotting object, but don't automatically render plobj.UpdateCoordinates(pts, render=False) plobj.UpdateScalars(Z.ravel(), render=False) # Render and get time to render rstart = time.time() plobj.Render() rstop = time.time() # compute time delay tpast = time.time() - tlast if tpast < tdelay and tpast >= 0: time.sleep(tdelay - tpast) # Print render time and actual FPS rtime = rstop - rstart act_fps = 1 / (time.time() - tlast + 1E-10) print( 'Frame render time: {:f} sec. Actual FPS: {:.2f}'.format( rtime, act_fps)) tlast = time.time() # Close movie and delete object plobj.Close()
def BeamExample(): # Load module and example file hexfile = hexbeamfile # Load Grid grid = vtkInterface.UnstructuredGrid(hexfile) # Create fiticious displacements as a function of Z location pts = grid.GetNumpyPoints(deep=True) d = np.zeros_like(pts) d[:, 1] = pts[:, 2]**3/250 # Displace original grid grid.SetNumpyPoints(pts + d) # Camera position cpos = [(11.915126303095157, 6.11392754955802, 3.6124956735471914), (0.0, 0.375, 2.0), (-0.42546442225230097, 0.9024244135964158, -0.06789847673314177)] try: import matplotlib colormap = 'bwr' except ImportError: colormap = None # plot this displaced beam plobj = vtkInterface.PlotClass() plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement', rng=[-d.max(), d.max()], colormap=colormap) plobj.SetCameraPosition(cpos) plobj.AddText('Static Beam Example') cpos = plobj.Plot(autoclose=False) # store camera position # plobj.TakeScreenShot('beam.png') plobj.Close() # Animate plot plobj = vtkInterface.PlotClass() plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement', showedges=True, rng=[-d.max(), d.max()], interpolatebeforemap=True, colormap=colormap) plobj.SetCameraPosition(cpos) plobj.AddText('Beam Animation Example') plobj.Plot(interactive=False, autoclose=False, window_size=[800, 600]) #plobj.OpenMovie('beam.mp4') # plobj.OpenGif('beam.gif') for phase in np.linspace(0, 4*np.pi, 100): plobj.UpdateCoordinates(pts + d*np.cos(phase), render=False) plobj.UpdateScalars(d[:, 1]*np.cos(phase), render=False) plobj.Render() # plobj.WriteFrame() time.sleep(0.01) plobj.Close() # Animate plot as a wireframe plobj = vtkInterface.PlotClass() plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement', showedges=True, rng=[-d.max(), d.max()], colormap=colormap, interpolatebeforemap=True, style='wireframe') plobj.SetCameraPosition(cpos) plobj.AddText('Beam Animation Example 2') plobj.Plot(interactive=False, autoclose=False, window_size=[800, 600]) # plobj.OpenMovie('beam.mp4') # plobj.OpenGif('beam_wireframe.gif') for phase in np.linspace(0, 4*np.pi, 100): plobj.UpdateCoordinates(pts + d*np.cos(phase), render=False) plobj.UpdateScalars(d[:, 1]*np.cos(phase), render=False) plobj.Render() # plobj.WriteFrame() time.sleep(0.01) plobj.Close()
def SolveKM(): """ Loads and solves a mass and stiffness matrix from an ansys full file """ import numpy as np from scipy.sparse import linalg import pyansys # load the mass and stiffness matrices full = pyansys.FullReader(pyansys.examples.fullfile) dofref, k, m = full.LoadKM(utri=False) # removing constrained nodes (this is not efficient) free = np.logical_not(full.const).nonzero()[0] k = k[free][:, free] m = m[free][:, free] # Solve w, v = linalg.eigsh(k, k=20, M=m, sigma=10000) # System natural frequencies f = (np.real(w))**0.5 / (2 * np.pi) #%% Plot result import vtkInterface # Get the 4th mode shape mode_shape = v[:, 3] # x, y, z displacement for each node # create the full mode shape including the constrained nodes full_mode_shape = np.zeros(dofref.shape[0]) full_mode_shape[np.logical_not(full.const)] = mode_shape # reshape and compute the normalized displacement disp = full_mode_shape.reshape((-1, 3)) n = (disp * disp).sum(1)**0.5 n /= n.max() # normalize # load an archive file and create a vtk unstructured grid archive = pyansys.ReadArchive(pyansys.examples.hexarchivefile) grid = archive.ParseVTK() # plot the normalized displacement # grid.Plot(scalars=n) # Fancy plot the displacement plobj = vtkInterface.PlotClass() # add two meshes to the plotting class. Meshes are copied on load plobj.AddMesh(grid, style='wireframe') plobj.AddMesh(grid, scalars=n, stitle='Normalized\nDisplacement', flipscalars=True) # Update the coordinates by adding the mode shape to the grid plobj.UpdateCoordinates(grid.GetNumpyPoints() + disp / 80, render=False) plobj.AddText('Cantliver Beam 4th Mode Shape at {:.4f}'.format(f[3]), fontsize=30) plobj.Plot() del plobj
def RayTrace(self, origin, end_point, first_point=False, plot=False): """ Performs a single ray trace calculation given a mesh and a line segment defined by an origin and end_point. Parameters ---------- origin : np.ndarray or list Start of the line segment. end_point : np.ndarray or list End of the line segment. first_point : bool, optional Returns intersection of first point only. plot : bool, optional Plots ray trace results Returns ------- intersection_points : np.ndarray Location of the intersection points. Empty array if no intersections. intersection_cells : np.ndarray Indices of the intersection cells. Empty array if no intersections. """ points = vtk.vtkPoints() cellIDs = vtk.vtkIdList() code = self.obbTree.IntersectWithLine(np.array(origin), np.array(end_point), points, cellIDs) intersection_points = vtk_to_numpy(points.GetData()) if first_point and intersection_points.shape[0] >= 1: intersection_points = intersection_points[0] intersection_cells = [] if intersection_points.any(): if first_point: ncells = 1 else: ncells = cellIDs.GetNumberOfIds() for i in range(ncells): intersection_cells.append(cellIDs.GetId(i)) intersection_cells = np.array(intersection_cells) if plot: plotter = vtki.PlotClass() plotter.AddMesh(self, label='Test Mesh') segment = np.array([origin, end_point]) plotter.AddLines(segment, 'b', label='Ray Segment') plotter.AddPoints(intersection_points, 'r', psize=10, label='Intersection Points') plotter.AddLegend() plotter.AddAxes() # if np.any(intersection_points): # if first_point: # plotter.SetFocus(intersection_points) # else: # plotter.SetFocus(intersection_points[0]) plotter.Plot() return intersection_points, intersection_cells
def test_axes(): plotter = vtki.PlotClass(off_screen=True) plotter.AddAxes() plotter.AddMesh(vtki.Sphere()) plotter.Plot()
def test_init(self): plotter = vtki.PlotClass() assert hasattr(plotter, 'renWin')
# Make data X = np.arange(-10, 10, 0.25) Y = np.arange(-10, 10, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) # Create and plot structured grid sgrid = vtkInterface.GenStructSurf(X, Y, Z) # Make deep copy of points pts = sgrid.GetNumpyPoints(deep=True) # Start a plotter object and set the scalars to the Z height plobj = vtkInterface.PlotClass() plobj.AddMesh(sgrid, scalars=Z.ravel()) plobj.Plot(autoclose=False) # Open a gif plobj.OpenGif('wave.gif') # Update Z and write a frame for each updated position nframe = 15 for phase in np.linspace(0, 2*np.pi, nframe + 1)[:nframe]: Z = np.sin(R + phase) pts[:, -1] = Z.ravel() plobj.UpdateCoordinates(pts) plobj.UpdateScalars(Z.ravel()) plobj.WriteFrame()