Search code examples
pythonmatplotlib-animation

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:

  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


Solution

  • 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