Complex Number to a PowerΒΆ

../../_images/anim_complex.png

Animation control:

Visualization Frame Value
Surface geometry functional 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

Based on the static plots from the Parametric Set example.

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

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

real = True
imaginary =  not real

def pover_Z(rtz, isReal, N) :
    r,t,z = rtz
    A = np.power(r,N)
    alpha = N*t if N>1 else t
    if isReal : Z = A*np.cos(alpha)
    else :      Z = A*np.sin(alpha)
    return r,alpha/N,Z

elev,azim,lightDir = 20, -150, [1,0,1]

xpont = [0.333, 0.5,  1,   2,    3]                         # exponents, n
ticPs = [0,     0.25, 0.5, 0.75, 1]                         # colorbar tick positions
ticLb = [r'$\frac{1}{3}$', r'$\frac{1}{2}$', '1', '2', '3'] # colorbar labels

val =           lambda b : s3d.frame_to_value(b,xpont)[0]   # linear segment path
frame_to_beta = lambda f : 2*f if f<0.5 else 2*(1-f)        # forward to reverse sequence

def indicator_by_A(fig, A, vOld=None) :
    # 0 < A < 1
    symbol, blank = r'$\blacktriangleright$', r'$\blacksquare$'
    horz, vCen, vRng = 0.825, 0.5, 0.28
    vert = vCen + vRng*(2*A-1)
    if vOld is not None: 
        fig.text(horz,vOld,blank, ha='right', va='center', fontsize='x-large', color='w')
    fig.text(horz,vert,symbol, ha='right', va='center', fontsize='large')
    return vert

# 2. Setup and map surfaces .........................................
frame = .0
beta = frame_to_beta(frame)
V = val(beta)

rez=5
zMap = cmu.hsv_cmap_gradient( [.5,1,1], [1.5,1,1] )

surface = s3d.PolarSurface(rez, 'squ_c', cmap=zMap)
surface.map_cmap_from_op( lambda rtz : pover_Z(rtz,imaginary,V)[2] )
surface.map_geom_from_op( lambda rtz : pover_Z(rtz,real,V) )

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

rtv = s3d.rtv(lightDir,elev,azim)
minmax = (-1,1) 
sm = plt.cm.ScalarMappable(cmap=cmu.binary_cmap('k','w'))
sm.set_array([])

fig = plt.figure(figsize=plt.figaspect(0.9))
ax = plt.axes(projection='3d')
ax.set_title( r'f(z) =  $z^n$', fontsize='xx-large' )
ax.view_init(elev,azim)
ax.set(xlim=minmax, ylim=minmax, zlim=minmax)
cbar = plt.colorbar(sm, ax=ax,  shrink=0.6, pad=-.05, aspect=50, ticks=ticPs )
cbar.set_label('Exponent, n', rotation=270, labelpad = 15)
cbar.ax.set_yticklabels(ticLb)
ax.set_axis_off()

ax.add_collection3d(surface.shade(0,rtv))
prevIndicator = indicator_by_A(fig, beta)

fig.tight_layout()
# 4. Animation ......................................................

def init_fig():
    return surface,

def update_fig(frame):
    global surface
    global prevIndicator
    ax.collections.remove(surface)

    beta = frame_to_beta(frame)
    V = val(beta)

    surface = s3d.PolarSurface(rez, 'squ_c', cmap=zMap)
    surface.map_cmap_from_op( lambda rtz : pover_Z(rtz,imaginary,V)[2] )
    surface.map_geom_from_op( lambda rtz : pover_Z(rtz,real,V) )
    surface.shade(0,rtv)
    prevIndicator = indicator_by_A(fig, beta, prevIndicator)

    ax.add_collection3d(surface)

    return surface,

ani = FuncAnimation(fig, update_fig, frames=np.linspace(0.0, 1.0, 121),
                    init_func=init_fig, blit=False, repeat=True, interval=50)

print(">>>>>>>>>>>>>>> Animation completed, file save proceeds")
#ani.save('ZZZ.mp4')                                   # use for movie file.
#ani.save(None,writer=animation.FFMpegFileWriter())    # use for temp files.
#print(">>>>>>>>>>>>>>> Save completed, screen display proceeds")

plt.show()