I have a figure that contains both a curve plot and a corresponding image. I'd like for the two of them to shift in sync with one another -- so that the white region of the image follows the location in the curve where all three curves match up. (For the curious, this is intended as a simple simulation of a multiwavelength interferogram.)
The three curves in the plot are copied point-by-point into the into the R, G, and B channels of the image frame. As a result, I expected the two to be naturally in sync. However, in the animation one can see that the curves shift at a faster rate than the colors in the image.
After trying a number of adjustments (aspect ratio of the image, changing the image "extent", etc.) I have so far failed to locate the problem.
from numpy import *
import matplotlib.pyplot as plt
from matplotlib import animation
npts = 501
wavelength_blue = 0.45
wavelength_green = 0.55
wavelength_red = 0.65
z = 1.5 * linspace(-0.75, 0.75, npts) ## distance in microns
nframes = 100
maxshift = 0.55 ## in microns of distance
img_height = 100
img = 255 * ones((img_height,npts,3), 'uint8')
(fig,axes) = plt.subplots(2, num='propagation_phase_shifted')
p1 = axes[0].plot([], [], 'b-')
p2 = axes[0].plot([], [], 'g-')
p3 = axes[0].plot([], [], 'r-')
axes[0].set_xlim((-0.8,0.8))
axes[0].set_ylim((-0.1,1.1))
p4 = axes[1].imshow(img, extent=[-0.8,0.8,-0.1,1.1], aspect=1/3)
axes[0].xaxis.set_label_position('top')
axes[0].xaxis.set_ticks_position('top')
axes[0].set_xlabel('z-distance (um)')
axes[0].set_ylabel('wave amplitude')
axes[0].tick_params(axis='x', direction='out')
plt.subplots_adjust(hspace=0.05)
def animate(n):
shift = (n / (nframes - 1.0)) * maxshift
phi_red = 2.0 * pi * (z-shift) / wavelength_red
phi_green = 2.0 * pi * (z-shift) / wavelength_green
phi_blue = 2.0 * pi * (z-shift) / wavelength_blue
y_red = 0.5 * (1.0 cos(phi_red))
y_green = 0.5 * (1.0 cos(phi_green))
y_blue = 0.5 * (1.0 cos(phi_blue))
for x in range(img_height):
img[x,:,0] = uint8(255 * y_red)
img[x,:,1] = uint8(255 * y_green)
img[x,:,2] = uint8(255 * y_blue)
p1[0].set_data(z, y_red)
p2[0].set_data(z, y_green)
p3[0].set_data(z, y_blue)
p4.set_data(img)
return(p1[0],p2[0],p3[0],p4)
anim = animation.FuncAnimation(fig, animate, frames=nframes, interval=20, blit=True)
FFwriter = animation.FFMpegWriter(fps=30)
anim.save('result.mp4', writer=FFwriter)
plt.show()
CodePudding user response:
I think the problem occurs when you convert your distance in microns. The same data is stretched between -1.125..1.125 on the top figure (1.5*0.75=1.125) and -0.8..0.8 on the bottom one. The top one then appear to move faster.
Fixing the intervals should work. Also if I'm not mistaken, you interverted red and blue in the top plot:
from numpy import *
import matplotlib.pyplot as plt
from matplotlib import animation
npts = 501
wavelength_blue = 0.45
wavelength_green = 0.55
wavelength_red = 0.65
z = 1.5 * linspace(-0.75, 0.75, npts) ## distance in microns
nframes = 100
maxshift = 0.55 ## in microns of distance
img_height = 100
img = 255 * ones((img_height,npts,3), 'uint8')
(fig,axes) = plt.subplots(2, num='propagation_phase_shifted')
p1 = axes[0].plot([], [], 'r-') # <--------- replacing b with r
p2 = axes[0].plot([], [], 'g-')
p3 = axes[0].plot([], [], 'b-') # <--------- replacing r with b
axes[0].set_xlim((-1.125,1.125)) # <--------- fixing interval
axes[0].set_ylim((-0.1,1.1))
p4 = axes[1].imshow(img, extent=[-1.125,1.125,-0.1,1.1], aspect=1/3) # <--------- fixing interval
axes[0].xaxis.set_label_position('top')
axes[0].xaxis.set_ticks_position('top')
axes[0].set_xlabel('z-distance (um)')
axes[0].set_ylabel('wave amplitude')
axes[0].tick_params(axis='x', direction='out')
plt.subplots_adjust(hspace=0.05)
def animate(n):
shift = (n / (nframes - 1.0)) * maxshift
phi_red = 2.0 * pi * (z-shift) / wavelength_red
phi_green = 2.0 * pi * (z-shift) / wavelength_green
phi_blue = 2.0 * pi * (z-shift) / wavelength_blue
y_red = 0.5 * (1.0 cos(phi_red))
y_green = 0.5 * (1.0 cos(phi_green))
y_blue = 0.5 * (1.0 cos(phi_blue))
for x in range(img_height):
img[x,:,0] = uint8(255 * y_red)
img[x,:,1] = uint8(255 * y_green)
img[x,:,2] = uint8(255 * y_blue)
p1[0].set_data(z, y_red)
p2[0].set_data(z, y_green)
p3[0].set_data(z, y_blue)
p4.set_data(img)
return(p1[0],p2[0],p3[0],p4)
anim = animation.FuncAnimation(fig, animate, frames=nframes, interval=20, blit=True)
FFwriter = animation.FFMpegWriter(fps=30)
anim.save('result.mp4', writer=FFwriter)
plt.show()