Animated graph using matplotlib issue? - python

I am trying to plot an animated graph for some data I have.The code works perfectly fine but I would like to see the line going down slowly and in steps.I tried adjusting the interval but it plots too fast.Can anyone tell me where I am doing wrong?The code is below
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
max_x = 12
max_rand = 0.5
x = np.arange(0, max_x)
ax.set_ylim(0, max_rand)
line, = ax.plot([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [0.2993408770000, 0.2861708408982, 0.2798758117082,
0.2798758117081, 0.2576574556766,
0.2569827358085, 0.2462213069654, 0.2461901361123,
0.2455803085695, 0.2455803085695, 0.2455803085695,
0.2455803085695])
def init(): # give a clean slate to start
line.set_ydata([np.nan] * len(x))
return line,
def animate(i): # update the y values (every 1000ms)
line.set_ydata(np.array([0.2993408770000, 0.2861708408982, 0.2798758117082,
0.2798758117081, 0.2576574556766,
0.2569827358085, 0.2462213069654, 0.2461901361123,
0.2455803085695, 0.2455803085695, 0.2455803085695,
0.2455803085695]))
return line,
ani = animation.FuncAnimation(
fig, animate, init_func=init, interval=1000, blit=True, save_count=5)
plt.show()

You're not changing the position of y inside the animate function, so there will be no movement. You would need to change the position depending on the input parameter i.
In the code below, there is a y0 representing a starting position (for example zero), and y1 represents the end position. The variable numsteps controls in how many steps the curve moves from the starting to the final position. The interval is lowered to get a smoother animation.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
max_x = 12
max_rand = 0.5
num_steps = 200
x = np.arange(0, max_x)
# y0 : starting position of the curve
y0 = x*0
# y1 : final position of the curve
y1 = np.array([0.2993408770000, 0.2861708408982, 0.2798758117082, 0.2798758117081, 0.2576574556766, 0.2569827358085,
0.2462213069654, 0.2461901361123, 0.2455803085695, 0.2455803085695, 0.2455803085695, 0.2455803085695])
ax.set_ylim(0, max_rand)
line, = ax.plot(x, y0, color='crimson')
def init(): # give a clean slate to start
line.set_ydata(np.full_like(x, np.NaN))
return line,
def animate(i): # update the y values (every 100ms)
line.set_ydata(y0 * (1 - i / num_steps) + y1 * i / num_steps)
return line,
ani = animation.FuncAnimation(
fig, animate, init_func=init, interval=100, blit=True, save_count=5, frames=num_steps, repeat=False)
plt.show()

Related

Creating Multi-Scene Animation using consecutive calls to Matplotlib.FuncAnimation creates flickered images

Context: I am trying to create a teaching demo tool to show how the iteration guesses through a set of points to ultimately arrive at the root of an equation
Problem: I want to animate using matplotlib to show the iterations viusally. Specifically, given a curve (see along side) and an initial guess (say 1.5 in this particular case), I want to compose an animation of 3 scenes:
draw a vertical line at x = guess (=1.5), to meet the curve at y= 9 (aka value).
Draw a line through (guess, value) with a slope 'm' (generated by my code). Delete the vertical line at this stage and keep the second line
Delete the second line after a pause
For illustration, here is the image
Additionally here is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
xdata2, ydata2 = [], []
ln, = plt.plot([], [])
def init():
ax.set_xlim(-3, 3)
ax.set_ylim(-10, 10)
return [ln]
def update(frame):
xdata.append(frame)
ydata.append(frame ** 3 + 4 * frame ** 2 + frame - 6)
ln.set_data(xdata, ydata)
return [ln]
def update2(frame):
xdata2.append(1.5)
ydata2.append(frame)
ln.set_data(xdata2,ydata2)
return[ln]
ani = FuncAnimation(fig, update, frames=np.linspace(-3, 3, 100),
init_func=init, blit=True)
ani2 = FuncAnimation(fig, update2, frames=np.linspace(0, 3, 100),blit=True)
plt.show()
This is a simplified version of the problem that I am trying to solve and is not part of the code that involves the calculation of the iterations etc. For now I am just trying to draw the curve in Update and post that, draw a vertical line at x=1.5.
Results: At my end, the entire animation is a set of flickering where it is apparent that matplotlib switches "thread context" very rapidly between the two FuncAnimation calls
The desired animation in your next question can be achieved in the form of drawing a curve as a base graph, adding line graphs frame by frame, and deleting that graph object when necessary.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import time
fig, ax = plt.subplots()
x = np.linspace(-3, 3, 100)
y = x ** 3 + 4 * x **2 + x -6
xx = x[74]
yy = y[74]
#print(xx,yy)
xx2 = x[65]
yy2 = y[65]
#print(xx2,yy2)
ln, = ax.plot(x, y)
ln2, = ax.plot([], [])
ln3, = ax.plot([],[])
ax.set_xlim(-3, 3)
ax.set_ylim(-10, 10)
# Move axes center and spines off
ax.spines[['top', 'right']].set_visible(False)
ax.spines[['left', 'bottom']].set_position('center')
# Show ticks axes only
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
def update(i):
ln2.set_data((xx, xx), (0, yy))
ln2.set_color('k')
if i == 2:
ln3.set_data((xx2, xx), (yy2, yy))
ln3.set_color('red')
ln3.set_width=3
if i >=3:
ln2.set_data([],[])
ln3.set_data([],[])
return ln2,ln3
ani = FuncAnimation(fig, update, frames=[0,1,2,3], interval=500, blit=True, repeat=True)
plt.show()

I want to animate the trajectory of a ball (really just a circle) using Matplotlib animation

I want to animate the trajectory of a circle (ball) defined by y = -t^2 + 11t - 18. Basically it would just be bouncing up and down (i.e. no change in x). Its intercepts are (2,0) and (9,0) so the animation should start at time t = 2 as it leaves the ground and end at time t = 9 as it returns to the ground. I am also hoping that a running display of the time could also be included in the animation. So basically between times t=0 and t=2, the ball would just be on the ground. This is the code I have so far but it doesn't seem to make sense. I'm not sure whether the animation is just going too fast.
%matplotlib notebook
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(3, 3)
ax = plt.axes(xlim=(0, 10), ylim=(0, 15))
patch = plt.Circle((5, 0), 0.2, fc='r')
def init():
patch.center = (5, 0)
ax.add_patch(patch)
return patch,
def animate(i):
x, y = patch.center
x = 0 * i+5
y = - i**2 + 11 * i - 18
patch.center = (x, y)
return patch,
anim = animation.FuncAnimation(fig, animate,
init_func=init,
frames=3600,
interval=1,
blit=True)
plt.show()

altering the size of a marker moving in a line in animated line plot

In a Python/matplotlib program I am trying to alter the size of the marker in the animated plot to show the magnitude of an array with python.
In this code if the marker moves to x[i],y[i] the size of the marker should be s[i]. Which means the size of the marker at point x[i],y[i] should show the value of s[i] at that point. Any suggestion on how to animate such a plot would be appreciated.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(0, 10, 100)
y = np.sin(x)
s = np.random.randint(10,20,100)
fig, ax = plt.subplots()
scat, = ax.plot(x[0], y[0], 'o', markersize = s[0])
def update(i, x, y, scat):
scat.set_data(x[i], y[i])
scat.axes.axis([0, 10, -1, 1])
return scat,
ani = animation.FuncAnimation(fig, update, len(x), fargs=[x,y, scat],
interval=25, blit=False)
plt.show()*
The function set_markersize in matplotlib.lines.Line2D allows for allows for updating the marker size just like updating the data:
def update(i, x, y, scat):
scat.set_data(x[i], y[i])
scat.set_markersize(s[i])
scat.axes.axis([0, 10, -1, 1])
return scat,

How to change speed in FuncAnimation

basically I am trying to have a sine wave be displayed by matplotlib and then when a certain x value is reached (block_start_pos) for the animation speed to change (slow down in this case). I understand that FuncAnimation repeatedly calls update_plot based on the given parameters but I was wondering if there was a way to change the interval mid animation. My code (mostly taken from a youtube video) is shown below. Thanks!
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import tkinter as tk
x = np.arange(0, 10*np.pi, 0.01)
index_of_refraction = 10
index_of_refraction_lst = [1, 200, 3, 4, 5]
medium = 20*index_of_refraction
w = 1
y = np.cos(w*x)
fig = plt.figure()
ax = plt.subplot(1, 1, 1)
data_skip = 50
block_start_pos = 6*np.pi
def init_func():
ax.clear()
plt.xlabel('pi')
plt.ylabel('sin(pi)')
plt.xlim((x[0], x[-1]))
plt.ylim((-1, 1))
def update_plot(i):
ax.plot(x[i:i+data_skip], y[i:i+data_skip], color='k')
ax.scatter(x[i], y[i], marker='o', color='r')
return medium_test(i)
def medium_test(i):
if x[i] > block_start_pos:
index_of_refraction = index_of_refraction_lst[1]
medium = 20*index_of_refraction
medium = 20*index_of_refraction
anim = FuncAnimation(fig,
update_plot,
frames=np.arange(0, len(x), data_skip),
init_func=init_func,
interval=medium)
plt.show()
# anim.save('sine.mp4', dpi=150, fps = 30, writer='ffmpeg')```

Animation with matplotlib where points are dynamically added to a graph

I've written a simple code which generates random points (x0, y0) between certain values using a while loop. After the coordinates of each point are set, that point is drawn in an empty graph which is showed at the end of the while loop.
However, I would like to set up an animation with matplotlib which would allow me to see the initial graph and the points progressively added to it as the code is calculating them. I've looked for some examples but the ones I found are mainly concerned with waves and so on and I guess I need a slightly different approach.
This is the basic code:
from numpy import *
from pylab import *
import random
figure(figsize=(8,6), dpi=150)
x = np.linspace(-1, 4.5, 250)
h=5
a=0.5
b=4
ylim(-0.5,5.5)
xlim(-1,5.0)
i= 0
while i< 500:
R1 = random.random()
R2 = random.random()
x0 = (b - a)*R1 + a
y0 = h*R2
scatter(x0, y0, 10, color="red")
i = i + 1
show()
Thanks for your help!
EDIT: ANIMATION CODE
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
import matplotlib.animation as animation
import random
fig = plt.figure(figsize=(8,6), dpi=150)
x = np.linspace(-2, 4.5, 250)
h=4
a=1
b=3
hlines(y=h, xmin=1, xmax=3, linewidth=1.5)
vlines(x=a, ymin=0, ymax=4, linewidth=1.5)
vlines(x=b, ymin=0, ymax=4, linewidth=1.5)
ylim(-2.5,10.5)
xlim(-2.5,4.5)
grid()
def data_gen():
i = 0
while i< 1:
R1 = random.random()
R2 = random.random()
x0 = (b - a)*R1 + a
y0 = h*R2
i = i + 1
yield x0, y0
line, = plot([], [], linestyle='none', marker='o', color='r')
ax = gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
xdata, ydata = [], []
def run(data):
x0,y0 = data
xdata.append(x0)
ydata.append(y0)
line.set_data(xdata, ydata)
return line,
ani = animation.FuncAnimation(fig, run, data_gen, blit=True, interval=0.5,
repeat=False)
plt.show()
I do not know if this is exactly what you are looking for; in any case, you can generate random points inside the run function and there plot them. You do not need neither blit = True nor clear the axis from one frame to another.
Here is my code:
from pylab import *
from matplotlib.animation import FuncAnimation
import random
fig = plt.figure(figsize=(8,6), dpi=150)
x = np.linspace(-2, 4.5, 250)
h=4
a=1
b=3
hlines(y=h, xmin=a, xmax=b, linewidth=1.5)
vlines(x=a, ymin=0, ymax=h, linewidth=1.5)
vlines(x=b, ymin=0, ymax=h, linewidth=1.5)
ylim(-2.5,10.5)
xlim(-2.5,4.5)
grid()
ax = gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
def run(i):
R1 = random.random()
R2 = random.random()
x0 = (b - a)*R1 + a
y0 = h*R2
ax.scatter(x0, y0, 10, color='red')
ani = FuncAnimation(fig = fig, func = run, frames = 500, interval = 10, repeat = False)
plt.show()
which produces this animation:
(I cut this animation to 100 points in order to get a lighter file, less than 2 MB; the code above produces an animation wiht 500 points)

Categories