Skip to content

[Bug]: matplotlib==3.5.2 breaks ipywidgets #23229

Closed
@TomBugnon

Description

@TomBugnon

Bug summary

After updating matplotlib to 3.5.2 (from 3.5.1) the display/updating of widgets created with ipywidgets is broken, at least for certain types of plots.
Update of print statements in response to moving the widgets works fine but the plot is not modified.

To reproduce:

  • dump the following into requirements.txt:

ipykernel
jupyterlab-widgets
ipywidgets
numpy
ipympl
matplotlib==3.5.2

  • conda create python=3.7 --name myenv & conda activate myenv & pip install -r requirements.txt
  • Run the code below in jupyter

Code for reproduction

from IPython.display import display
from ipywidgets import (
    FloatSlider,
    HBox,
    VBox,
    Layout,
    fixed,
    interactive_output,
)

class MiniRaster:
    def __init__(
        self,
    ):
        self._trains = [
            np.linspace(0, 10, 100), 
            np.linspace(0, 10, 1000)
        ]

    def _interact(self, ax, linewidth, xmax):
        if ax is None:
            fig, ax = plt.subplots()
        ax.cla()
        ax.eventplot(
            self._trains,
            linewidth=linewidth
        )
        plt.xlim(0, xmax)

        print('linewidth = ', linewidth)
        print('xmax = ', xmax)
        return ax

    def interact(self):
        fig, ax = plt.subplots()

        linewidth_slider = FloatSlider(
            min=0,
            max=10,
            step=1,
            value=1,
            description="width=",
            continuous_update=False,
            layout=Layout(width="95%"),
        )

        xmax_slider = FloatSlider(
            min=1,
            max=20,
            step=1,
            value=10,
            description="xmax=",
            continuous_update=False,
            layout=Layout(width="95%"),
        )

        ui = VBox([linewidth_slider, xmax_slider])

        out = interactive_output(
        # return interactive_output(
            self._interact,
            {
                "ax": fixed(ax),
                "linewidth": linewidth_slider,
                "xmax": xmax_slider
            },
        )
        display(ui, out)

raster = MiniRaster()

%matplotlib widget
raster.interact()

Actual outcome

image
Print statements follow the widgets, not the figure

Expected outcome

When pinning matplotlib version to 3.5.1, both the print statement and the figure follow the widgets

image

Additional information

This doesn't happen for all types of figures/widgets.
I'm at a loss as to why, but this snippet works fine for me for both versions

import ipywidgets as widgets

m = widgets.FloatSlider(min=-5,max=5,step=0.5, description="Slope")
c = widgets.FloatSlider(min=-5,max=5,step=0.5, description="Intercept")

# An HBox lays out its children horizontally
ui = widgets.HBox([m, c])

def plot(m, c):
    x = np.random.rand(10)
    y = m *x + c
    plt.cla()
    plt.plot(x,y)
    plt.show()

out = widgets.interactive_output(plot, {'m': m, 'c': c})

display(out, ui)

I had the same behavior on python3.7 and 3.10, and on VSCode jupyter and jupyter notebook.

conda == 4.11.0

Operating system

Ubuntu

Matplotlib Version

3.5.2

Matplotlib Backend

module://ipympl.backend_nbagg

Python version

3.10.4

Jupyter version

6.4.12

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions