# Intersect a vtkImageData (voxel dataset) with planes # from vtkplotter import Plotter, vtkio, analysis, vector vp = Plotter(axes=4) img = vtkio.loadImageData('data/embryo.slc') pos = img.GetCenter() lines = [] for i in range(60): # probe scalars on 60 parallel lines step = (i - 30) * 2 p1, p2 = pos + vector(-100, step, step), pos + vector(100, step, step) a = analysis.probeLine(img, p1, p2, res=200) a.alpha(0.5).lineWidth(9) lines.append(a) #print(a.scalars(0)) # numpy scalars can be access here #print(a.scalars('vtkValidPointMask')) # the mask of valid points vp.show(lines)
# Shrink the triangulation of a mesh to make the inside visible # from vtkplotter import Plotter, sphere vp = Plotter() vp.load('data/shapes/teapot.vtk').shrink(0.75) vp.add(sphere(r=0.2).pos([0,0,-0.5])) vp.show(viewup='z')
""" Show a cube for each available color name """ print(__doc__) from vtkplotter import Plotter, Cube, Text from vtkplotter.colors import colors, getColor from operator import itemgetter # sorting by hex color code: sorted_colors = sorted(colors.items(), key=itemgetter(1)) # or by name: # sorted_colors = sorted(colors.items(), key=itemgetter(0)) vp = Plotter(N=len(sorted_colors), axes=0, size="fullscreen", bg='w') for i, sc in enumerate(sorted_colors): cname = sc[0] rgb = getColor(cname) cb = Cube(c=rgb) tname = Text(cname, pos=3) vp.show(cb, tname, at=i) vp.camera.Azimuth(20) vp.camera.Elevation(20) print("click on any cube and press i") vp.show(interactive=1)
warped.alpha(0.4).color("lg").pointSize(10) allarr = Arrows(apos.points(), warped.points()) set1 = [apos, warped, src, trs, arr, __doc__] vp = show([set1, allarr], N=2, bg='bb') # returns the Plotter class ################################################# RBF from scipy.interpolate import Rbf x, y, z = sources[:, 0], sources[:, 1], sources[:, 2] dx, dy, dz = deltas[:, 0], deltas[:, 1], deltas[:, 2] itrx = Rbf(x, y, z, dx) # Radial Basis Function interpolator: itry = Rbf(x, y, z, dy) # interoplate the deltas in each separate itrz = Rbf(x, y, z, dz) # cartesian dimension positions_x = itrx(xr, yr, zr) + xr positions_y = itry(xr, yr, zr) + yr positions_z = itrz(xr, yr, zr) + zr positions_rbf = np.vstack([positions_x, positions_y, positions_z]) warped_rbf = Points(positions_rbf, r=2).alpha(0.4).color("lg").pointSize(10) allarr_rbf = Arrows(apos.points(), warped_rbf.points()) arr = Arrows(sources, sources + deltas) vp2 = Plotter(N=2, pos=(200, 300), bg='bb') vp2.camera = vp.camera # share the same camera with previous Plotter vp2.show(apos, warped_rbf, src, trs, arr, "Radial Basis Function", at=0) vp2.show(allarr_rbf, at=1, interactive=1)
or as a reference to an external already existing function. Red points indicate where the function does not exist. ''' print(__doc__) from vtkplotter import Plotter, fxy, sin, cos def my_z(x, y): return sin(2 * x * y) * cos(3 * y) / 2 vp = Plotter(shape=(2, 2), sharecam=False, bg='snow') # draw at renderer nr.0 the first actor, show it with a texture # an existing function z(x,y) can be passed: f1 = fxy(my_z) vp.show(f1, at=0) # c=None shows the original z-scalar color scale. No z-level lines. f2 = fxy(lambda x, y: sin(x * y), c=None, zlevels=None, texture=None, wire=1) vp.show(f2, at=1) # red dots are shown where the function does not exist (y>x): # if vp is set to verbose, sympy calculates derivatives and prints them: f3 = fxy('sin(3*x)*log(x-y)/3') vp.show(f3, at=2) # specify x and y ranges and z vertical limits: f4 = fxy('log(x**2+y**2 - 1)', x=[-2, 2], y=[-2, 2], zlimits=[-1, 1.5]) vp.show(f4, at=3, axes=2, interactive=1)
import numpy as np from vtkplotter import Plotter, fitLine, fitPlane, Points, Text # declare the class instance vp = Plotter(verbose=0, title="linear fitting") # draw 500 fit lines superimposed and very transparent for i in range(500): x = np.linspace(-2, 5, 20) # generate each time 20 points y = np.linspace(1, 9, 20) z = np.linspace(-5, 3, 20) data = np.array(list(zip(x, y, z))) data += np.random.normal(size=data.shape) * 0.8 # add gauss noise vp += fitLine(data).lw(4).alpha(0.03) # fit a line # 'data' still contains the last iteration points vp += Points(data, r=10, c="yellow") # the first fitted slope direction is stored # in actor.info['slope] and actor.info['normal] print("Line Fit slope = ", vp.actors[0].info["slope"]) plane = fitPlane(data) # fit a plane print("Plan Fit normal=", plane.info["normal"]) vp += [plane, Text(__doc__)] vp.show(axes=1)
''' from __future__ import division, print_function from random import uniform as u from vtkplotter import Plotter, procrustes, Text, Points vp = Plotter(shape=[1, 2], verbose=0, axes=2, sharecam=0, bg='w') N = 15 # number of points x = 1. # add some randomness pts1 = [(u(0, x), u(0, x), u(0, x)+i) for i in range(N)] pts2 = [(u(0, x)+3, u(0, x)+i/2+2, u(0, x)+i+1) for i in range(N)] pts3 = [(u(0, x)+4, u(0, x)+i/4-3, u(0, x)+i-2) for i in range(N)] act1 = Points(pts1, c='r').legend('set1') act2 = Points(pts2, c='g').legend('set2') act3 = Points(pts3, c='b').legend('set3') vp.show([act1, act2, act3], at=0) # find best alignment among the n sets of Points, # return an Assembly formed by the aligned sets aligned = procrustes([act1, act2, act3]) # print(aligned.info['transform']) vp.show([aligned, Text(__doc__)], at=1, interactive=1)
# Show a cube for each available color name # from vtkplotter import Plotter, cube, text from vtkplotter.colors import colors, getColor from operator import itemgetter # sorting by hex color code: sorted_colors = sorted(colors.items(), key=itemgetter(1)) # or by name: # sorted_colors = sorted(colors.items(), key=itemgetter(0)) vp = Plotter(N=len(sorted_colors), axes=0, size='fullscreen') for i, sc in enumerate(sorted_colors): cname = sc[0] rgb = getColor(cname) cb = cube(c=rgb) tname = text(cname, pos=3) vp.show([cb, tname], at=i) print('click on any cube and press i') vp.show(zoom=1.1, interactive=1)
# Extract the mesh region that has the largest connected surface # from vtkplotter import Plotter, printc, extractLargestRegion vp = Plotter(shape=(2,1)) act1 = vp.load('data/embryo.slc', c='y') printc('area1 =', act1.area(), c='y') act2 = extractLargestRegion(act1).color('b') printc('area2 =', act2.area(), c='b') vp.show(act1, at=0) vp.show(act2, at=1, zoom=1.2, interactive=1)
# generate two random sets of points as 2 actors # and align them using the Iterative Closest Point algorithm. # from __future__ import division from random import uniform as u from vtkplotter import Plotter, align, arrow vp = Plotter(shape=[1, 2], verbose=0, axes=2) N1 = 15 # number of points of first set N2 = 15 # number of points of second set x = 1. # add some randomness pts1 = [(u(0, x), u(0, x), u(0, x) + i) for i in range(N1)] pts2 = [(u(0, x) + 3, u(0, x) + i / 2 + 2, u(0, x) + i + 1) for i in range(N2)] act1 = vp.points(pts1, r=8, c='b', legend='source') act2 = vp.points(pts2, r=8, c='r', legend='target') vp.show(at=0) # find best alignment between the 2 sets of points, e.i. find # how to move act1 to best match act2 alpts1 = align(act1, act2).coordinates() vp.points(alpts1, r=8, c='b') for i in range(N1): #draw arrows to see where points end up vp.add(arrow(pts1[i], alpts1[i], c='k', s=0.007, alpha=.1)) vp.show(at=1, interactive=1)
for colony in colonies: newcells = [] for cell in colony.cells: if cell.dieAt(t): continue if cell.divideAt(t): newc = cell.split() # make daughter cell vp += Line(cell.pos, newc.pos, c="k", lw=3, alpha=0.5) newcells.append(newc) newcells.append(cell) colony.cells = newcells pts = [c.pos for c in newcells] # draw all points at once vp += Points(pts, c=colony.color, r=5, alpha=0.80) # nucleus vp += Points(pts, c=colony.color, r=15, alpha=0.05) # halo msg += str(len(colony.cells)) + "," pb.print(msg + str(int(t))) vp.show(resetcam=0) # draw the oriented ellipsoid that contains 50% of the cells for colony in colonies: pts = [c.pos for c in colony.cells] a = pcaEllipsoid(pts, pvalue=0.5, pcaAxes=0) a.color(colony.color).alpha(0.3) a.legend("1/rate=" + str(colony.cells[0].tdiv) + "h") vp += a vp.show(resetcam=0, interactive=1)
pcmi = p[i] - ptot * mi / mtot # transform momenta to cm frame pcmj = p[j] - ptot * mj / mtot rrel = versor(pos[j] - pos[i]) pcmi = pcmi - 2 * np.dot(pcmi, rrel) * rrel # bounce in cm frame pcmj = pcmj - 2 * np.dot(pcmj, rrel) * rrel p[i] = pcmi + ptot * mi / mtot # transform momenta back to lab frame p[j] = pcmj + ptot * mj / mtot pos[i] = pos[i] + (p[i] / mi) * deltat # move forward deltat in time pos[j] = pos[j] + (p[j] / mj) * deltat # Bounce off the boundary of the torus for j in range(Natoms): poscircle[j] = versor(pos[j]) * RingRadius * [1, 1, 0] outside = np.greater_equal(mag(poscircle - pos), RingThickness - 2 * Ratom) for k in range(len(outside)): if outside[k] == 1 and np.dot(p[k], pos[k] - poscircle[k]) > 0: p[k] = reflection(p[k], pos[k] - poscircle[k]) # then update positions of display objects for i in range(Natoms): Atoms[i].pos(pos[i]) ### <-- outside = np.greater_equal(mag(pos), RingRadius + RingThickness) vp.show() ### <-- vp.camera.Azimuth(0.5) vp.camera.Elevation(0.1) pb.print() vp.show(interactive=1)
# Work with vtkVolume objects and surfaces. # from vtkplotter import vtkio, Plotter from vtkplotter.actors import Volume vp = Plotter() # Load a 3D voxel dataset (returns a vtkImageData object): img = vtkio.loadImageData('data/embryo.slc', spacing=[1, 1, 1]) # Build a vtkVolume object. # A set of transparency values - of any length - can be passed # to define the opacity transfer function in the range of the scalar. # E.g.: setting alphas=[0, 0, 0, 1, 0, 0, 0] would make visible # only voxels with value close to 98.5 (see print output). vol = Volume(img, c='green', alphas=[0, 0.4, 0.9, 1]) # vtkVolume # can relocate volume in space: #vol.scale(0.3).pos([10,100,0]).rotate(90, axis=[0,1,1]) sph = vp.sphere(pos=[100, 100, 100], r=20) # add a dummy surface vp.show([vol, sph], zoom=1.4) # show both vtkVolume and vtkActor
th = (90 - ilat) / 57.3 ph = ilong / 57.3 r = value + rbias p = np.array([sin(th) * cos(ph), sin(th) * sin(ph), cos(th)]) * r pts.append(p) return pts vp = Plotter(shape=[2, 2], verbose=0, axes=3, interactive=0) shape1 = Sphere(alpha=0.2) shape2 = vp.load(datadir + "shapes/icosahedron.vtk").normalize().lineWidth(1) agrid1, actorpts1 = makeGrid(shape1, N) vp.show(shape1, actorpts1, at=0) agrid2, actorpts2 = makeGrid(shape2, N) vp.show(shape2, actorpts2, at=1) vp.camera.Zoom(1.2) vp.interactive = False clm1 = pyshtools.SHGrid.from_array(agrid1).expand() clm2 = pyshtools.SHGrid.from_array(agrid2).expand() # clm1.plot_spectrum2d() # plot the value of the sph harm. coefficients # clm2.plot_spectrum2d() for t in arange(0, 1, 0.005): act21 = Points(morph(clm2, clm1, t, lmax), c="r", r=4) act12 = Points(morph(clm1, clm2, t, lmax), c="g", r=4)
# Intersect a vtkImageData (voxel dataset) with planes # from vtkplotter import Plotter, vtkio, analysis, vector vp = Plotter(axes=4) img = vtkio.loadImageData('data/embryo.slc') planes=[] for i in range(6): print('probing slice plane #',i) pos = img.GetCenter() + vector(0,0,(i-3)*25.) a = analysis.probePlane(img, origin=pos, normal=(0,0,1)).alpha(0.2) planes.append(a) #print(max(a.scalars(0))) # access scalars this way, 0 means first vp.show(planes)
from vtkplotter import Plotter, colorMap from vtkplotter.analysis import smoothMLS2D import numpy as np vp1 = Plotter(shape=(1,4), axes=4) act = vp1.load('data/shapes/bunny.obj', c='k 0.05', wire=1).normalize().subdivide() pts = act.coordinates(copy=True) # pts is a copy of the points not a reference pts += np.random.randn(len(pts),3)/40 # add noise, will not mess up the original points #################################### smooth cloud with MLS # build the points actor s0 = vp1.points(pts, c='blue', r=3, legend='point cloud') vp1.show(s0, at=0) s1 = s0.clone(c='dg') # a dark green copy of s0 # project s1 points into a smooth surface of points # return a demo actor showing 30 regressions at random points mls1 = smoothMLS2D(s1, f=0.5, showNPlanes=30) # first pass vp1.show(mls1, at=1, legend='first pass') mls2 = smoothMLS2D(s1, f=0.3, showNPlanes=30) # second pass vp1.show(mls2, at=2, legend='second pass') mls3 = smoothMLS2D(s1, f=0.1) # third pass vp1.show(s1, at=3, legend='third pass', zoom=1.3)
vp.xtitle = "" vp.ytitle = "Psi^2(x,t)" vp.ztitle = "" bck = vp.load(datadir + "images/schrod.png", alpha=0.3).scale(0.0255).pos([0, -5, -0.1]) barrier = Line(list(zip(x, V * 15, [0] * len(x))), c="black", lw=2) lines = [] for i in range(0, Nsteps): for j in range(500): Psi += d_dt(Psi) * dt # integrate for a while before showing things A = np.real(Psi * np.conj(Psi)) * 1.5 # psi squared, probability(x) coords = list(zip(x, A, [0] * len(x))) Aline = Line(coords, c="db", lw=3) vp.show([Aline, barrier, bck]) lines.append([Aline, A]) # store objects # now show the same lines along z representing time vp.actors = [] vp.camera.Elevation(20) vp.camera.Azimuth(20) bck.alpha(1) for i in range(Nsteps): p = [0, 0, size * i / Nsteps] # shift along z l, a = lines[i] # l.pointColors(a, cmap='rainbow') l.pointColors(-a, cmap="gist_earth") # inverted gist_earth vp += [l.pos(p), barrier.clone().alpha(0.3).pos(p)] vp.show()
""" Mirror a mesh along one of the Cartesian axes. """ from vtkplotter import Plotter, Text, datadir vp = Plotter(axes=2) myted1 = vp.load(datadir + "teddy.vtk") myted2 = myted1.clone().mirror("y").pos([0, 3, 0]).color("green") vp.show(myted1, myted2, Text(__doc__), viewup="z")
from vtkplotter.utils import clean from vtkplotter.analysis import smoothMLS1D import numpy as np N = 9 # nr. of iterations # build some initial cloud of noisy points along a line #pts = [ (sin(6*x), sin(2*x)/(x+1), cos(9*x)) for x in arange(0,1, .001)] #pts = [ (0, sin(x), cos(x)) for x in arange(0,6, .002) ] pts = [(sqrt(x), sin(x), x / 10) for x in arange(0, 16, .01)] pts += np.random.randn(len(pts), 3) / 10 # add noise np.random.shuffle(pts) # make sure points are not ordered vp = Plotter(N=N, axes=5) a = vp.points(pts) vp.show(a, at=0, legend='cloud') for i in range(1, N): a = a.clone().color(i) smoothMLS1D(a, f=0.2) # at last iteration make sure points are separated by tol if i == N - 1: clean(a, tol=.01) print('iteration', i, '#points:', len(a.coordinates())) vp.show(a, at=i, legend='iter #' + str(i)) vp.show(interactive=1)
R12 = Pos[s2] - Pos[s1] nR12 = np.linalg.norm(R12) d12 = Radius[s1] + Radius[s2] - nR12 tau = R12 / nR12 DR0 = d12 * tau x1 = Mass[s1] / (Mass[s1] + Mass[s2]) x2 = 1 - x1 # x2 = Mass[s2]/(Mass[s1]+Mass[s2]) Pos[s1] -= x2 * DR0 Pos[s2] += x1 * DR0 DV0 = 2 * dot(Vel[s2] - Vel[s1], tau) * tau Vel[s1] += x2 * DV0 Vel[s2] -= x1 * DV0 # Update the location of the spheres for s in range(Nsp): Spheres[s].pos([Pos[s][0], Pos[s][1], 0]) if not int(i) % 10: # every ten steps: rsp = [Pos[0][0], Pos[0][1], 0] rsv = [Vel[0][0], Vel[0][1], 0] p = vp.ring(pos=rsp, axis=rsv, r=Rb / 4, thickness=Rb / 40, c='r', alpha=0.05) # leave an oriented trace vp.render(p) # add actor p and render scene pb.print('#actors=' + str(len(vp.actors))) vp.show(interactive=1)
# (values can be copied in the code by pressing C in the rendering window) vp = Plotter(verbose=0, axes=0, interactive=0) vp.camera.SetPosition(962, -239, 1034) vp.camera.SetFocalPoint(0.0, 0.0, 10.0) vp.camera.SetViewUp(-0.693, -0.479, 0.539) pb = ProgressBar(0,nc, c='g') # a green progress bar for t1 in pb.range(): # for each time point t2=t1+1 if t1==nc-1: t2=t1 # avoid index overflow with last time point vp.actors=[] # clean up the list of actors at each iteration vp.cylinder([0,0,-15], r=260, height=10, texture='marble', res=60) vp.cylinder([0,0, 10], r=260, height=50, wire=1, c='gray', res=60) pts, cols = [],[] for i,p in enumerate(mesh): # for each vertex in the mesh c1, c2 = conc[t1,i], conc[t2,i] cgrad = abs(c2-c1)*cgradfac # intensity of variation gx, gy, gz = np.random.randn(3) # make points wiggle a bit pts.append(p + vector(gx/4, gy/4, gz + c1*20)) cols.append([0, c1, cgrad]) # RGB color vp.points(pts, c=cols, alpha=1.0, r=6) # points actor vp.points(pts, c=cols, alpha=0.1, r=30) # halos actor vp.camera.Azimuth(60/nc) # rotate camera by a fraction vp.show() # show the four new actors at each iteration pb.print() vp.show(interactive=1)
"""Generate 3 random sets of points and align them using Procrustes method. """ from __future__ import division, print_function from random import uniform as u from vtkplotter import Plotter, alignProcrustes, Points vp = Plotter(shape=[1, 2], axes=2, sharecam=0) N = 15 # number of points x = 1.0 # add some randomness pts1 = [(u(0, x), u(0, x), u(0, x) + i) for i in range(N)] pts2 = [(u(0, x) + 3, u(0, x) + i / 2 + 2, u(0, x) + i + 1) for i in range(N)] pts3 = [(u(0, x) + 4, u(0, x) + i / 4 - 3, u(0, x) + i - 2) for i in range(N)] vpts1 = Points(pts1, c="r").legend("set1") vpts2 = Points(pts2, c="g").legend("set2") vpts3 = Points(pts3, c="b").legend("set3") vp.show(vpts1, vpts2, vpts3, __doc__, at=0) # find best alignment among the n sets of Points, # return an Assembly object formed by the aligned sets aligned = alignProcrustes([vpts1, vpts2, vpts3]) # print(aligned.info['transform']) vp.show(aligned, at=1, interactive=1)
# 1. An object is loaded and noise is added to its vertices. # 2. the point cloud is smoothened with MLS (see moving_least_squares.py) # 3. clean(actor) imposes a minimum distance among mesh points where # 'tol' is the fraction of the actor size. # 4. a triangular mesh is extracted from this set of sparse points # 'bins' is the number of voxels of the subdivision # NB: recoSurface only works with vtk version >7 # from __future__ import division, print_function from vtkplotter import Plotter, recoSurface, smoothMLS2D import numpy as np vp = Plotter(shape=(1, 4), axes=0) act = vp.load('data/shapes/pumpkin.vtk') vp.show(act, at=0) noise = np.random.randn(act.N(), 3) * 0.05 act_pts0 = vp.points(act.coordinates() + noise, r=3) #add noise act_pts1 = act_pts0.clone() #make a copy to modify vp.show(act_pts0, at=1, legend='noisy cloud') smoothMLS2D(act_pts1, f=0.4) #smooth cloud, input actor is modified print('Nr of points before cleaning polydata:', act_pts1.N()) act_pts1.clean(tol=0.01) #impose a min distance among mesh points print(' after cleaning polydata:', act_pts1.N()) vp.show(act_pts1, at=2, legend='smooth cloud')
def d_dt(psi): # find Psi(t+dt)-Psi(t) /dt with 4th order Runge-Kutta method k1 = f(psi) k2 = f(psi + dt / 2 * k1) k3 = f(psi + dt / 2 * k2) k4 = f(psi + dt * k3) return (k1 + 2 * k2 + 2 * k3 + k4) / 6 vp = Plotter(bg="white", interactive=0, axes=2, verbose=0) vp.xtitle = "" vp.ytitle = "Psi^2(x,t)" vp.ztitle = "" bck = vp.load(datadir + "images/schrod.png").scale(0.012).pos([0, 0, -0.5]) barrier = Line(list(zip(x, V * 15)), c="dr", lw=3) lines = [] for j in range(150): for i in range(500): Psi += d_dt(Psi) * dt # integrate for a while A = np.real(Psi * np.conj(Psi)) * 1.5 # psi squared, probability(x) coords = list(zip(x, A, [0] * len(x))) Aline = Tube(coords, c="db", r=0.08) vp.show(Aline, barrier, bck) lines.append(Aline) vp.show(interactive=1)
""" Mesh smoothing with two different VTK methods. See also analogous Plotter method smoothMLS2D() in exammples/advanced/moving_least_squares2D.py """ print(__doc__) from vtkplotter import Plotter, datadir vp = Plotter(shape=(1, 3), axes=4) # Load a mesh and show it a0 = vp.load(datadir+"embryo.tif", c="v") vp.show(a0, at=0) # Adjust mesh using Laplacian smoothing a1 = a0.clone().smoothLaplacian().color("crimson").alpha(1).legend("laplacian") vp.show(a1, at=1) # Adjust mesh using a windowed sinc function interpolation kernel a2 = a0.clone().smoothWSinc().color("seagreen").alpha(1).legend("window sinc") vp.show(a2, at=2) vp.renderers[0].SetBackground(0.8, 1, 1) # set first renderer color vp.show(zoom=1.4, interactive=True)
""" Modify mesh vertex positions. (vtkActor transformation matrix is reset when mesh is modified) """ from vtkplotter import Plotter, Disc, Text import numpy as np vp = Plotter(axes=4, interactive=0) dsc = Disc() coords = dsc.coordinates() for i in range(50): noise = np.random.randn(len(coords), 3) * 0.02 noise[:, 0] = 0 # only perturb z noise[:, 1] = 0 dsc.setPoints(coords + noise) # modify mesh vp.show(dsc, elevation=-1) vp.add(Text(__doc__)) vp.show(interactive=1)
See e.g. https://en.wikipedia.org/wiki/Rutherford_scattering """ vp = Plotter(title='Particle Simulator', bg='black', axes=0, interactive=False) vp.camera.Elevation(20) # Initial camera position vp.camera.Azimuth(40) vp.cube(wire=True, c='white') # a wireframe cube sim = ParticleSim(dt=5e-6, iterations=200) sim.add_particle((-0.4, 0, 0), color='w', charge=3e-6, radius=0.01, fixed=True) # the target positions = np.random.randn(500, 3) / 60 # generate a beam of 500 particles for p in positions: p[0] = -0.5 # Fix x position. Their charge are small/negligible compared to target: sim.add_particle(p, charge=.01e-6, mass=0.1e-6, vel=(1000, 0, 0), negligible=True) sim.simulate() vp.show(interactive=True, resetcam=False)
# Example of reading a vtk file containing vtkStructuredPoints data # (representing the orbitals of the electron in the hydrogen atom). # The dataset contains an existing scalar array named 'probability_density' # which is transformed into a color map. # The list of existing arrays can be found by selecting an actor and # pressing i in the rendering window. # import numpy as np from vtkplotter import Plotter, vtkio vp = Plotter(axes=4) actor = vtkio.loadStructuredPoints('data/hydrogen.vtk') actor.alpha(0.2).pointSize(15) scals = actor.scalars('probability_density') # retrieve the array scals[scals < 0.1] = 0.0 # put to zero low values (noise) print('scalars min, max =', np.min(scals), np.max(scals)) # minus sign inverts color map actor.pointColors(-scals, cmap='hot', alpha=0.05) vp.show(actor)
pos = position corner number: horizontal [1-4] or vertical [11-14] """ print(__doc__) from vtkplotter import Plotter, datadir vp = Plotter(axes=0, bg="w") mesh = vp.load(datadir + "magnolia.vtk", c=0) def slider1(widget, event): value = widget.GetRepresentation().GetValue() mesh.color(value) def slider2(widget, event): value = widget.GetRepresentation().GetValue() mesh.alpha(value) vp.addSlider2D(slider1, -9, 9, value=0, pos=4, title="color number") vp.addSlider2D(slider2, xmin=0.01, xmax=0.99, value=0.5, pos=14, c="blue", title="alpha value (opacity)") vp.show()
class VirtualKeyboard: def __init__(self, songname=''): self.KB = dict() self.vp = None self.rightHand = None self.leftHand = None self.vpRH = None self.vpLH = None self.playsounds = True self.verbose = True self.songname = songname self.t0 = 0 # keep track of how many seconds to play self.dt = 0.1 self.speedfactor = 1 self.engagedfingersR = [False] * 6 # element 0 is dummy self.engagedfingersL = [False] * 6 self.engagedkeysR = [] self.engagedkeysL = [] self.build_keyboard() ####################################################### def makeHandActor(self, f=1): a1, a2, a3, c = (10 * f, 0, 0), (0, 7 * f, 0), (0, 0, 3 * f), (.7, 0.3, 0.3) palm = Ellipsoid(pos=(0, -3, 0), axis1=a1, axis2=a2, axis3=a3, alpha=0.6, c=c) wrist = Box(pos=(0, -9, 0), length=6 * f, width=5, height=2, alpha=0.4, c=c) arm = Assembly([palm, wrist]) self.vp.actors.append(arm) # add actor to internal list f1 = self.vp.add( Cylinder((-2, 1.5, 0), axis=(0, 1, 0), height=5, r=.8 * f, c=c)) f2 = self.vp.add( Cylinder((-1, 3, 0), axis=(0, 1, 0), height=6, r=.7 * f, c=c)) f3 = self.vp.add( Cylinder((0, 4, 0), axis=(0, 1, 0), height=6.2, r=.75 * f, c=c)) f4 = self.vp.add( Cylinder((1, 3.5, 0), axis=(0, 1, 0), height=6.1, r=.7 * f, c=c)) f5 = self.vp.add( Cylinder((2, 2, 0), axis=(0, 1, 0), height=5, r=.6 * f, c=c)) return [arm, f1, f2, f3, f4, f5] def build_RH(self, hand): if self.verbose: print('Building Right Hand..') self.rightHand = hand f = utils.handSizeFactor(hand.size) self.vpRH = self.makeHandActor(f) for limb in self.vpRH: # initial x positions are superseded later limb.x(limb.x() * 2.5) limb.addPos([16.5 * 5 + 1, -7.5, 3]) # vtkplotter < 8.7.1 was addpos() def build_LH(self, hand): ######################### if self.verbose: print('Building Left Hand..') self.leftHand = hand f = utils.handSizeFactor(hand.size) self.vpLH = self.makeHandActor(f) for limb in self.vpLH: limb.x(limb.x() * 2.5) limb.addPos([16.5 * 3 + 1, -7.5, 3]) # vtkplotter < 8.7.1 was addpos() ####################################################### def build_keyboard(self): if self.verbose: print('Building Keyboard..') nts = ("C", "D", "E", "F", "G", "A", "B") tol = 0.12 keybsize = 16.5 # in cm, span of one octave wb = keybsize / 7 nr_octaves = 7 span = nr_octaves * wb * 7 self.vp = Plotter(title='PianoPlayer ' + __version__, axes=0, size=(700, 1400), bg='lb', verbose=0) #wooden top and base self.vp.add( Box(pos=(span / 2 + keybsize, 6, 1), length=span + 1, height=3, width=5).texture('wood5')) #top self.vp.add( Box(pos=(span / 2 + keybsize, 0, -1), length=span + 1, height=1, width=17).texture('wood5')) self.vp.add( Text('PianoPlayer ' + __version__, pos=(18, 5.5, 2), depth=.7, c='w')) self.vp.add( Text('https://github.com/marcomusy/pianoplayer', pos=(105, 4.8, 2), depth=.7, c='w', s=.8)) leggio = self.vp.add( Box(pos=(span / 1.55, 8, 10), length=span / 2, height=span / 8, width=0.08, c=(1, 1, 0.9))) leggio.rotateX(-20) self.vp.add( Text('Playing\n\n' + self.songname, pos=[0, 0, 0], s=1.2, c='k').rotateX(70).pos([49, 7, 9])) for ioct in range(nr_octaves): for ik in range(7): #white keys x = ik * wb + (ioct + 1) * keybsize + wb / 2 tb = self.vp.add( Box(pos=(x, -2, 0), length=wb - tol, height=1, width=12, c='white')) self.KB.update({nts[ik] + str(ioct + 1): tb}) if not nts[ik] in ("E", "B"): #black keys tn = self.vp.add( Box(pos=(x + wb / 2, 0, 1), length=wb * .6, height=1, width=8, c='black')) self.KB.update({nts[ik] + "#" + str(ioct + 1): tn}) self.vp.show(interactive=0) self.vp.camera.Azimuth(4) self.vp.camera.Elevation(-30) ##################################################################### def play(self): printc('Press [0-9] to proceed by one note or for more seconds', c=1) printc('Press Esc to exit.', c=1) self.vp.keyPressFunction = self.runTime # enable observer if self.rightHand: self.engagedkeysR = [False] * len(self.rightHand.noteseq) self.engagedfingersR = [False] * 6 # element 0 is dummy if self.leftHand: self.engagedkeysL = [False] * len(self.leftHand.noteseq) self.engagedfingersL = [False] * 6 t = 0.0 while True: if self.rightHand: self._moveHand(1, t) if self.leftHand: self._moveHand(-1, t) if t > 1000: break t += self.dt # absolute time flows if self.verbose: printc('End of note sequence reached.') self.vp.keyPressFunction = None # disable observer ################################################################### def _moveHand(self, side, t): ############# runs inside play() loop if side == 1: c1, c2 = 'tomato', 'orange' engagedkeys = self.engagedkeysR engagedfingers = self.engagedfingersR H = self.rightHand vpH = self.vpRH else: c1, c2 = 'purple', 'mediumpurple' engagedkeys = self.engagedkeysL engagedfingers = self.engagedfingersL H = self.leftHand vpH = self.vpLH for i, n in enumerate(H.noteseq): ##################### start, stop, f = n.time, n.time + n.duration, n.fingering if isinstance(f, str): continue if f and stop <= t <= stop + self.dt and engagedkeys[ i]: #release key engagedkeys[i] = False engagedfingers[f] = False name = nameof(n) krelease(self.KB[name]) frelease(vpH[f]) self.vp.interactor.Render() for i, n in enumerate(H.noteseq): ##################### start, stop, f = n.time, n.time + n.duration, n.fingering if isinstance(f, str): print('Warning: cannot understand lyrics:', f, 'skip note', i) continue if f and start <= t < stop and not engagedkeys[ i] and not engagedfingers[f]: #press key if i >= len(H.fingerseq): return engagedkeys[i] = True engagedfingers[f] = True name = nameof(n) if t > self.t0 + self.vp.clock: self.t0 = t self.vp.show(zoom=2, interactive=True) for g in [1, 2, 3, 4, 5]: vpH[g].x(side * H.fingerseq[i][g]) vpH[0].x(vpH[3].x() ) # index 0 is arm, put it where middle finger is fpress(vpH[f], c1) kpress(self.KB[name], c2) self.vp.show(zoom=2, interactive=False) if self.verbose: msg = 'meas.' + str(n.measure) + ' t=' + str(round(t, 2)) if side == 1: printc(msg, '\t\t\t\tRH.finger', f, 'hit', name, c='b') else: printc(msg, '\tLH.finger', f, 'hit', name, c='m') if self.playsounds: playSound(n, self.speedfactor) else: time.sleep(n.duration * self.speedfactor) ########################################## def runTime(self, key): secs = [str(i) for i in range(10)] if key not in secs: return printc('Will execute score for ' + key + ' seconds') self.vp.interactive = False self.vp.clock = int(key) self.vp.interactor.ExitCallback()