diff --git a/doc/users/next_whats_new/2019-07-31-AL.rst b/doc/users/next_whats_new/2019-07-31-AL.rst new file mode 100644 index 000000000000..afee0e2c91dc --- /dev/null +++ b/doc/users/next_whats_new/2019-07-31-AL.rst @@ -0,0 +1,5 @@ +xkcd style +`````````` + +The xkcd style previously available as `.pyplot.xkcd` is now also available as +a regular style file, which can be used as ``matplotlib.style.use("xkcd")``. diff --git a/lib/matplotlib/mpl-data/stylelib/_seaborn-v0_8-common.py b/lib/matplotlib/mpl-data/stylelib/_seaborn-v0_8-common.py new file mode 100644 index 000000000000..2263a4e73d93 --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/_seaborn-v0_8-common.py @@ -0,0 +1,21 @@ +{ + "figure.facecolor": "white", + "text.color": "0.15", + "axes.labelcolor": "0.15", + "legend.frameon": False, + "legend.numpoints": 1, + "legend.scatterpoints": 1, + "xtick.direction": "out", + "ytick.direction": "out", + "xtick.color": "0.15", + "ytick.color": "0.15", + "axes.axisbelow": True, + "image.cmap": "Greys", + "font.family": "sans-serif", + "font.sans-serif": [ + "Arial", "Liberation Sans", "DejaVu Sans", "Bitstream Vera Sans", + "sans-serif", + ], + "grid.linestyle": "-", + "lines.solid_capstyle": "round" +} diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.mplstyle b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.mplstyle deleted file mode 100644 index 55b50b5bdd26..000000000000 --- a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.mplstyle +++ /dev/null @@ -1,30 +0,0 @@ -# Seaborn common parameters -# .15 = dark_gray -# .8 = light_gray -figure.facecolor: white -text.color: .15 -axes.labelcolor: .15 -legend.frameon: False -legend.numpoints: 1 -legend.scatterpoints: 1 -xtick.direction: out -ytick.direction: out -xtick.color: .15 -ytick.color: .15 -axes.axisbelow: True -image.cmap: Greys -font.family: sans-serif -font.sans-serif: Arial, Liberation Sans, DejaVu Sans, Bitstream Vera Sans, sans-serif -grid.linestyle: - -lines.solid_capstyle: round - -# Seaborn dark parameters -axes.grid: False -axes.facecolor: EAEAF2 -axes.edgecolor: white -axes.linewidth: 0 -grid.color: white -xtick.major.size: 0 -ytick.major.size: 0 -xtick.minor.size: 0 -ytick.minor.size: 0 diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.py b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.py new file mode 100644 index 000000000000..5d99ea246d60 --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-dark.py @@ -0,0 +1,16 @@ +import ast +from pathlib import Path + + +__mpl_style__ = { + **ast.literal_eval(Path(__file__).with_name("_seaborn-v0_8-common.py").read_text()), + "axes.grid": False, + "axes.facecolor": "#EAEAF2", + "axes.edgecolor": "white", + "axes.linewidth": 0, + "grid.color": "white", + "xtick.major.size": 0, + "ytick.major.size": 0, + "xtick.minor.size": 0, + "ytick.minor.size": 0, +} diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.mplstyle b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.mplstyle deleted file mode 100644 index 0f5d955d7df6..000000000000 --- a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.mplstyle +++ /dev/null @@ -1,30 +0,0 @@ -# Seaborn common parameters -# .15 = dark_gray -# .8 = light_gray -figure.facecolor: white -text.color: .15 -axes.labelcolor: .15 -legend.frameon: False -legend.numpoints: 1 -legend.scatterpoints: 1 -xtick.direction: out -ytick.direction: out -xtick.color: .15 -ytick.color: .15 -axes.axisbelow: True -image.cmap: Greys -font.family: sans-serif -font.sans-serif: Arial, Liberation Sans, DejaVu Sans, Bitstream Vera Sans, sans-serif -grid.linestyle: - -lines.solid_capstyle: round - -# Seaborn darkgrid parameters -axes.grid: True -axes.facecolor: EAEAF2 -axes.edgecolor: white -axes.linewidth: 0 -grid.color: white -xtick.major.size: 0 -ytick.major.size: 0 -xtick.minor.size: 0 -ytick.minor.size: 0 diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.py b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.py new file mode 100644 index 000000000000..8844eca0fbac --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-darkgrid.py @@ -0,0 +1,16 @@ +import ast +from pathlib import Path + + +__mpl_style__ = { + **ast.literal_eval(Path(__file__).with_name("_seaborn-v0_8-common.py").read_text()), + "axes.grid": True, + "axes.facecolor": "#EAEAF2", + "axes.edgecolor": "white", + "axes.linewidth": 0, + "grid.color": "white", + "xtick.major.size": 0, + "ytick.major.size": 0, + "xtick.minor.size": 0, + "ytick.minor.size": 0, +} diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.mplstyle b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.mplstyle deleted file mode 100644 index c2a1cab9a5eb..000000000000 --- a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.mplstyle +++ /dev/null @@ -1,30 +0,0 @@ -# Seaborn common parameters -# .15 = dark_gray -# .8 = light_gray -figure.facecolor: white -text.color: .15 -axes.labelcolor: .15 -legend.frameon: False -legend.numpoints: 1 -legend.scatterpoints: 1 -xtick.direction: out -ytick.direction: out -xtick.color: .15 -ytick.color: .15 -axes.axisbelow: True -image.cmap: Greys -font.family: sans-serif -font.sans-serif: Arial, Liberation Sans, DejaVu Sans, Bitstream Vera Sans, sans-serif -grid.linestyle: - -lines.solid_capstyle: round - -# Seaborn white parameters -axes.grid: False -axes.facecolor: white -axes.edgecolor: .15 -axes.linewidth: 1.25 -grid.color: .8 -xtick.major.size: 6 -ytick.major.size: 6 -xtick.minor.size: 3 -ytick.minor.size: 3 diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.py b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.py new file mode 100644 index 000000000000..00c88d23ebba --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-ticks.py @@ -0,0 +1,16 @@ +import ast +from pathlib import Path + + +__mpl_style__ = { + **ast.literal_eval(Path(__file__).with_name("_seaborn-v0_8-common.py").read_text()), + "axes.grid": False, + "axes.facecolor": "white", + "axes.edgecolor": ".15", + "axes.linewidth": 1.25, + "grid.color": ".8", + "xtick.major.size": 6, + "ytick.major.size": 6, + "xtick.minor.size": 3, + "ytick.minor.size": 3, +} diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.mplstyle b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.mplstyle deleted file mode 100644 index dcbe3acf31da..000000000000 --- a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.mplstyle +++ /dev/null @@ -1,30 +0,0 @@ -# Seaborn common parameters -# .15 = dark_gray -# .8 = light_gray -figure.facecolor: white -text.color: .15 -axes.labelcolor: .15 -legend.frameon: False -legend.numpoints: 1 -legend.scatterpoints: 1 -xtick.direction: out -ytick.direction: out -xtick.color: .15 -ytick.color: .15 -axes.axisbelow: True -image.cmap: Greys -font.family: sans-serif -font.sans-serif: Arial, Liberation Sans, DejaVu Sans, Bitstream Vera Sans, sans-serif -grid.linestyle: - -lines.solid_capstyle: round - -# Seaborn white parameters -axes.grid: False -axes.facecolor: white -axes.edgecolor: .15 -axes.linewidth: 1.25 -grid.color: .8 -xtick.major.size: 0 -ytick.major.size: 0 -xtick.minor.size: 0 -ytick.minor.size: 0 diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.py b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.py new file mode 100644 index 000000000000..b7fbcdaa9cb2 --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-white.py @@ -0,0 +1,17 @@ + +import ast +from pathlib import Path + + +__mpl_style__ = { + **ast.literal_eval(Path(__file__).with_name("_seaborn-v0_8-common.py").read_text()), + "axes.grid": False, + "axes.facecolor": "white", + "axes.edgecolor": ".15", + "axes.linewidth": 1.25, + "grid.color": ".8", + "xtick.major.size": 0, + "ytick.major.size": 0, + "xtick.minor.size": 0, + "ytick.minor.size": 0, +} diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.mplstyle b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.mplstyle deleted file mode 100644 index 612e21813e19..000000000000 --- a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.mplstyle +++ /dev/null @@ -1,30 +0,0 @@ -# Seaborn common parameters -# .15 = dark_gray -# .8 = light_gray -figure.facecolor: white -text.color: .15 -axes.labelcolor: .15 -legend.frameon: False -legend.numpoints: 1 -legend.scatterpoints: 1 -xtick.direction: out -ytick.direction: out -xtick.color: .15 -ytick.color: .15 -axes.axisbelow: True -image.cmap: Greys -font.family: sans-serif -font.sans-serif: Arial, Liberation Sans, DejaVu Sans, Bitstream Vera Sans, sans-serif -grid.linestyle: - -lines.solid_capstyle: round - -# Seaborn whitegrid parameters -axes.grid: True -axes.facecolor: white -axes.edgecolor: .8 -axes.linewidth: 1 -grid.color: .8 -xtick.major.size: 0 -ytick.major.size: 0 -xtick.minor.size: 0 -ytick.minor.size: 0 diff --git a/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.py b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.py new file mode 100644 index 000000000000..4979447ab3c4 --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/seaborn-v0_8-whitegrid.py @@ -0,0 +1,16 @@ +import ast +from pathlib import Path + + +__mpl_style__ = { + **ast.literal_eval(Path(__file__).with_name("_seaborn-v0_8-common.py").read_text()), + "axes.grid": True, + "axes.facecolor": "white", + "axes.edgecolor": ".8", + "axes.linewidth": 1, + "grid.color": ".8", + "xtick.major.size": 0, + "ytick.major.size": 0, + "xtick.minor.size": 0, + "ytick.minor.size": 0, +} diff --git a/lib/matplotlib/mpl-data/stylelib/xkcd.py b/lib/matplotlib/mpl-data/stylelib/xkcd.py new file mode 100644 index 000000000000..9ee59d827d7e --- /dev/null +++ b/lib/matplotlib/mpl-data/stylelib/xkcd.py @@ -0,0 +1,21 @@ +from matplotlib import patheffects + + +__mpl_style__ = { + "axes.edgecolor": "black", + "axes.grid": False, + "axes.linewidth": 1.5, + "axes.unicode_minus": False, + "figure.facecolor": "white", + "font.family": ["xkcd", "Humor Sans", "Comic Sans MS"], + "font.size": 14.0, + "grid.linewidth": 0.0, + "lines.linewidth": 2.0, + "path.effects": [patheffects.withStroke(linewidth=4, foreground="w")], + "path.sketch": (1, 100, 2), + "text.usetex": False, + "xtick.major.size": 8, + "xtick.major.width": 3, + "ytick.major.size": 8, + "ytick.major.width": 3, +} diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 026be7ae90cf..1b491e4b8e82 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -712,25 +712,9 @@ def xkcd( stack = ExitStack() stack.callback(dict.update, rcParams, rcParams.copy()) # type: ignore - from matplotlib import patheffects rcParams.update({ - 'font.family': ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', - 'Comic Sans MS'], - 'font.size': 14.0, + **style.library["xkcd"], 'path.sketch': (scale, length, randomness), - 'path.effects': [ - patheffects.withStroke(linewidth=4, foreground="w")], - 'axes.linewidth': 1.5, - 'lines.linewidth': 2.0, - 'figure.facecolor': 'white', - 'grid.linewidth': 0.0, - 'axes.grid': False, - 'axes.unicode_minus': False, - 'axes.edgecolor': 'black', - 'xtick.major.size': 8, - 'xtick.major.width': 3, - 'ytick.major.size': 8, - 'ytick.major.width': 3, }) return stack diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py index 7e9008c56165..a924d6a836bc 100644 --- a/lib/matplotlib/style/core.py +++ b/lib/matplotlib/style/core.py @@ -12,6 +12,7 @@ """ import contextlib +import importlib import logging import os from pathlib import Path @@ -214,6 +215,29 @@ def read_style_directory(style_dir): return styles +def _read_pystyle_base_directory(): + """ + Return directory of styles defined in *style_dir* as Python files. + + Because Python style files can execute arbitrary code, this feature is only + used internally to load files provided by Matplotlib itself, not + user-provided style files. + + A Python style is a non-private Python module that exports a dict named + ``__mpl_style__``, from which a `RcParams` is constructed. This convention + may be revisited if this feature ever becomes public. + """ + styles = {} + for path in Path(BASE_LIBRARY_PATH).glob("*.py"): + if path.name.startswith("_"): + continue + spec = importlib.util.spec_from_file_location(path.stem, path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + styles[path.stem] = mpl.RcParams(module.__mpl_style__) + return styles + + def update_nested_dict(main_dict, new_dict): """ Update nested dict (only level of nesting) with new values. @@ -230,7 +254,10 @@ def update_nested_dict(main_dict, new_dict): # Load style library # ================== -_base_library = read_style_directory(BASE_LIBRARY_PATH) +_base_library = { + **read_style_directory(BASE_LIBRARY_PATH), + **_read_pystyle_base_directory(), +} library = {} available = []