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

Viewed 35

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:

  1. draw a vertical line at x = guess (=1.5), to meet the curve at y= 9 (aka value).
  2. 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
  3. Delete the second line after a pause For illustration, here is the image enter image description here

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

1 Answers

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()

enter image description here

Related