Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add easy style sheet selection#2236

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
mdboom merged 36 commits intomatplotlib:masterfromtonysyu:stylesheets
Nov 18, 2013
Merged

Conversation

tonysyu
Copy link
Contributor

Add easy switching between rcParams based on the implementation inmpltools.style. Basically, just call

frommatplotlibimportstylestyle.use('ggplot')

... to switch to a style sheet that sort of mimics ggplot's style.

Notes:

  • In the current implementation, shipped style files are stored inmatplotlib/style/stylelib and user files are stored in~/.matplotlib/stylelib.
  • I chose*.mplrc as an extension for the style files, but I'm fine with changing that. Style files in the style libraries have the extension*.style*.mplstyle.
  • Ideally there would an rc parameter (or some other mechanism) to easily add search paths for style files
  • One thing I liked in the original implementation was the ability to chain style sheets, with each style sheet adding the parameters they set. The current implementation doesn't work like this becauserc_params_from_file initializes the defaultrcParams and then updates the defaults from the file. Thus, updating using the result fromrc_params_from_file will overwrite all values.

@dpsanders
Copy link

Fantastic news! - many thanks for this. 💯
Apologies for not pulling this in myself -- I am still getting to grips with the code.
(But glad that my "gentle" prodding worked ;) )

I suggest.style as the extension for the style files.

@dpsanders
Copy link

I merged your branch and installedmatplotlib, but there is nostyle submodule available to import frommatplotlib.

@dpsandersdpsanders mentioned this pull requestJul 21, 2013
@tonysyu
Copy link
ContributorAuthor

@dpsanders Most likely I should have added thestyle package to some list for installation. One of the matplotlib devs will have to enlighten me on where this would be.

BTW, it sounds like you might want to tweak your git workflow. You don't need to merge my branch to test it out (unless by merge, you meant pull). Just checkout the branch and test on there (never merge into master---only pull from the "official" master). This might be helpful:

https://gist.github.com/piscisaureus/3342247

Also, if you runpython setup.py develop, then you can avoid re-installing (unless there are compiled extensions) when testing out different branches.

@dpsanders
Copy link

On Sun, Jul 21, 2013 at 11:14 AM, Tony S Yunotifications@github.comwrote:

@dpsandershttps://github.com/dpsanders Most likely I should have added
the style package to some list for installation. One of the matplotlib
devs will have to enlighten me on where this would be.

I am a novice at this stuff, but a quick Google threw up this, which seems
to be the answer:

http://stackoverflow.com/questions/16020725/python-setup-install-one-module-as-a-sub-module-of-another-module

I'll give it a go

BTW, it sounds like you might want to tweak your git workflow. You don't
need to merge my branch to test it out (unless by merge, you meant pull).
Just checkout the branch and test on there (never merge into master---only
pull from the "official" master). This might be helpful:

https://gist.github.com/piscisaureus/3342247

Also, if you run python setup.py develop, then you can avoid
re-installing (unless there are compiled extensions) when testing out
different branches.

Ah, many thanks -- that will make my life much easier :)

D.


Reply to this email directly or view it on GitHubhttps://github.com//pull/2236#issuecomment-21312409
.

Dr. David P. Sanders

Profesor Titular "A" / Associate Professor
Departamento de Física, Facultad de Ciencias
Universidad Nacional Autónoma de México (UNAM)

dpsanders@gmail.com
http://sistemas.fciencias.unam.mx/~dsanders

Cubículo / office:#414, 4o. piso del Depto. de Física

Tel.: +52 55 5622 4965

@ChrisBeaumont
Copy link
Contributor

+1 on this

A few outsider thoughts

  1. It would be easy to extendstyle.use to accept paths or urls, in addition to style names. Urls would be especially nice, since people could peruse nbviewer/github for good styles, and try them out without remembering the search path forstyle.use.
  2. Since rcParams is essentially a dict, It would be easy to accept json style sheets (e.g.https://raw.github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/master/styles/bmh_matplotlibrc.json)
  3. Is it already possible to configure MPL to use a style by default? If not, perhaps there should be an rcParams option like 'style.default', to specify this?

@ChrisBeaumont
Copy link
Contributor

One other thought: if I'm parsing this correctly, it looks like styles update the current rcParams settings, but don't touch options that aren't specifically in the style sheet. I guess this enables the "chaining" behavior you talk about, but it also means that the state of rcParams after callingstyle.use is not always obvious. For example:

use('ggplot')  # image.cmap not modified, = 'jet'use('greyscale') # image.cmap = 'gray'use('ggplot') # image.cmap='gray'

It might be nice to have an option to explicitly set unspecified style options to a default (the obvious choice beingrcParamsDefault orrcParamsOrig).

if np.isscalar(name):
name = [name]
for s in name:
plt.rcParams.update(library[s])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This would benefit from a more helpful error message ifs not in library

@tonysyu
Copy link
ContributorAuthor

@ChrisBeaumont Thanks for the feedback!

It would be easy to extend style.use to accept paths or urls, in addition to style names.

That's a great idea. Done!

Since rcParams is essentially a dict, It would be easy to accept json style sheets

I'm going to punt on this idea. It'd be simple to use the json file to update the settings, but ideally, it would be run through the same validation mechanism as normal rc files. Unfortunately, that validation mechanism is a bit tangled with the parser at the moment. I don't think it'd be hard to fix, but I'm not jumping at the opportunity to fix it myself ;)

Is it already possible to configure MPL to use a style by default?

Yeah, I would stick to the standard~/.matplotlib/matplotlibrc file for this type of thing.

styles update the current rcParams settings, but don't touch options that aren't specifically in the style sheet. I guess this enables the "chaining" behavior you talk about, but it also means that the state of rcParams after calling style.use is not always obvious.

True. You can just callplt.rcdefaults() to do what you're suggesting. I'm thinking about addingstyle.reset() as an alias, but matplotlib already has too many names for the same thing so I'm hesitant.

@ChrisBeaumont
Copy link
Contributor

Good points.

My main reason for the suggestion about an rcParams-specified default style is to pave the way to change the defaults in MPL -- if users could add astyle.default : classic line to their rcParams, then they could maintain a stable set of rcParams even if the defaults change. From discussions on the mailing list, such functionality sounds like a prerequisite for any proposed change to the defaults.

import re

import numpy as np
import matplotlib.pyplot as plt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I hope you don't really need pyplot for this.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Good point. Fixed.

@efiring
Copy link
Member

On 2013/07/21 10:15 AM, Tony S Yu wrote:

You can just call |plt.rcdefaults()| to do what you're suggesting. I'm
thinking about adding |style.reset()| as an alias, but matplotlib
already has too many names for the same thing so I'm hesitant.

plt.rcdefaults() is part of the present confusing mess, with too many
rc* names that are too hard to remember and that don't clearly indicate
what they are or do. style.reset() is clearer, but I think we need to
think longer term, about how to improve the pyplot layer itself.

@mdboom
Copy link
Member

Thanks, Tony. This looks quite good. I'm going to second@ChrisBeaumont's suggestion that an rcParam to set the style would be good, to make the transition easier, as suggested. It's a tricky bootstrapping problem, however. If it's applied when it is read in, because then subsequent values in the matplotlibrc file would overwrite the style. Maybe that's correct, but it has potential for surprise and introduces some order-dependence on the rc files that we don't currently have. And then there's what to do with cyclical references to styles. All resolvable problems -- just tricky to get right I suspect.

I don't likestyle as an extension. It's too generic, and these files are very matplotlib-specific. I'd prefermplstyle (or something better than that).

I agree that we want two ways of applying styles: one for chaining styles over top of the existing settings, and one that resets and then applies the style. Not sure on the best way to present that.

@efiring: One of the complications with rcParams that has long irked me is that it combines style things with platform configuration. I've often felt that style belongs much closer to the plot -- not really in user-global configuration as we do now -- whereas the platform configuration stuff (which backend to use, and font formats to write out)do belong where they are. I'd love to see this separate out into two separate files (which would also solve the cyclical reference problem above, since the platform config would choose a style, but a style file could not choose another style (perhaps only inherit from another style). I don't think that would be hard to implement, but devising the right way to transition people is the hard part.

@ChrisBeaumont
Copy link
Contributor

@mdboom agreed, the bootstrapping issue seems a little awkward, with three layers to apply (default values, matplotlibrc values, default style). For compatibility, I think this order is needed to start

  1. rcParams populated withrcsetup.defualtParams
  2. matplotlibrc values applied
  3. default style applied in "implicit mode" (i.e. values not explicitly named are not overridden)

For now, the default style is an empty called 'classic'. If the default style changes, people have the option of switching back to 'classic' in matplotlibrc.

Long term, I agree it would be cleaner to pull the visual-level options out of defaultParams, and then load the default style in "explicit mode" (which applies the visual options currently in defaultParams). Likewise, matplotlibrc would not have visual-level options, so styles and matplotlibrc never conflict. The transition period would be awkward, however (you'd have to warn users that matplotlibrc values should not have visual level options, and then load them anyways after the default style is applied in explicit mode).

@@ -0,0 +1,2 @@
from core import *
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

is there a reason that this file doesn't just contain all the contents of core, instead of wildcard importing them?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Just a matter of style, I guess. I prefer__init__.py modules to be fairly lightweight, but if that's frowned upon, I'm fine with changing it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

also, aren't we doing the dot-style imports now? I also still don't like the import *.

@ivanov
Copy link
Member

I'm just jumping in here because it was mentioned on twitter, but will it be possible to either make a context manager for this, or re-use thewith mpl.rc_context(...) manager for this?

@mdboom
Copy link
Member

@ivanov: Good idea on the context manager.

Also, as a side note -- we should be able to wrap thexkcd command in this, and it wouldn't be a special one-off function any more.

@tonysyu
Copy link
ContributorAuthor

@ChrisBeaumont,@mdboom I'm convinced: It would be good to make style sheets an rcParam, but in the current state it'll be difficult to validate because of circular imports.

I'm guessing that I need to add the stylelib directory to some sort of package data field insetup.py, but it's not clear to me where.

Updates:

  • I added a context manager as suggested by@ivanov
  • I switched the extension to*.mplstyle.
  • Tests!

@WeatherGod
Copy link
Member

I am not yet convinced that having a style rcParam makes any sense.
Conceptually speaking, the matplotlibrc file is more like the style, and
having multiple versions of these files is like having multiple styles to
choose from. The circular logic involved in implementing a style rcParam
should be a huge red warning sign saying "you are thinking this wrong!".

Instead, why don't we jump on the other idea@mdboom had, which was the
separation of style-type parameters from the non-style type parameters
(like the default backend and such), and use the "style" parameter in that
configuration file to point to the desired configuration file that contains
the style parameters?

@mdboom
Copy link
Member

@WeatherGod: The tricky thing about my suggestion -- of separating style from other parameters -- is how best to transition to it, as@ChrisBeaumont pointed out:

The transition period would be awkward, however (you'd have to warn users that matplotlibrc values should not have visual level options, and then load them anyways after the default style is applied in explicit mode).

But maybe we should bite the bullet and do it, despite its akwardness.

@tonysyu
Copy link
ContributorAuthor

I agree that it would be good to separate style parameters from config parameters. Just to be clear though, this would be work for a separate PR, correct? (As part of that, removing the bulk of the rc logic from__init__.py and the mixing of data and logic inrcsetup.py would be very desirable---but maybe quite a bit of work.)

@WeatherGod
Copy link
Member

Understandable, but I would suggest holding off on a "style" parameter
until that split happens. It just makes zero sense to me until the split is
made.

@tonysyu
Copy link
ContributorAuthor

I'd agree with holding off on a "style" parameter. In any case, a lot of rc-refactoring will need to be done before that.

@ChrisBeaumont
Copy link
Contributor

I understand the concern, but it's too bad -- once a style with better defaults matures, it will be a shame to have to write 'style.use('better')' at the top of every script.

I'd definitely be willing to help and/or spearhead the proposed rcParams refactoring, to keep momentum going on this -- though I may not be the most qualified person to tackle a big API change like this.

@tonysyu
Copy link
ContributorAuthor

I understand the concern, but it's too bad -- once a style with better defaults matures, it will be a shame to have to write 'style.use('better')' at the top of every script

Sorry, I don't mean to suggest that we should punt on this indefinitely. I just think that smaller, more focused PRs are easier for everyone involved. (Plus, I don't think I want to lead the refactor :)

I'd definitely be willing to help and/or spearhead the proposed rcParams refactoring, to keep momentum going on this -- though I may not be the most qualified person to tackle a big API change like this.

I think this could be split into two PRs: One just to refactorrcsetup.py and the rc parts of__init__.py into something a bit cleaner but with no API changes, and then the second part would be separating styles from config params. That's how I would do it at least.

@tacaswell
Copy link
Member

I understand the concern, but it's too bad -- once a style with better defaults matures, it will be a shame to have to write 'style.use('better')' at the top of every script.

This is far preferable than having to go back and touch every existing script that is broken by the 'better' defaults.

I am in favor of treating anything more than near trivial tweaks to defaults as amajor api break (like bump to 2.0). If a change requires re-generating a test image, you are breaking the api, and I suspect that this will require a majority of the test images to be re-generated.

That said, the ability easily save and set the styling is first order good, in part as protection against the defaults changing.

[edit: gah I know grammer, I swear]

@dpsanders
Copy link

As far as I can see, the style module is still unusable from matplotlib master.
Does anybody have a fix to register it --@mdboom ?

@ChrisBeaumont
Copy link
Contributor

@dpsanders@tonysyu you probably want to addmatplotlib.style to the list insetupext.Matplotlib.get_packages, andstyle/stylelib/* toget_package_data in the same class (though I don't know if styles belong inmpl-data instead)

@ChrisBeaumont
Copy link
Contributor

@tacaswell I don't think that is the issue being discussed here. Instead, this is about enabling a kind of opt-in behavior where someone can specify a default style in their ownmatplotlibrc. That would make it easier for MPL to develop alternative sets of rcParams that people could use by default if they want, without breaking test images or legacy user code.

@dpsanders
Copy link

@pelson Great, thanks -- I tried that, but got the following error frompython setup.py build:

error: package directory 'lib/matplotlib/stylematplotlib/testing' does not exist

Any ideas?

tonysyuand others added13 commitsNovember 17, 2013 14:04
@tonysyu
Copy link
ContributorAuthor

Tests arealmost passing. Maybe Python 2.6 has an issue with a context-manager returning a generator?

@mdboom
Copy link
Member

I've made a PR against this one with a Python 2.6 fix

@tonysyu
Copy link
ContributorAuthor

Woot! Tests passing!

mdboom added a commit that referenced this pull requestNov 18, 2013
@mdboommdboom merged commit0e7daad intomatplotlib:masterNov 18, 2013
@mdboom
Copy link
Member

Merged. Thanks, Tony. This was a big one!

@ChrisBeaumont
Copy link
Contributor

Phew! That was harder than I expected, but I'm glad this is now part of MPL

@tonysyu
Copy link
ContributorAuthor

Thanks to everyone for all the improvements and fixes. It definitely took longer than expected, but it's great to have this in master. On to the rcparams refactor! (I'm not volunteering to lead that charge, but I'm happy to help where I can :).

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers
No reviews
Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
v1.4.0
Development

Successfully merging this pull request may close these issues.

11 participants
@tonysyu@dpsanders@ChrisBeaumont@efiring@mdboom@ivanov@WeatherGod@tacaswell@Tillsten@adrn@pelson

[8]ページ先頭

©2009-2025 Movatter.jp