0
0
Matplotlibdata~20 mins

Interactive animation with widgets in Matplotlib - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Interactive Animation Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
Output of a simple interactive sine wave plot

What is the output of this code when you move the slider to change the frequency?

Matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x)

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
line, = ax.plot(x, y)
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03])
freq_slider = Slider(axfreq, 'Freq', 0.1, 5.0, valinit=1)

def update(val):
    freq = freq_slider.val
    line.set_ydata(np.sin(freq * x))
    fig.canvas.draw_idle()

freq_slider.on_changed(update)
plt.show()
AA plot of a sine wave that changes frequency smoothly as the slider moves
BA static sine wave plot that does not change when the slider moves
CA plot that shows a cosine wave instead of sine wave when slider moves
DAn error occurs because Slider is not imported
Attempts:
2 left
💡 Hint

Think about what the update function does when the slider value changes.

data_output
intermediate
2:00remaining
Number of frames updated in an interactive animation

Given this interactive animation code with a slider controlling the frame index, how many frames will be updated if the slider range is from 0 to 9?

Matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

frames = [np.sin(np.linspace(0, 2 * np.pi, 100) + i) for i in range(10)]

fig, ax = plt.subplots()
line, = ax.plot(frames[0])
ax_slider = plt.axes([0.25, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, 'Frame', 0, 9, valinit=0, valstep=1)

def update(val):
    frame = int(slider.val)
    line.set_ydata(frames[frame])
    fig.canvas.draw_idle()

slider.on_changed(update)
plt.show()
A100 frames will be updated because each frame has 100 points
B9 frames will be updated because the slider stops before 9
COnly 1 frame will be shown regardless of slider position
D10 frames will be updated as the slider moves from 0 to 9
Attempts:
2 left
💡 Hint

Check the slider range and how many frames are in the list.

🔧 Debug
advanced
2:00remaining
Identify the error in this interactive plot code

What error will this code raise when run?

Matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

fig, ax = plt.subplots()
line, = ax.plot(x, y)
ax_slider = plt.axes([0.25, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, 'Amplitude', 0.1, 2.0, valinit=1)

def update(val):
    amp = slider.val
    line.set_ydata(amp * np.sin(x))  # Fixed mistake here
    fig.canvas.draw_idle()

slider.on_changed(update)
plt.show()
AValueError because x and y data lengths do not match
BNo error, the plot updates correctly showing scaled sine wave
CTypeError because line.set_ydata expects array-like but gets a float array
DTypeError because multiplying float by numpy array is invalid
Attempts:
2 left
💡 Hint

Look carefully at what line.set_ydata is given compared to original y data.

visualization
advanced
2:00remaining
Effect of multiple sliders on a 2D plot

What will the plot show when two sliders control amplitude and frequency of a sine wave?

Matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

x = np.linspace(0, 2 * np.pi, 400)

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.35)
line, = ax.plot(x, np.sin(x))

ax_amp = plt.axes([0.25, 0.2, 0.65, 0.03])
ax_freq = plt.axes([0.25, 0.1, 0.65, 0.03])

slider_amp = Slider(ax_amp, 'Amplitude', 0.1, 2.0, valinit=1)
slider_freq = Slider(ax_freq, 'Frequency', 0.1, 5.0, valinit=1)

def update(val):
    amp = slider_amp.val
    freq = slider_freq.val
    line.set_ydata(amp * np.sin(freq * x))
    fig.canvas.draw_idle()

slider_amp.on_changed(update)
slider_freq.on_changed(update)
plt.show()
AA static sine wave plot that does not respond to sliders
BTwo separate plots, one for amplitude and one for frequency
CA sine wave plot that changes amplitude and frequency interactively as sliders move
DAn error because two sliders cannot update the same plot
Attempts:
2 left
💡 Hint

Think about how the update function uses both slider values.

🚀 Application
expert
3:00remaining
Creating an interactive animation with play/pause button and slider

Which code snippet correctly implements an interactive sine wave animation with a play/pause button and a slider controlling the frame?

A
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

x = np.linspace(0, 2 * np.pi, 100)
frames = [np.sin(x + i * 0.1) for i in range(100)]

fig, ax = plt.subplots()
line, = ax.plot(frames[0])
ax_slider = plt.axes([0.25, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, 'Frame', 0, 99, valinit=0, valstep=1)
ax_button = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(ax_button, 'Play')

playing = False

def update(val):
    frame = int(slider.val)
    line.set_ydata(frames[frame])
    fig.canvas.draw_idle()

slider.on_changed(update)

def play(event):
    global playing
    playing = not playing
    button.label.set_text('Pause' if playing else 'Play')

import matplotlib.animation as animation

def animate(i):
    if playing:
        frame = (int(slider.val) + 1) % 100
        slider.set_val(frame)

button.on_clicked(play)
ani = animation.FuncAnimation(fig, animate, interval=100)
plt.show()
B
)(wohs.tlp
)001=lavretni ,etamina ,gif(noitaminAcnuF.noitamina = ina
)yalp(dekcilc_no.nottub

)emarf(lav_tes.redils        
001 % )1 + )lav.redils(tni( = emarf        
:gniyalp fi    
:)i(etamina fed

noitamina sa noitamina.biltolptam tropmi

)'yalP' esle gniyalp fi 'esuaP'(txet_tes.lebal.nottub    
gniyalp ton = gniyalp    
gniyalp labolg    
:)tneve(yalp fed

)etadpu(degnahc_no.redils

)(eldi_ward.savnac.gif    
)]emarf[semarf(atady_tes.enil    
)lav.redils(tni = emarf    
:)lav(etadpu fed

eslaF = gniyalp

)'yalP' ,nottub_xa(nottuB = nottub
)]40.0 ,1.0 ,520.0 ,8.0[(sexa.tlp = nottub_xa
)1=petslav ,0=tinilav ,99 ,0 ,'emarF' ,redils_xa(redilS = redils
)]30.0 ,56.0 ,1.0 ,52.0[(sexa.tlp = redils_xa
)]0[semarf(tolp.xa = ,enil
)(stolpbus.tlp = xa ,gif

])001(egnar ni i rof )1.0 * i + x(nis.pn[ = semarf
)001 ,ip.pn * 2 ,0(ecapsnil.pn = x

nottuB ,redilS tropmi stegdiw.biltolptam morf
tlp sa tolpyp.biltolptam tropmi
pn sa ypmun tropmi
C
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

x = np.linspace(0, 2 * np.pi, 100)
frames = [np.sin(x + i * 0.1) for i in range(100)]

fig, ax = plt.subplots()
line, = ax.plot(frames[0])
ax_slider = plt.axes([0.25, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, 'Frame', 0, 99, valinit=0, valstep=1)
ax_button = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(ax_button, 'Play')

playing = False

def update(val):
    frame = int(slider.val)
    line.set_ydata(frames[frame])
    fig.canvas.draw_idle()

slider.on_changed(update)

def play(event):
    global playing
    playing = not playing
    button.label.set_text('Pause' if playing else 'Play')

import matplotlib.animation as animation

def animate(i):
    if playing:
        frame = (int(slider.val) + 1) % 100
        line.set_ydata(frames[frame])
        slider.set_val(frame)
        fig.canvas.draw_idle()

button.on_clicked(play)
ani = animation.FuncAnimation(fig, animate, interval=100)
plt.show()
D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

x = np.linspace(0, 2 * np.pi, 100)
frames = [np.sin(x + i * 0.1) for i in range(100)]

fig, ax = plt.subplots()
line, = ax.plot(frames[0])
ax_slider = plt.axes([0.25, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, 'Frame', 0, 99, valinit=0, valstep=1)
ax_button = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(ax_button, 'Play')

playing = False

def update(val):
    frame = int(slider.val)
    line.set_ydata(frames[frame])
    fig.canvas.draw_idle()

slider.on_changed(update)

def play(event):
    global playing
    playing = not playing
    button.label.set_text('Pause' if playing else 'Play')

import matplotlib.animation as animation

def animate(i):
    global playing
    if playing:
        frame = (int(slider.val) + 1) % 100
        slider.set_val(frame)

button.on_clicked(play)
ani = animation.FuncAnimation(fig, animate, interval=100)
plt.show()
Attempts:
2 left
💡 Hint

Check how the play/pause button toggles the animation and how the slider updates the frame.