Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Reset matplotlib using rc_file_defaults, not rcdefaults. #280

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

Closed
wants to merge 1 commit into from

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Aug 1, 2017

rcdefaults() restores the internal defaults of matplotlib.
rc_file_defaults() restores to whatever was loaded when matplotlib was
first imported, which includes settings from the user's matplotlibrc,
and can be different.

Before this PR, the first item generated by the gallery uses the user's
matplotlibrc whereas all others uses the internal default one.

Alternatively, you may decide that s-g should always ignore the user's
matplotlibrc (although it would still be nice to provide some way to
customize the defaults), in which case a call to rcdefaults() should be
added before the first example is generated (for example, it the call
could just happen before every example rather than after every example).

rcdefaults() restores the internal defaults of matplotlib.
rc_file_defaults() restores to whatever was loaded when matplotlib was
first imported, which includes settings from the user's matplotlibrc,
and can be different.

Before this PR, the first item generated by the gallery uses the user's
matplotlibrc whereas all others uses the internal default one.

Alternatively, you may decide that s-g should always ignore the user's
matplotlibrc (although it would still be nice to provide some way to
customize the defaults), in which case a call to rcdefaults() should be
added before the first example is generated (for example, it the call
could just happen before every example rather than after every example).
@lesteve
Copy link
Member

lesteve commented Aug 1, 2017

This looks fine to me.

I think using the user's matplotlib default is what should happen. Basically I expect the same plots to show up whether I run the example with ipython or generate the doc with sphinx-gallery.

I'll wait for second opinions and merge if there is no complaint.

FWIW I checked and rc_file_defaults has been there for a while (I could find it mentioned in the 1.2.1 doc) so this does not pose any problem with old matptlotlib versions.

@Titan-C
Copy link
Member

Titan-C commented Aug 1, 2017

I use this patch as well in my personal config, I find it extremely useful. Nevertheless as already discussed in #235, I don't think we(as Sphinx-Gallery) have agreed on setting our personal defaults over the matplotlib defaults. The reason for that is that Sphinx-Gallery is aimed for teaching purposes, and when people copy the code presented in the examples and does not get the same output they might be confused. I rarely ever meet people that tinker with the defaults, even when the software comes with bad defaults.

@lesteve
Copy link
Member

lesteve commented Aug 1, 2017

I have to admit I am not sure which way we should go on this one.

Either we take the user perspective. In my mind he is very unlikely to have a matplotlibrc. So going with matplotlib default seems more natural.

Or we take the developer (aka documentation producer) perspective. He may have a matplotlibrc (to be honest I am not sure how many people bother with this). Going with user defaults seems more natural since running the example locally and sphinx-gallery will produce identical plots.

So basically with @Titan-C's input and thinking a bit more about it, I am slightly leaning towards surprising the developer rather than the user, so I would be in favour with matplotlib's default aka plt.rcdefaults.

If we agree on this, we should fix this as reported by @anntzer:

Before this PR, the first item generated by the gallery uses the user's
matplotlibrc whereas all others uses the internal default one.

To be perfectly honest, I never felt the need to tweak my matplotlibrc so I'd be happy to hear what people do with it :-).

@choldgraf
Copy link
Contributor

My 2 cents: we should use matplotlib's defaults and tell people to override these in conf.py or something like this. Otherwise I envision we'll create confusion in multi-developer projects (e.g., 10 people, each have their own matplotlib config, each would see something different when they build the gallery)

To be perfectly honest, I never felt the need to tweak my matplotlibrc so I'd be happy to hear what people do with it :-).

90% of my usecase is in re-setting the default backend so that my computer doesn't break when I import pyplot :-)

@larsoner
Copy link
Contributor

larsoner commented Aug 1, 2017

So basically with @Titan-C's input and thinking a bit more about it, I am slightly leaning towards surprising the developer rather than the user, so I would be in favour with matplotlib's default aka plt.rcdefaults.

This sounds reasonable to me. It also shouldn't be too painful to expose some conf parameter to control whether the mpl-defaults or user-defaults are used.

@anntzer
Copy link
Contributor Author

anntzer commented Nov 17, 2017

Thinking about it again, I think it is correct to apply the file defaults, while the docs should encourage devs to add a (empty or not) matplotlibrc file to the source directory (https://matplotlib.org/users/customizing.html#the-matplotlibrc-file): this file will override any system wide config.

@lesteve
Copy link
Member

lesteve commented Nov 17, 2017

Trying to remember this, my opinion is still the same as #280 (comment):

  • we should keep plt.rcdefaults. As I said above I'd rather surprise the developer generating the documentation than the user copying and pasting the snippet from the website and expecting the same plots to show up. Maybe we can document that .matplotlibrc is not used because examples should be considered as completely stand-alone.
  • there seems to be a bug if I understand @anntzer correctly: the first plot use .matplotlibrc and all the others don't. We should fix that and the first plot should use the matplotlib defaults like all the others.

@lesteve
Copy link
Member

lesteve commented Nov 17, 2017

@anntzer out of curiosity what do you use your .matplotlibrc for?

@larsoner
Copy link
Contributor

we should keep plt.rcdefaults.

How about the order be:

  1. use .matplotlibrc in doc root
  2. if not found, fall back to plt.rcdefaults

This would allow setting the style on a project-level that plots the same way for everyone.

@lesteve
Copy link
Member

lesteve commented Nov 17, 2017

This would allow setting the style on a project-level that plots the same way for everyone.

Let's say I am a scikit-learn user. There is no reason I have the scikit-learn code checked out. I copy and paste the snippet from the examples website. I don't think your suggestion helps in this case.

@larsoner
Copy link
Contributor

Let's say I am a scikit-learn user. There is no reason I have the scikit-learn checked out. I copy and paste the snippet from the examples website. I don't think your suggestion helps in this case.

It works fine in this case, I think. The sklearn devs can choose to have no .matplotlibrc, or a blank one. The proposal will make it fall back to rcdefaults, which is what you want (for sklearn).

The advantage of this proposal (what @anntzer is suggesting) is that it allows additional, opt-in flexibility for devs who might put different weights on their gallery appearance vs copy-paste reproducibility, and thus want to use SG to choose to make their plots conform to some non-standard style. This comes at the cost (as you point out) of having users running the example not look the same unless they adopt the same .matplolibrc. As long as we add this caveat in the docs, I see no problem with it, as it's backward-compatible, opt-in behavior.

@lesteve
Copy link
Member

lesteve commented Nov 17, 2017

The advantage of this proposal (what @anntzer is suggesting) is that it allows additional, opt-in flexibility for devs who might put different weights on their gallery appearance vs copy-paste reproducibility, and thus want to use SG to choose to make their plots conform to some non-standard style. This comes at the cost (as you point out) of having users running the example not look the same unless they adopt the same .matplolibrc. As long as we add this caveat in the docs, I see no problem with it, as it's backward-compatible, opt-in behavior.

How likely is it that this feature is actually used? I think sphinx-gallery need to push back about micro-features like this, unless there is a clear-cut benefit. I have never felt the need for .matplotlibrc and I am really curious what kind of use cases it could be useful for in a sphinx-gallery context.

@larsoner
Copy link
Contributor

If the feature existed, I would probably add one to a few repos that made it so there were no top and right spines, for example, because I prefer it aesthetically (and also maybe add grid lines, etc.). To me the maintenance overhead for SG is low enough, and added flexibility high enough that it seems warranted. But I can live without it if others disagree.

@anntzer
Copy link
Contributor Author

anntzer commented Nov 17, 2017

These are there relevant parts of my matplotlibrc:

axes.formatter.use_mathtext: True # Because why not?
axes.formatter.useoffset: False   # I think the offset text makes axes less legible.
hist.bins: auto                   # Seems like a saner default.
image.cmap: cubehelix             # I like it better than viridis.
savefig.directory:                # Not relevant here, but better than ~ as default IMO.
savefig.transparent: True         # Generally useful when making slides.
path.simplify_threshold: .125     # Speed up plotting a little bit.

savefig.transparent is actually the setting that led me to notice this issue: the first figure of the gallery would end up being saved with a transparent background, which shows up as black on the webpage. It's actually not useful for s-g and I would not include it in the "local" matplotlibrc.

But I generally like the other settings (except that savefig.directory is also irrelevant for s-g) and I would be perfectly happy to prefix my examples with some text like "the figure was generated with the following (link) matplotlibrc settings in effect" (and live with the fact that a straight copy-paste of just the source does not produce exactly the same figure), rather than having to copy-paste it every time to the beginning of the source.

@GaelVaroquaux
Copy link
Contributor

GaelVaroquaux commented Nov 17, 2017 via email

@GaelVaroquaux
Copy link
Contributor

GaelVaroquaux commented Nov 17, 2017 via email

@anntzer
Copy link
Contributor Author

anntzer commented Nov 17, 2017

mpl_config is actually worse, isn't it? Now you actually need to edit the copy-pasted source to remove the import, or also download mpl_config into the right folder, to make the code run.
Using a local matplotlibrc, if you don't have it, you get a differently styled plot, but still a plot with the same semantic contents. It is the dev's (explicit!) choice to allow for that.

Indeed. Also, when maintaining software, the documentation generated
should be independent of the configuration file of whoever builds it.
It's bad for reproduciblity if it's not the case.

I agree that using the user matplotlibrc is error prone. Using the per-directory matplotlibrc, not so, as it'll be distributed with the source tree, which you are very likely to have if you are building the docs locally.

@larsoner
Copy link
Contributor

Also, when maintaining software, the documentation generated should be independent of the configuration file of whoever builds it. It's bad for reproduciblity if it's not the case.

@GaelVaroquaux to be clear in case you missed the latest proposal, it is to use a .matplotlibrc in the doc/ root (or possibly per-directory?) if it exists, which does satisfy this doc-building reproducibilty requirement. But it does still violate the user-copy-paste requirement.

@GaelVaroquaux
Copy link
Contributor

GaelVaroquaux commented Nov 17, 2017 via email

@anntzer
Copy link
Contributor Author

anntzer commented Nov 17, 2017

Actually, this discussion made me realize that I can just patch matplotlib.rcParamsDefault myself in conf.py if I really want to, which is just as good -- so we can do without that feature.
The remaining bug still stands, though.

@GaelVaroquaux
Copy link
Contributor

GaelVaroquaux commented Nov 17, 2017 via email

@lesteve
Copy link
Member

lesteve commented Nov 20, 2017

I am going to close this PR and open an issue about the bug that we should fix.

@larsoner
Copy link
Contributor

larsoner commented Aug 6, 2018

@anntzer this seems easily solvable by something I'm putting in #313 now (it was easy to add while refactoring other things)

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.

6 participants