Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider widget not updating when using multiple slider plots in a jupyter notebook #319

Closed
chw90 opened this issue Apr 21, 2021 · 3 comments

Comments

@chw90
Copy link

chw90 commented Apr 21, 2021

When creating multiple plots in a notebook from a function call that each have a slider widget, the sliders become completely unresponsive when I change them fast and alternate between adjusting the sliders of different plots.

Here an example to reproduce (I took the plot code from https://matplotlib.org/stable/gallery/widgets/slider_demo.html and stuffed it in a function without changing anything else):

  1. Paste this into the first cell of a clean jupyter notebook:
%matplotlib ipympl

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

def slider_plot():
    # The parametrized function to be plotted
    def f(t, amplitude, frequency):
        return amplitude * np.sin(2 * np.pi * frequency * t)

    t = np.linspace(0, 1, 1000)

    # Define initial parameters
    init_amplitude = 5
    init_frequency = 3

    # Create the figure and the line that we will manipulate
    fig, ax = plt.subplots()
    line, = plt.plot(t, f(t, init_amplitude, init_frequency), lw=2)
    ax.set_xlabel('Time [s]')

    axcolor = 'lightgoldenrodyellow'
    ax.margins(x=0)

    # adjust the main plot to make room for the sliders
    plt.subplots_adjust(left=0.25, bottom=0.25)

    # Make a horizontal slider to control the frequency.
    axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
    freq_slider = Slider(
        ax=axfreq,
        label='Frequency [Hz]',
        valmin=0.1,
        valmax=30,
        valinit=init_frequency,
    )

    # Make a vertically oriented slider to control the amplitude
    axamp = plt.axes([0.1, 0.25, 0.0225, 0.63], facecolor=axcolor)
    amp_slider = Slider(
        ax=axamp,
        label="Amplitude",
        valmin=0,
        valmax=10,
        valinit=init_amplitude,
        orientation="vertical"
    )


    # The function to be called anytime a slider's value changes
    def update(val):
        line.set_ydata(f(t, amp_slider.val, freq_slider.val))
        fig.canvas.draw_idle()


    # register the update function with each slider
    freq_slider.on_changed(update)
    amp_slider.on_changed(update)

    # Create a `matplotlib.widgets.Button` to reset the sliders to initial values.
    resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')


    def reset(event):
        freq_slider.reset()
        amp_slider.reset()
    button.on_clicked(reset)

    plt.show()
  1. Define two more cells, containing the call slider_plot()

  2. Run. Adjust one of the sliders of each plot quickly, then go to the second plot and do the same. After going back and forth a few times, the sliders will freeze and not do anything anymore.

The unresponsive plots may be "revived" by reevaluating the respective cell, but this is an annoying workaround for my usecase.

@ianhi
Copy link
Collaborator

ianhi commented Apr 21, 2021

If I add a block=False to your plt.show call then I can replicate this in terminal ipython which means that this is either:

  1. An issue with core matplotlib
  2. Something funny going on with keeping references to the callbacks and figures.

I suspect that second is the root cause. Can you try to replicate either from ipython or from a script? If you can I'd recommend closing this and asking about how to deal with this on https://discourse.matplotlib.org/ (you'll get more eyes on the issue there)

@chw90
Copy link
Author

chw90 commented Apr 21, 2021

Thanks for looking into it! Yes, I can replicate what you described in an ipython shell. I'll open a ticked over at matplotlib then :) .

@chw90 chw90 closed this as completed Apr 21, 2021
@chw90
Copy link
Author

chw90 commented Apr 22, 2021

Turns out this problem is avoided by keeping references to the slider instances of every plot (e.g. by returning them from the slider_plot() and binding to a variable). See here: matplotlib/matplotlib#3105

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants