-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add a backend kwarg to savefig. #15536
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
Conversation
Notionally 👍 one slight behavior question. Adding a the new parameter which is sometimes None first is a bit odd to me, but I see the argument for that as it is consulted first. |
backend has priority over fmt, so that's why I put them in this order (also, it's private API anyways). |
I'm a bit hesitant. A backend parameter in
|
6650f21
to
f647d15
Compare
lib/matplotlib/backend_bases.py
Outdated
else: | ||
# Return a default canvas for the requested format, if it exists. | ||
canvas_class = get_registered_canvas_class(fmt) | ||
if not hasattr(canvas_class, f"print_{fmt}"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is in the wrong block of the if/elif/else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That probably means that a unit test should be written for this :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough, done
f647d15
to
7852a8f
Compare
re @timhoffm:
I believe not (the backend-dependent logic is in draw(), which is only called by savefig()).
Backend switching is subject to the same rules as use() (i.e. you cannot switch to an interactive backend requiring a GUI event loop once another GUI event loop is running). But switching to a noninteractive backend is fine (and the intended use case) -- note that we already implicitly do so for printing to pdf/ps/svg; this kwarg only makes it explicit and allows you to switch to backend_pgf rather than backend_pdf when printing to pdf.
I don't think there is anything else one would want to do within the context manager other than doing the save, which suggests that factoring out the backend switching is not worth it.
This has been added per @tacaswell's suggestion. |
@anntzer thanks for the clarification.
Are use cases affected that use an intermediate draw to get some position information and use that to position subsequent elements?
Something like this should be explicitly mentioned in the docstring of the backend parameter; maybe even with a list of supported builtin backends. The other points are ok. |
You'd run into the same issues (if any) as if saving to pdf from an interactive canvas, so nothing new.
done. |
7852a8f
to
9fd5da5
Compare
@anntzer Thanks for this work! Does the PR include a |
It doesn't and fwiw I still don't like the idea. |
9fd5da5
to
d001e38
Compare
lib/matplotlib/backend_bases.py
Outdated
backend : str, optional | ||
When set, forcibly use this non-interactive backend for rendering. | ||
This can be either a standard backend name ("agg", "pdf", "pgf", | ||
"ps", "svg") or a custom backend name ("module://..."). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use a comment as to why we would ever want to do this. I'm not sure I understand from the PR what the goal is, so I can imagine users trying to dutifully use this keyword and getting themselves into a mess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
d001e38
to
ab74e58
Compare
lib/matplotlib/backend_bases.py
Outdated
"ps", "svg") or a custom backend name ("module://..."). The main | ||
use case of this parameter is to render to a format using a backend | ||
that is neither the current backend, nor the default backend for | ||
this format, e.g. for rendering pdfs using the pgf backend. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not clear. Are there other examples, like cairo instead of agg etc? If there is just one use case, I don't think this should get such a generic sounding kwarg name. If there are other cases, I'm confused about which ones are allowed. If I save to png, can I use pgf? Can I use the pdf backend to save to svg? Where are the compatibilities documented?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, you can also use cairo (either the builtin, so "cairo", or mplcairo ("module://mplcairo.base")) to save to any format.
For the builtin backends the compat table is at https://matplotlib.org/devdocs/tutorials/introductory/usage.html#the-builtin-backends (except that pgf is missing -- will open a separate PR for that -- now at #15555).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, thats more clear. I wonder if we change the kwarg to renderer
and refer to this table somehow?
renderer: str, optional
Use a non-default backend to render the file, i.e. `renderer='cairo'` for a png
rather than the default 'agg' backend, or 'pgf' for a PDF instead of the default 'pdf'.
See :doc:`/tutorials/introductory/usage` for a list of valid backends for each file format.
Note custom backends can be referenced as "module://...".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW just to be clear, I'm balking at "backend" because the user will already have likely been subjected to the confusing idea that they have to select a backend, and then see this kwarg and assume the have to make it match up somehow. I think we should try and be clear that 99.9% of the time the user should not need to use this kwarg.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc sounds good, mostly used your suggestion with minor edits.
The argument matches the argument to matplotlib.use()
, so I think it makes sense to keep the same argument name, so I'd still prefer backend
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and added "Note that the default backend is normally sufficient."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good (though you didn't push anything yet, right?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, missed the push, done now
ab74e58
to
bfe34be
Compare
Doc failures look real:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 modulo fixing the doc build
This makes it easier e.g. to test the pgf backend without globally switching the backend.
bfe34be
to
154a312
Compare
doc build fixed |
This makes it easier e.g. to test the pgf backend without globally
switching the backend.
Makes it easier to work on pgf related issues; also helps with #13994 (attn @ArchangeGabriel; see changelog).
PR Summary
PR Checklist