Skip to content

Fix plt.show() - #608

Open
nvaytet wants to merge 7 commits into
mainfrom
plt-show-fix
Open

Fix plt.show()#608
nvaytet wants to merge 7 commits into
mainfrom
plt-show-fix

Conversation

@nvaytet

@nvaytet nvaytet commented Sep 3, 2026

Copy link
Copy Markdown
Member

Fixes #607

@jokasimr

jokasimr commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Seems reasonable, but this is a test that fails on this branch but not on main:

  import matplotlib.pyplot as plt
  import scipp as sc

  sc.arange("x", 5.0).plot()
  plt.close("all")  # Should succeed; PR 608 raises AttributeError.

@nvaytet

nvaytet commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

@jokasimr I decided to just use plt.figure() in cases where we are not in the notebook.
Hope this fixes everything

@jokasimr

jokasimr commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Here's a test that AI found that passes on main but does not pass on this branch:

  import matplotlib.pyplot as plt
  import plopp as pp
  import scipp as sc


  def test_tiling_leaves_no_temporary_figures():
      plt.switch_backend("WebAgg")
      left = pp.tiled(1, 1)
      right = sc.arange("x", 5.0).plot()
      plt.close("all")              # Close the inputs.
      plt.close((left + right).fig) # Create and close the result.
      assert plt.get_fignums() == []

I've verified manually that this actually leaves a non-closed figure that is displayed the next time the user calls plt.show().

The issue

The issue: left + right creates an internal temporary figure. The PR registers that
figure with pyplot without closing it afterward. Even after closing both inputs and the
result, the temporary figure remains: the assertion fails with [1] == [], and plt.show()
would display it.

Difference between main and plt-show-fix:

  • main: Uses plt.Figure() and attaches a manager without registering it with pyplot.
    plt.show() ignores it—and also ignores the intended figures, which is the original
    bug.
  • plt-show-fix: Uses plt.figure(), which registers every figure with pyplot. That
    includes the internal temporary figure. It stays registered after the result is
    closed, so plt.show() displays an unwanted extra plot.

Possible fix

In Tiled.__add__ (src/plopp/backends/matplotlib/tiled.py:139), close the temporary figure:

  t = Tiled(1, 1)
  t[0, 0] = other
  plt.close(t.fig)  # Added
  other = t

Closing removes the figure from pyplot and closes its window. Its contents remain
available for copying into the final result.

Apply the same line to the temporary wrappers in __truediv__, hstack, and vstack—six
locations total.

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

Successfully merging this pull request may close these issues.

Matplotlib's plt.show() does not work

2 participants