Vector Magnitude within a DomainΒΆ
Animation control:
Visualization |
Frame Value |
|---|---|
Surface geometry |
sectioning parameter per frame |
Surface position |
fixed to the coordinate axis |
Surface color |
color per frame |
Shading and highlighting |
fixed to the coordinate axis |
Axis coordinate |
constant |
This example illustrates the magnitude of a vector field within a domain, as also shown in the static Vector Surfaces example for constant values.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import s3dlib.surface as s3d
import s3dlib.pntcloud as ptc
import s3dlib.cmap_utilities as cmu
# 0. Define animation control parameters ............................
totalTime, f_domain, numFrames = 10, (0.0,1.0), 101 # time in seconds
frames=np.linspace(*f_domain, numFrames, endpoint=True)
interval = int(1000.0*totalTime/numFrames) # milliseconds
# 1. Define function to examine ....................................
def vector_mag(xyz) :
x,y,z = xyz
u = np.sin(np.pi*x) * np.cos(np.pi*z)
v = -2*np.sin(np.pi*y) * np.cos(2*np.pi*z)
w = np.cos(np.pi*x)*np.sin(np.pi*z) + np.cos(np.pi*y)*np.sin(2*np.pi*z)
vect = np.array([u,v,w]).T
return np.linalg.norm(vect,axis=3).T
def frame_to_vals(f,cloud,zeta=0.85) :
min_cldV, max_cldV = cloud.bounds['vlim']
del_cldV = max_cldV - min_cldV
mid_cldV = (max_cldV + min_cldV)/2
frame_to_A = lambda t : 2*t if t<.5 else 2*(1-t) # 0 <= A <= 1
A = frame_to_A(f)
A_to_Fo = lambda A : (A-.5)*zeta*del_cldV + mid_cldV
A_to_cB = lambda A : zeta*A + (1-zeta)/2
return A_to_cB(A), A_to_Fo(A)
def indicator_by_A(fig, A, vOld=None) :
''' 0 <= A <= 1 '''
symbol, blank = r'$\blacktriangleright$', r'$\blacksquare$'
horz, vBot, vRng = 0.80, 0.22, 0.56
horz, vBot, vRng = 0.825, 0.22, 0.56
vert = vBot + vRng*A
bkgrd = fig.get_facecolor()
if vOld is not None: #.. cover current indicator with a blank symbol before showing indicator.
fig.text(horz,vOld,blank, ha='right', va='center', fontsize='x-large', color=bkgrd)
fig.text(horz,vert,symbol, ha='right', va='center', fontsize='large', color='k')
return vert
# 2. Setup and map surfaces .........................................
domain = [ [0,1], [0,1], [0,1] ]
xlim,ylim,zlim = domain
drez, cmap = 5, cmu.hue_cmap('b','r',2.0,name='BlRd')
cloudObj = ptc.Point3DCloud(drez, domain=domain)
cloudObj.map_vals_from_op(vector_mag)
cloudObj.map_cmap_from_cloudvals(cmap)
t=.25
vbar,Vo = frame_to_vals(t,cloudObj)
surface = cloudObj.valsurf(Vo)
# 3. Construct figures, add surfaces, and plot ....................
fig = plt.figure(figsize=(5,4))
fig.text(.5,0.9,'Magnitude',ha='center')
ax = fig.add_subplot(111, projection='3d', aspect='equal', focal_length=0.25)
ax.view_init(0,-120)
ax.set(xlim=xlim, ylim=ylim, zlim=zlim, xlabel='x',ylabel='y',zlabel='z')
prevIndicator = indicator_by_A(fig, vbar)
surface = surface.shade(.4,ax=ax).hilite(.5,ax=ax)
ax.add_collection3d(surface)
s3d.add_boxCorner(ax,domain)
cbar =fig.colorbar(cloudObj.cBar_ScalarMappable, ax=ax,shrink=0.6, pad=.12)
cbar.set_label('cloud values', rotation=270, labelpad = 15)
fig.tight_layout(pad=1)
plt.show()
# 4. Animation ======================================================
def update_fig(frame):
global surface,prevIndicator
surface.remove()
vbar,Vo = frame_to_vals(frame,cloudObj)
surface = cloudObj.valsurf(Vo)
prevIndicator = indicator_by_A(fig, vbar, prevIndicator)
surface.shade(.4,ax=ax).hilite(.5,ax=ax)
ax.add_collection3d(surface)
return
anim = FuncAnimation(fig, update_fig, frames, interval=interval, repeat=True)
anim.save('anim_vmag.html',writer='html')
msg = "saved {} frames, values: [{:.3f} to {:.3f}] @ {} milliseconds/frane"
print(msg.format(numFrames,np.min(frames),np.max(frames),interval))
print('DONE')
