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

[Bug]: Zoom und pan not working after writing pdf pages. #27865

Closed
Erwin-Wert opened this issue Mar 5, 2024 · 8 comments · Fixed by #27869
Closed

[Bug]: Zoom und pan not working after writing pdf pages. #27865

Erwin-Wert opened this issue Mar 5, 2024 · 8 comments · Fixed by #27869

Comments

@Erwin-Wert
Copy link

Erwin-Wert commented Mar 5, 2024

Bug summary

Ladies and Gentlemen,
Zoom und pan is not working after writing pdf pages.
Within matplotlib version 3.7.5 it is working.
In e.g. 3.8.3 it does not react any more.

Code for reproduction

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
filename = "test4.pdf"
with PdfPages(filename) as pdf:
    fig.show()
    pdf.savefig() # <== if you comment this line, then zoom is working fine. However it is not getting stored.

Actual outcome

zoom not possible

Expected outcome

zoom is possible

Additional information

In earlier versions it has been working fine.
It is also not working within jupyterlab.
It was testet in Spyder IDE 5.5.1 and IDLE(Python 3.12 64-bit)
I take the earlier matplotlib version instead.

Operating system

Windows 7,

Matplotlib Version

3.8.3

Matplotlib Backend

QtAgg

Python version

Python 3.12.2 64-bit

Jupyter version

4.1.2

Installation

pip

@Impaler343
Copy link
Contributor

Impaler343 commented Mar 6, 2024

I believe a more appropriate code for reproduction is:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages

filename = "test4.pdf"

with PdfPages(filename) as pdf:
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3], [4, 5, 6])
    pdf.savefig() # <== if you comment this line, then zoom is working fine. However it is not getting stored.

plt.show()

@Impaler343
Copy link
Contributor

Impaler343 commented Mar 6, 2024

To solve this issue, you just need to write plt.show() before saving the figure and pass the figure to the savefig() function. Like:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
filename = "test4.pdf"

with PdfPages(filename) as pdf:
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3], [4, 5, 6])
    plt.show()
    pdf.savefig(fig) # <== if you comment this line, then zoom is working fine. However it is not getting stored.

But you might have to undo changes that you did while inspecting the figure to save the original figure

@Impaler343
Copy link
Contributor

On another note,
image
The import statement is slightly incorrect from matplotlib.backends.backend_pgf import PdfPages and needs to be backend_pdf instead of backend_pgf. Is it recommended to open a PR in small changes like this one?

@QuLogic
Copy link
Member

QuLogic commented Mar 6, 2024

This bisects to a6230cc, or #25546, by @anntzer.

@QuLogic
Copy link
Member

QuLogic commented Mar 6, 2024

However, that appears to be exposing an existing different bug. For some reason, this context manager is not restoring the old canvas:

with cbook._setattr_cm(figure, canvas=FigureCanvasPdf(figure)):
figure.savefig(self, format="pdf", **kwargs)

QuLogic added a commit to QuLogic/matplotlib that referenced this issue Mar 6, 2024
Calling `FigureCanvasPdf(figure)` will call `figure.set_canvas(self)`,
meaning the `cbook._setattr_cm` context manager that wraps this change
will see the _new_ canvas, and the old canvas isn't restored.

Instead, just pass the `backend` parameter, as `savefig` already knows
how to correctly save and restore the canvas if it needs to change
backends.

Fixes matplotlib#27865
@QuLogic
Copy link
Member

QuLogic commented Mar 6, 2024

The import statement is slightly incorrect from matplotlib.backends.backend_pgf import PdfPages and needs to be backend_pdf instead of backend_pgf. Is it recommended to open a PR in small changes like this one?

That is not a typo; there are two PdfPages classes, one in the PDF backend and one in the PGF backend. That example uses the PDF backend, and the line is a cross-reference to the PGF backend.

@QuLogic QuLogic added this to the v3.9.0 milestone Mar 6, 2024
@Erwin-Wert
Copy link
Author

To solve this issue, you just need to write plt.show() before saving the figure and pass the figure to the savefig() function. Like:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
filename = "test4.pdf"

with PdfPages(filename) as pdf:
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3], [4, 5, 6])
    plt.show()
    pdf.savefig(fig) # <== if you comment this line, then zoom is working fine. However it is not getting stored.

But you might have to undo changes that you did while inspecting the figure to save the original figure

The code snippet was just used to reproduce the effect. The real application has multiple figures opened in a tkinter window. Then a function is called to export these figures to the pdf. After that I need the figures to be responsive to zoom and pan. Adding plt.show() opens an extra window with the figure. So this is not an option.

@Impaler343
Copy link
Contributor

To solve this issue, you just need to write plt.show() before saving the figure and pass the figure to the savefig() function. Like:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
filename = "test4.pdf"

with PdfPages(filename) as pdf:
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3], [4, 5, 6])
    plt.show()
    pdf.savefig(fig) # <== if you comment this line, then zoom is working fine. However it is not getting stored.

But you might have to undo changes that you did while inspecting the figure to save the original figure

The code snippet was just used to reproduce the effect. The real application has multiple figures opened in a tkinter window. Then a function is called to export these figures to the pdf. After that I need the figures to be responsive to zoom and pan. Adding plt.show() opens an extra window with the figure. So this is not an option.

What I collect from this is that the showing functionality must work after saving the figure. The initial code had a fig.show() function before saving the figure due to which I interpreted it in that way

Impaler343 pushed a commit to Impaler343/matplotlib that referenced this issue Mar 8, 2024
Calling `FigureCanvasPdf(figure)` will call `figure.set_canvas(self)`,
meaning the `cbook._setattr_cm` context manager that wraps this change
will see the _new_ canvas, and the old canvas isn't restored.

Instead, just pass the `backend` parameter, as `savefig` already knows
how to correctly save and restore the canvas if it needs to change
backends.

Fixes matplotlib#27865
Impaler343 pushed a commit to Impaler343/matplotlib that referenced this issue Mar 14, 2024
Calling `FigureCanvasPdf(figure)` will call `figure.set_canvas(self)`,
meaning the `cbook._setattr_cm` context manager that wraps this change
will see the _new_ canvas, and the old canvas isn't restored.

Instead, just pass the `backend` parameter, as `savefig` already knows
how to correctly save and restore the canvas if it needs to change
backends.

Fixes matplotlib#27865
Impaler343 added a commit to Impaler343/matplotlib that referenced this issue Mar 14, 2024
pin pytest

Deprecate plot_date

Correctly set temporary pdf/pgf backends

Calling `FigureCanvasPdf(figure)` will call `figure.set_canvas(self)`,
meaning the `cbook._setattr_cm` context manager that wraps this change
will see the _new_ canvas, and the old canvas isn't restored.

Instead, just pass the `backend` parameter, as `savefig` already knows
how to correctly save and restore the canvas if it needs to change
backends.

Fixes matplotlib#27865

Bump the actions group with 2 updates

Bumps the actions group with 2 updates: [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) and [scientific-python/upload-nightly-action](https://github.com/scientific-python/upload-nightly-action).

Updates `pypa/gh-action-pypi-publish` from 1.8.11 to 1.8.12
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@2f6f737...e53eb8b)

Updates `scientific-python/upload-nightly-action` from 0.3.0 to 0.5.0
- [Release notes](https://github.com/scientific-python/upload-nightly-action/releases)
- [Commits](scientific-python/upload-nightly-action@6e9304f...b67d7fc)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: scientific-python/upload-nightly-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>

Bump pydata-sphinx-theme to 0.15

Fix search button placement in navbar

Fix doc sidebar

Fix version switcher url for circleCI

Don't use custom CSS for announcement banner

Disable parallel build

Don't show doc source link

Add dtype/copy args to internal testing class

Use pybind11 string formatter for exception messages

This can eventually be replaced by `std::format` when we require C++20.

doc: add description of **kwargs usage to collections (matplotlib#27872)

* doc: add description of **kwargs usage to collections
* Update lib/matplotlib/collections.py

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>

---------

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>

TST: adding tests of current clear behavior on ticks

closes matplotlib#23839

DOC: update comments and docstrings

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>

Update lib/matplotlib/tests/test_axes.py

BLD,Cygwin: Included Python.h first in src/_c_internal_utils.cpp

Python.h needs to be included before any system includes.  This is easiest if it is the first include.  Interestingly, pybind11/pybind11.h does not include Python, possibly depending on downstream projects including Python.h beforehand.

CI: Include Python.h first in _tkagg.cpp

Needs to be included before system headers to set visibility macros for pybind11

BLD: Include Python.h first in _backend_agg.cpp

BLD: Include Python.h before pybind11/pybind11.h

pybind11 assumes Python.h is included first.

CI: Specify python version for default pytest.

CI,Cygwin: Run pytest with python -m pytest

Cygwin pytest recently updated, and only installs pytest-3.9

CI,Cygwin: Revert use of alternatives to set pytest script.

Cygwin pytest only installs pytest-3.9.
I should possibly suggest using alternatives for that and pip.

CI,Cygwin: Avoid running pytest in root directory.

CI,Cygwin: Revert running pytest in different directory.

CI,Cygwin: Call pytest-3.9 explicitly.

BLD: Include Python.h first in src/_path.h

BLD,BUG: Remove Python.h includes immediately preceeding pybind11/pybind11.h includes

pybind11 seems decent about including Python.h before any system headers, once you chase three layers of includes in to see that.

FIX: handle nans in RGBA input with ScalarMappables

DOC: Update some animation related topics

- use `set_data_3d`
- cross-reference `Line2d` `set_data`, `set_xdata`, `set_ydata`
- Rewrite parts of the FuncAnimation description

Inspired through matplotlib#27830.

Revert "Merge branch 'matplotlib:main' into doc-change"

This reverts commit feeabe6, reversing
changes made to bcbc2ef.

Reapply "Merge branch 'matplotlib:main' into doc-change"

This reverts commit ed91cee.

Convert path extension to pybind11

Add a pybind11 type caster for agg::rect_d

Add a pybind11 type caster for agg::trans_affine

Add a pybind11 type caster for mpl::PathIterator

Add a pybind11 type caster for e_snap_mode

Add a pybind11 type caster for SketchParams

Optimize convert_polygon_vector a bit

FIX: don't copy twice on RGB input

Fix devdocs version switcher

Allow passing a transformation to secondary_[xy]axis

Add transform argument to secondary axes

Update _secax_docstring

Move new params to end of functions

Add input check to secondary axes

Add tests

Add examples

Move transform type checks and improve docs

Add type stubs

Update _secax_docstring

Move new params to end of functions

Add input check to secondary axes

Move transform type checks and improve docs

Fix rebase error

Fix stub for SecondaryAxis.__init__

Clarify example

Add default param to secax constructor

Fix stub for secax constructor

Simplify imports

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

Remove redundancy in docs

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

Fix typo

DOC: fix stray release note entry

BLD: Add a fallback URL for FreeType

FreeType is available from both Savannah and SourceForge, and sometimes
AppVeyor seems to have trouble downloading from Savannah, so perhaps
this fallback will help. We used to try both these URLs in the pre-Meson
build system.

DOC: State approximate documentation build time

Since the doc build takes very long, an order-of-magnitude estimate
is helpful to manage expectations.

I'm not wedded to the actual numbers, if somebody has better
suggestions. A quick test on an old i7 6700 (from 2015) yielded

- `O=-j1`: 23min
- `O=-j4`: 15min

Doc build on CI is around 18min.

Add BackendRegistry singleton class

Use backend_registry for name of singleton instance

Use class variables for immutable collections

Review comments

Update lib/matplotlib/backend_bases.py

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>

Linting/mypy fixes

Remove INTERACTIVE_NON_WEB backend filter

Small changes from review

Use _api.caching_module_getattr for deprecated module-level attributes

Add docstrings

Add api changes and what new docs

Fix docs

Inline the deprecation function calls

Import BackendFilter and backend_registry into
matplotlib.backends.__init__.py

Mypy fixes

Remove unused _safe_pyplot_import

Remove unneeded type annotations

Make sure custom alpha param does not change 'none' colors in a list of colors (matplotlib#27845)

* fix issue 27839, make sure alpha param does not affect none colors
Apply review feedbacks

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>

* Update lib/matplotlib/colors.py

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

---------

Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

DOC: fix :mpltype:`color` role

`inline.interpreted()` already returns a list of nodes. We mustn't wrap
it in another list.

Use :mpltype:`color` for color types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants