def test_box(): geom = pyvista.Box() assert np.any(geom.points) bounds = [-10.0, 10.0, 10.0, 20.0, -5.0, 5.0] level = 3 quads = True mesh1 = pyvista.Box(bounds, level, quads) assert mesh1.n_cells == (level + 1) * (level + 1) * 6 assert np.allclose(mesh1.bounds, bounds) quads = False mesh2 = pyvista.Box(bounds, level, quads) assert mesh2.n_cells == mesh1.n_cells * 2
def test_where_is(): plotter = pyvista.Plotter(shape=(2, 2)) plotter.subplot(0, 0) plotter.add_mesh(pyvista.Box(), name='box') plotter.subplot(0, 1) plotter.add_mesh(pyvista.Sphere(), name='sphere') plotter.subplot(1, 0) plotter.add_mesh(pyvista.Box(), name='box') plotter.subplot(1, 1) plotter.add_mesh(pyvista.Cone(), name='cone') places = plotter.where_is('box') assert isinstance(places, list) for loc in places: assert isinstance(loc, tuple)
def test_pv_box(): box = pv.Box((-1.0, 1.0, -5.0, 5.0, -1.0, 1.0)) #box = examples.load_hexbeam() tet = tetgen.TetGen(box.triangulate()) tet.tetrahedralize(order=1, mindihedral=20, minratio=2.0) print("tet: ", tet.mesh.points) grid = tet.grid verts = grid.points print("Cells: \n", grid.cells) print("Points: \n", verts) cell_arr = extract_tets(grid.cells) print(cell_arr) constraints = [[1, [1, 1, 1]], [3, [1, 1, 1]], [4, [1, 1, 1]], [6, [1, 1, 1]]] loads = [[0, 10., 0.0, 0], [2, 10., 0.0, 0], [5, 10., 0.0, 0], [7, 10., 0.0, 0]] poisson = 0.3 youngs = 2000 displacements = solve_full(cell_arr, verts, poisson, youngs, constraints, loads) print(pd.DataFrame(displacements)) magnitudes = get_displacement_magnitudes(displacements) display_tets(verts, cell_arr, magnitudes)
def test_multiplotter(qtbot, plotting): mp = MultiPlotter( nrows=1, ncols=2, window_size=(300, 300), show=False, title='Test', off_screen=False, ) qtbot.addWidget(mp._window) mp[0, 0].add_mesh(pyvista.Cone()) mp[0, 1].add_mesh(pyvista.Box()) assert not mp._window.isVisible() with qtbot.wait_exposed(mp._window): mp.show() assert mp._window.isVisible() for p in mp._plotters: assert not p._closed with qtbot.wait_signals([mp._window.signal_close], timeout=1000): mp.close() for p in mp._plotters: assert p._closed # cover default show=True mp = MultiPlotter(off_screen=False, menu_bar=False, toolbar=False) qtbot.addWidget(mp._window) with qtbot.wait_exposed(mp._window): assert mp._window.isVisible() mp.close()
def vtk_plot(vtk): spacing = vtk.spacing[0] pl = pv.Plotter() pl.add_mesh(vtk.threshold((-spacing*3,spacing*3)),opacity=0.5) pl.add_mesh(pv.Box(bounds=vtk.bounds),style='wireframe') pl.add_axes() pl.show()
def outline_corners(self, factor=0.2, nested=False, progress_bar=False): """Produce an outline of the corners for the all blocks in this composite dataset. Parameters ---------- factor : float, optional Controls the relative size of the corners to the length of the corresponding bounds. nested : bool, optional If ``True``, these creates individual outlines for each nested dataset. progress_bar : bool, optional Display a progress bar to indicate progress. Returns ------- pyvista.PolyData Mesh containing outlined corners. """ if nested: return DataSetFilters.outline_corners(self, factor=factor, progress_bar=progress_bar) box = pyvista.Box(bounds=self.bounds) return box.outline_corners(factor=factor, progress_bar=progress_bar)
def outline(self, generate_faces=False, nested=False, progress_bar=False): """Produce an outline of the full extent for the all blocks in this composite dataset. Parameters ---------- generate_faces : bool, optional Generate solid faces for the box. This is disabled by default. nested : bool, optional If ``True``, these creates individual outlines for each nested dataset. progress_bar : bool, optional Display a progress bar to indicate progress. Returns ------- pyvista.PolyData Mesh containing the outline. """ if nested: return DataSetFilters.outline(self, generate_faces=generate_faces, progress_bar=progress_bar) box = pyvista.Box(bounds=self.bounds) return box.outline(generate_faces=generate_faces, progress_bar=progress_bar)
def test_subplot_groups(): plotter = pyvista.Plotter(shape=(3, 3), groups=[(1, [1, 2]), (np.s_[:], 0)]) plotter.subplot(0, 0) plotter.add_mesh(pyvista.Sphere()) plotter.subplot(0, 1) plotter.add_mesh(pyvista.Cube()) plotter.subplot(0, 2) plotter.add_mesh(pyvista.Arrow()) plotter.subplot(1, 1) plotter.add_mesh(pyvista.Cylinder()) plotter.subplot(2, 1) plotter.add_mesh(pyvista.Cone()) plotter.subplot(2, 2) plotter.add_mesh(pyvista.Box()) # Test group overlap with pytest.raises(AssertionError): # Partial overlap pyvista.Plotter(shape=(3, 3), groups=[([1, 2], [0, 1]), ([0, 1], [1, 2])]) with pytest.raises(AssertionError): # Full overlap (inner) pyvista.Plotter(shape=(4, 4), groups=[(np.s_[:], np.s_[:]), ([1, 2], [1, 2])]) with pytest.raises(AssertionError): # Full overlap (outer) pyvista.Plotter(shape=(4, 4), groups=[(1, [1, 2]), ([0, 3], np.s_[:])])
def _create_testing_scene(empty_scene, show=False, off_screen=False): if empty_scene: plotter = pyvista.BackgroundPlotter(show=show, off_screen=off_screen) else: plotter = pyvista.BackgroundPlotter(shape=(2, 2), border=True, border_width=10, border_color='grey', show=show, off_screen=off_screen) plotter.set_background('black', top='blue') plotter.subplot(0, 0) cone = pyvista.Cone(resolution=4) actor = plotter.add_mesh(cone) plotter.remove_actor(actor) plotter.add_text('Actor is removed') plotter.subplot(0, 1) plotter.add_mesh(pyvista.Box(), color='green', opacity=0.8) plotter.subplot(1, 0) cylinder = pyvista.Cylinder(resolution=6) plotter.add_mesh(cylinder, smooth_shading=True) plotter.show_bounds() plotter.subplot(1, 1) sphere = pyvista.Sphere(phi_resolution=6, theta_resolution=6) plotter.add_mesh(sphere) plotter.enable_cell_picking() return plotter
def test_mesh_conversion(): #mesh = pv.Sphere() mesh = pv.Box((-1.0, 1.0, -5.0, 5.0, -1.0, 1.0)) mesh = mesh.triangulate() bounds = mesh.bounds scale = list(zip(bounds[::2], bounds[1::2])) grid = mesh_to_grid(mesh, 0.5) tets, verts, manager = grid_to_tets(grid) print(tets) #display_tets(verts, tets) constraints = [[0, [1, 1, 1]], [10, [1, 1, 1]], [20, [1, 1, 1]], [30, [1, 1, 1]], [40, [1, 1, 1]], [15, [1, 1, 1]], [26, [1, 1, 1]], [32, [1, 1, 1]], [5, [1, 1, 1]], [15, [1, 1, 1]], [12, [1, 1, 1]], [3, [1, 1, 1]]] loads = [[520, 10., 0.0, 0], [516, 10., 0.0, 0], [512, 10., 0.0, 0], [508, 10., 0.0, 0], [504, 10., 0.0, 0], [500, 10., 0.0, 0], [496, 10., 0.0, 0], [492, 10., 0.0, 0], [484, 10., 0.0, 0], [480, 10., 0.0, 0], [518, 10., 0.0, 0], [510, 10., 0.0, 0]] poisson = 0.35 youngs = 3.5 displacements, B_mats = solve_full(tets, verts, poisson, youngs, constraints, loads) #magnitudes = get_displacement_magnitudes(displacements) D = generate_elasticity_mat(youngs, poisson) print("generating strains") sigmas = get_stresses(tets, displacements, B_mats, D)
def is_inside_mesh(self, mesh): """Returns True when all corners of its bounding box are enclosed.""" bounding_box = pv.Box(bounds=(self.bounding_box())) selected = bounding_box.select_enclosed_points(mesh) # The `select_enclosed_points` returns an mask/indicator array with 0/1 # for points that are outside/inside the mesh respectively. Only when # all eight points are inside (i.e. are set to 1) the cell is # considered fully inside the mesh. return sum(selected['SelectedPoints']) == 8
def get_unit_cell_box() -> pv.PolyData: """Return a box unit. The box has length 1 in all 3 dimensions, and is centered at the origin. Having the box centered at origin will make it easier for rotating the spider on a box. Returns: pv.PolyData: ``pv.Polydata`` containing the box unit. """ default_box = pv.Box() default_box.points /= 2 return default_box
def draw_3D( self, atom_scale: float = 1, background_color: str = "white", buried_color: str = "tomato", free_color: str = "steelblue", opacity: float = 0.5, size: float = 5, ) -> None: """Draw a the molecule with the buried and free points. Args: atom_scale: Scaling factor for atom size background_color: Background color for plot buried_color: Color of buried points free_color: Color of free points opacity: Point opacity size: Point size """ # Set up plotter p = BackgroundPlotter() p.set_background(background_color) # Draw molecule for atom in self._atoms: color = hex2color(jmol_colors[atom.element]) radius = atom.radius * atom_scale sphere = pv.Sphere(center=list(atom.coordinates), radius=radius) p.add_mesh(sphere, color=color, opacity=1, name=str(atom.index)) # Add buried points p.add_points(self._buried_points, color=buried_color, opacity=opacity, point_size=size) # Add free points p.add_points(self._free_points, color=free_color, opacity=opacity, point_size=size) if hasattr(self, "_octant_limits"): for name, limits_ in self._octant_limits.items(): limits = tuple(itertools.chain(*limits_)) box = pv.Box(limits) p.add_mesh(box, style="wireframe") x = np.array(limits)[:2][np.argmax(np.abs(limits[:2]))] y = np.array(limits)[2:4][np.argmax(np.abs(limits[2:4]))] z = np.array(limits)[4:][np.argmax(np.abs(limits[4:]))] p.add_point_labels(np.array([x, y, z]), [OCTANT_SIGNS[name]], text_color="black") self._plotter = p
def length(self) -> float: """Return the length of the diagonal of the bounding box. Examples -------- >>> import pyvista as pv >>> data = [pv.Sphere(center=(2, 0, 0)), pv.Cube(center=(0, 2, 0)), pv.Cone()] >>> blocks = pv.MultiBlock(data) >>> blocks.length 4.3584 """ return pyvista.Box(self.bounds).length
def test_subplot_groups(): plotter = pyvista.Plotter(shape=(3,3), groups=[(1,[1,2]),(np.s_[:],0)]) plotter.subplot(0, 0) plotter.add_mesh(pyvista.Sphere()) plotter.subplot(0, 1) plotter.add_mesh(pyvista.Cube()) plotter.subplot(0, 2) plotter.add_mesh(pyvista.Arrow()) plotter.subplot(1, 1) plotter.add_mesh(pyvista.Cylinder()) plotter.subplot(2, 1) plotter.add_mesh(pyvista.Cone()) plotter.subplot(2, 2) plotter.add_mesh(pyvista.Box()) plotter.show(before_close_callback=verify_cache_image)
def test_multi_block_list_index(ant, sphere, uniform, airplane, globe): multi = multi_from_datasets(ant, sphere, uniform, airplane, globe) # Now check everything indices = [0, 3, 4] sub = multi[indices] assert len(sub) == len(indices) for i, j in enumerate(indices): assert id(sub[i]) == id(multi[j]) assert sub.get_block_name(i) == multi.get_block_name(j) # check list of key names multi = MultiBlock() multi["foo"] = pyvista.Sphere() multi["goo"] = pyvista.Box() multi["soo"] = pyvista.Cone() indices = ["goo", "foo"] sub = multi[indices] assert len(sub) == len(indices) assert isinstance(sub["foo"], PolyData)
def draw_pixels(plotter, pixels, center, color): bounds = [ center[0] - 1.0, center[0] + 1.0, center[1] - 1.0, center[1] + 1.0, -10.0, +10.0, ] for rows in pixels: for pixel in rows: if pixel == True: box = pv.Box(bounds=bounds) plotter.add_mesh(box, color=color) bounds[0] += 2.0 bounds[1] += 2.0 bounds[0] = center[0] - 1.0 bounds[1] = center[0] + 1.0 bounds[2] += -2.0 bounds[3] += -2.0 return plotter
def test_multi_block_list_index(): multi = pyvista.MultiBlock() # Add examples multi.append(ex.load_ant()) multi.append(ex.load_sphere()) multi.append(ex.load_uniform()) multi.append(ex.load_airplane()) multi.append(ex.load_globe()) # Now check everything indices = [0, 3, 4] sub = multi[indices] assert len(sub) == len(indices) for i, j in enumerate(indices): assert id(sub[i]) == id(multi[j]) assert sub.get_block_name(i) == multi.get_block_name(j) # check list of key names multi = pyvista.MultiBlock() multi["foo"] = pyvista.Sphere() multi["goo"] = pyvista.Box() multi["soo"] = pyvista.Cone() indices = ["goo", "foo"] sub = multi[indices] assert len(sub) == len(indices) assert isinstance(sub["foo"], pyvista.PolyData)
def length(self): """Return the length of the diagonal of the bounding box of the scene.""" return pyvista.Box(self.bounds).length
def main(): datenow = datetime.datetime.now() datenow = datenow.strftime("%d/%m/%Y %H:%M:%S") sys.argv[0] = sys.argv[0].replace(" ", "\ ") start = time.perf_counter() # Write a log file log = open("nc_cryst.log", "a+") log_line = " ".join(sys.argv) log.write(datenow + " " + log_line + "\n") log.close() warnings.filterwarnings("ignore") # Disable ################################################################################## def blockPrint(): sys.stdout = open(os.devnull, 'w') # Restore def enablePrint(): sys.stdout = sys.__stdout__ def complementary(hex): """returns RGB components of complementary color""" hex = hex.lstrip('#') r, g, b = tuple(int(hex[i:i + 2], 16) for i in (0, 2, 4)) hsv = rgb_to_hsv(r, g, b) return (r / 255, g / 255, b / 255), tuple( np.array(hsv_to_rgb(((hsv[0] + 0.5) % 1), hsv[1], hsv[2])) / 255) def update_axes_label_color(axes_actor, color=None): """Set the axes label color (internale helper).""" if color is None: color = rcParams['font']['color'] color = parse_color(color) if isinstance(axes_actor, vtk.vtkAxesActor): prop_x = axes_actor.GetXAxisCaptionActor2D( ).GetCaptionTextProperty() prop_y = axes_actor.GetYAxisCaptionActor2D( ).GetCaptionTextProperty() prop_z = axes_actor.GetZAxisCaptionActor2D( ).GetCaptionTextProperty() for prop in [prop_x, prop_y, prop_z]: prop.SetColor(color[0], color[1], color[2]) prop.SetShadow(False) elif isinstance(axes_actor, vtk.vtkAnnotatedCubeActor): axes_actor.GetTextEdgesProperty().SetColor(color) return def create_axes_marker2(label_color=None, x_color=None, y_color=None, z_color=None, xlabel='a', ylabel='b', zlabel='c', labels_off=False, line_width=50): """Return an axis actor to add in the scene.""" if x_color is None: x_color = rcParams['axes']['x_color'] if y_color is None: y_color = rcParams['axes']['y_color'] if z_color is None: z_color = rcParams['axes']['z_color'] axes_actor = vtk.vtkAxesActor() axes_actor.GetXAxisShaftProperty().SetColor(parse_color(x_color)) axes_actor.GetXAxisTipProperty().SetColor(parse_color(x_color)) axes_actor.GetYAxisShaftProperty().SetColor(parse_color(y_color)) axes_actor.GetYAxisTipProperty().SetColor(parse_color(y_color)) axes_actor.GetZAxisShaftProperty().SetColor(parse_color(z_color)) axes_actor.GetZAxisTipProperty().SetColor(parse_color(z_color)) transform = vtk.vtkTransform() mat = transform.GetMatrix() latt_or = np.array(latt) latt_or[:, 0] = 2 * latt_or[:, 0] / np.linalg.norm(latt_or[:, 0]) latt_or[:, 1] = 2 * latt_or[:, 1] / np.linalg.norm(latt_or[:, 1]) latt_or[:, 2] = 2 * latt_or[:, 2] / np.linalg.norm(latt_or[:, 2]) for i in range(len(latt)): for j in range(len(latt)): mat.SetElement(i, j, 2 * latt_or[i, j]) axes_actor.SetUserTransform(transform) text = vtk.vtkTextProperty() text.SetFontSize(100) text.SetBold(True) text.SetFontFamilyAsString("Times") # Set labels axes_actor.SetXAxisLabelText(xlabel) axes_actor.SetYAxisLabelText(ylabel) axes_actor.SetZAxisLabelText(zlabel) axes_actor.SetNormalizedLabelPosition((1.3, 1.3, 1.3)) axes_actor.GetXAxisCaptionActor2D().SetCaptionTextProperty(text) axes_actor.GetYAxisCaptionActor2D().SetCaptionTextProperty(text) axes_actor.GetZAxisCaptionActor2D().SetCaptionTextProperty(text) if labels_off: axes_actor.AxisLabelsOff() # Set Line width axes_actor.GetXAxisShaftProperty().SetLineWidth(line_width) axes_actor.GetYAxisShaftProperty().SetLineWidth(line_width) axes_actor.GetZAxisShaftProperty().SetLineWidth(line_width) #axes_actor.SetNormalizedTipLength(1,1,1) #axes_actor.SetNormalizedShaftLength(2,2,2) update_axes_label_color(axes_actor, label_color) #axes_actor.SetNormalizedShaftLength(1.6,1.6,1.6) #axes_actor.SetNormalizedTipLength(0.4,0.4,0.4) #axes_actor.SetTotalLength(2,2,2) return axes_actor #atomic valency valency = np.array([ 1, 0, 1, 2, 3, 4, 5, 8, 1, 0, 1, 2, 3, 4, 5, 6, 6, 0, 1, 2, 3, 6, 5, 6, 7, 6, 5, 6, 4, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 4, 3, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 4, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 6, 6, 7, 2, 3, 4, 5, 6, 4, 7, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 6, 4, 5, 4, 4, 3, 3, 3, 4, 5, 6, 7, 8, 6, 6, 3, 2, 1, 2, 3, 4, 0, 8 ]) # Some functions track_r = np.array([[-10, -10, -10]]) def field_lines(point_grid): #ds=(V**(1/3))/N #ads=2/N mag_2 = [] N = 100 #ds=0.01 track_n = [] track_r = np.array([[-10, -10, -10]]) lines = np.zeros((2 * len(point_grid), N, 3)) mag = np.zeros((2 * len(point_grid), N)) j = -1 for o, r0 in enumerate(point_grid): F_old = [0, 0, 0] F_mag = 0 for one in [1, -1]: j += 1 xs = [] ys = [] zs = [] r = r0 for n in range(N): s = 0.01 xs.append(r[0]) ys.append(r[1]) zs.append(r[2]) lines[j, n, :] = r mag[j, n] = np.linalg.norm(F_mag) #mag.append(np.linalg.norm(F_mag)) #mag_2.append(np.linalg.norm(F_mag)) if nc_fort.is_close(track_r, r, len(track_r), 5e-3): break track_r = np.vstack((track_r, r)) if r[0] >= np.max(X) or r[0] <= np.min( X) or r[1] >= np.max(Y) or r[1] <= np.min( Y) or r[2] >= np.max(Z) or r[2] <= np.min(Z): break x, y, z = r try: vec_x = f_x([x, y, z]) except: vec_x = [0, 0, 0] try: vec_y = f_y([x, y, z]) except: vec_y = [0, 0, 0] try: vec_z = f_z([x, y, z]) except: vec_z = [0, 0, 0] F = np.array([vec_x[0], vec_y[0], vec_z[0]]) #line_gen(r) F_mag = F F = F / np.linalg.norm(F) phi = np.dot(F, F_old) phi = np.arccos(phi) / np.pi #print(n,phi) if np.round(phi, 4) == 1: break r = r + one * F * s F_old = F track_n.append(n) xs = np.array(xs) ys = np.array(ys) zs = np.array(zs) line_points = np.column_stack((xs, ys, zs)) return lines, mag, track_n ############################################################# #import matplotlib.pyplot as plt # LEFT BLANK ############################################################### ### ####### ###### # # # # # ## ##### #### ###### ##### # # # # # # # # # # # # # # # # ##### ###### # # # # #### ##### # # # # # # ###### ##### # # ##### # # # # # # # # # # # # # ### ####### # # # # # #### ###### # # ################################################################ # We want to read the parameters from a file called seed.nc_param # get from the commandline the seed parser = argparse.ArgumentParser( description= "Visualisation of cell structures and non-collinear magentic properties from a CASTEP job." ) parser.add_argument("seed", help="The seed from the CASTEP calculation.") parser.add_argument("-v", "--verbose", action="store_true", help="Turn on verbose output.") #parser.add_argument("-s","--sym",help="Tolerance for specifying reproduction of atoms outside unit cell (Ang)",default=1) parser.add_argument("-i", "--initmag", action="store_true", help="Plot initial magnetic moment vectors.") parser.add_argument( "-c", "--castep", action="store_true", help= "Read <seed>.castep file to determine moments. Only for NCM calculation (BETA)" ) parser.add_argument( "-f", "--field", help= "Read formatted potential or density to produce field. Only from VECTOR magnetic run.", action="store_true") parser.add_argument( "-o", "--orient", help= "Orientation of the crystal structure, takes values 'a,b,c,a*,b*,c*'.", default="sd") parser.add_argument("-B", "--bond", help="Set maximun bond length.", default=2.4) parser.add_argument("--save", help="Save image.", action="store_true") parser.add_argument("-d", "--delete", help="Delete atoms", nargs='+') parser.add_argument("-p", "--position", help="Camera position vector", nargs=6, default=np.array([0., 0., 0., 0., 0., 0.])) parser.add_argument( "-V", "--volumetric", help= "Provide file with volumetric data: .xsf .den_fmt .pot_fmt accepted.") parser.add_argument("-I", "--iso", help="Isosurface value for volumetric data", nargs="*") parser.add_argument("--colour", help="HEX code for Isosurface colouring", default="#0000FF") parser.add_argument("-z", "--zoom", help="Zoom multiplier", default=1) parser.add_argument("-e", "--exclude", help="Exclude atoms outside first unitcell", action="store_false") parser.add_argument( "-l", "--lines", help="Disable plotting of field lines of a provoded field line", action="store_true") parser.add_argument( "-P", "--plane", help= "Three points in fractional coordinates to define a plane for B-field.", nargs="*") parser.add_argument("-w", "--widget", help="Disable interactive widgets", action="store_false") parser.add_argument("-s", "--saturation", help="Saturation level for sections.", default=1) parser.add_argument("-S", "--spin", help="Plot spin isosurfaces from .den_fmt", action="store_true") parser.add_argument("-C", "--charge", help="Plot charge isosurfaces from .den_fmt", action="store_true") parser.add_argument( "-r", "--reduction", help= "Factor used to reduce the size of atoms, useful for visualising volumetric data without loss of context.", default=1.0) args = parser.parse_args() seed = args.seed #do_legend = args.legend do_verbose = args.verbose do_init_mag = args.initmag do_magmom = args.castep #do_Bfield=args.B_XC field = args.field #sym_tol=np.float(args.sym) orient = args.orient bond_cut = np.float(args.bond) save = args.save hide = args.delete cam_pos = args.position z = np.float(args.zoom) hide_lines = args.lines plane = args.plane exclude = args.exclude widgets = args.widget sat = np.float(args.saturation) docharge = args.charge dospin = args.spin reduction = np.float(args.reduction) iso = args.iso if plane == None: do_plane = False elif len(plane) == 9: do_plane = True elif len(plane) == 0: do_plane = True widgets = True else: print("Insufficient points provided for plane") sys.exit() if iso == None: do_iso = False elif len(iso) == 0: do_iso = True iso = None elif len(iso) > 1: print("Incorrect number of ISO arguments") sys.exit() else: do_iso = True # Make Charge the default if not docharge and not dospin: docharge = True if dospin: docharge = False xsf_file = args.volumetric hex_col = args.colour sym_tol = bond_cut for i in range(len(cam_pos)): cam_pos[i] = np.float(cam_pos[i]) if hide == None: hide = [""] # Define all the options (and the defaults) do_bonds = True #do_magmom = False #do_Bfield = False do_proj = False h = 0.5 #b_xc_file=seed+".B_xc.pot_fmt" xsffile = False denfile = False potfile = False noncollinear = False # Set iso surface colourmap iso_colours = complementary(hex_col) colors = list(iso_colours) colours = [colors[1], colors[0]] cmap_name = "iso_colors" cm = LinearSegmentedColormap.from_list(cmap_name, colours, N=2) # Open the tkinter window window = Tk() window.resizable(False, False) window.title("NC_CRYST: " + seed) output = Text(window) output.grid(row=1, column=0, columnspan=4) #,sticky=N+S+W) ################################################################## # Define all of the atom positions blockPrint() #if do_verbose: # print("Parsing .cell") cell = io.read(seed + ".cell") ccalc = Castep() ase_cell = cell.get_cell() a, b, c, alpha, beta, gamma = cell.get_cell_lengths_and_angles() pos = cell.get_positions() prim_pos = pos cell.set_calculator(ccalc) latt = np.transpose(np.matmul(np.identity(3), cell.get_cell())) init_mag = np.zeros((len(pos), 3)) init_spin = np.zeros((len(pos), 3)) if do_init_mag: try: with open(seed + ".cell") as init_cell: data = init_cell.readlines() except: print("No file: " + seed + ".cell") sys.exit() pos_i = [] counter = 0 for i in data: if "spin" in i.lower(): try: i = i.replace("=", " ") i = i.strip("\n") except: None i = i.split() if len(i) > 6: pos_i.append([np.float(j) for j in i[1:4]]) init_mag[counter] = [np.float(j) for j in i[5:8]] else: pos_i.append([np.float(j) for j in i[1:4]]) temp = [0., 0., np.float(i[5])] init_mag[counter] = temp counter += 1 init_spin = np.zeros((len(pos), 3)) sum_dat = "".join(data).lower() for i in range(len(pos_i)): for j in range(len(pos)): if "positions_frac" in sum_dat: dist = np.sum((np.matmul(latt, pos_i[i]) - pos[j])**2) if dist < 0.00001: init_spin[j] = init_mag[i] else: dist = np.sum((pos_i[i] - pos[j])**2) if dist < 0.00001: init_spin[j] = init_mag[i] cell.set_velocities(init_spin) # Make the supercell (gets all of the positions for me) scell = make_supercell(cell, 3 * np.identity(3)) pos = scell.get_positions() atoms = scell.get_atomic_numbers() symb = scell.get_chemical_symbols() Vol = cell.get_volume() enablePrint() #print(pos) atom_colours = jmol_colors[atoms] atom_radii = vdw_radii[atoms] inv_latt = np.linalg.inv(np.array(ase_cell.T)) init_spin = scell.get_velocities() #prim_count=0 #prim_list=np.zeros(len(pos),order="F") prim_count, prim_list, pos, keep, n_atoms, bonds, n_bonds = nc_fort.sym_positions( bond_cut, len(pos), pos, latt, inv_latt, exclude) prim_list = np.array(keep[0:prim_count]) #sys.exit() pos = pos[prim_list] atoms = atoms[prim_list] #pos=pos[prim_list] atom_radii = atom_radii[prim_list] atom_colours = atom_colours[prim_list] symb = np.array(symb)[prim_list] init_spin = init_spin[prim_list] unique_atom, atom_counts = np.unique(atoms, return_counts=True) atom_label = [] sort = [] ###################################### SYMMETRY POSITIONS ################### for j in unique_atom: for i in range(len(cell.get_atomic_numbers())): if atoms[i] == j: sort.append(i) sort = np.array(sort) if do_magmom: with open(seed + ".castep") as castep: castep_lines = castep.readlines() for no, test in enumerate(castep_lines): if "Noncollinear Spin Vectors" in test: line_no = no mom_vec = [] vec_symb = [] for i in range(line_no + 4, line_no + 4 + len(prim_pos)): cline = castep_lines[i] cline = cline.split() vec = [np.float(cline[2]), np.float(cline[3]), np.float(cline[4])] vec_symb.append(cline[0]) mom_vec.append(vec) #print(mom_vec) vec_symb_2 = list(vec_symb) mom_vec_2 = list(mom_vec) for i in range(len(sort)): vec_symb_2[sort[i]] = vec_symb[i] mom_vec_2[sort[i]] = mom_vec[i] vec_symb = list(vec_symb_2) mom_vec = list(mom_vec_2) if do_magmom: ccell = cell.copy() ccell.set_velocities(mom_vec) ccell = make_supercell(ccell, 3 * np.identity(3)) mom_vec = ccell.get_velocities() sort = np.argsort(atoms) atoms = atoms[sort] pos = pos[sort] atom_radii = atom_radii[sort] atom_colours = atom_colours[sort] symb = np.array(symb)[sort] if do_init_mag: init_spin = init_spin[sort] if do_magmom: mom_vec = np.array(mom_vec) mom_vec = mom_vec[sort] for i in atom_counts: for j in range(i): atom_label.append(j + 1) hide_num = [] for i in range(len(symb)): for j in hide: if j == symb[i]: hide_num.append(i) # Time for some plotting pv.set_plot_theme("document") if save: p = pv.Plotter(off_screen=True) else: p = pv.Plotter() p.enable_parallel_projection() orientation = [latt[:, 0], latt[:, 1], latt[:, 2]] for i in range(3): orientation[i] = orientation[i] / 2 * np.linalg.norm(orientation[i]) arrow_or=pv.Arrow([0,0,0],orientation[0],tip_length=0.25, tip_radius=0.09, tip_resolution=20, shaft_radius=0.03, shaft_resolution=20) +\ pv.Arrow([0,0,0],orientation[1],tip_length=0.25, tip_radius=0.09, tip_resolution=20, shaft_radius=0.03, shaft_resolution=20) +\ pv.Arrow([0,0,0],orientation[2],tip_length=0.25, tip_radius=0.09, tip_resolution=20, shaft_radius=0.03, shaft_resolution=20)+\ pv.Sphere(0.1,[0,0,0]) test = create_axes_marker2(label_color="black", line_width=4, x_color="r", y_color="g", z_color="b", xlabel="a", ylabel="b", zlabel="c", labels_off=False) p.add_orientation_widget(test) ######################################################################################################################## # _______ _ _ _ ______ _ _ _ #(_______|_) | | | | / _____) | | | | _ (_) # _____ _ ____| | _ | | | / ____| | ____ _ _| | ____| |_ _ ___ ____ ___ #| ___) | |/ _ ) |/ || | | | / _ | |/ ___) | | | |/ _ | _)| |/ _ \| _ \ /___) #| | | ( (/ /| ( (_| | | \____( ( | | ( (___| |_| | ( ( | | |__| | |_| | | | |___ | #|_| |_|\____)_|\____| \______)_||_|_|\____)\____|_|\_||_|\___)_|\___/|_| |_(___/ ######################################################################################################################## if xsf_file != None: # See what sort of file we have. if ".den_fmt" in xsf_file: denfile = True elif ".pot_fmt" in xsf_file: potfile = True elif ".xsf" in xsf_file: xsffile = True nx, ny, nz, mesh_mag = xsf.read_xsf(xsf_file) if potfile: docharge = False dospin = False if potfile or denfile: with open(xsf_file) as header: data = header.readlines()[0:11] nx, ny, nz = data[8].split()[0:3] nx, ny, nz = int(nx), int(ny), int(nz) #latt=np.array([data[3].split()[0:3],data[4].split()[0:3],data[5].split()[0:3]]).astype(float) #latt=np.transpose(latt) V = np.loadtxt(xsf_file, skiprows=11) #n= np.round(h*nz) #mask=(V[:,2] == n ) V3D = V #V=V[mask] if potfile: if np.shape(V3D)[1] == 9: noncollinear = True V1 = V3D[:, 3] + 1j * V3D[:, 4] V2 = V3D[:, 5] + 1j * V3D[:, 6] V3 = V3D[:, 7] + 1j * V3D[:, 8] B_x = np.real((V3 + np.conj(V3)) / 2) B_y = np.real(1j * (V3 - np.conj(V3)) / 2) B_z = np.real((V1 - V2) / 2) else: noncollinear = False print("3D data only accepted for NCM .pot_fmt, Exiting...") sys.exit() if denfile: if np.shape(V3D)[1] == 7: noncollinear = True B_x = V3D[:, 4] B_y = V3D[:, 5] B_z = V3D[:, 6] charge = V3D[:, 3] mesh_mag = np.zeros((nx, ny, nz)) if docharge: for i in range(len(V3D)): mesh_mag[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = charge[i] else: noncollinear = False charge = V3D[:, 3] spin = V3D[:, 4] mesh_mag = np.zeros((nx, ny, nz)) if docharge: for i in range(len(V3D)): mesh_mag[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = charge[i] if dospin: for i in range(len(V3D)): mesh_mag[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = spin[i] mesh_mag = mesh_mag / (nx * ny * nz) #print("NCM: ",noncollinear) #print("POT: ",potfile) #print("DEN: ",denfile) #print("Charge: ",docharge) #print("Spin: ",dospin) if noncollinear and not docharge: mesh3D_x = np.zeros((nx, ny, nz)) mesh3D_y = np.zeros((nx, ny, nz)) mesh3D_z = np.zeros((nx, ny, nz)) for i in range(len(V3D)): mesh3D_x[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = B_x[i] mesh3D_y[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = B_y[i] mesh3D_z[int(V3D[i, 0] - 1), int(V3D[i, 1] - 1), int(V3D[i, 2] - 1)] = B_z[i] mesh_mag = np.sqrt(mesh3D_x**2 + mesh3D_y**2 + mesh3D_z**2) # Calcuate the Div x_flux = np.sum(mesh3D_x[0:-1, 0, 0]) - np.sum(mesh3D_x[0:-1, -1, -1]) y_flux = np.sum(mesh3D_x[0, 0:-1, 0]) - np.sum(mesh3D_x[-1, 0:-1, -1]) z_flux = np.sum(mesh3D_x[0, 0, 0:-1]) - np.sum(mesh3D_x[-1, -1, 0:-1]) flux = x_flux + y_flux + z_flux # Play here might cause asymmetry Vx = (V[:, 0] - 1) / (nx) Vy = (V[:, 1] - 1) / (ny) Vz = (V3D[:, 2] - 1) / (nz) # Set up for fieldlines calc X = np.linspace(np.min(Vx), np.max(Vx), nx, endpoint=True) Y = np.linspace(np.min(Vy), np.max(Vy), ny, endpoint=True) Z = np.linspace(np.min(Vz), np.max(Vz), nz, endpoint=True) f_x = RegularGridInterpolator((X, Y, Z), mesh3D_x) f_y = RegularGridInterpolator((X, Y, Z), mesh3D_y) f_z = RegularGridInterpolator((X, Y, Z), mesh3D_z) #X,Y=np.meshgrid(X,Y) n_grid = 175 ix = int(np.round(a / np.cbrt(Vol / n_grid))) iy = int(np.round(b / np.cbrt(Vol / n_grid))) iz = int(np.round(c / np.cbrt(Vol / n_grid))) if ix == 0: ix = 1 if iy == 0: iy = 1 if iz == 0: iz = 1 #sys.exit() #ix,iy,iz=[8,8,3] N = 500 k = 0.5 x = np.linspace(0.1, 0.9, ix, endpoint=True) y = np.linspace(0.1, 0.9, iy, endpoint=True) z = np.linspace(0.1, 0.9, iz, endpoint=True) gx, gy, gz = np.meshgrid(x, y, z) gx = gx.reshape(ix * iy * iz) gy = gy.reshape(ix * iy * iz) gz = gz.reshape(ix * iy * iz) point_grid = np.zeros((ix * iy * iz, 3)) point_grid[:, 0] = gx point_grid[:, 1] = gy point_grid[:, 2] = gz if field: #for m,gpoint in enumerate(point_grid): #i,j,k=gpoint # track_r=field_lines(np.array([i,j,k]),track_r)#map[m][0:counter[m]]) lines, mags, n_track = field_lines(point_grid) mags = np.power(mags, 0.45) #mags=mags/np.max(mags) for k in range(2 * len(point_grid)): if n_track[k] > 1: line_points = lines[k, 0:n_track[k], :] mag = mags[k, 0:n_track[k]] line_points = nc_fort.multmatmul( latt, line_points, len(line_points)) mag[0] = mag[1] #mag=mag/np.max(mag) #mag[mag<0.3*np.max(mag)]=0#0.5*np.max(mag) r = 0.008 polyLine = pv.PolyData(line_points) polyLine.points = line_points polyLine["scalars"] = np.array(mag) theCell = np.arange(0, len(line_points), dtype=np.int) theCell = np.insert(theCell, 0, len(line_points)) polyLine.lines = theCell tube = polyLine.tube(radius=r) #p.add_mesh(tube,color="black", smooth_shading=True) p.add_mesh( tube, show_scalar_bar=False, cmap="gist_yarg", opacity=mag, pickable=False ) #,color="black")#cmap='binary',opacity=mag) #Flatten the mesh if not xsffile: mesh_mag = mesh_mag.flatten('F') else: mesh_mag = mesh_mag.flatten('C') #if not xsffile: xs = np.linspace(0, 1, nx, endpoint=True) ys = np.linspace(0, 1, ny, endpoint=True) zs = np.linspace(0, 1, nz, endpoint=True) points = np.zeros((mesh_mag.shape[0], 3)) counter = 0 for z in zs: for y in ys: for x in xs: points[counter, :] = np.matmul(latt, [x, y, z]) counter += 1 sgrid = pv.StructuredGrid() sgrid.points = points sgrid.dimensions = [nx, ny, nz] sgrid.point_arrays["values"] = mesh_mag if do_plane: # calculate the vectors if len(plane) > 1: plane = nc_fort.multmatmul(latt, plane, 3) v1 = plane[0] - plane[1] v2 = plane[0] - plane[2] print(v1, v2) norm = np.cross(v1, v2) if np.linalg.norm(norm) == 0: print("Plane vectors colinear: Exiting...") sys.exit() v2 = np.cross(norm, v1) cmap = "autumn" #"plasma" if save or len(plane) > 1: slice = sgrid.slice(norm, plane[0]) val = slice.point_arrays["values"] p.add_mesh(slice, cmap=cmap, show_scalar_bar=False, clim=(np.min(val), sat * np.max(val)), pickable=False) else: p.add_mesh_slice(sgrid, show_scalar_bar=False, cmap=cmap, show_edges=False, implicit=False, clim=(np.min(mesh_mag), sat * np.max(mesh_mag)), pickable=False) if do_iso: if iso == None: iso = 0.05 * np.max([np.max(mesh_mag), abs(np.min(mesh_mag))]) else: iso = np.float(iso[0]) output.insert(END, "VOLUMETRIC\n") output.insert(END, "----------\n") output.insert( END, "Max: " + str(np.max(mesh_mag)) + " Min: " + str(np.min(mesh_mag)) + "\n") output.insert(END, "Isovalue: " + str(iso) + "\n") output.insert(END, " \n") if save or not widgets: contours = sgrid.contour([iso, -iso]) slider_contour = p.add_mesh(contours, opacity=0.4, cmap=cm, smooth_shading=True, show_scalar_bar=False, lighting=True, name="contour", pickable=False) else: def cont(iso_val): contours = sgrid.contour([iso_val, -iso_val]) slider_contour = p.add_mesh(contours, opacity=0.4, cmap=cm, smooth_shading=True, show_scalar_bar=False, lighting=True, name="contour", pickable=False) return p.add_slider_widget(cont, rng=(np.min(mesh_mag), np.max(mesh_mag)), value=iso, style="modern", title="Isosurface Value", pointa=(0.1, 0.9), pointb=(0.3, 0.9)) ######################################################################################################################## ######################################################################################################################## ######################################################################################################################## ######################################################################################################################## ######################################################################################################################## ######################################################################################################################## # Add the box edges = np.array([[[0., 0., 0.], [0., 0., 1.]], [[0., 0., 0.], [0., 1., 0.]], [[0., 0., 0.], [1., 0., 0.]], [[1., 1., 1.], [1., 0., 1.]], [[1., 1., 1.], [1., 1., 0.]], [[1., 1., 1.], [0., 1., 1.]], [[0., 1., 1.], [0., 0., 1.]], [[0., 1., 1.], [0., 1., 0.]], [[1., 1., 0.], [1., 0., 0.]], [[1., 1., 0.], [0., 1., 0.]], [[1., 0., 0.], [1., 0., 1.]], [[0., 0., 1.], [1., 0., 1.]]]) for i, main in enumerate(edges): for j, sub in enumerate(main): edges[i, j] = np.matmul(latt, sub) box = pv.Box([0, 1, 0, 1, 0, 1]) for i in range(0, 12): p.add_lines(edges[i], color="black", width=1.5) # Do the atoms for i, vec in enumerate(pos): if i in hide_num: continue sphere = pv.Sphere(atom_radii[i] / (reduction * 5), vec, theta_resolution=200, phi_resolution=200) p.add_mesh(sphere, color=atom_colours[i], specular=0.3, specular_power=30, ambient=0.2, diffuse=1, pickable=True) def pick_atom(actor, two): if actor != None: centre = actor.center #np.matmul(np.linalg.inv(latt),actor.center) for i in range(len(pos)): if (np.isclose(pos[i], centre)).all(): break vec = np.round(np.matmul(np.linalg.inv(latt), pos[i]), 4) string = "Atom " + str(i) + ":" + " " + symb[i] + " (" + str( vec[0]) + " , " + str(vec[1]) + " , " + str(vec[2]) + ")\n" #print(string) output.insert(END, string) #p.enable_cell_picking(through=True,callback=pick_atom,show_message=False,use_mesh=True) p.enable_point_picking(callback=pick_atom, use_mesh=True, show_message=False, show_point=False) p.window_size = 1000, 1000 p.store_image = True # Do the bonds #print("No. atoms: ",len(atoms)) output.insert(END, "No. atoms: " + str(len(atoms)) + "\n") if do_bonds: bond_length = [] bond_name = [] bond_ind = [] bonds = np.zeros(len(atoms)) for atom1 in range(len(pos)): for atom2 in range(atom1, len(pos)): dist = np.sqrt(np.sum((pos[atom1] - pos[atom2])**2)) if dist > 0 and dist < bond_cut: bond_length.append(dist) bond_name.append(symb[atom1] + str(atom_label[atom1]) + "-" + symb[atom2] + str(atom_label[atom2])) bond_ind.append([atom1, atom2]) bonds[atom1] += 1 bonds[atom2] += 1 bond_length = np.array(bond_length) valence = valency[atoms - 1] over = -valence + bonds pop = [] for atom in range(len(over)): if over[atom] <= 0: continue atom_loc = [] for n, i in enumerate(bond_ind): if atom == i[0] or atom == i[1]: atom_loc.append(n) lengths = bond_length[atom_loc] loc = np.argsort(lengths)[-int(over[atom]):] for i in loc: pop.append(atom_loc[i]) bond_length = list(bond_length) pop = np.flip(np.unique(pop)) for pi in pop: bond_length.pop(pi) bond_name.pop(pi) bond_ind.pop(pi) for i, index in enumerate(bond_ind): i, j = index if i in hide_num or j in hide_num: continue points = np.array([pos[i], (pos[j] + pos[i]) / 2]) direc = points[0] - points[1] mid = (points[1] + points[0]) / 2 height = np.sqrt(np.sum((points[0] - points[1])**2)) cyl = pv.Cylinder(mid, direc, np.min(atom_radii) / 20, height) p.add_mesh(cyl, color=atom_colours[i], pickable=False) points = np.array([pos[j], (pos[j] + pos[i]) / 2]) direc = points[0] - points[1] mid = (points[1] + points[0]) / 2 height = np.sqrt(np.sum((points[0] - points[1])**2)) cyl = pv.Cylinder(mid, direc, np.min(atom_radii) / 20, height) p.add_mesh(cyl, color=atom_colours[j], specular=0.3, specular_power=30, ambient=0.2, diffuse=1, pickable=False) #for i in bond_name: # print(i) if do_magmom: for i in range(len(pos)): if i in hide_num: continue temp_pos = pos[i] - np.array(mom_vec[i]) / 2 arrow = pv.Arrow(temp_pos, mom_vec[i], tip_length=0.15, tip_radius=0.09, tip_resolution=20, shaft_radius=0.04, shaft_resolution=20, scale='auto') p.add_mesh(arrow, color='b', pickable=False) if do_init_mag: for i in range(len(pos)): if i in hide_num: continue temp_pos = pos[i] - np.array(1.5 * init_spin[i]) / 2 arrow = pv.Arrow(temp_pos, 1.5 * init_spin[i], tip_length=0.15, tip_radius=0.09, tip_resolution=20, shaft_radius=0.04, shaft_resolution=20, scale='auto') p.add_mesh(arrow, color='g', pickable=False) try: p.camera.zoom(z) except: output.insert(END, "Zoom not implemented in this version of PyVista.\n") #print("Zoom not implemented in this version of PyVista.") ############################################################################################### def screenshot(): wind = p.window_size height = 2560 p.window_size = [ height, int(height * p.window_size[1] / p.window_size[0]) ] p.save_graphic(seed + ".eps") p.window_size = wind if do_verbose: output.insert(END, "Graphic saved!\n") p.add_key_event("s", screenshot) def perpendicular(a): b = np.empty_like(a) b[0] = -a[1] b[1] = a[0] return b # calculate the reciprocal lattice vectors a1 = latt[:, 0] a2 = latt[:, 1] a3 = latt[:, 2] b1 = np.cross(a2, a3) b2 = np.cross(a3, a1) b3 = np.cross(a1, a2) focus = np.matmul(latt, np.array([0.5, 0.5, 0.5])) if orient != None: cp = p.camera_position if orient == 'a': o = a3 vpvec = a1 / np.linalg.norm(a1) elif orient == 'a*': o = a3 vpvec = b1 / np.linalg.norm(b1) elif orient == 'b': o = a3 vpvec = a2 / np.linalg.norm(a2) elif orient == 'b*': o = a3 vpvec = b2 / np.linalg.norm(b2) elif orient == 'c': o = a2 vpvec = a3 / np.linalg.norm(a3) elif orient == 'c*': o = a2 vpvec = b3 / np.linalg.norm(b3) elif orient == "sd": o = a3 #T=[latt[i,i] for i in range(0,3)] T = 0.9 * a1 + 0.4 * a2 + 0.1 * a3 vpvec = T / np.linalg.norm(T) vp = focus + 15 * vpvec p.camera_position = [vp, focus, o] if np.sum(cam_pos) != 0: v = (cam_pos[0], cam_pos[1], cam_pos[2]) o = (cam_pos[3], cam_pos[4], cam_pos[5]) p.camera_position = [v, focus, o] def button_sd(): o = a3 T = 0.9 * a1 + 0.4 * a2 + 0.1 * a3 vpvec = T / np.linalg.norm(T) vp = focus + 15 * vpvec p.camera_position = [vp, focus, o] def button_a(): o = a3 vpvec = a1 / np.linalg.norm(a1) vp = focus + 15 * vpvec p.camera_position = [vp, focus, o] def button_b(): o = a3 vpvec = a2 / np.linalg.norm(a2) vp = focus + 15 * vpvec p.camera_position = [vp, focus, o] def button_c(): o = a2 vpvec = a3 / np.linalg.norm(a3) vp = focus + 15 * vpvec p.camera_position = [vp, focus, o] end = time.perf_counter() p.add_key_event("o", button_sd) p.add_key_event("a", button_a) p.add_key_event("b", button_b) p.add_key_event("c", button_c) output.insert(END, "Time: " + str(np.round(end - start, 4)) + " s\n") if save: p.window_size = [5000, 5000] #p.save_graphic(seed+".pdf") p.show(title=seed, screenshot=seed + ".png") else: p.show(title=seed) if do_verbose: print("Final Camera Position:") print(p.camera_position[0][0], p.camera_position[0][1], p.camera_position[0][2], p.camera_position[2][0], p.camera_position[2][1], p.camera_position[2][2]) sys.exit() window.mainloop()
plt = pv.Plotter() mesh = pv.PolyData(lidar[:, 0:3]) mesh["intensity"] = lidar[:, 3] plt.add_mesh(mesh, render_points_as_spheres=True) plt.add_axes_at_origin() def roty(angle): c = np.cos(angle) s = np.sin(angle) return np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]]) for i in range(len(target["class"])): print(target["class"][i]) R = roty(target["yaw"][i]) h, w, l = target["size"][i, 0:3] x = [l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2] y = [0, 0, 0, 0, -h, -h, -h, -h] z = [w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2] obb = np.vstack([x, y, z]) obb = np.dot(R, np.vstack([x, y, z])) obb = obb.T + target["center"][i] bounds = np.c_[np.amin(obb, axis=0), np.amax(obb, axis=0)] bounds = np.ravel(bounds, order="C") box = pv.Box(bounds) plt.add_mesh(box, style="wireframe", line_width=8.0) plt.enable_eye_dome_lighting() plt.show() plt.close()
def test_box(): geom = pyvista.Box() assert np.any(geom.points)
(599088.1433822059, 3982089.287834022, -11965.14728669936), (0.3738545892415734, 0.244312810377319, 0.8947312427698892), ] p.show() ############################################################################### contours = voi.contour(np.arange(5, 55, 5)) contours ############################################################################### contours.plot(cmap="nipy_spectral", opacity=0.15) ############################################################################### roi = [*voi.bounds[0:4], *aoi.bounds[4:6]] aoi_clipped = aoi.clip_box(roi, invert=False) pv.plot([aoi, pv.Box(roi).outline()], cpos="xy") ############################################################################### p = pv.Plotter(window_size=np.array([1024, 768]) * 2) # Add all the data we want to see p.add_mesh(contours, cmap="nipy_spectral", opacity=0.15) p.add_mesh(gebco_a, color="#ff0000") p.add_mesh(gebco_b, color="#ff0000") p.add_mesh(aoi_clipped, cmap="coolwarm", opacity=0.7) # Add a title p.add_text("Vent and Magma Chambers\nDamavand Volcano, Alborz") # A nice perspective p.camera_position = [
particles = Lethe_pyvista_tools('D:/multiple particles sedimentation', 'IB_flow_PBR.prm') particles.path_output('') particles.read_lethe_to_pyvista('ib_particles_reconstruct.pvd') for i in range(0, len(particles.list_vtu)): exec( f'particles.df_{i}[\'Velocity_x\'] = particles.df_{i}[\'Velocity\'][:, 0]' ) #create a sphere with diameter 1 sphere = pv.Sphere(theta_resolution=50, phi_resolution=50) #create the box box = pv.Box(bounds=(-5.25, -3.25, -0.25, 0.25, -0.25, 0.25)) #Choose the white background for the figure pv.set_plot_theme("document") #Create a plotter plotter = pv.Plotter(off_screen=None) plotter.camera_position = ([ (-5.592937351020412, -4.137862113540812, 2.192970961001668), (-4.177361512303915, -0.1970836549756708, -0.12578112629332203), (-0.9551137293493976, 0.26392817505908883, -0.13453506018233582) ]) #plotter.camera.focal_point = (0, 0, 0) #plotter.camera.roll += 180
def length(self) -> float: """Return the length of the diagonal of the bounding box.""" return pyvista.Box(self.bounds).length
The "Hello, world!" of VTK """ import pyvista as pv ############################################################################### # This runs through several of the available geometric objects available in # VTK which PyVista provides simple convenience methods for generating. # # Let's run through creating a few geometric objects! cyl = pv.Cylinder() arrow = pv.Arrow() sphere = pv.Sphere() plane = pv.Plane() line = pv.Line() box = pv.Box() cone = pv.Cone() poly = pv.Polygon() disc = pv.Disc() ############################################################################### # Now let's plot them all in one window p = pv.Plotter(shape=(3, 3)) # Top row p.subplot(0, 0) p.add_mesh(cyl, color="tan", show_edges=True) p.subplot(0, 1) p.add_mesh(arrow, color="tan", show_edges=True) p.subplot(0, 2) p.add_mesh(sphere, color="tan", show_edges=True)
def length(self): """the length of the diagonal of the bounding box""" return pyvista.Box(self.bounds).length
def cli(rbc, plt, verbose, output, axes, bounding_box, clip, stl): """Convert and visualise cell position files used in HemoCell [0]. The script reads from any number of red blood cell position files (RBC.pos) and allows for direct visualisation with PyVista [1] or conversion to XDMF for inspection with Paraview through `-o, --output`. The RBC positions can be provided through `stdin` by specifying a dash (`-`) as argument and piping the input, e.g. `cat RBC.pos | pos_to_vtk -`. Optionally, any number of platelets position files (PLT.pos) can be supplied by the `--plt` argument, which might be repeated any number of times to specify multiple PLT.pos files. [0] https://hemocell.eu [1] https://dev.pyvista.org/index.html """ if len(rbc) == 0 and len(plt) == 0: message = """No input files provided. When passing an RBC through `stdin`, please provide a dash (`-`) as the argument.""" raise click.UsageError(message) if (bounding_box is not None) and (stl is not None): message = """Options `--bounding-box` and `--stl` are exclusive and cannot be combined. Please provide only one.""" raise click.UsageError(message) rbcs = Cells(flatten([Cells.from_pos(rbc) for rbc in rbc])) plts = Cells(flatten([Cells.from_pos(plt) for plt in plt])) if len(rbcs) == 0: # The script terminates early when no RBCs are present. This # most-likely corresponds with users error, e.g. by providing the wrong # file path or an empty file. raise click.UsageError("No RBC cells to display." "") if bounding_box: bounds = flatten(zip((0, 0, 0), bounding_box)) wireframe = pv.Box(bounds) if stl: wireframe = pv.get_reader(stl).read() wireframe.scale((1e3, 1e3, 1e3)) if clip: rbcs = rbcs.clip(wireframe, bounding_box) plts = plts.clip(wireframe, bounding_box) if len(rbcs) == 0 and len(plts) == 0: raise click.UsageError("No cells remain after clipping.") if output: rbcs = create_glyphs(rbcs, CellType.RBC) merged_cells = rbcs.merge(plts) if plt else rbcs pv.save_meshio(output, merged_cells) if verbose: click.echo(f"Written to: '{click.format_filename(output)}'") return 0 plotter = pv.Plotter() rbcs_glyph = create_glyphs(rbcs, CellType.RBC) rbcs_actor = plotter.add_mesh(rbcs_glyph, color="red") if plt: plts_glyph = create_glyphs(plts, CellType.PLT) plts_actor = plotter.add_mesh(plts_glyph, color="yellow") if bounding_box or stl: plotter.add_mesh(wireframe, style='wireframe') message = f'RBC: {len(rbcs)}\nPLT: {len(plts)}\n' if clip: # Only when the domain is clipped, a bounding domain is known either # through the given bounding box or by the given STL surface mesh. # These allow to determine an estimate of the domain's volume and # thereby estimate the expected hematocrit given the number of RBCs # left after clipping. volume = 1e-6 * wireframe.volume hc_percentage = 100 * rbcs.hematocrit(wireframe) message += f'Domain volume estimate (µm^3): {volume:.2f}\n' message += f'Hematocrit (vol%): {hc_percentage:.2f}\n' plotter.add_text(message, position='lower_right') # A simple widget illustrating the x-y-z axes orientation of the domain. if axes: plotter.add_axes(line_width=5, labels_off=False) # Two radio buttons are added that enable to show/hide the glyphs # corresponding to all RBCs or PLTs, where the lambda functions are given # to implement the callback function toggling the right set of glyphs. plotter.add_checkbox_button_widget(lambda x: rbcs_actor.SetVisibility(x), position=(5, 12), color_on="red", value=True) plotter.add_checkbox_button_widget(lambda x: plts_actor.SetVisibility(x), position=(5, 62), color_on="yellow", value=True) return plotter.show()