Observed Matplotlib animation duration doubled compared to theory - python

I'm trying to plot an animated sine signal as if it's passing through a figure window. So I expect that it takes 5 seconds for a 3-sec sine signal to pass through a 2-second window in my animation.
However, looking at the pop-up figure live, it takes twice as long by clock time on my machine using the following code, adapted from this excellent tutorial: https://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/ .
The recorded video seems OK at the specified frame rate though.
I can't seem to see where I did wrong in the logic. Is it just a performance issue? If so, how should I optimize the code with constraints, e.g., if possible, I hope I won't have to lower the sampling rate? The purpose of this is to prepare for drawing real-time data coming from the network.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import sys
# Signal comes in from right to left.
SR = 44100 # sampling rate in Hz
DurSec = 3 # Signal duration in seconds
Freq = 440 # frequency in Hz
Amp = 1.0 # amplitude
WindowDurSec = 2 # figure window size in seconds
FPS = 30 # frame per second
msPerSec = 1000
frameDurMs = int(np.floor(1 / FPS * msPerSec)) # animation frame duration
passThruSec = WindowDurSec + DurSec # Playback stops at DurSec, but graph moves on until leaving window.
passThruFrames = int(round(FPS * passThruSec)) # number of frames of the entire animation.
sampPerFrame = int(frameDurMs/1000*SR) # frame size in samples
sampPerWindow = int(SR*WindowDurSec) # window size in samples
x = np.linspace(0, DurSec, int(SR*DurSec))
y = Amp * np.sin(2 * np.pi * Freq * x) # effective signal
# Add head and tail = 2 * windowSize
pad = np.zeros((sampPerWindow,), dtype=float)
Y = np.concatenate((pad, y, pad))
# Set up the figure
fig = plt.figure()
ax = plt.axes(xlim=(0, WindowDurSec), ylim=(-2*Amp, 2*Amp))
line, = ax.plot([], [], lw=2)
# initialization function: plot the background of each frame
def init():
line.set_data([], [])
return line,
# animation function. This is called sequentially
def animate(i):
x = np.linspace(0, WindowDurSec, sampPerWindow)
start = i*sampPerFrame
stop = start + sampPerWindow
step = 1
y = Y[start : stop : step]
line.set_data(x, y)
return line,
# call the animator.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=passThruFrames, interval=frameDurMs, blit=True, repeat=False)
anim.save('sinewave_animation.mp4', fps=FPS, extra_args=['-vcodec', 'libx264'])
plt.show()

Related

Oscilloscope animation of an electric signal in Python

Good evening,
I am new to Python. I am trying to process a signal saved in a npy file.
This file contains an electrical signal that I want to view as I do in the laboratory with the oscilloscope, so I want to generate an animation that shows me how the signal changes over time.
Here is my attempt:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
signal = np.load('signal.npy')
fig = plt.figure()
def animation(i):
plt.cla()
plt.plot(signal)
# what to do here?
anim = FuncAnimation(fig, animation, frames = len(signal), interval = 10)
plt.show()
I have no idea what to do in the animation function.
Thanks in advance and sorry for my english
Since I do not have access to your signal data, I generate mine in order to run the animation. Replace my random signal with yours.
A basic code to view you signal with respect to time could be this:
# import
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# signal generation
N = 10001
stop = 100
time = np.linspace(0, stop, N)
A = 1/4*np.cos(2*np.pi*(np.abs(time - stop/2)/stop)) + 1
f = np.concatenate((1*np.ones(int(N/4)), 2*np.ones(int(N/2) + 1), 1*np.ones(int(N/4))))
signal = A * np.sin(2*np.pi*f*time) + 0.05*np.random.randn(N)
# figure preparation
fig, ax = plt.subplots(1, 1, figsize = (8*0.9, 6*0.9))
displayed_period = int(2*f.min())
span = int(N/stop/f.min())
def animation(i):
# delete previous frame
ax.cla()
# plot and set axes limits
ax.plot(time[span*i: 1 + span*(i + displayed_period)],
signal[span*i: 1 + span*(i + displayed_period)])
ax.set_xlim([time[span*i], time[span*(i + displayed_period)]])
ax.set_ylim([1.1*signal.min(), 1.1*signal.max()])
# run animation
anim = FuncAnimation(fig, animation, frames = int(len(time)/span - 1), interval = 10)
plt.show()
which gives this animation:
Explanation
In my case, the signal is a sine wave which changes amplitude and frequency over time (plus some noise). I choose to see two complete oscillations of my signal per each frame, so I set
displayed_period = int(2*f.min())
to be sure to see at least the two complete oscillations. Then I have to define the amount of time passed through x axis between a frame and the following, so I set:
span = int(N/stop/f.min())
That being said, when you run the code, the animation function is called multiple times, in each time the i counter increases by 1. So you can use this counter to slice the time and the signal arrays: time[span*i: 1 + span*(i + displayed_period)].
In this way you plot a displayed_period number of complete oscillations and, for each frame, you scroll the x axis by span element.
You have to set displayed_period and span according to your signal properties in order to get a similar result.
If you want a little bit customization like an oscilloscope, check this code:
# import
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# signal generation
N = 10001
stop = 100
time = np.linspace(0, stop, N)
A = 1/4*np.cos(2*np.pi*(np.abs(time - stop/2)/stop)) + 1
f = np.concatenate((1*np.ones(int(N/4)), 2*np.ones(int(N/2) + 1), 1*np.ones(int(N/4))))
signal = A * np.sin(2*np.pi*f*time) + 0.05*np.random.randn(N)
# color definition
black = '#0F110D'
grey = '#3B3D3A'
yellow = '#FFFF21'
# figure preparation
fig, ax = plt.subplots(1, 1, figsize = (8*0.9, 6*0.9))
displayed_period = int(2*f.min())
span = int(N/stop/f.min())
def animation(i):
# delete previous frame
ax.cla()
# set background color and plot
ax.set_facecolor(black)
ax.plot(time[span*i: 1 + span*(i + displayed_period)],
signal[span*i: 1 + span*(i + displayed_period)],
color = yellow)
# plot axes lines
ax.hlines(y = 0,
xmin = 0,
xmax = stop,
lw = 2,
colors = grey)
ax.vlines(x = time[int(span*i + (1 + span*displayed_period)/2)],
ymin = 1.1*signal.min(),
ymax = 1.1*signal.max(),
lw = 2,
colors = grey)
# set grid, axes limits and ticks
ax.grid(which = 'major',
ls = '-',
lw = 0.5,
color = grey)
ax.set_xlim([time[span*i], time[span*(i + displayed_period)]])
ax.set_ylim([1.1*signal.min(), 1.1*signal.max()])
plt.tick_params(axis = 'both',
which = 'both',
bottom = False,
left = False,
labelbottom = False,
labelleft = False)
# run animation
anim = FuncAnimation(fig, animation, frames = int(len(time)/span - 1), interval = 10)
anim.save('oscilloscope.gif', writer = 'imagemagick')
plt.show()
I do not changed the functionalities, only the aspect of the animation:
In the matplotlib documentation you can see an example of a simulation of an oscilloscope here

Add delay between specific frames of a matplotlib animation

I want to create an animation in matplotlib using FuncAnimation. The animation contains various "stages" which I would like to separate (emphasize) by adding an extra delay to the interval between the two corresponding frames. Consider the following example code that draws five circles and the drawing of each two consecutive circles should be separated by 1 second:
import time
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
f, ax = plt.subplots()
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
radius = 1
dp = 2*np.pi / 50
circles = [[(radius, 0)]]
plots = ax.plot([radius], [0])
def update(frame):
global radius
if frame % 50 == 0:
radius += 1
circles.append([(radius, 0)])
plots.extend(ax.plot([radius], [0]))
# I want to add a delay here, i.e. before the drawing of a new circle starts.
# This works for `plt.show()` however it doesn't when saving the animation.
time.sleep(1)
angle = (frame % 50) * dp
circles[-1].append((radius * np.cos(angle), radius * np.sin(angle)))
plots[-1].set_data(*zip(*circles[-1]))
return plots[-1]
animation = FuncAnimation(f, update, frames=range(1, 251), interval=50, repeat=False)
### Uncomment one of the following options.
# animation.save('test.mp4', fps=20)
# with open('test.html', 'w') as fh:
# fh.write(animation.to_html5_video())
# plt.show()
This works when playing the animation via plt.show() however it doesn't work when saving as .mp4 or HTML5 video. This makes sense since, according to the documentation, the FPS determines the frame delay for mp4 video and the interval parameter is used for HTML5 video. Then frames are just played one after another (ignoring any compute time as well).
So how can I add a delay that will be retained upon saving the animation?
You should be able to use a generating function for your frames argument. For example:
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
INTERVAL = 50 # ms
HOLD_MS = 1000
HOLD_COUNT = HOLD_MS // INTERVAL
def frame_generator():
for frame in range(1, 251):
# Yield the frame first
yield frame
# If we should "sleep" here, yield None HOLD_COUNT times
if frame % 50 == 0:
for _ in range(HOLD_COUNT):
yield None
f, ax = plt.subplots()
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
radius = 1
dp = 2*np.pi / 50
circles = [[(radius, 0)]]
plots = ax.plot([radius], [0])
def update(frame):
global radius
if frame is None: return #--------------------------------- Added
if frame % 50 == 0:
radius += 1
circles.append([(radius, 0)])
plots.extend(ax.plot([radius], [0]))
#-------------------------------------------------------- sleep removed
angle = (frame % 50) * dp
circles[-1].append((radius * np.cos(angle), radius * np.sin(angle)))
plots[-1].set_data(*zip(*circles[-1]))
return plots[-1]
# Slightly changed
animation = FuncAnimation(f, update, frames=frame_generator(), interval=INTERVAL, repeat=False)
plt.show()
Should work.
print(list(frame_generator()))
May help clarify what's going on.
You may use the frame argument to steer your animation. Essentially a pause after frame n is the same as showing the frame number n repeatedly until the pause ends. E.g. if you run an animation at a rate of 1 frame per second, and want 3 seconds pause after the second frame, you can supply
0, 1, 1, 1, 1, 2, 3, ....
as frames, such that the frame with number 1 is shown four times.
Applying that concept can be done as follows in your code.
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
f, ax = plt.subplots()
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
radius = 0
bu = 50
dp = 2*np.pi / bu
circles = [[(radius, 0)]]
plots = ax.plot([radius], [0])
def update(frame):
global radius
if frame % bu == 0:
radius += 1
circles.append([(radius, 0)])
plots.extend(ax.plot([radius], [0]))
angle = (frame % bu) * dp
circles[-1].append((radius * np.cos(angle), radius * np.sin(angle)))
plots[-1].set_data(*zip(*circles[-1]))
return plots[-1]
interval = 50 # milliseconds
pause = int(1 * 1000 / interval)
cycles = 4
frames = []
for c in range(cycles):
frames.extend([np.arange(c*bu, (c+1)*bu), np.ones(pause)*((c+1)*bu)])
frames = np.concatenate(frames)
animation = FuncAnimation(f, update, frames=frames, interval=50, repeat=False)
### Uncomment one of the following options.
# animation.save('test.mp4', fps=20)
# with open('test.html', 'w') as fh:
# fh.write(animation.to_html5_video())
plt.show()

python animation reading data from file

I'm trying to plot the time evolution of a function f(x,t). The data is stored in a file which has the following format:
1st row:f(0,0) f(0,1) f(0,2) ....f(0,N)
2nd row:f(1,0) f(1,1) f(1,2) ....f(1,N)
Mth row:f(M,0) f(M,1) f(M,2) ....f(M,N)
where N is the no: of points of the simulation box and M is the number of timesteps.
I used basic_animation by Jake Vanderplas (https://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/) to start with, the original example works fine as long as i put blit=False.
Then i tried to replace x by :
x= np.arange(0,192)
and y by the contents of the file mentioned above.
If i do just plt.plot(x,y), it does plot f(x,t) at a given time t, but I want the animation of f(x,t) in time.
set_data should accept 2 1Darrays and I've checked that len(x)=len(y).
But I get the following error message:
'RuntimeError: xdata and ydata must be the same length'
This is the code (in the future i would like to plot multiple functions):
"""
Modified Matplotlib Animation Example
original example:
email: vanderplas#astro.washington.edu
website: http://jakevdp.github.com
license: BSD
Feel free to use and modify this, but keep the above information.
"""
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from itertools import islice
filename = 'DensityByPropagation__a_0_VHxcS_kick'
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 192), ylim=(-2, 2))
lineS, = ax.plot([], [], lw=2)
# initialization function: plot the background of each frame
def init():
lineS.set_data([], [])
return lineS,
# animation function. This is called sequentially
def animate(i):
w = np.linspace(0, 2, 1000)
z = np.sin(2 * np.pi * (w - 0.01 * i))
x= np.arange(0,192)
with open(filename) as fobj:
ketchup = islice(fobj, 0, None, 10)
for line in ketchup:
x,y = x,zip(*([float(y) for y in line.split("\t")] for line in fobj))
#plt.plot(x,y)
#plt.show()
#print len(x)
#print len(y)
#lineS.set_data(w,z)
lineS.set_data(x,y)
return lineS,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=200, interval=20, blit=False)
# save the animation as an mp4. This requires ffmpeg or mencoder to be
# installed. The extra_args ensure that the x264 codec is used, so that
# the video can be embedded in html5. You may need to adjust this for
# your system: for more information, see
# http://matplotlib.sourceforge.net/api/animation_api.html
anim.save('movieJoh.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()
I'm not sure what exactly is causing your error, but let me point something out, then I'll make a toy example that should help clarify what's happening.
These lines seem unnecessarily complicated.
with open(filename) as fobj:
ketchup = islice(fobj, 0, None, 10)
for line in ketchup:
x,y = x,zip(*([float(y) for y in line.split("\t")] for line in fobj))
If your data is in fact in the simple format you stated, i.e., values separated by spaces, np.loadtxt() would load all the values into an easy to manage array.
Example
Lets assume this is your data file (10 time steps, 2 points on plot at each step):
0 0 0 0 0 0 0 0 0 0
9 8 7 6 5 4 3 2 1 0
Now some code:
filename = 'data.txt'
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 1), ylim=(0, 9))
lineS, = ax.plot([], [], lw=2)
x = range(2) # the domain
Now we load the data in with np.loadtxt(), this creates a 2-d matrix with t in the columns and x in the rows. We then transpose it to make indexing each time step possible in animate().
# load the data from file
data = np.loadtxt(filename)
# transpose so we could easily index in the animate() function
data = np.transpose(data)
Now for animation functions. This part is really quite simple. animate(i) takes one argument - the frame number. Using the frame number, we extract the values of f(x,t=frameNumber) and set that as the data on the plot.
# initialization function: plot the background of each frame
def init():
lineS.set_data([], [])
return lineS,
# animation function. This is called sequentially
def animate(i):
lineS.set_data(x, data[i])
return lineS,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=10, interval=100, blit=True)
plt.show()
This is the working code:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
# Input
filename = 'PeriodicDensity' # Filename
x = np.linspace(-7.5,7.5,192) # Domain
xLimits=[-7.5,7.5] # x limits
yLimits=[0,1] # y limits
framesToUse = range(1,9000,150)# The time-steps to plot
# load the data from file
data = np.loadtxt(filename)
# Set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=xLimits,ylim=yLimits)
lineS, = ax.plot([], [], lw=2)
# Initialisation function
def init():
lineS.set_data([],[])
return lineS,
# Animation function (called sequentially)
def animate(i):
lineS.set_data(x,data[i])
return lineS,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,interval=1000, frames=framesToUse, blit=True)
# save the animation as an mp4. This requires ffmpeg or mencoder to be
# installed. The extra_args ensure that the x264 codec is used, so that
# the video can be embedded in html5. You may need to adjust this for
# your system: for more information, see
# http://matplotlib.sourceforge.net/api/animation_api.html
anim.save('movieDensity.mp4', fps=1, extra_args=['-vcodec', 'libx264'])
plt.show()

plot that only shows most recent points

I want to make a real time plot of temeperature vs. iteration but I will end up having so many points that it would not make sense to have them on the same plot. Does anyone know of any good ways to only show the most recent (lets say 100) data points so that after the first 100 the plot starts to replace the old data points with the new data points?
I thought it would be easier without code but here is the real time ploting that I have now.
from time import sleep
from labjack import ljm
import pylab as pl
import matplotlib.pyplot as plt
# Open T7 over USB
handle = ljm.openS("T7", "USB", "ANY")
# Configure thermocouple line on AIN0
ljm.eWriteName(handle, "AIN0_EF_INDEX", 22) # Feature index for type K thermocouple
ljm.eWriteName(handle, "AIN0_EF_CONFIG_A", 1) # Units. Default = Kelvin. 1 = Celsius. 2 = Fahrenheit.
ljm.eWriteName(handle, "AIN0_EF_CONFIG_B", 60052) # CJC source, address for device temperature sensor
ljm.eWriteName(handle, "AIN0_EF_CONFIG_D", 1.0) # Slope for CJC reading
ljm.eWriteName(handle, "AIN0_EF_CONFIG_E", 0.0) # Offset for CJC reading
temperature = []
x = list()
y = list()
x1 = list()
y1 = list()
dT_tol = .5
plt.ion()
fig=plt.figure()
# Read loop
for i in range(60):
# Get the thermocouple reading on AIN0.
tempC = ljm.eReadName(handle, "AIN0_EF_READ_A")
temperature.append(tempC)
dT = temperature[i]-temperature[i-1]
if -dT_tol<dT<dT_tol:
print "Temperature:","%.3f"% temperature[i]," " "dT:", "%.3f"% dT, " " "Steady State"
sleep(1)
else:
print "Temperature:","%.3f"% temperature[i]," " "dT:", "%.3f"% dT
sleep(1)
#Plotting
plt.figure(1)
plt.subplot(211)
plt.axis([0,60,0,80])
x.append(i)
y.append(temperature[i])
plt.scatter(x,y)
plt.ylabel('Temperature (C)')
plt.subplot(212)
plt.axis([0,60,-4,4])
x1.append(i)
y1.append(dT)
plt.scatter(x1,y1,zorder = 2)
#Set dT steady state boundaries
plt.axhspan(-dT_tol, dT_tol, color='#87CEFA', alpha=1, zorder = 1)
plt.ylabel('dT')
plt.xlabel('Time (s)')
plt.show()
plt.pause(.0001)
# Close handle
ljm.close(handle)
you can use list of array to show the all data given for a while.
for example
tempaturelist=[]
for i in range(50):
enter code here
tempaturelist.append(tempature)
print tempaturelist
There is a overwriting if you use same variable for all values.
Thats why you see only most recent values .
Edit:
You might consider using a deque object to improve performance. It is like a stack/queue hybrid, which may be faster than numpy.roll. I left the old code in for example..
from collections import deque
You can use something like this, just update it to fit your needs ( I am just going to make up random data because im too lazy to use your example)
import numpy as np
import pylab as plt
buffer_size = 100 # how many data points you want to plot at any given time
#data_buffer = np.zeros( buffer_size) # this is where you will keep the latest data points
data_buffer = deque()
for i in range( buffer_size):
data_buffer.append(0)
temperatures = np.random.random( 200 ) # some random temperature data, i dunno
# setup the figure
fig = plt.figure(1)
plt.suptitle('Previous %d temperatures'%buffer_size, fontsize=12)
ax = plt.gca()
for i,Temp in enumerate( temperatures ):
#data_buffer = np.roll( data_buffer, shift=-1)
#data_buffer[ -1] = Temp
data_buffer.popleft()
data_buffer.append( Temp)
ax.plot( data_buffer, 'rs', ms=6) # whatever style you want...
plt.draw()
plt.pause(0.01)
plt.cla() # clears the axis
I won't post the output of this plot because it will always be changing, but try it yourself ;)

imshow.set_data() not working for FuncAnimation

I am writing a program for 2D FDTD light propagation, in this code, when I run the program with ax.imshow() command in the animate function, the program works fine whereas when I use the im.set_data() command, it gives me a blank image. Can somebody please tell me what am I doing wrong? Also, can somebody tell me how to set the colormap at the beginning so that I dont have to update it during the animation loop. The point is I don't want the imshow() command to draw everything everytime the loop is run.
Thanks for all the help. I am learning programming please suggest me what to do.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
xdim = 100
ydim = 100
epsilon = np.ones([xdim,ydim])*8.854187817*10**(-12)
mu = np.ones([xdim,ydim])*4*np.pi*10**(-7)
c = 299792458
delta = 10**-6
deltat = delta/(c*(2**0.5))
Hz = np.zeros([xdim,ydim])
Ey = np.zeros([xdim,ydim])
Ex = np.zeros([xdim,ydim])
fig = plt.figure()
ax = plt.axes()
im = ax.imshow(Hz)
Hz[xdim/2,ydim/2]=1
def init():
im.set_data(np.zeros(Hz.shape))
return
def animate(n, *args, **kwargs):
Ex[0:xdim-1,0:ydim-1]=Ex[0:xdim-1,0:ydim-1]+(deltat/(delta*mu[0:xdim-1,0:ydim-1]))*(Hz[1:xdim,0:ydim-1]-Hz[0:xdim-1,0:ydim-1])
Ey[0:xdim-1,0:ydim-1]=Ey[0:xdim-1,0:ydim-1]-(deltat/(delta*mu[0:xdim-1,0:ydim-1]))*(Hz[0:xdim-1,1:ydim]-Hz[0:xdim-1,0:ydim-1])
Hz[1:xdim,1:ydim]=Hz[1:xdim,1:ydim]+(deltat/(delta*epsilon[1:xdim,1:ydim]))*(Ex[1:xdim,1:ydim]-Ex[0:xdim-1,1:ydim]-Ey[1:xdim,1:ydim]+Ey[1:xdim,0:ydim-1])
if(n==0):Hz[xdim/2,ydim/2]=0
#im.set_data(Hz)
ax.imshow(Hz) # Delete this command and try running the program with the above command.
return
ani = animation.FuncAnimation(fig, animate, init_func=init, frames = 200, interval = 10, blit = False, repeat = False)
fig.show()
Actually, your first version was working just fine also. The problem was that because im is initialized with an array of zeros, the vmin and vmax for the colorscale were both zero. Updates to im after that using set_data did not update vmin and vmax, whereas ax.imshow automatically rescales the color ranges. If you set the color ranges at the beginning to something reasonable, it works fine:
ax.imshow(Hz, vmin=-0.2, vmax=0.2)
That's the only thing you need to change from the code in the question to make it work (with im.set_data in the animation function).
I got the program to work by making a few changes, though i cannot understand why it is not working the way i wrote it in the question. Here is what i changed:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
xdim = 100
ydim = 100
epsilon = np.ones([xdim,ydim])*8.854187817*10**(-12)
mu = np.ones([xdim,ydim])*4*np.pi*10**(-7)
c = 299792458
delta = 10**-6
deltat = delta/(c*(2**0.5))
Hz = np.zeros([xdim,ydim])
Ey = np.zeros([xdim,ydim])
Ex = np.zeros([xdim,ydim])
Hz[xdim/2,ydim/2]=1
def init():
global fig, ax, im
fig = plt.figure()
ax = plt.axes()
im = ax.imshow(Hz, cmap="jet")
im.set_data(np.zeros(Hz.shape))
return
def animate(n):
Ex[0:xdim-1,0:ydim-1]=Ex[0:xdim-1,0:ydim-1]+(deltat/(delta*mu[0:xdim-1,0:ydim-1]))*(Hz[1:xdim,0:ydim-1]-Hz[0:xdim-1,0:ydim-1])
Ey[0:xdim-1,0:ydim-1]=Ey[0:xdim-1,0:ydim-1]-(deltat/(delta*mu[0:xdim-1,0:ydim-1]))*(Hz[0:xdim-1,1:ydim]-Hz[0:xdim-1,0:ydim-1])
Hz[1:xdim,1:ydim]=Hz[1:xdim,1:ydim]+(deltat/(delta*epsilon[1:xdim,1:ydim]))*(Ex[1:xdim,1:ydim]-Ex[0:xdim-1,1:ydim]-Ey[1:xdim,1:ydim]+Ey[1:xdim,0:ydim-1])
if(n==0):Hz[xdim/2,ydim/2]=0
im.set_data(Hz)
return
init()
ani = animation.FuncAnimation(fig, animate, frames = 500, interval = 10, blit = False, repeat = False)
fig.show()

Categories