How to animate a complex function with matplotlib? - python

I want to make an animation with the function ((phi^n)-((-1/phi)^n))/(5^0.5) (Binet's formula) as n ∈ ℝ,
so that the graph starts as a straight line on the real axes then shifts into the actual graph.
I have tried to add
from matplotlib.animation import FuncAnimation
.
.
.
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
animation = FuncAnimation(main_graph, func=g, frames=arange(0, 10, 0.1), interval=10)
plt.show
However, it did not work and I have no clue why I followed various tutorials and all of them had the same result (An error)
I also tried
import matplotlib.animation as animation
.
.
.
def init():
main_graph.set_ydata([np.nan] * len(real(f(x))))
return main_graph,
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
ani = animation.FuncAnimation(main_graph, g, init_func=init, interval=2, blit=True, save_count=50)
The error, in both cases, is AttributeError: 'Line2D' object has no attribute 'canvas'. Here is the full code
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
plt.legend()
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
animation = FuncAnimation(main_graph, func=g, frames=arange(0, 10, 0.1), interval=10)
plt.show()
To see the final graph use this code
import matplotlib.pyplot as plt
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
plt.legend()
plt.show()

I have adapted the example from matplotlib's animation documentation. Here's how the code has been modified to allow for the modification of axis elements (in this case, the legend) by setting blit=False
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
#plt.legend(loc=4)
def init():
global legs
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_ylim(-4,4)
legs=ax.legend(loc=4, prop={'size': 12})
return main_graph,
def g(val):
main_graph.set_ydata(imag(f(x))*val)
label = '((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)x{}'.format(val)
legs.texts[0].set_text(label)
return main_graph,
#Note that blit has been set to False, because axes elements are being modified
animation = FuncAnimation(fig, func=g,frames=arange(0, 10, 0.1), init_func=init,interval=10,blit=False)
animation.save('animation.gif', writer='imagemagick', fps=30)
plt.show()
Here's how the animation is:

Related

How to use an image instead of a marker in an animated graph using Matplot.lib

I have been trying to use an image that moves in an animation instead of "ro" (red dots) or similar markers. image_1, image_2, image_3 So far I have a graph that has a little red dot moving over the dotted line. I want an image to be the one that moves through the dotted line instead of a red dot.
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
img = plt.imread("/Users/salomondabbah/Desktop/mar.jpg")
ax.imshow(img, extent=[0, 2 * np.pi, -1, 1])
xtrack = np.linspace(0, 2 * np.pi, 240)
ytrack = np.sin(xtrack)
ln, = plt.plot([], [], ***'ro'***, zorder=15)
ax.plot(xtrack, np.sin(xtrack), 'k', linewidth=25.0, zorder=5)
ax.plot(xtrack, ytrack, '--y',linewidth=2.0, zorder=10)
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
ln.set_data(frame, np.sin(frame))
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=False)
plt.show()
Thank you in advance for any solutions provided to my issue!
Similar to what you are doing, but using set_extent with imshow instead of set_data with a line:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(figsize=(5,5))
xdata, ydata = [], []
xtrack = np.linspace(0, 2 * np.pi, 240)
ytrack = np.sin(xtrack)
img = plt.imread("car.png")
im = ax.imshow(img, zorder=10, aspect='auto')
ax.plot(xtrack, np.sin(xtrack), 'k', linewidth=25.0, zorder=5)
ax.plot(xtrack, ytrack, '--y',linewidth=2.0, zorder=10)
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
l = frame - 0.5
r = frame + 0.5
b = np.sin(frame) - 0.2
t = np.sin(frame) + 0.2
im.set_extent([l,r,b,t])
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=False)
ani.save('ani.gif', writer='pillow')
The only finnicky thing is getting the desired size & aspect ratio of the graph and size & aspect ratio of the car. The overall graph can be edited by using figsize when it is created as I have added. But if you don't set the aspect parameter of the imshow to auto, it will override the figure size and shape, in order to make the image have correct dimensions (it seems). So you may have to play around with the 0.5 and 0.2 values in the update to keep your image having approximately correct dimensions.

i have problem with animate function.it gives me an empty plot

I had some problem with Animate function of matplotlib.
here the code: it gives me an empty graph. maybe i need to dowload some other modules?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib.animation as animation
x_data = []
y_data = []
fig, ax = plt.subplots()
ax.set_xlim(0, 105)
ax.set_ylim(0, 12)
line, = ax.plot(0, 0)
def animation_frame(i):
x_data.append(i*10)
y_data.append(i)
line.set_x_data(x_data)
line.set_y_data(y_data)
return line,
ani = animation.FuncAnimantion(fig, func = animation_frame, frames = np.arange(0, 10, 0.01), interval = 10)
plt.show()
the output is:
File "C:\Users\Utente\untitled0.py", line 28, in <module>
ani = animation.FuncAnimantion (fig,func= animation_frame,frames=np.arange(0,10,0.01),interval=10)
*****AttributeError: module 'matplotlib.animation' has no attribute 'FuncAnimantion'*****
with an empty graph!
someone can kindly help me?
There were a few typos:
FuncAnimantion -> FuncAnimation
set_x_data -> set_xdata
set_y_data -> set_ydata
Otherwise it should work:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x_data = []
y_data = []
fig, ax = plt.subplots()
ax.set_xlim(0, 105)
ax.set_ylim(0, 12)
line, = ax.plot(0, 0)
def animation_frame(i):
x_data.append(i * 10)
y_data.append(i)
line.set_xdata(x_data)
line.set_ydata(y_data)
return line,
ani = animation.FuncAnimation(fig, func=animation_frame, frames=np.arange(0, 10, 0.01), interval=10)
plt.show()

How to animate 3D graphs with python [duplicate]

I want to make 3D animation with matplotlib, but I don't know how to. Here is my non-working code.
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
from math import *
fig = plt.figure()
ax = fig.add_subplot(111) #, projection='3d'
#setting
ax.set_xlim(-5,5)
ax.set_ylim(-5,5)
#ax.set_zlim(-5,5)
ax.set_xlabel('x')
ax.set_ylabel('y')
#ax.set_zlabel('z')
ax.grid()
f1, = ax.plot([], [], "r-", lw=1) #plot1
def gen():
for phi in np.linspace(0,2*pi,100):
yield np.cos(phi), np.sin(phi), phi
def update(data):
p1, q1, psi = data
f1.set_data(p1,q1)
#f1.set_3d_properties(psi)
ani = animation.FuncAnimation(fig, update, gen, blit=False, interval=100, repeat=True)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
I used this example http://matplotlib.org/1.4.1/examples/animation/simple_3danim.html
and modified your code:
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
def gen(n):
phi = 0
while phi < 2*np.pi:
yield np.array([np.cos(phi), np.sin(phi), phi])
phi += 2*np.pi/n
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
N = 100
data = np.array(list(gen(N))).T
line, = ax.plot(data[0, 0:1], data[1, 0:1], data[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([-1.0, 1.0])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 10.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(data, line), interval=10000/N, blit=False)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
Here is the following code for a sphere moving to the right and off the screen.
You will have to run this code in a folder for tidiness, as it generates 26 .png images (and a .gif image):
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from numpy import sin, cos, pi, outer, ones, size, linspace
# Define x, y, z lists for sphere
a = linspace(0, 2 * pi)
b = linspace(0, pi)
x = 10 * outer(cos(a), sin(b))
y = 10 * outer(sin(a), sin(b))
z = 10 * outer(ones(size(a)), cos(b))
# The amount of frames in the animation
frames = 26
# Generate each frame
for n in range(frames):
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, color=('b'))
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
plt.savefig(f"{n}.png")
plt.close()
# Add 1 to the x so the sphere moves right by 1
x += 1
# Use pillow to save all frames as an animation in a gif file
from PIL import Image
images = [Image.open(f"{n}.png") for n in range(frames)]
images[0].save('ball.gif', save_all=True, append_images=images[1:], duration=100, loop=0)
Output:

How do I get a fill_between shape in Funcanimation?

I would like to make a moving plot where the area under the curve gets colored while the curve is getting plotted.
I have googled a bit and found that I should somehow create a patch. However, I do not understand any of the examples they give, so let me ask it here with my specific example:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import pylab as p
data = np.loadtext('datafile.dat', delimiter=',')
A = data[:,1]
B = data[:,2]
fig = plt.figure(figsize=(25,5), dpi=80)
ax = plt.axes(xlim=(0, 3.428), ylim=(-1,1))
line, = ax.plot([], [], lw=5)
def init():
line.set_data([], [])
return line,
def animate(i):
x = A[0:(i-1)*400]
y = B[0:(i-1)*400]
line.set_data(x,y)
# Here is the problem. I would now like to add the following line
# p.fill_between(x, 0, y, facecolor = 'C0', alpha = 0.2)
return line,
anim = animation.FuncAnimation(fig,animate, init_func=init, frames = 857, interval=20, blit=True)
I hope someone can give me a solution for my problem or at least point me in the correct direction.
So my question would be: how can I add the commented part without any errors?
Assuming you want blit = True, you will need to return the patch produced by fill_between as well.
p = plt.fill_between(x, y, 0)
return line, p,
Complete working example:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
X = np.linspace(0,3.428, num=250)
Y = np.sin(X*3)
fig = plt.figure(figsize=(13,5), dpi=80)
ax = plt.axes(xlim=(0, 3.428), ylim=(-1,1))
line, = ax.plot([], [], lw=5)
def init():
line.set_data([], [])
return line,
def animate(i):
x = X[0:(i-1)]
y = Y[0:(i-1)]
line.set_data(x,y)
p = plt.fill_between(x, y, 0, facecolor = 'C0', alpha = 0.2)
return line, p,
anim = animation.FuncAnimation(fig,animate, init_func=init,
frames = 250, interval=20, blit=True)
plt.show()

Plot a graph point to point python

I wonder if there is some way to plot a waveform point to point at a certain rate through the matplotlib so that the graph appears slowly in the window. Or another method to graph appears at a certain speed in the window and not all the points simultaneously. I've been tried this but I can only plot a section of points at a time
import numpy as np
import matplotlib.pyplot as plt
import time
x = np.arange(0,5,0.001)
y = np.sin(2*np.pi*x)
ind_i = 0
ind_f = 300
while ind_f <= len(x):
xtemp = x[ind_i:ind_f]
ytemp = y[ind_i:ind_f]
plt.hold(True)
plt.plot(xtemp,ytemp)
plt.show()
time.sleep(1)
ind_i = ind_f
ind_f = ind_f + 300
You can also do this with Matplotlib's FuncAnimation function. Adapting one of the matplotlib examples:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.arange(0,5,0.001)
y = np.sin(2*np.pi*x)
def update_line(num, data, line):
line.set_data(data[..., :num])
return line,
fig = plt.figure()
data = np.vstack((x,y))
l, = plt.plot([], [], 'r-')
plt.xlim(0, 5)
plt.ylim(-1, 1)
line_ani = animation.FuncAnimation(fig, update_line, frames=1000,
fargs=(data, l), interval=20, blit=False)
plt.show()

Categories