Retinal Scan

../../_images/anim_retinal_scan.png

Animation control:

Visualization

Frame Value

Surface geometry

constant

Surface position

fixed to the coordinate axis

Surface color

constant

Shading and highlighting

fixed to the coordinate axis

Axis coordinate

azim per frame using view_init

Based on the static plot from the Function and Image Mapping example.

Changing only the axis coordinate results in ‘stationary object’ perception.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu

#.. Retinal Scan Animation

# 0. Define animation control parameters ............................

totalTime, f_domain, numFrames = 9, (0.0,1.0), 70   # time in seconds
frames=np.linspace(*f_domain, numFrames, endpoint=False)
interval = int(1000.0*totalTime/numFrames)         # milliseconds

# 1. Define functions to examine ....................................

def collapse( rtp) :
    r,t,p = rtp
    T = np.where(t>np.pi,t,-t)
    R = np.where(t>np.pi,r+0.03,r)
    return R,T,p

def azim( time ) :
    min, max, ofs = 0, 170, 5
    middle = (max+min)/2.0 + ofs
    hilo = (max-min)/2.0
    return middle - hilo*np.cos(time*2*np.pi)

# 2. Setup and map surfaces .........................................
start_azim_time = 0
rez=6
cmap = cmu.binary_cmap(negColor='black' ,posColor=[0.918,0.549,0.377])
imagefilename = 'data/retinal_scan.png'
vp = [ 0.065, 0.131, 0.435, 0.869]

eye = s3d.SphericalSurface(rez,basetype='octa')
eye.map_cmap_from_op( lambda rtp : rtp[1] ,cmap=cmap) 
eye.map_color_from_image(imagefilename,viewport=vp)
eye.map_geom_from_op(collapse)
eye.shade(direction=[0,1,1],contrast=0.5)
eye.transform(rotate=s3d.eulerRot(0,30))

# 3. Construct figures, add surfaces, and plot ......................

fig = plt.figure(figsize=plt.figaspect(1) )
ax = plt.axes(projection='3d', aspect='equal')
minmax = (-0.75,0.75)
ax.set(xlim=minmax, ylim=minmax, zlim=minmax)
ax.set_title('Retinal  Scan')
ax.set_axis_off()
ax.view_init( elev=30, azim=azim(start_azim_time) )

ax.add_collection3d(eye)

#plt.show()

# 4. Animation ======================================================

def update_fig(frame):
    ax.view_init(elev=30, azim=azim(frame) )
    return

anim = FuncAnimation(fig, update_fig, frames, interval=interval, repeat=True)
anim.save('retinal_scan.html',writer='html')

msg = "saved {} frames, values: [{:.3f} to {:.3f}] @ {} milliseconds/frane"
print(msg.format(numFrames,np.min(frames),np.max(frames),interval))