def build_manifold(w, q, c_range, n, t3, tlim, out_file): ADAPT_MAXLEVEL = 2 ADAPT_TOL = 0.2 # Hidden-Nonseizing-Seizing boundary # c = np.linspace(c_range[0], c_range[1], n) c = np.linspace(c_range[0], c_range[1], n * 2**ADAPT_MAXLEVEL) boundary_hns = get_c_hss(w, q, c, tlim, t3) # Hidden-Hidden-Seizing manifold verts_hhs, triangs_hhs = get_c_hhs_adaptive(w, q, c_range, n, c_range, n, t3, tol=ADAPT_TOL, maxlevel=ADAPT_MAXLEVEL) # Cutting mesh cut_line = np.copy(boundary_hns) cut_line[:, 2] = c_range[0] cut_line = vp.Line(cut_line) cut_mesh = cut_line.extrude(zshift=c_range[1] - c_range[0]) # Hidden-Nonseizing-Seizing manifold vmesh_hhs = vp.Mesh([verts_hhs, triangs_hhs]) vmesh_hns = vmesh_hhs.cutWithMesh(cut_mesh, invert=False) verts_hns = vmesh_hns.points() triangs_hns = vmesh_hns.faces() # Hidden-Nonseizing-Seizing inverted manifold vmesh_hhs = vp.Mesh([verts_hhs, triangs_hhs]) vmesh_hnsi = vmesh_hhs.cutWithMesh(cut_mesh, invert=True) verts_hnsi = vmesh_hnsi.points() triangs_hnsi = vmesh_hnsi.faces() assert all([len(f) == 3 for f in triangs_hns]) assert all([len(f) == 3 for f in triangs_hnsi]) np.savez(out_file, boundary_hns=boundary_hns, verts_hns=verts_hns, triangs_hns=triangs_hns, verts_hnsi=verts_hnsi, triangs_hnsi=triangs_hnsi, verts_hhs=verts_hhs, triangs_hhs=triangs_hhs)
def remesh(mesh, res=50): if isinstance(mesh, vedo.Mesh): vmesh = mesh else: vmesh = vedo.Mesh([mesh.coordinates(), mesh.cells()]) bpts = vmesh.computeNormals(cells=True).boundaries().join( reset=1) #extract boundary vz = vmesh.celldata["Normals"][0][ 2] # check z component of normals at first point bpts.tomesh(invert=vz < 0).smooth().write( 'tmpmesh.xml') #vedo REMESHING + smoothing return Mesh("tmpmesh.xml")
def get_results(filename, q, w, clim, nc, nt, nsamples, refine_mesh=False): data = np.load(filename) # Create and refine mesh verts = data['verts_hns'] triangs = data['triangs_hns'] mesh = vp.Mesh([verts, triangs]) if refine_mesh: # Subdivision fails for A. Perhaps because it's flat? mesh = subdivide_adapt(mesh, max_edge_length=0.1, max_triangle_area=1, max_num_triangles=1000000) verts = mesh.points() triangs = mesh.faces() # Calculate triangle areas triangle_areas = np.zeros(len(triangs)) triangle_centers = np.zeros((len(triangs), 3)) for i, triang in enumerate(triangs): vs = verts[triang, :] triangle_areas[i] = 0.5 * np.linalg.norm( np.cross(vs[1] - vs[0], vs[2] - vs[0])) triangle_centers[i] = np.mean(vs, axis=0) prior = np.exp(-np.sum(triangle_centers**2, axis=1) / 2.) / np.sqrt( 2 * np.pi) triangle_post = prior * triangle_areas triangle_post /= np.sum(triangle_post) # Get samples csamples = triangle_centers[np.random.choice(len(triangs), size=nsamples, p=triangle_post)] # Density bins = np.linspace(clim[0], clim[1], nc + 1) cdens = np.zeros((3, nc)) for i in range(3): cdens[i] = np.histogram(csamples[:, i], bins=bins, density=True)[0] # Onset time samples tsamples = np.zeros_like(csamples) for i, c in enumerate(csamples): tsamples[i, :] = simprop.prop(c, w, q) psz = recprob(tsamples, nt + 1, tlim) return cdens, psz
def viz_structure(regpos, w, surfaces, w_perc=3): # Connections wmax = np.max(w) vlines = [] for reg1, reg2 in zip(*np.where( w > np.percentile(w.flat, (100 - w_perc)))): vlines.append( vp.Line(regpos[reg1], regpos[reg2], c='k', lw=5 * w[reg1, reg2] / wmax)) # Brain surfaces vmeshes = [ vp.Mesh([verts, triangs], 'grey', alpha=0.05) for verts, triangs in surfaces ] return vlines, vmeshes
def threshold(self, value=None, flip=False): """ Create a polygonal Mesh from a Picture by filling regions with pixels luminosity above a specified value. Parameters ---------- value : float, optional The default is None, e.i. 1/3 of the scalar range. flip: bool, optional Flip polygon orientations Returns ------- Mesh A polygonal mesh. """ mgf = vtk.vtkImageMagnitude() mgf.SetInputData(self._data) mgf.Update() msq = vtk.vtkMarchingSquares() msq.SetInputData(mgf.GetOutput()) if value is None: r0, r1 = self._data.GetScalarRange() value = r0 + (r1 - r0) / 3 msq.SetValue(0, value) msq.Update() if flip: rs = vtk.vtkReverseSense() rs.SetInputData(msq.GetOutput()) rs.ReverseCellsOn() rs.ReverseNormalsOff() rs.Update() output = rs.GetOutput() else: output = msq.GetOutput() ctr = vtk.vtkContourTriangulator() ctr.SetInputData(output) ctr.Update() return vedo.Mesh(ctr.GetOutput(), c='k').bc('t').lighting('off')
def build_mesh(verts, ind_faces, scalars=None, timing=False): """ Builds the polygonal Mesh. Args: verts (:obj:`numpy.array`): Vertices of the elements. ind_faces (:obj:`numpy.array`): Connectivity of the faces of the elements. scalars (:obj:`int`, optional): Values to add the scalar bar. Defaults to None. timing (:obj:`bool`, optional): If True shows the time to build the mesh. Defaults to False. Returns: Build an instance of the Mesh object from the Vedo library. """ t0 = time() mesh = vt.Mesh([verts, ind_faces]) if scalars is not None: mesh.pointColors(scalars, cmap="cool").addScalarBar() #.normalize() else: mesh.lineColor('black').lineWidth(1).color('grey') #.normalize() tf = time() if timing: print("Time to build mesh: " + str(round((tf - t0), 6)) + '[s]') return mesh
def viz_structure(regpos, w, surfaces, contacts): # Connections wmax = np.max(w) vlines = [] for reg1, reg2 in zip(*np.where(w > np.percentile(w.flat, 97))): vlines.append( vp.Line(regpos[reg1], regpos[reg2], c='k', lw=15 * w[reg1, reg2] / wmax)) # Brain surfaces vmeshes = [ vp.Mesh([verts, triangs], 'grey', alpha=0.05) for verts, triangs in surfaces ] # Electrodes ncontacts = contacts.shape[0] vcontacts = [] for i in range(ncontacts): vcontacts.append(vp.Sphere(contacts[i], r=0.8, c='green')) return vlines, vmeshes, vcontacts
"""pymeshlab interoperability example: Surface reconstruction by ball pivoting""" import pymeshlab import vedo pts = vedo.Mesh(vedo.dataurl + 'cow.vtk').points() # numpy array of vertices m = pymeshlab.Mesh(vertex_matrix=pts) ms = pymeshlab.MeshSet() ms.add_mesh(m) ms.surface_reconstruction_ball_pivoting(ballradius=0.15) # ms.compute_normals_for_point_sets() # ms.surface_reconstruction_screened_poisson() mlab_mesh = ms.current_mesh() reco_mesh = vedo.Mesh(mlab_mesh).computeNormals().flat() vedo.show(__doc__, reco_mesh, axes=True, bg2='blue9', title="vedo + pymeshlab") ################################################################################ # Full list of filters, https://pymeshlab.readthedocs.io/en/latest/filter_list.html # # MeshLab offers plenty of useful filters, among which: # # ambient_occlusion # compute_curvature_principal_directions # colorize_by_geodesic_distance_from_a_given_point # colorize_by_border_distance
import pymeshlab import vedo filepath = vedo.download(vedo.dataurl + 'bunny.obj') ms = pymeshlab.MeshSet() ms.load_new_mesh(filepath) # vedo.show(ms, axes=True) # this already works! filter_name = 'close_holes' ms.apply_filter(filter_name) mlab_mesh = ms.current_mesh() vedo_mesh = vedo.Mesh(mlab_mesh).color('b5').lw(0.1) print("Can convert back to pymeshlab.MeshSet:\n\t", vedo_mesh.to_meshlab()) vedo.show(vedo_mesh, "Applied pymeshlab filter:\n " + filter_name, axes=True, bg='green9', bg2='blue9', title="pymeshlab + vedo") ################################################################################ # MeshLab offers plenty of useful filters, among which: # # ambient_occlusion # compute_curvature_principal_directions
''' Mesh objects can be combined with (1) `mesh.merge` - creates a new mesh object; this new mesh inherits properties (color, etc.) of the first mesh. (2) `assembly.Assembly` - combines meshes (or other actors); preserves properties (3) `+` - equivalent to `Assembly` ''' import vedo import numpy as np # Define vertices and faces verts = np.array([(0, 0, 0), (10, 0, 0), (0, 10, 0), (0, 0, 10)]) faces = np.array([(0, 1, 2), (2, 1, 3), (1, 0, 3), (0, 2, 3)]) # Create a tetrahedron and a copy mesh = vedo.Mesh([verts, faces], c='red') mesh2 = mesh.clone().x(15).y(15).c('blue') # Create a copy, shift it; change color # Merge: creates a new mesh, color of the second mesh is lost mesh_all = vedo.merge(mesh, mesh2) print('1. Type:', type(mesh_all)) # Show plotter = vedo.show(mesh_all, viewup='z', axes=1) # -> all red plotter.close() # Assembly: groups meshes mesh_all = vedo.assembly.Assembly(mesh, mesh2) print('2. Type:', type(mesh_all)) # Show plotter = vedo.show(mesh_all, viewup='z', axes=1) # -> red and blue plotter.close()
def viz_param_manifold(filename, size): data = np.load(filename) vline = vp.Tube(data['boundary_hns'], r=0.08) vline.color('g') # HNS manifold vmesh_hns = vp.Mesh([data['verts_hns'], data['triangs_hns']]) k = 3 prior = (2 * np.pi)**(-k / 2) * (np.exp( -0.5 * np.sum(vmesh_hns.points()**2, axis=1))) vmesh_hns.pointColors(prior, cmap='Reds', vmin=0) vmesh_hns.addScalarBar(horizontal=True, nlabels=6, c='k', pos=(0.74, 0.01), titleFontSize=44) vmesh_hns.scalarbar.SetLabelFormat("%.2g") vmesh_hns.scalarbar.SetBarRatio(1.0) # Inverted HNS manifold vmesh_hnsi = vp.Mesh([data['verts_hnsi'], data['triangs_hnsi']]) # vmesh_hnsi.color([0.68, 0.68, 0.68]) vmesh_hnsi.color([0.9, 0.9, 0.9]).alpha(0.0) # Invisible points to set the extent vpoints = vp.Points([(-5.01, -5.01, -5.01), (5.01, 5.01, 5.01)]).alpha(0.0) vplotter = vp.Plotter(offscreen=True, size=size, axes=dict(xyGrid=True, yzGrid=True, zxGrid=True, xTitleSize=0, yTitleSize=0, zTitleSize=0, xHighlightZero=True, yHighlightZero=True, zHighlightZero=True, xHighlightZeroColor='b', yHighlightZeroColor='b', zHighlightZeroColor='b', numberOfDivisions=10, axesLineWidth=5, tipSize=0.02, gridLineWidth=2, xLabelSize=0.05, yLabelSize=0.05, zLabelSize=0.05, xLabelOffset=0.05, yLabelOffset=0.05, zLabelOffset=0.0, zTitleRotation=225)) vlabels = [ vp.Text2D("H", (0.09 * size[0], 0.10 * size[1]), s=3, font='Arial'), vp.Text2D("N", (0.87 * size[0], 0.16 * size[1]), s=3, font='Arial'), vp.Text2D("S", (0.49 * size[0], 0.90 * size[1]), s=3, font='Arial') ] k = 2 vecs = np.array([[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[k, -k, 0, 0, 0, 0], [0, 0, k, -k, 0, 0], [0, 0, 0, 0, k, -k]]]) varrows = vp.Arrows(vecs[0].T, vecs[1].T, s=1.2, c='k') vp.show([vline, vmesh_hns, vmesh_hnsi, vpoints, varrows] + vlabels, camera=dict(pos=(16, 13, 20), focalPoint=(0, 0, 1.5), viewup=(0, 0, 1))) img = vp.screenshot(None, scale=1, returnNumpy=True) vp.clear() vp.closePlotter() return img
if do_remesh: mesh = remesh(new_mesh) else: mesh = new_mesh meshes.append(mesh) displacements.append(displacement) # plot things: txt = vedo.Text2D(f"step{i}") arrow = vedo.Arrow2D([0, 0], F * 20).z(1) vedo.dolfin.plot(mesh, arrow, txt, c='grey5', at=i, N=N, zoom=1.1) #PRESS q dmesh_i = meshes[0] # initial mesh dmesh_f = meshes[-1] # final mesh vmesh_i = vedo.Mesh([dmesh_i.coordinates(), dmesh_i.cells()], c='grey5').z(-1) vmesh_f = vedo.Mesh( [dmesh_f.coordinates(), dmesh_f.cells()], c='grey3').wireframe() plt = vedo.Plotter() # move a few points along the deformation of the circle seeds = vedo.Circle(r=50, res=res).points()[:, (0, 1)] # make points 2d with [:,(0,1)] endpoints = [] for i, p in enumerate(seeds): line = [p] for u in displacements: p = p + u(p) line.append(p)
plt.add(vedo.Points(pos, c='b')) plt.add(vedo.Text2D(path, pos=(.02, .02), c='k')) plt.add(boundary_mesh) plt.render() plt = vedo.Plotter(interactive=False) pos, path = getpos(data_idx) pts = vedo.Points(pos, c='b') plt.keyPressFunction = keyfunc data_info = vedo.Text2D(path, pos=(.02, .02), c='k') verts = [(-1.5, 0, -1.5), (-1.5, 0, 1.5), (1.5, 0, 1.5), (1.5, 0, -1.5), (-1.5, 5, -1.5), (-1.5, 5, 1.5), (1.5, 5, 1.5), (1.5, 5, -1.5)] # faces = [(3,2,1,0),(0,1,5,4),(4,5,6,7),(2,3,7,6),(1,2,6,5),(4,7,3,0)] faces = [(3, 2, 1, 0), (0, 1, 5, 4), (4, 7, 3, 0)] boundary_mesh = vedo.Mesh([verts, faces]).lineColor('black').lineWidth(1) plt += boundary_mesh plt += pts plt += data_info plt.show() vedo.interactive()
import numpy as np import napari, vedo # Load the surface, triangulate just in case, and compute vertex normals surf = vedo.Mesh(vedo.dataurl + "beethoven.ply").triangulate().computeNormals() surf.rotateX(180).rotateY(60) vertices = surf.points() faces = np.array(surf.faces()) normals = surf.normals() # generate vertex values by projecting normals on a "lighting vector" values = np.dot(normals, [-1, 1, 1]) print(vertices.shape, faces.shape, values.shape) # (2521, 3) (5030, 3) (2521,) with napari.gui_qt(): # create an empty viewer viewer = napari.Viewer() # add the surface viewer.add_surface((vertices, faces, values), opacity=0.8) viewer.add_points(vertices, size=0.05, face_color='pink') # turn on 3D rendering viewer.dims.ndisplay = 3
import pymeshlab import vedo filepath = vedo.download(vedo.dataurl+'bunny.obj') ms = pymeshlab.MeshSet() ms.load_new_mesh(filepath) # vedo.show(ms, axes=True) # this already works! pt = [0.02343884, 0.0484675, 0.03972297] ms.colorize_by_geodesic_distance_from_a_given_point(startpoint=pt) mlab_mesh = ms.current_mesh() vedo_mesh = vedo.Mesh(mlab_mesh).cmap('Paired').addScalarBar("distance") print("Can convert back to pymeshlab.MeshSet:", type(vedo_mesh.to_meshlab())) vedo.show("pymeshlab interoperability example", vedo_mesh, vedo.Point(pt), axes=True, bg='green9', bg2='blue9', title="vedo + pymeshlab", ) ################################################################################ # Full list of filters, https://pymeshlab.readthedocs.io/en/latest/filter_list.html # # MeshLab offers plenty of useful filters, among which: # # ambient_occlusion
def viz_observation_manifold(t3, tlim, size): tmin = 0 tmax = 2 * tlim # tlim line vline1 = vp.Tube([[tmin, tlim, t3], [tmax, tlim, t3]], r=2.0) vline1.color('g') # t = 0 line vline2 = vp.Tube([[tmin, tlim, t3], [tmin, tmax, t3]], r=2.0) vline2.color((1, 1, 1)) # Manifold verts = [[tmin, tlim, t3], [tmax, tlim, t3], [tmin, tmax, t3], [tmax, tmax, t3]] triangs = [[0, 1, 3], [0, 3, 2]] vmesh1 = vp.Mesh([verts, triangs]) vmesh1.color((1, 1, 1)) # Inverse manifold verts = [[tmin, tmin, t3], [tmax, tmin, t3], [tmin, tlim, t3], [tmax, tlim, t3]] triangs = [[0, 1, 3], [0, 3, 2]] vmesh2 = vp.Mesh([verts, triangs]) vmesh2.color((0.9, 0.9, 0.9)).alpha(0.0) # Invisible points to set the extent vpoints = vp.Points([(tmin - 0.1, tmin - 0.1, tmin - 0.1), (1.01 * tmax, 1.01 * tmax, 1.01 * tmax)]).alpha(0.0) lpos = [(p, str(p)) for p in [0, 50, 100, 150]] vplotter = vp.Plotter(offscreen=True, size=size, axes=dict(xyGrid=True, yzGrid=True, zxGrid=True, xTitleSize=0, yTitleSize=0, zTitleSize=0, xPositionsAndLabels=lpos, yPositionsAndLabels=lpos, zPositionsAndLabels=lpos[1:], axesLineWidth=5, tipSize=0.02, gridLineWidth=2, xLabelSize=0.05, yLabelSize=0.05, zLabelSize=0.05, xLabelOffset=0.05, yLabelOffset=0.05, zLabelOffset=0.0, zTitleRotation=225)) vlabels = [ vp.Text2D("H", (0.09 * size[0], 0.10 * size[1]), s=3, font='Arial'), vp.Text2D("N", (0.87 * size[0], 0.16 * size[1]), s=3, font='Arial'), vp.Text2D("S", (0.49 * size[0], 0.90 * size[1]), s=3, font='Arial') ] vp.show([vline1, vline2, vmesh1, vpoints] + vlabels, camera=dict(pos=(378, 324, 450), focalPoint=(tlim, tlim, tlim + 27), viewup=(0, 0, 1))) img = vp.screenshot(None, scale=1, returnNumpy=True) vp.clear() vp.closePlotter() return img
import numpy as np import vedo ln1 = [[1, 1, x / 2] for x in np.arange(0, 15, 0.15)] ln2 = [[np.sin(x), np.cos(x), x / 2] for x in np.arange(0, 15, 0.15)] rads = [0.4 * (np.cos(6 * ir / len(ln2)))**2 + 0.1 for ir in range(len(ln2))] vmesh1 = vedo.Tube(ln1, r=0.08, c="tomato").triangulate().clean() vmesh2 = vedo.Tube(ln2, r=rads, c="tomato").triangulate().clean() verts1 = vmesh1.points() verts2 = vmesh2.points() faces = np.array(vmesh1.faces()) # construct model SSM = StatisticalShapeModel(lambda ref: FundamentalCoords(ref)) surfaces = [Surface(v, faces) for v in [verts1, verts2]] SSM.construct(surfaces) # sample trajectory along the main mode of variation shapes = [vmesh1] std = np.sqrt(SSM.variances[0]) for t in np.linspace(-1.0, 1.0, 20): e = SSM.space.exp(SSM.mean_coords, t * std * SSM.modes[0]) v = SSM.space.from_coords(e) shapes.append(vedo.Mesh([v, faces])) shapes.append(vmesh2.rotateY(-90).flat()) plt = vedo.applications.Browser(shapes, prefix="shape ") plt.show(viewup='z', bg2='lb')