pythonanimationjupyter-notebook

An iterative plot is not drawn in jupyter notebook while python works fine. Why?


I have written an iterative plot code for python using plt.draw(). While it works fine for python interpreter and ipython also, but it does not work in jupyter notebook. I am running python in virtualenv in Debian. The codes are

import matplotlib.pyplot as plt 
import numpy as np

N=5
x = np.arange(-3, 3, 0.01)
fig = plt.figure()
ax = fig.add_subplot(111)
for n in range(N):
    y = np.sin(np.pi*x*n)
    line, = ax.plot(x, y)
    plt.draw()
    plt.pause(0.5)
    line.remove()

This works fine in command line such as

$ python a.py

But, in jupyter notebook, it plots first figure and then, repeat <Figure size ... 0 Axes> for N-1 times, not drawing the new figure inside axis. It looks the problem of jupyter, because no problem in running python code. How can I fix this? Or plotly would work in jupyter? (N.B. I happen to find a jupyter community site and posted there also.)

result from jupyter notebook


Solution

  • Jupyter Notebook handles plot display differently. If you’re able to modify the code, you can try the following approach:

    %matplotlib widget
    
    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.animation import FuncAnimation
    
    # Parameters for the plot
    N = 5
    x = np.arange(-3, 3, 0.01)
    
    # Create a figure and axes
    fig, ax = plt.subplots()
    line, = ax.plot([], [], lw=2)  # Line object
    
    # Set the limits for the axes
    ax.set_xlim(-3, 3)
    ax.set_ylim(-1.5, 1.5)
    
    # Initialization function: called at the start
    def init():
        line.set_data([], [])
        return line,
    
    # Update function: called for each frame
    def update(n):
        y = np.sin(np.pi * x * n)  # Calculate sine wave
        line.set_data(x, y)        # Update line data
        return line,
    
    # Create the animation using FuncAnimation
    ani = FuncAnimation(fig, update, frames=N, init_func=init, blit=True, interval=500)
    

    This method works well for me in VSCode.

    If you want more control over the animation, you can display it directly in the Jupyter Notebook using:

    # Display the animation in the Jupyter notebook
    from IPython.display import HTML
    HTML(ani.to_jshtml())  # Render the animation as HTML/JS
    

    The frames parameter specifies the data passed to the update(n) function during each interaction step. Setting frames=N is equivalent to using frames=range(N). This operates similarly to the following loop:

    for n in range(N):
        update(n)
    

    For more details about FuncAnimation, please refer to the documentation at: https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html.