def test_slices_are_associated_single_index(): dataset = examples.load_structured() points = pyvista_ndarray(dataset.GetPoints().GetData(), dataset=dataset) assert points[1, 1].VTKObject == points.VTKObject assert points[1, 1].dataset.Get() == points.dataset.Get() assert points[1, 1].association == points.association
def points(self): """Return a pointer to the points as a numpy object.""" pts = self.GetPoints() if pts is None: return None vtk_data = pts.GetData() # arr = vtk_to_numpy(vtk_data) return pyvista.pyvista_ndarray(vtk_data, dataset=self)
def test_slices_are_associated(): dataset = examples.load_structured() points = pyvista_ndarray(dataset.GetPoints().GetData(), dataset=dataset) # check that slices of pyvista_ndarray are associated correctly assert points[1, :].VTKObject == points.VTKObject assert points[1, :].dataset.Get() == points.dataset.Get() assert points[1, :].association == points.association
def test_copies_are_not_associated(): dataset = examples.load_structured() points = pyvista_ndarray(dataset.GetPoints().GetData(), dataset=dataset) points_2 = points.copy() # check that copies of pyvista_ndarray are dissociated from the original dataset assert points_2.VTKObject is None assert points_2.dataset is None assert points_2.association.name == 'NONE' assert not np.shares_memory(points, points_2)
def test_modifying_modifies_dataset(): dataset = examples.load_structured() points = pyvista_ndarray(dataset.GetPoints().GetData(), dataset=dataset) dataset_modified = mock.Mock() array_modified = mock.Mock() dataset.AddObserver(_vtk.vtkCommand.ModifiedEvent, dataset_modified) points.AddObserver(_vtk.vtkCommand.ModifiedEvent, array_modified) # __setitem__ calls dataset.Modified() and points.Modified() points[:] *= 0.5 assert dataset_modified.call_count == 1 assert array_modified.call_count == 1 # __setitem__ with single-indices works does same points[0, 0] = 0.5 assert dataset_modified.call_count == 2 assert array_modified.call_count == 2 # setting all new points calls dataset.Modified() dataset.points = points.copy() assert dataset_modified.call_count == 3 assert array_modified.call_count == 2
def wrap(dataset): """Wrap any given VTK data object to its appropriate PyVista data object. Other formats that are supported include: * 2D :class:`numpy.ndarray` of XYZ vertices * 3D :class:`numpy.ndarray` representing a volume. Values will be scalars. * 3D :class:`trimesh.Trimesh` mesh. * 3D :class:`meshio.Mesh` mesh. Parameters ---------- dataset : :class:`numpy.ndarray`, :class:`trimesh.Trimesh`, or VTK object Dataset to wrap. Returns ------- pyvista.DataSet The PyVista wrapped dataset. Examples -------- Wrap a numpy array representing a random point cloud. >>> import numpy as np >>> import pyvista >>> points = np.random.random((10, 3)) >>> cloud = pyvista.wrap(points) >>> cloud # doctest:+SKIP PolyData (0x7fc52db83d70) N Cells: 10 N Points: 10 X Bounds: 1.123e-01, 7.457e-01 Y Bounds: 1.009e-01, 9.877e-01 Z Bounds: 2.346e-03, 9.640e-01 N Arrays: 0 Wrap a Trimesh object. >>> import trimesh >>> import pyvista >>> points = [[0, 0, 0], [0, 0, 1], [0, 1, 0]] >>> faces = [[0, 1, 2]] >>> tmesh = trimesh.Trimesh(points, faces=faces, process=False) >>> mesh = pyvista.wrap(tmesh) >>> mesh # doctest:+SKIP PolyData (0x7fc55ff27ad0) N Cells: 1 N Points: 3 X Bounds: 0.000e+00, 0.000e+00 Y Bounds: 0.000e+00, 1.000e+00 Z Bounds: 0.000e+00, 1.000e+00 N Arrays: 0 Wrap a VTK object. >>> import pyvista >>> import vtk >>> points = vtk.vtkPoints() >>> p = [1.0, 2.0, 3.0] >>> vertices = vtk.vtkCellArray() >>> pid = points.InsertNextPoint(p) >>> _ = vertices.InsertNextCell(1) >>> _ = vertices.InsertCellPoint(pid) >>> point = vtk.vtkPolyData() >>> _ = point.SetPoints(points) >>> _ = point.SetVerts(vertices) >>> mesh = pyvista.wrap(point) >>> mesh # doctest:+SKIP PolyData (0x7fc55ff27ad0) N Cells: 1 N Points: 3 X Bounds: 0.000e+00, 0.000e+00 Y Bounds: 0.000e+00, 1.000e+00 Z Bounds: 0.000e+00, 1.000e+00 N Arrays: 0 """ # Return if None if dataset is None: return # Check if dataset is a numpy array. We do this first since # pyvista_ndarray contains a VTK type that we don't want to # directly wrap. if isinstance(dataset, (np.ndarray, pyvista.pyvista_ndarray)): if dataset.ndim == 1 and dataset.shape[0] == 3: return pyvista.PolyData(dataset) if dataset.ndim > 1 and dataset.ndim < 3 and dataset.shape[1] == 3: return pyvista.PolyData(dataset) elif dataset.ndim == 3: mesh = pyvista.UniformGrid(dataset.shape) mesh['values'] = dataset.ravel(order='F') mesh.active_scalars_name = 'values' return mesh else: raise NotImplementedError( 'NumPy array could not be wrapped pyvista.') # wrap VTK arrays as pyvista_ndarray if isinstance(dataset, _vtk.vtkDataArray): return pyvista.pyvista_ndarray(dataset) # Check if a dataset is a VTK type if hasattr(dataset, 'GetClassName'): key = dataset.GetClassName() try: return pyvista._wrappers[key](dataset) except KeyError: logging.warning( f'VTK data type ({key}) is not currently supported by pyvista.' ) return # wrap meshio if is_meshio_mesh(dataset): return from_meshio(dataset) # wrap trimesh if dataset.__class__.__name__ == 'Trimesh': # trimesh doesn't pad faces n_face = dataset.faces.shape[0] faces = np.empty((n_face, 4), dataset.faces.dtype) faces[:, 1:] = dataset.faces faces[:, 0] = 3 return pyvista.PolyData(np.asarray(dataset.vertices), faces) # otherwise, flag tell the user we can't wrap this object raise NotImplementedError( f'Unable to wrap ({type(dataset)}) into a pyvista type.')
size=int(dataset.n_points * subset)) return dataset.points[ids] # points = generate_points() # point_cloud = pv.PolyData(points) # #point_cloud.plot(eye_dome_lighting=True) # data = points[:,-1] # point_cloud["elevation"] = data # point_cloud.plot(render_points_as_spheres=True) points, data = readdata() points = pv.pyvista_ndarray(points) datac = pv.pyvista_ndarray(data) point_cloud = pv.PolyData(points) print("Points uniquement") point_cloud.plot(eye_dome_lighting=True) #datac = points[:,-1] point_cloud["NICS"] = datac print("Points et valeurs sur des spheres") point_cloud.plot(render_points_as_spheres=True) #s = point_cloud.extract_surface() #s.plot() #surf = s.delaunay_3d() #surf.plot() for i in range(11):
def main(): # Begin trating arguments parser = argparse.ArgumentParser( description='Display the calcuated data of IMS calculations.') parser.add_argument('--showstat', action='store_true', help='Show statistics') parser.add_argument('--open3d', action='store_false', help='Turn on open3d rendering') parser.add_argument('--mate', action='store_true', help='Turn on mate rendering') parser.add_argument('--colormode', '-c', type=str, default="auto", help='Color mode: auto|iso. default: %(default)s') parser.add_argument( '--representation', '-r', type=str, default="cloud", help='Representation mode: cloud|surface. default: %(default)s') parser.add_argument('--shot', action='store_true', help='Save a picture') parser.add_argument('--twopanels', '-2', action='store_true', help='Show the molecule') parser.add_argument('--molecule', '-m', action='store_true', help='Show the molecule') args = parser.parse_args() showstat = args.showstat colormode = args.colormode mate = args.mate representation = args.representation molecule = args.molecule open3d = args.open3d twopanels = args.twopanels shot = args.shot # End trating arguments # Read ims.dat # The ims.dat format is: # x, y, z, nx, ny, nz, val #skirow does not read the first line values = np.loadtxt("ims.dat", delimiter=",", skiprows=1) if showstat: a = np.hstack(values[:, 6]) _ = plt.hist(a, bins='auto') # arguments are passed to np.histogram plt.title("Repartition of IMS values") plt.show() geom = geometry.geometry.Geometry("geom.xyz") if open3d: pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(values[:, :3]) pcd.normals = o3d.utility.Vector3dVector(values[:, 3:6]) spheres = [] mesh_molecule = None #generate molecule in open3D format if molecule: for at in geom.atoms: mat = [[1, 0, 0, at['x']], [0, 1, 0, at['y']], [0, 0, 1, at['z']], [0, 0, 0, 1]] mesh_sphere = o3d.geometry.TriangleMesh.create_sphere( radius=0.4) mesh_sphere.transform(mat) mesh_sphere.compute_vertex_normals() if at['label'] == 'C': color = [0.4, 0.4, 0.4] elif at['label'] == 'H': color = [0.9, 0.9, 0.9] else: color = [1.0, 0.0, 0.0] mesh_sphere.paint_uniform_color(color) spheres.append(mesh_sphere) cylinders = [] molecularGraph = graph_theory.detect_cycle.MolecularGraph( "geom.xyz") for e in molecularGraph.getEdges(): idx1 = e.GetBeginAtomIdx() idx2 = e.GetEndAtomIdx() at1 = geom.getAtom(idx1) at2 = geom.getAtom(idx2) pos1 = np.asarray([at1['x'], at1['y'], at1['z']]) pos2 = np.asarray([at2['x'], at2['y'], at2['z']]) vect_bond = pos2 - pos1 middle_bond = 0.5 * (pos1 + pos2) mat_translation = np.asarray([[1, 0, 0, middle_bond[0]], [0, 1, 0, middle_bond[1]], [0, 0, 1, middle_bond[2]], [0, 0, 0, 1]]) # print(mat_translation) vect_axis = np.cross( vect_bond, [0, 0, 1]) #cylinders are aligne along z when created theta = np.arcsin( np.linalg.norm(vect_axis) / np.linalg.norm(vect_bond)) vect_axis = vect_axis / np.linalg.norm(vect_axis) ux = vect_axis[0] uy = vect_axis[1] uz = vect_axis[2] c = np.cos(theta) s = np.sin(theta) mat_rotation = np.asarray([[ ux * ux * (1 - c) + c, ux * uy * (1 - c) - uz * s, ux * uz * (1 - c) + uy * s, 0 ], [ ux * uy * (1 - c) + uz * s, uy * uy * (1 - c) + c, uy * uz * (1 - c) - ux * s, 0 ], [ ux * uz * (1 - c) - uy * s, uy * uz * (1 - c) + ux * s, uz * uz * (1 - c) + c, 0 ], [0, 0, 0, 1]]) mesh_cylinder = o3d.geometry.TriangleMesh.create_cylinder( radius=.2, height=np.linalg.norm(vect_bond)) mesh_cylinder.transform(mat_rotation) mesh_cylinder.transform(mat_translation) mesh_cylinder.compute_vertex_normals() mesh_cylinder.paint_uniform_color([0.0, 0.6, 1.0]) cylinders.append(mesh_cylinder) mesh_molecule = spheres mesh_molecule.extend(cylinders) # end generate molecule in open3D format point_rgb = valtoRGB(values[:, 6], colormode=colormode) pcd.colors = o3d.utility.Vector3dVector(np.asarray(point_rgb)) if representation == 'cloud': if molecule: o3d.visualization.draw_geometries([pcd] + mesh_molecule) else: o3d.visualization.draw_geometries([pcd]) poisson_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( pcd, depth=9)[0] if not (mate): poisson_mesh.compute_vertex_normals() density_mesh = o3d.geometry.TriangleMesh() if representation == 'surface': if molecule: vis = o3d.visualization.draw_geometries([poisson_mesh] + mesh_molecule) else: vis = o3d.visualization.draw_geometries([poisson_mesh]) o3d.io.write_triangle_mesh("./surface_mesh.ply", poisson_mesh) else: #begin pysta points = values[:, :3] data = values[:, 6] points = pv.pyvista_ndarray(points) datac = pv.pyvista_ndarray(data) point_cloud = pv.PolyData(points) point_cloud["IMS"] = datac cloud = pv.wrap(point_cloud) cloud.save('test.vtk', binary=False) # cloud.save('test_asc.vtk', binary=False) # cloud.save('test_bin.vtk', binary=True) alpha = 1 superred = np.array([1, 1, 0, alpha]) red = np.array([1, 0, 0, alpha]) darkred = np.array([1, .25, .25, alpha]) lightred = np.array([1, .75, .75, alpha]) lightblue = np.array([1, .75, .75, alpha]) darkblue = np.array([1, .25, .25, alpha]) blue = np.array([1, 0, 0, alpha]) purple = np.array([1, 0, 1, alpha]) mapping = np.linspace(datac.min(), datac.max(), 256) newcolors = np.empty((256, 4)) newcolors[mapping < 40] = superred newcolors[mapping < 30] = red newcolors[mapping < 20] = darkred newcolors[mapping < 10] = lightred newcolors[mapping < -10] = lightblue newcolors[mapping < -20] = darkblue newcolors[mapping < -30] = blue newcolors[mapping <= -40] = purple my_colormap = ListedColormap(newcolors) #Palette (1) ACIE Karadakov: p1_level_1 = np.array([1, 0.9, 0.8, alpha]) # Pale Brown p1_level_2 = np.array([0.6, 0.7, 0.95, alpha]) # Clear blue p1_level_3 = np.array([0, 0.4, 0.85, alpha]) # Clear blue but no so clear p1_level_4 = np.array([0, 0, 1, alpha]) #Plain blue p1_level_5 = np.array([0, 0, 0.4, alpha]) # Noir blue #Palette (2) Yellow to blue: p2_level_1 = np.array([1, 0.5, 0, alpha]) # Orange p2_level_2 = np.array([1, 1, 0, alpha]) # Yellow p2_level_3 = np.array([0, 1, 0, alpha]) # Green p2_level_4 = np.array([0, 0, 1, alpha]) # Blue p2_level_5 = np.array([1, 0, 1, alpha]) # "Noir blue #Palette (3) The Oranges: p3_level_1 = np.array([1, 0.9, 0.75, alpha]) # White Orange p3_level_2 = np.array([1, 0.75, 0.5, alpha]) # Clear Orange p3_level_3 = np.array([1, 0.6, 0.25, alpha]) # Pale Orange p3_level_4 = np.array([1, 0.5, 0, alpha]) # Orange p3_level_5 = np.array([0.5, 0.25, 0, alpha]) # Dark Orange #Palette (4) The Reds: p4_level_1 = np.array([1, 0.8, 0.8, alpha]) # White Red p4_level_2 = np.array([1, 0.6, 0.6, alpha]) # Clear Red p4_level_3 = np.array([1, 0.2, 0.2, alpha]) # Pale Red p4_level_4 = np.array([1, 0, 0, alpha]) # Red p4_level_5 = np.array([0.5, 0, 0, alpha]) # Dark Red #Palette (5) The Greens: p5_level_1 = np.array([0.8, 1, 0.8, alpha]) # White Green p5_level_2 = np.array([0.6, 1, 0.6, alpha]) # Clear Green p5_level_3 = np.array([0.4, 1, 0.4, alpha]) # Pale Green p5_level_4 = np.array([0, 1, 0, alpha]) # Green p5_level_5 = np.array([0, 0.25, 0, alpha]) # Dark Green #Palette (6) The Purples: p6_level_1 = np.array([1, 0.8, 1, alpha]) # White Purple p6_level_2 = np.array([1, 0.6, 1, alpha]) # Clear Purple p6_level_3 = np.array([1, 0.4, 1, alpha]) # Pale Purple p6_level_4 = np.array([1, 0, 1, alpha]) # Purple p6_level_5 = np.array([0.25, 0, 0.25, alpha]) # Dark Purple #Palette (7) The Blues: p7_level_1 = np.array([0.8, 0.8, 1, alpha]) # White Blue p7_level_2 = np.array([0.6, 0.6, 1, alpha]) # Clear Blue p7_level_3 = np.array([0.4, 0.4, 1, alpha]) # Pale Blue p7_level_4 = np.array([0, 0, 1, alpha]) # Blue p7_level_5 = np.array([0, 0, 0.25, alpha]) # Dark Blue #Palette (8) The Greyscale: p8_level_1 = np.array([1, 1, 1, alpha]) # White p8_level_2 = np.array([0.8, 0.8, 0.8, alpha]) # Clear Grey p8_level_3 = np.array([0.6, 0.6, 0.6, alpha]) # Pale Grey p8_level_4 = np.array([0.4, 0.4, 0.4, alpha]) # Grey p8_level_5 = np.array([0, 0, 0, alpha]) # Black #Colors used mapping = np.linspace(datac.min(), datac.max(), 256) newcolors = np.empty((256, 4)) newcolors[mapping > 16.5] = p4_level_5 newcolors[mapping < 16.5] = p4_level_3 newcolors[mapping < 11] = p4_level_2 newcolors[mapping < 5.5] = p1_level_1 newcolors[mapping < -5.5] = p1_level_2 newcolors[mapping < -11] = p1_level_3 newcolors[mapping < -16.5] = p1_level_5 my_colormap = ListedColormap(newcolors) if twopanels: p = MyPlotter(shape=(1, 2)) else: p = MyPlotter() p.subplot(0, 0) p.add_points(point_cloud, render_points_as_spheres=True, cmap=my_colormap) if twopanels: p.subplot(0, 1) else: p.subplot(0, 0) # spheres = [] cylinders = [] if molecule: for at in geom.atoms: mesh_sphere = pv.Sphere(radius=0.5, center=[at['x'], at['y'], at['z']]) if at['label'] == 'C': color = [0.4, 0.4, 0.4] elif at['label'] == 'H': color = [0.9, 0.9, 0.9] else: color = [1.0, 0.0, 0.0] spheres.append(mesh_sphere) molecularGraph = graph_theory.detect_cycle.MolecularGraph( "geom.xyz") for e in molecularGraph.getEdges(): idx1 = int(lbl1.replace('a', '')) - 1 idx2 = int(lbl2.replace('a', '')) - 1 at1 = geom.getAtom(idx1) at2 = geom.getAtom(idx2) pos1 = np.asarray([at1['x'], at1['y'], at1['z']]) pos2 = np.asarray([at2['x'], at2['y'], at2['z']]) vect_bond = pos2 - pos1 middle_bond = 0.5 * (pos1 + pos2) mesh_cylinder = pv.Cylinder(center=middle_bond, direction=vect_bond, radius=.2, height=np.linalg.norm(vect_bond)) cylinders.append(mesh_cylinder) # for sphere in spheres: p.add_mesh(sphere, color="tan", show_edges=False) for cyl in cylinders: p.add_mesh(cyl, color="tan", show_edges=False) p.link_views() if shot: p.show(screenshot='airplane.png') else: p.show()