├── .gitignore ├── LICENSE ├── MANIFEST.in ├── dist ├── themepy-0.1.1-py3-none-any.whl ├── themepy-0.1.1.tar.gz ├── themepy-0.3.0.tar.gz └── themepy-0.3.1.tar.gz ├── environment.yml ├── readme.md ├── requirements.txt ├── sample ├── add_theme_sample.png ├── adjusted_mpl.png ├── adjusted_mpl_dark.png ├── gadfly_mpl.png └── standard_mpl.png ├── setup.py └── themepy ├── __init__.py ├── helper.py ├── set_theme.py ├── theme.py └── themes ├── .gitignore ├── __init__.py ├── barcanumbers-lightgrey.txt ├── blueprint.txt ├── dark.txt ├── financial-times-light.txt ├── fivethirtyeight-grey.txt ├── fivethirtyeight-white.txt ├── gadfly.txt ├── git_themes_list.log ├── neon.txt ├── paper.txt ├── sample-dark.txt ├── sample-dark2.txt ├── sample-light.txt └── sample-light2.txt /.gitignore: -------------------------------------------------------------------------------- 1 | notebooks/ 2 | build/ 3 | .ipynb_checkpoints/ 4 | *.csv 5 | *.xlsm 6 | *.png 7 | *.svg 8 | *__pycache__ 9 | .vscode/ 10 | *.pyc 11 | themepy.egg-info 12 | themepy.egg-info/ 13 | pip-wheel-metadata 14 | env 15 | .DS_Store 16 | themepy/.DS_Store 17 | dist/.DS_Store 18 | change.log 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Peter McKeever 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include thempy/themes/*.txt 2 | include readme.md -------------------------------------------------------------------------------- /dist/themepy-0.1.1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/dist/themepy-0.1.1-py3-none-any.whl -------------------------------------------------------------------------------- /dist/themepy-0.1.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/dist/themepy-0.1.1.tar.gz -------------------------------------------------------------------------------- /dist/themepy-0.3.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/dist/themepy-0.3.0.tar.gz -------------------------------------------------------------------------------- /dist/themepy-0.3.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/dist/themepy-0.3.1.tar.gz -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: themepy-dev 2 | channels: 3 | - conda-forge 4 | - defaults 5 | dependencies: 6 | - appnope=0.1.0 7 | - argon2-cffi=20.1.0 8 | - asn1crypto=1.4.0 9 | - attrs=19.3.0 10 | - backcall=0.2.0 11 | - backports=1.0 12 | - backports.functools_lru_cache=1.6.1 13 | - bleach=3.1.5 14 | - brotlipy=0.7.0 15 | - bzip2=1.0.8 16 | - ca-certificates=2020.6.20 17 | - certifi=2020.6.20 18 | - cffi=1.14.1 19 | - chardet=3.0.4 20 | - cmarkgfm=0.4.2 21 | - colorama=0.4.3 22 | - cryptography=2.5 23 | - cycler=0.10.0 24 | - dbus=1.13.6 25 | - decorator=4.4.2 26 | - defusedxml=0.6.0 27 | - docutils=0.16 28 | - entrypoints=0.3 29 | - expat=2.2.9 30 | - freetype=2.10.2 31 | - future=0.18.2 32 | - gettext=0.19.8.1 33 | - glib=2.65.0 34 | - icu=58.2 35 | - idna=2.10 36 | - importlib-metadata=1.7.0 37 | - importlib_metadata=1.7.0 38 | - ipykernel=5.3.4 39 | - ipython=7.17.0 40 | - ipython_genutils=0.2.0 41 | - ipywidgets=7.5.1 42 | - jedi=0.15.2 43 | - jinja2=2.11.2 44 | - jpeg=9d 45 | - jsonschema=3.2.0 46 | - jupyter=1.0.0 47 | - jupyter_client=6.1.6 48 | - jupyter_console=6.1.0 49 | - jupyter_core=4.6.3 50 | - keyring=21.3.0 51 | - kiwisolver=1.2.0 52 | - lcms2=2.11 53 | - libblas=3.8.0 54 | - libcblas=3.8.0 55 | - libcxx=10.0.1 56 | - libffi=3.2.1 57 | - libgfortran=4.0.0 58 | - libiconv=1.15 59 | - liblapack=3.8.0 60 | - libopenblas=0.3.10 61 | - libpng=1.6.37 62 | - libsodium=1.0.18 63 | - libtiff=4.1.0 64 | - libwebp-base=1.1.0 65 | - llvm-openmp=10.0.1 66 | - lz4-c=1.9.2 67 | - markupsafe=1.1.1 68 | - matplotlib=3.3.1 69 | - matplotlib-base=3.3.1 70 | - mistune=0.8.4 71 | - nbconvert=5.6.1 72 | - nbformat=5.0.7 73 | - ncurses=6.2 74 | - notebook=6.1.3 75 | - numpy=1.19.1 76 | - olefile=0.46 77 | - openssl=1.0.2u 78 | - packaging=20.4 79 | - pandas=1.1.0 80 | - pandoc=2.10.1 81 | - pandocfilters=1.4.2 82 | - parso=0.7.1 83 | - pcre=8.44 84 | - pexpect=4.8.0 85 | - pickleshare=0.7.5 86 | - pillow=7.2.0 87 | - pip=20.2.2 88 | - pkginfo=1.5.0.1 89 | - prometheus_client=0.8.0 90 | - prompt-toolkit=3.0.6 91 | - prompt_toolkit=3.0.6 92 | - ptyprocess=0.6.0 93 | - pycparser=2.20 94 | - pygments=2.6.1 95 | - pyopenssl=19.0.0 96 | - pyparsing=2.4.7 97 | - pyqt=5.9.2 98 | - pyrsistent=0.16.0 99 | - pysocks=1.7.1 100 | - python=3.7.0 101 | - python-dateutil=2.8.1 102 | - python_abi=3.7 103 | - pytz=2020.1 104 | - pyzmq=19.0.2 105 | - qt=5.9.7 106 | - qtconsole=4.7.5 107 | - qtpy=1.9.0 108 | - readline=7.0 109 | - readme_renderer=24.0 110 | - requests=2.24.0 111 | - requests-toolbelt=0.9.1 112 | - rfc3986=1.4.0 113 | - send2trash=1.5.0 114 | - setuptools=49.6.0 115 | - sip=4.19.8 116 | - six=1.15.0 117 | - sqlite=3.28.0 118 | - terminado=0.8.3 119 | - testpath=0.4.4 120 | - tk=8.6.10 121 | - tornado=6.0.4 122 | - tqdm=4.48.2 123 | - traitlets=4.3.3 124 | - twine=3.2.0 125 | - urllib3=1.25.10 126 | - wcwidth=0.2.5 127 | - webencodings=0.5.1 128 | - wheel=0.35.1 129 | - widgetsnbextension=3.5.1 130 | - xz=5.2.5 131 | - zeromq=4.3.2 132 | - zipp=3.1.0 133 | - zlib=1.2.11 134 | - zstd=1.4.5 135 | prefix: /Users/peter.mckeever/anaconda3/envs/themepy-dev 136 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![](https://img.shields.io/badge/PyPi%20latest%20relsease-v0.3.1-brightgreen)](https://pypi.org/project/themepy/) 2 | 3 | # ThemePy 4 | 5 | An open source theme selector / creator and aesthetic manager for Matplotlib. This wrapper is intended to create an open-source community-driven theme library for matplotlib. The aim is to simplify the process of customising matplotlib plots and to enable users who are relatively new to python or matplotlib to move beyond the default plotting params we are given with matplotlib. 6 | 7 | Taking a class-based approach, themes can now hold state. This makes it easier to keep track of colors and params that are usually set as variables, hardcoded, or added as args to matplotlib/pyplot functions. This allows us to reduce complexity of setting custom fonts etc... and gives us flexibility in moving between themes, not to mention the reduced typing by breaking down our interaction with matplotlib's rcParams into declarative functions. 8 | 9 | # Contributing 10 | 11 | Contributors are welcome to this pacakge. The key idea behind this is to simplify interaction with matplotlib and have usable themes and modifications through declarative language. To acheive this each function should look to do just one thing and params for each function should be relatively few. 12 | 13 | All contributing is handled through PRs (Pull Requests). In order to contri bute users must: 14 | 1. Fork this repo and create branch from `master` 15 | 2. Clone the environment - `conda env create -f environment.yml` 16 | 3. Make changes to code or additions to codebase / new themes 17 | 4. Test these to ensure that they function as expected 18 | 5. Commit code and create a pull request outlining changes made 19 | 20 | ### Contributing Themes 21 | The main goal of this package is to have professional, well thought out themes available to all. If you would like to contribute a theme, look in the themes folder for a sample of how they should look. Including fonts in here is okay, but please only include fonts that are free and publicly available. If a font is included, please provide a url to the source in the PR. Similar to the above, to contribute themes: 22 | 23 | 1. Fork this repo and create branch from `master` 24 | 2. Clone the environment 25 | 3. Add your theme .txt file to the themes folder 26 | 4. Test these to ensure that they function as expected 27 | 5. Commit code and create a pull request outlining your new theme, including its name. Do not commit images. 28 | 29 | 30 | To get started after cloning, in the root of the repo, create a `notebooks` folder and inside create a new jupyter notebook. Add the following: 31 | 32 | ```python 33 | import sys 34 | sys.path.append("..") 35 | import themepy 36 | ``` 37 | 38 | 39 | 40 | 41 | # Examples 42 | 43 | This is still in early development. A python version >= 3.7 is required (just clone the env). There is an unstable version (0.3.1) available through pip - `pip install themepy`. 44 | 45 | We can get started straight away by instantiating a Theme class. We can do this without passing a specific theme, this will use matplotlib's defaults. 46 | 47 | ```python 48 | import matplotlib.pyplot as plt 49 | import themepy 50 | 51 | theme = themepy.Theme() 52 | ``` 53 | 54 | if we created a plot it would look like a regular matplotlib plot. 55 | 56 | ```python 57 | # creating random data 58 | np.random.seed(402) 59 | x = np.random.uniform(0,1,50) 60 | y = np.random.uniform(0,1,50) 61 | 62 | # can adjust themes and params here 63 | (theme 64 | .set_theme() # we could change to a different theme here. Passing no theme resets theme to default matplotlib 65 | .set_font() # we could set a new font here 66 | .set_pips() # we could set the tick marks on the x and y axis on or off here 67 | .set_spines() # we could show or hide the borders of the plot here 68 | .set_ticklabel_size() # we could change the size of the x and y tick labels here 69 | .set_grid() # we could set the grid on or off and set params like color and linewidth 70 | .set_rcparams() # we could also set any matplotlib rcParams here 71 | ) 72 | 73 | 74 | # create plot 75 | fig, ax = plt.subplots(figsize=(8,8)) 76 | ax.set_title("This is a title using {} theme".format(theme.theme_name), 77 | loc="left", **theme.title_font, fontsize=18, fontweight="bold") 78 | 79 | 80 | ax.grid(linewidth=.25, zorder=1) 81 | # creating random data 82 | np.random.seed(402) 83 | x = np.random.uniform(0,1,50) 84 | y = np.random.uniform(0,1,50) 85 | 86 | ax.scatter(x,y, 87 | color=theme.primary_color, # the first colour in cycle, our primary color 88 | edgecolors=theme.background, # our background colour (figure.facecolor) 89 | s=400, 90 | zorder=2) 91 | 92 | ax.set_xlim(0,1) 93 | ax.set_ylim(0,1) 94 | 95 | plt.show() 96 | 97 | ``` 98 | 99 | ![](sample/standard_mpl.png) 100 | 101 | However, we can now make some quick alterations to our plot 102 | 103 | ```python 104 | 105 | # creating random data 106 | np.random.seed(402) 107 | x = np.random.uniform(0,1,50) 108 | y = np.random.uniform(0,1,50) 109 | 110 | # adjusting font, pips, spines, and tick size here 111 | (theme 112 | .set_font("Century Gothic") 113 | .set_pips(False) 114 | .set_spines("off", which=["top","right"]) 115 | .set_ticklabel_size(12) 116 | ) 117 | 118 | 119 | # create plot 120 | fig, ax = plt.subplots(figsize=(8,8)) 121 | ax.set_title("This is a title using {} theme".format(theme.theme_name), 122 | loc="left", **theme.title_font, fontsize=18, fontweight="bold") 123 | 124 | 125 | ax.grid(linewidth=.25, zorder=1) 126 | 127 | ax.scatter(x,y, 128 | color=theme.primary_color, # the first colour in cycle, our primary color 129 | edgecolors=theme.background, # our background colour (figure.facecolor) 130 | s=400, 131 | zorder=2) 132 | 133 | ax.set_xlim(0,1) 134 | ax.set_ylim(0,1) 135 | 136 | plt.show() 137 | 138 | ``` 139 | ![](sample/adjusted_mpl.png) 140 | 141 | `theme.title_font` and `theme.body_font` take the font passed either through the theme or through `theme.set_font`, but they can also be set individually. 142 | 143 | There are two sample themes included. Dark version shown below: 144 | ```python 145 | 146 | # creating random data 147 | np.random.seed(402) 148 | x = np.random.uniform(0,1,50) 149 | y = np.random.uniform(0,1,50) 150 | 151 | # can adjust themes and params here 152 | (theme 153 | .set_theme('sample-dark') 154 | .set_font("Century Gothic") 155 | .set_pips(False) 156 | .set_spines("off", which=["top","right"]) 157 | .set_ticklabel_size(12) 158 | ) 159 | 160 | 161 | # create plot 162 | fig, ax = plt.subplots(figsize=(8,8)) 163 | ax.set_title("This is a title using {} theme".format(theme.theme_name), 164 | loc="left", **theme.title_font, fontsize=18, fontweight="bold") 165 | 166 | 167 | ax.grid(linewidth=.25, zorder=1) 168 | 169 | ax.scatter(x,y, 170 | color=theme.primary_color, # the first colour in cycle, our primary color 171 | edgecolors=theme.background, # our background colour (figure.facecolor) 172 | s=400, 173 | zorder=2) 174 | 175 | ax.set_xlim(0,1) 176 | ax.set_ylim(0,1) 177 | 178 | plt.show() 179 | 180 | ``` 181 | 182 | ![](sample/adjusted_mpl_dark.png) 183 | 184 | It also includes the Gadfly theme as present in [this blog post](https://towardsdatascience.com/a-new-plot-theme-for-matplotlib-gadfly-2cffc745ff84) 185 | 186 | ```python 187 | # creating random data 188 | np.random.seed(402) 189 | x = np.random.uniform(0,1,50) 190 | y = np.random.uniform(0,1,50) 191 | 192 | theme.set_theme('gadfly') 193 | 194 | # create plot 195 | fig, ax = plt.subplots(figsize=(8,8)) 196 | ax.set_title("This is a title using {} theme".format(theme.theme_name), loc="left") 197 | ax.grid(linewidth=.25, zorder=1) 198 | ax.scatter(x, y, s=400, zorder=2) 199 | ax.set_xlim(0,1) 200 | ax.set_ylim(0,1) 201 | 202 | plt.show() 203 | ``` 204 | ![](sample/gadfly_mpl.png) 205 | 206 | # Adding Themes 207 | 208 | It is now possible to add themes locally directly from scripts / notebooks. Simply create your customised plot using the theme accessors and save it by using `add_theme()` 209 | 210 | For example: 211 | ```python 212 | theme = themepy.Theme() 213 | 214 | theme.set_theme() # ensures set to default matplotlib rcParams 215 | 216 | 217 | (theme 218 | .set_font("Kulim Park", color="white") # sets default font and text color 219 | .set_pips(False) # turns off tick lines 220 | .set_spines("off", which=["top","right"], color="white") # turns off top and right ax borders & sets color of others to white 221 | .set_background("#2c3042") # sets the fig, axis, and savefig facecolors 222 | .set_ticklabel_size(12) # sets size of tick labels 223 | .set_plot_colors("#DC5349","#26D8FF","#D3CFBD") # sets first three colors of cycler and also colors of theme.primary_color, theme.secondary_color, and theme.tertiary_color 224 | ) 225 | 226 | ``` 227 | 228 | After plotting and being happy with how this theme looks, we can save it locally for future use: 229 | 230 | ```python 231 | theme.add_theme("midnight") 232 | ``` 233 | 234 | If theme name already exists, users will be asked to overwrite existing theme or not. Once saved, users can then use this newly created theme by using 235 | 236 | ```python 237 | theme.set_theme("midnight") 238 | 239 | # creating random data 240 | np.random.seed(402) 241 | x = np.random.uniform(0,1,30) 242 | y = np.random.uniform(0,1,30) 243 | 244 | 245 | # create plot 246 | fig, ax = plt.subplots(figsize=(8,8)) 247 | ax.set_title("This is a title using a brand new theme", 248 | loc="left", **theme.title_font, fontsize=18, fontweight="bold") 249 | 250 | 251 | ax.grid(linewidth=.25, zorder=1, color="grey") 252 | 253 | ax.scatter(x[:10],y[:10], 254 | edgecolors=theme.background, 255 | s=400, 256 | zorder=2) 257 | 258 | ax.scatter(x[10:20],y[10:20], 259 | edgecolors=theme.background, 260 | s=400, 261 | zorder=2) 262 | 263 | ax.scatter(x[20:],y[20:], 264 | edgecolors=theme.background, 265 | s=400, 266 | zorder=2) 267 | 268 | ax.set_xlim(0,1) 269 | ax.set_ylim(0,1) 270 | 271 | ax.set_xlabel("Test x Label", fontsize=16) 272 | ax.set_ylabel("Test y Label", fontsize=16) 273 | 274 | plt.tight_layout() 275 | plt.show() 276 | ``` 277 | 278 | ![](sample/add_theme_sample.png) 279 | 280 | # To Do: 281 | 282 | - Docstring on Theme class 283 | - Testing script 284 | - Apply code formatting and guidelines for contributors 285 | 286 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: osx-64 4 | appnope=0.1.0=py37hc8dfbb8_1001 5 | argon2-cffi=20.1.0=py37h60d8a13_1 6 | asn1crypto=1.4.0=pyh9f0ad1d_0 7 | attrs=19.3.0=py_0 8 | backcall=0.2.0=pyh9f0ad1d_0 9 | backports=1.0=py_2 10 | backports.functools_lru_cache=1.6.1=py_0 11 | bleach=3.1.5=pyh9f0ad1d_0 12 | brotlipy=0.7.0=py37h9bfed18_1000 13 | bzip2=1.0.8=haf1e3a3_2 14 | ca-certificates=2020.6.20=hecda079_0 15 | certifi=2020.6.20=py37hc8dfbb8_0 16 | cffi=1.14.1=py37hf5b7abd_0 17 | chardet=3.0.4=py37hc8dfbb8_1006 18 | cmarkgfm=0.4.2=py37h0b31af3_2 19 | colorama=0.4.3=py_0 20 | cryptography=2.5=py37hdbc3d79_1 21 | cycler=0.10.0=py_2 22 | dbus=1.13.6=h2f22bb5_0 23 | decorator=4.4.2=py_0 24 | defusedxml=0.6.0=py_0 25 | docutils=0.16=py37hc8dfbb8_1 26 | entrypoints=0.3=py37hc8dfbb8_1001 27 | expat=2.2.9=hb1e8313_2 28 | freetype=2.10.2=h8da9a1a_0 29 | future=0.18.2=py37hc8dfbb8_1 30 | gettext=0.19.8.1=h46ab8bc_1002 31 | glib=2.65.0=h577aef8_0 32 | icu=58.2=h0a44026_1000 33 | idna=2.10=pyh9f0ad1d_0 34 | importlib-metadata=1.7.0=py37hc8dfbb8_0 35 | importlib_metadata=1.7.0=0 36 | ipykernel=5.3.4=py37h43977f1_0 37 | ipython=7.17.0=py37hc6149b9_0 38 | ipython_genutils=0.2.0=py_1 39 | ipywidgets=7.5.1=py_0 40 | jedi=0.15.2=py37_0 41 | jinja2=2.11.2=pyh9f0ad1d_0 42 | jpeg=9d=h0b31af3_0 43 | jsonschema=3.2.0=py37hc8dfbb8_1 44 | jupyter=1.0.0=py_2 45 | jupyter_client=6.1.6=py_0 46 | jupyter_console=6.1.0=py_1 47 | jupyter_core=4.6.3=py37hc8dfbb8_1 48 | keyring=21.3.0=py37hc8dfbb8_0 49 | kiwisolver=1.2.0=py37ha1cc60f_0 50 | lcms2=2.11=h174193d_0 51 | libblas=3.8.0=17_openblas 52 | libcblas=3.8.0=17_openblas 53 | libcxx=10.0.1=h5f48129_0 54 | libffi=3.2.1=hb1e8313_1007 55 | libgfortran=4.0.0=2 56 | libiconv=1.15=h0b31af3_1006 57 | liblapack=3.8.0=17_openblas 58 | libopenblas=0.3.10=openmp_h63d9170_4 59 | libpng=1.6.37=hb0a8c7a_2 60 | libsodium=1.0.18=h01d97ff_0 61 | libtiff=4.1.0=h2ae36a8_6 62 | libwebp-base=1.1.0=h0b31af3_3 63 | llvm-openmp=10.0.1=h28b9765_0 64 | lz4-c=1.9.2=hb1e8313_2 65 | markupsafe=1.1.1=py37h9bfed18_1 66 | matplotlib=3.3.1=0 67 | matplotlib-base=3.3.1=py37h886f89f_0 68 | mistune=0.8.4=py37h9bfed18_1001 69 | nbconvert=5.6.1=py37hc8dfbb8_1 70 | nbformat=5.0.7=py_0 71 | ncurses=6.2=hb1e8313_1 72 | notebook=6.1.3=py37hc8dfbb8_0 73 | numpy=1.19.1=py37h7e69742_0 74 | olefile=0.46=py_0 75 | openssl=1.0.2u=h0b31af3_0 76 | packaging=20.4=pyh9f0ad1d_0 77 | pandas=1.1.0=py37hdadc0f0_0 78 | pandoc=2.10.1=haf1e3a3_0 79 | pandocfilters=1.4.2=py_1 80 | parso=0.7.1=pyh9f0ad1d_0 81 | pcre=8.44=h4a8c4bd_0 82 | pexpect=4.8.0=py37hc8dfbb8_1 83 | pickleshare=0.7.5=py37hc8dfbb8_1001 84 | pillow=7.2.0=py37hfd78ece_1 85 | pip=20.2.2=py_0 86 | pkginfo=1.5.0.1=py_0 87 | prometheus_client=0.8.0=pyh9f0ad1d_0 88 | prompt-toolkit=3.0.6=py_0 89 | prompt_toolkit=3.0.6=0 90 | ptyprocess=0.6.0=py_1001 91 | pycparser=2.20=pyh9f0ad1d_2 92 | pygments=2.6.1=py_0 93 | pyopenssl=19.0.0=py37_0 94 | pyparsing=2.4.7=pyh9f0ad1d_0 95 | pyqt=5.9.2=py37h2a560b1_4 96 | pyrsistent=0.16.0=py37h9bfed18_0 97 | pysocks=1.7.1=py37hc8dfbb8_1 98 | python=3.7.0=h145921a_1006 99 | python-dateutil=2.8.1=py_0 100 | python_abi=3.7=1_cp37m 101 | pytz=2020.1=pyh9f0ad1d_0 102 | pyzmq=19.0.2=py37hf1e22d8_0 103 | qt=5.9.7=h93ee506_2 104 | qtconsole=4.7.5=pyh9f0ad1d_0 105 | qtpy=1.9.0=py_0 106 | readline=7.0=hcfe32e1_1001 107 | readme_renderer=24.0=py_0 108 | requests=2.24.0=pyh9f0ad1d_0 109 | requests-toolbelt=0.9.1=py_0 110 | rfc3986=1.4.0=pyh9f0ad1d_0 111 | send2trash=1.5.0=py_0 112 | setuptools=49.6.0=py37hc8dfbb8_0 113 | sip=4.19.8=py37h0a44026_0 114 | six=1.15.0=pyh9f0ad1d_0 115 | sqlite=3.28.0=h9721f7c_0 116 | terminado=0.8.3=py37hc8dfbb8_1 117 | testpath=0.4.4=py_0 118 | tk=8.6.10=hb0a8c7a_0 119 | tornado=6.0.4=py37h9bfed18_1 120 | tqdm=4.48.2=pyh9f0ad1d_0 121 | traitlets=4.3.3=py37hc8dfbb8_1 122 | twine=3.2.0=py37hc8dfbb8_0 123 | urllib3=1.25.10=py_0 124 | wcwidth=0.2.5=pyh9f0ad1d_1 125 | webencodings=0.5.1=py_1 126 | wheel=0.35.1=pyh9f0ad1d_0 127 | widgetsnbextension=3.5.1=py37hc8dfbb8_1 128 | xz=5.2.5=haf1e3a3_1 129 | zeromq=4.3.2=h4a8c4bd_3 130 | zipp=3.1.0=py_0 131 | zlib=1.2.11=1007 132 | zstd=1.4.5=h289c70a_2 133 | -------------------------------------------------------------------------------- /sample/add_theme_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/sample/add_theme_sample.png -------------------------------------------------------------------------------- /sample/adjusted_mpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/sample/adjusted_mpl.png -------------------------------------------------------------------------------- /sample/adjusted_mpl_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/sample/adjusted_mpl_dark.png -------------------------------------------------------------------------------- /sample/gadfly_mpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/sample/gadfly_mpl.png -------------------------------------------------------------------------------- /sample/standard_mpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/sample/standard_mpl.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("readme.md", "r") as f: 4 | readme = f.read() 5 | 6 | setuptools.setup( 7 | name="themepy", 8 | version ="0.3.1", 9 | author ="Peter McKeever", 10 | author_email ="hello@petermckeever.com", 11 | description ="a tools suite to manage themes in matplotlib", 12 | long_description=readme, 13 | long_description_content_type="text/markdown", 14 | url ="https://github.com/petermckeeverPerform/themepy", 15 | packages=setuptools.find_packages(), 16 | package_data={ 17 | # If any package contains *.txt or *.rst files, include them: 18 | "": ["*.txt"]}, 19 | include_package_data=True, 20 | classifiers=[ 21 | "Programming Language :: Python :: 3.7", 22 | "Framework :: Matplotlib" 23 | ], 24 | python_requires='>=3.7', 25 | ) -------------------------------------------------------------------------------- /themepy/__init__.py: -------------------------------------------------------------------------------- 1 | from .theme import Theme 2 | from .set_theme import list_themes 3 | -------------------------------------------------------------------------------- /themepy/helper.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | 3 | 4 | def get_rcparams_containing(string="", return_values=True): 5 | """helper to search rcParams for keys containing a specific string, eg. "axes" 6 | 7 | Args: 8 | string (str): string that rcParam keys should contain. Defaults to "" returning all rcParams. 9 | return_values (bool, optional): whether to return the values in addition to the keys. Defaults to True. 10 | 11 | Returns: 12 | dict: rcParams with keys containing `string` 13 | """ 14 | if return_values: 15 | return {key: val for key, val in dict(mpl.rcParams).items() if string in key} 16 | else: 17 | return [key for key in dict(mpl.rcParams).keys() if string in key] 18 | -------------------------------------------------------------------------------- /themepy/set_theme.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | from cycler import cycler 3 | import os 4 | import ast 5 | import os.path as path 6 | import requests 7 | 8 | 9 | def list_themes(local=True): 10 | """ 11 | Displays list of current themes found in themes folder 12 | If local is set to false, list themes available in github repo 13 | """ 14 | if local: 15 | theme_list = os.listdir(path.dirname(path.abspath(__file__))+'/themes/') 16 | # only list .txt files and drop .txt extension from name 17 | theme_list = [x.split(".")[0] for x in theme_list if ".txt" in x in theme_list] 18 | else: 19 | target_url = "https://raw.githubusercontent.com/petermckeeverPerform/themepy/master/themepy/themes/git_themes_list.log" 20 | res = requests.get(target_url) 21 | theme_list = res.text.split("\n") 22 | return theme_list 23 | 24 | 25 | def set_params(self, theme_name=None): 26 | """ 27 | Passes values from our selected theme (or defaults) 28 | Input 29 | ===== 30 | theme_name: str - name of theme to use 31 | 32 | Returns 33 | ======= 34 | changed properties of instantiated class 35 | """ 36 | 37 | self.theme_name = None 38 | 39 | # resetting to remove potential artifacts from previous themes 40 | mpl.rcParams.update(mpl.rcParamsDefault) 41 | 42 | if theme_name is None: 43 | mpl.rcParams.update(mpl.rcParamsDefault) 44 | self.theme_name = "Matplotlib" 45 | self.background = mpl.rcParams['figure.facecolor'] 46 | self.primary_color = '#1f77b4' 47 | self.secondary_color = '#ff7f0e' 48 | self.tertiary_color = '#2ca02c' 49 | self.markings = "k" 50 | self.fontfamily = mpl.rcParams['font.family'] 51 | self.title_font = {"fontfamily": mpl.rcParams['font.family']} 52 | self.body_font = {"fontfamily": mpl.rcParams['font.family']} 53 | 54 | elif theme_name.lower() in list_themes(local=True): 55 | theme_dict = (ast.literal_eval( 56 | open(path.dirname(path.abspath(__file__))+"/themes/" + 57 | theme_name + 58 | ".txt", 'r').read())) 59 | 60 | self.theme_name = theme_name 61 | param_keys = theme_dict.keys() 62 | param_vals = theme_dict.values() 63 | for key, val in zip(param_keys, param_vals): 64 | if key == 'cycler-prop-cycles': 65 | pass 66 | else: 67 | mpl.rcParams[key] = val 68 | 69 | c_cycler = [] 70 | i = 0 71 | for i in range(len(theme_dict['cycler-prop-cycles'])): 72 | c_cycler.append(theme_dict['cycler-prop-cycles'][i]) 73 | 74 | mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=c_cycler) 75 | 76 | self.background = mpl.rcParams['figure.facecolor'] 77 | self.primary_color = c_cycler[0] 78 | self.secondary_color = c_cycler[1] 79 | self.tertiary_color = c_cycler[2] 80 | self.markings = "lightgrey" 81 | self.fontfamily = mpl.rcParams['font.family'] 82 | self.title_font = {"fontfamily": mpl.rcParams['font.family']} 83 | self.body_font = {"fontfamily": mpl.rcParams['font.family']} 84 | 85 | elif theme_name.lower() in list_themes(local=False): 86 | target_url = "https://raw.githubusercontent.com/petermckeeverPerform/themepy/master/themepy/themes/{}.txt" 87 | res = requests.get(target_url.format(theme_name.lower())) 88 | theme_dict = ast.literal_eval(res.text) 89 | 90 | self.theme_name = theme_name 91 | param_keys = theme_dict.keys() 92 | param_vals = theme_dict.values() 93 | for key, val in zip(param_keys, param_vals): 94 | if key == 'cycler-prop-cycles': 95 | pass 96 | else: 97 | mpl.rcParams[key] = val 98 | 99 | c_cycler = [] 100 | i = 0 101 | for i in range(len(theme_dict['cycler-prop-cycles'])): 102 | c_cycler.append(theme_dict['cycler-prop-cycles'][i]) 103 | 104 | mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=c_cycler) 105 | 106 | self.background = mpl.rcParams['figure.facecolor'] 107 | self.primary_color = c_cycler[0] 108 | self.secondary_color = c_cycler[1] 109 | self.tertiary_color = c_cycler[2] 110 | self.markings = "lightgrey" 111 | self.fontfamily = mpl.rcParams['font.family'] 112 | self.title_font = {"fontfamily": mpl.rcParams['font.family']} 113 | self.body_font = {"fontfamily": mpl.rcParams['font.family']} 114 | 115 | 116 | else: 117 | raise NameError("This theme does not exist. Choose one of the existing themes - found by running themepy.list_themes()") 118 | 119 | return self 120 | -------------------------------------------------------------------------------- /themepy/theme.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | from .set_theme import set_params, list_themes 3 | import os.path as path 4 | 5 | 6 | class Theme: 7 | 8 | def __init__(self, theme_name=None): 9 | self.theme_list = list_themes() 10 | if theme_name is None: 11 | mpl.rcParams.update(mpl.rcParamsDefault) 12 | self.theme_name = "Matplotlib" 13 | self.background = mpl.rcParams['figure.facecolor'] 14 | self.primary_color = '#1f77b4' 15 | self.secondary_color = '#ff7f0e' 16 | self.tertiary_color = '#2ca02c' 17 | self.markings = "k" 18 | self.fontfamily = mpl.rcParams['font.family'] 19 | self.title_font = {"fontfamily": mpl.rcParams['font.family']} 20 | self.body_font = {"fontfamily": mpl.rcParams['font.family']} 21 | self.dpi = 100 22 | 23 | else: 24 | set_params(self, theme_name) 25 | 26 | def __repr__(self): 27 | return self.theme_name + " is the active theme" 28 | 29 | def __str__(self): 30 | return self.theme_name + " is the active theme" 31 | 32 | def set_theme(self, theme_name=None): 33 | """ 34 | Passes values from our selected theme (or defaults) 35 | 36 | Input 37 | ===== 38 | theme_name: str - name of theme to use 39 | 40 | Returns 41 | ======= 42 | changed properties of instantiated class 43 | """ 44 | set_params(self, theme_name) 45 | 46 | return self 47 | 48 | def set_background(self, facecolor, figure=True, ax=True): 49 | """[summary] 50 | 51 | Args: 52 | facecolor (string): color to set as background 53 | figure (bool, optional): Apply to matplotlib figure Defaults to True. 54 | ax (bool, optional): Apply to matplotlib ax background. Defaults to True. 55 | """ 56 | if figure: 57 | mpl.rcParams['figure.facecolor'] = facecolor 58 | mpl.rcParams['savefig.facecolor'] = facecolor 59 | if ax: 60 | mpl.rcParams['axes.facecolor'] = facecolor 61 | 62 | self.background = facecolor 63 | 64 | return self 65 | 66 | def set_plot_colors(self, primary_color=None, secondary_color=None, 67 | tertiary_color=None, fourth_color=None, 68 | fifth_color=None, sixth_color=None): 69 | """[summary] 70 | 71 | Args: 72 | primary_color ([type], optional): [description]. Defaults to None. 73 | secondary_color ([type], optional): [description]. Defaults to None. 74 | tertiary_color ([type], optional): [description]. Defaults to None. 75 | fourth_color ([type], optional): [description]. Defaults to None. 76 | fifth_color ([type], optional): [description]. Defaults to None. 77 | sixth_color ([type], optional): [description]. Defaults to None. 78 | """ 79 | 80 | current_cycler = [x['color'] for x in list(mpl.rcParams['axes.prop_cycle'])] 81 | set_colors = [primary_color, secondary_color, 82 | tertiary_color, fourth_color, 83 | fifth_color, sixth_color] 84 | i = 0 85 | for color in set_colors: 86 | if color is not None: 87 | current_cycler[i] = color 88 | i += 1 89 | 90 | mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=current_cycler) 91 | self.primary_color = current_cycler[0] 92 | self.secondary_color = current_cycler[1] 93 | self.tertiary_color = current_cycler[2] 94 | self.fourth_color = current_cycler[3] 95 | 96 | return self 97 | 98 | def set_font(self, fontfamily=None, color=None): 99 | """Sets the font that will be used for plotting. 100 | 101 | Args: 102 | fontfamily (str, optional): name of font that is 103 | currently availble in matplotlib. Defaults to None. 104 | color (string, optional): color as name, hexcode, or RGB. Defaults to None. 105 | 106 | Returns: 107 | updated self.fontfamily 108 | self.title_font 109 | self.body_font 110 | """ 111 | 112 | if fontfamily is None: 113 | self.fontfamily = mpl.rcParams['font.family'] 114 | else: 115 | self.fontfamily = fontfamily 116 | mpl.rcParams['font.family'] = fontfamily 117 | self.title_font = {"fontfamily": fontfamily} 118 | self.body_font = {"fontfamily": fontfamily} 119 | 120 | if color is None: 121 | self.fontcolor = mpl.rcParams['axes.labelcolor'] 122 | else: 123 | self.fontcolor = color 124 | mpl.rcParams['text.color'] = color 125 | mpl.rcParams['axes.labelcolor'] = color 126 | mpl.rcParams['xtick.color'] = color 127 | mpl.rcParams['ytick.color'] = color 128 | self.title_font.update({"color": color}) 129 | self.body_font.update({"color": color}) 130 | 131 | return self 132 | 133 | def set_title_font(self, title_font=None, color=None): 134 | """ 135 | Allows us to use a different font with **kwarg. 136 | This does not automatically change the title font. 137 | e.g: 138 | theme = themepy.Theme() 139 | theme.set_title_font("Arial") 140 | 141 | fig, ax = plt.subplots(figsize=(8,8)) 142 | 143 | ax.set_title("This is a title", **theme.title_font) 144 | 145 | plt.show() 146 | 147 | Input 148 | ===== 149 | title_font: str - name of font that is 150 | currently availble in matplotlib 151 | 152 | Returns 153 | ======= 154 | updated self.title_font 155 | 156 | 157 | """ 158 | if title_font is None: 159 | self.title_font = {"fontfamily": mpl.rcParams['font.family']} 160 | else: 161 | self.title_font = {"fontfamily": title_font} 162 | 163 | if color is not None: 164 | self.title_font.update({"color": color}) 165 | 166 | return self 167 | 168 | def set_body_font(self, body_font=None, color=None): 169 | """ 170 | Allows us to use a different font with **kwarg. 171 | This does not automatically change the body font. 172 | 173 | e.g: 174 | theme = themepy.Theme() 175 | theme.set_title_font("Arial") 176 | 177 | fig, ax = plt.subplots(figsize=(8,8)) 178 | 179 | ax.text(0.5, 0.5, 180 | "This is a some text", **theme.body_font) 181 | 182 | plt.show() 183 | 184 | Input 185 | ===== 186 | body_font: str - name of font that is 187 | currently availble in matplotlib 188 | 189 | Returns 190 | ======= 191 | updated self.body_font 192 | """ 193 | if body_font is None: 194 | self.body_font = {"fontfamily": mpl.rcParams['font.family']} 195 | else: 196 | self.body_font = {"fontfamily": body_font} 197 | 198 | if color is not None: 199 | self.body_font.update({"color": color}) 200 | 201 | return self 202 | 203 | def set_pips(self, state=True, color=None): 204 | """ 205 | Show or hide tick lines on plots. 206 | 207 | Input 208 | ===== 209 | state: bool - True or False 210 | color: str 211 | 212 | Returns 213 | ======= 214 | updated mpl.rcParams with ticks toggled on or off 215 | """ 216 | if state in ["on", True]: 217 | mpl.rcParams['xtick.bottom'] = True 218 | mpl.rcParams['ytick.left'] = True 219 | elif state in ["off", False]: 220 | mpl.rcParams['xtick.bottom'] = False 221 | mpl.rcParams['ytick.left'] = False 222 | 223 | else: 224 | raise NameError("unrecognised state. Must be one of True/False or 'on'/'off") 225 | 226 | if color is not None: 227 | mpl.rcParams['xtick.color'] = color 228 | mpl.rcParams['ytick.color'] = color 229 | 230 | return self 231 | 232 | def set_spines(self, state="on", 233 | which=["top", "right", "bottom", "left"], 234 | color=None, 235 | linewidth=None): 236 | """ 237 | Sets the spines on or off. A method in matplotlib 238 | to turn spines off might be: 239 | 240 | Input 241 | ===== 242 | state: str - "on" or "off" 243 | which: list - spines to be turned on or off. 244 | color: (optional) str - option to change color of spine 245 | 246 | Returns 247 | ======= 248 | updated mpl.rcParams for spine visibility 249 | """ 250 | if state == "on": 251 | switch = True 252 | else: 253 | switch = False 254 | 255 | for spine in which: 256 | mpl.rcParams['axes.spines.'+spine] = switch 257 | 258 | if color is not None: 259 | mpl.rcParams['axes.edgecolor'] = color 260 | 261 | if linewidth is not None: 262 | mpl.rcParams['axes.linewidth'] = linewidth 263 | 264 | return self 265 | 266 | def set_ticklabel_size(self, size="medium", which="both"): 267 | """ 268 | Sets the size of x, y, or both ticklabels. 269 | 270 | Input 271 | ===== 272 | size: str or int 273 | which: str - 'both', 'x', or 'y' 274 | 275 | Returns 276 | ======= 277 | updated mpl.rcParams for x and/or y tick labelsize 278 | """ 279 | if (type(size) is str) & (size not in ["small", "medium", "large"]): 280 | raise ValueError("""{} is not a value size arguement. Size must either be a value or one of xx-small, x-small, small, medium, large, x-large, xx-large, smaller, larger""".format(size)) 281 | 282 | if which == "both": 283 | mpl.rcParams['xtick.labelsize'] = size 284 | mpl.rcParams['ytick.labelsize'] = size 285 | 286 | elif which == "x": 287 | mpl.rcParams['xtick.labelsize'] = size 288 | 289 | elif which == "y": 290 | mpl.rcParams['ytick.labelsize'] = size 291 | 292 | else: 293 | raise KeyError("{} is not a valid arg. Must be 'both' or one of 'x' or 'y'".format(which)) 294 | 295 | return self 296 | 297 | def set_grid(self, state="on", which=None, axis=None, color=None, 298 | alpha=None, linestyle=None, linewidth=None): 299 | """ 300 | Sets the grid on or off. 301 | 302 | Input 303 | ===== 304 | state: str - "on" or "off" 305 | which: (optional) str - {'major', 'minor', 'both'} 306 | axis: (optional) str - {"both", "x", "y"} 307 | color: (optional) str - grid color 308 | alpha: (optional) str - grid alpha 309 | linestyle: (optional) str - grid linestyle 310 | linewidth: (optional) str - grid linewidth 311 | 312 | Returns 313 | ======= 314 | updated mpl.rcParams for the axes grid 315 | 316 | """ 317 | if state == "on": 318 | switch = True 319 | else: 320 | switch = False 321 | 322 | mpl.rcParams['axes.grid'] = switch 323 | mpl.rcParams['polaraxes.grid'] = switch 324 | mpl.rcParams['axes3d.grid'] = switch 325 | 326 | if which is not None: 327 | mpl.rcParams['axes.grid.which'] = which 328 | 329 | if color is not None: 330 | mpl.rcParams['grid.color'] = color 331 | 332 | if axis is not None: 333 | mpl.rcParams['axes.grid.axis'] = axis 334 | 335 | if alpha is not None: 336 | mpl.rcParams['grid.alpha'] = alpha 337 | 338 | if linestyle is not None: 339 | mpl.rcParams['grid.linestyle'] = linestyle 340 | 341 | if linewidth is not None: 342 | mpl.rcParams['grid.linewidth'] = linewidth 343 | 344 | return self 345 | 346 | def set_rcparams(self, *args): 347 | """general purpose function to update the rcParams 348 | 349 | example: 350 | theme.set_rcparams({'axes.titlepad': 20, 'axes.titleweight': 'bold'}) 351 | """ 352 | mpl.rcParams.update(*args) 353 | return self 354 | 355 | def set_updated_rcparams(self): 356 | """ 357 | sets the non-default rcParams to updated_params 358 | """ 359 | self.updated_params = {} 360 | 361 | for key, val in mpl.rcParams.items(): 362 | default = mpl.rcParamsDefault[key] 363 | if default != val: 364 | self.updated_params[key] = val 365 | 366 | if 'axes.prop_cycle' in self.updated_params: 367 | cycler_ = self.updated_params.pop('axes.prop_cycle') 368 | cycler_colors = cycler_.by_key()['color'] 369 | self.updated_params['cycler-prop-cycles'] = cycler_colors 370 | 371 | def add_theme(self, theme_name): 372 | """ 373 | saves the non-default params of the theme locally to /themes/[theme_name].txt 374 | 375 | Input 376 | ===== 377 | theme_name (string): the name of the theme 378 | """ 379 | if theme_name in list_themes(): 380 | choice = input(f"A theme named {theme_name} already exists, would you like to overwrite? [y/n]") 381 | if "y" in choice.lower(): 382 | self.set_updated_rcparams() 383 | with open(path.dirname(path.abspath(__file__))+'/themes/'+theme_name+'.txt', 'w') as file: 384 | print(str(self.updated_params).replace(', ', ',\n'), file=file) 385 | 386 | print(f"Theme {theme_name} successfully overwritten") 387 | else: 388 | print("please use a different theme name") 389 | 390 | else: 391 | self.set_updated_rcparams() 392 | with open(path.dirname(path.abspath(__file__))+'/themes/'+theme_name+'.txt', 'w') as file: 393 | print(str(self.updated_params).replace(', ', ',\n'), file=file) 394 | 395 | print(f"Theme {theme_name} successfully added locally") 396 | -------------------------------------------------------------------------------- /themepy/themes/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ -------------------------------------------------------------------------------- /themepy/themes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petermckeeverPerform/themepy/25cf3f5c814af200588b900242dd038bc770a97f/themepy/themes/__init__.py -------------------------------------------------------------------------------- /themepy/themes/barcanumbers-lightgrey.txt: -------------------------------------------------------------------------------- 1 | {'axes.edgecolor': '#000000', 2 | 'axes.facecolor': '#f9f9f9', 3 | 'axes.grid': True, 4 | 'axes.labelcolor': '#503939', 5 | 'axes.labelpad': 10.0, 6 | 'axes.linewidth': 0.25, 7 | 'axes.spines.right': False, 8 | 'axes.spines.top': False, 9 | 'axes.titlelocation': 'left', 10 | 'axes.titlepad': 25.0, 11 | 'axes.titlesize': 16.0, 12 | 'axes.titleweight': 'regular', 13 | 'figure.facecolor': '#f9f9f9', 14 | 'figure.subplot.wspace': 0.25, 15 | 'font.family': ['Roboto'], 16 | 'grid.color': '#e6e6e6', 17 | 'grid.linewidth': 0.25, 18 | 'lines.linewidth': 1.0, 19 | 'savefig.bbox': 'tight', 20 | 'savefig.edgecolor': '#f9f9f9', 21 | 'savefig.facecolor': '#f9f9f9', 22 | 'text.color': '#503939', 23 | 'xtick.bottom': False, 24 | 'xtick.color': '#503939', 25 | 'xtick.labelsize': 10.0, 26 | 'ytick.color': '#503939', 27 | 'ytick.labelsize': 10.0, 28 | 'ytick.left': False, 29 | 'cycler-prop-cycles': ['#d62728', 30 | '#1f77b4', 31 | '#2ca02c', 32 | '#ff7f0e', 33 | '#e377c2', 34 | '#17becf', 35 | '#bcbd22', 36 | '#9467bd', 37 | '#7f7f7f']} 38 | -------------------------------------------------------------------------------- /themepy/themes/blueprint.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "white", 3 | 'ytick.color' : "white", 4 | 'text.color' : "white", 5 | 'figure.facecolor' : "#2E3561", 6 | 'figure.edgecolor' : "#2E3561", 7 | 'axes.facecolor' : "#2E3561", 8 | 'axes.edgecolor' : "white", 9 | 'axes.labelcolor':'white', 10 | 'savefig.edgecolor' : "#2E3561", 11 | 'savefig.facecolor' : "#2E3561", 12 | 'grid.color' : "#323034", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#000F55', '#D22042', 15 | '#03873C', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | 'font.family': 'Neucha' 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /themepy/themes/dark.txt: -------------------------------------------------------------------------------- 1 | {'axes.edgecolor': '#969696', 2 | 'axes.facecolor': '#252526', 3 | 'axes.grid': True, 4 | 'axes.labelcolor': '#f0f0f0', 5 | 'axes.labelsize': 10.0, 6 | 'axes.linewidth': 0.25, 7 | 'axes.spines.right': False, 8 | 'axes.spines.top': False, 9 | 'axes.titlecolor': '#f0f0f0', 10 | 'axes.titlepad': 20.0, 11 | 'axes.titlesize': 16.0, 12 | 'figure.edgecolor': '#252526', 13 | 'figure.facecolor': '#252526', 14 | 'figure.subplot.wspace': 0.25, 15 | 'font.family': ['Roboto'], 16 | 'grid.color': '#bdbdbd', 17 | 'grid.linewidth': 0.175, 18 | 'legend.edgecolor': '#252526', 19 | 'legend.facecolor': '#252526', 20 | 'legend.frameon': False, 21 | 'savefig.bbox': 'tight', 22 | 'savefig.edgecolor': '#252526', 23 | 'savefig.facecolor': '#252526', 24 | 'text.color': '#f0f0f0', 25 | 'xtick.bottom': False, 26 | 'xtick.color': '#f0f0f0', 27 | 'xtick.labelsize': 8.0, 28 | 'ytick.color': '#f0f0f0', 29 | 'ytick.labelsize': 8.0, 30 | 'ytick.left': False, 31 | 'cycler-prop-cycles': ['#aaff17', 32 | '#ffaa00', 33 | '#00e5ff', 34 | '#fc68af', 35 | '#fbff00', 36 | '#ff2b2b', 37 | '#0077ff', 38 | '#d000ff', 39 | '#00eb1b']} 40 | -------------------------------------------------------------------------------- /themepy/themes/financial-times-light.txt: -------------------------------------------------------------------------------- 1 | {'axes.edgecolor': '#6b5e55', 2 | 'axes.facecolor': '#fff1e5', 3 | 'axes.grid': True, 4 | 'axes.labelcolor': '#66605c', 5 | 'axes.labelpad': 6.0, 6 | 'axes.spines.left': False, 7 | 'axes.spines.right': False, 8 | 'axes.spines.top': False, 9 | 'axes.titlelocation': 'left', 10 | 'axes.titlepad': 20.0, 11 | 'axes.titlesize': 16.0, 12 | 'figure.facecolor': '#fff1e5', 13 | 'figure.subplot.wspace': 0.25, 14 | 'font.family': ['Roboto'], 15 | 'grid.color': '#e6d9ce', 16 | 'lines.linewidth': 2.5, 17 | 'savefig.bbox': 'tight', 18 | 'savefig.edgecolor': '#fff1e5', 19 | 'savefig.facecolor': '#fff1e5', 20 | 'text.color': '#66605c', 21 | 'xtick.color': '#66605c', 22 | 'xtick.labelsize': 12.0, 23 | 'ytick.color': '#66605c', 24 | 'ytick.labelsize': 12.0, 25 | 'ytick.left': False, 26 | 'cycler-prop-cycles': ['#ea538c', 27 | '#70dce6', 28 | '#f34d5b', 29 | '#0f5499', 30 | '#79972a', 31 | '#288dc5', 32 | '#e377c2', 33 | '#7f7f7f', 34 | '#bcbd22', 35 | '#17becf']} 36 | -------------------------------------------------------------------------------- /themepy/themes/fivethirtyeight-grey.txt: -------------------------------------------------------------------------------- 1 | {'axes.facecolor': '#f0f0f0', 2 | 'axes.grid': True, 3 | 'axes.labelcolor': '#222222', 4 | 'axes.labelpad': 5.0, 5 | 'axes.spines.bottom': False, 6 | 'axes.spines.left': False, 7 | 'axes.spines.right': False, 8 | 'axes.spines.top': False, 9 | 'axes.titlelocation': 'left', 10 | 'axes.titlepad': 15.0, 11 | 'axes.titlesize': 14.0, 12 | 'axes.titleweight': 'regular', 13 | 'figure.facecolor': '#f0f0f0', 14 | 'figure.subplot.wspace': 0.25, 15 | 'font.family': ['Roboto'], 16 | 'grid.color': '#cdcdcd', 17 | 'grid.linewidth': 0.4, 18 | 'lines.linewidth': 2.5, 19 | 'patch.linewidth': 1.75, 20 | 'savefig.facecolor': '#f0f0f0', 21 | 'text.color': '#222222', 22 | 'xtick.bottom': False, 23 | 'xtick.color': '#999999', 24 | 'xtick.labelsize': 10.0, 25 | 'xtick.major.pad': 0.5, 26 | 'xtick.minor.pad': 0.5, 27 | 'ytick.color': '#999999', 28 | 'ytick.labelsize': 10.0, 29 | 'ytick.left': False, 30 | 'ytick.major.pad': 0.5, 31 | 'ytick.minor.pad': 0.5, 32 | 'cycler-prop-cycles': ['#67bec8', 33 | '#f4d04f', 34 | '#7056a1', 35 | '#fc5285', 36 | '#34b8ff', 37 | '#ff7f04', 38 | '#48a949', 39 | '#ff4e03']} 40 | -------------------------------------------------------------------------------- /themepy/themes/fivethirtyeight-white.txt: -------------------------------------------------------------------------------- 1 | {'axes.facecolor': 'w', 2 | 'axes.grid': True, 3 | 'axes.labelcolor': '#222222', 4 | 'axes.labelpad': 5.0, 5 | 'axes.spines.bottom': False, 6 | 'axes.spines.left': False, 7 | 'axes.spines.right': False, 8 | 'axes.spines.top': False, 9 | 'axes.titlelocation': 'left', 10 | 'axes.titlepad': 15.0, 11 | 'axes.titlesize': 14.0, 12 | 'axes.titleweight': 'regular', 13 | 'figure.facecolor': 'w', 14 | 'figure.subplot.wspace': 0.25, 15 | 'font.family': ['Roboto'], 16 | 'grid.color': '#cdcdcd', 17 | 'grid.linewidth': 0.4, 18 | 'lines.linewidth': 2.5, 19 | 'patch.linewidth': 1.75, 20 | 'savefig.facecolor': 'w', 21 | 'text.color': '#222222', 22 | 'xtick.bottom': False, 23 | 'xtick.color': '#999999', 24 | 'xtick.labelsize': 10.0, 25 | 'xtick.major.pad': 0.5, 26 | 'xtick.minor.pad': 0.5, 27 | 'ytick.color': '#999999', 28 | 'ytick.labelsize': 10.0, 29 | 'ytick.left': False, 30 | 'ytick.major.pad': 0.5, 31 | 'ytick.minor.pad': 0.5, 32 | 'cycler-prop-cycles': ['#67bec8', 33 | '#f4d04f', 34 | '#7056a1', 35 | '#fc5285', 36 | '#34b8ff', 37 | '#ff7f04', 38 | '#48a949', 39 | '#ff4e03']} 40 | -------------------------------------------------------------------------------- /themepy/themes/gadfly.txt: -------------------------------------------------------------------------------- 1 | { 2 | "lines.linewidth" : 2, 3 | 4 | "lines.markeredgecolor": "white", 5 | "lines.markeredgewidth": 1, 6 | "lines.markersize": 7, 7 | 8 | "patch.linewidth": 1, 9 | "patch.facecolor": "C0", 10 | "patch.edgecolor": "black", 11 | 12 | "boxplot.patchartist": True, 13 | 14 | "boxplot.flierprops.color": "C0", 15 | "boxplot.flierprops.marker": "o", 16 | "boxplot.flierprops.markerfacecolor": "auto", 17 | "boxplot.flierprops.markeredgecolor": "white", 18 | "boxplot.flierprops.markersize": 7, 19 | "boxplot.flierprops.linestyle": "none", 20 | "boxplot.flierprops.linewidth": 1.0, 21 | 22 | "boxplot.boxprops.color": "#9ae1f9", 23 | "boxplot.boxprops.linewidth": 0, 24 | "boxplot.boxprops.linestyle": "-", 25 | 26 | "boxplot.whiskerprops.color": "C0", 27 | "boxplot.whiskerprops.linewidth": 1.0, 28 | "boxplot.whiskerprops.linestyle": "-", 29 | 30 | "boxplot.capprops.color": "C0", 31 | "boxplot.capprops.linewidth": 1.0, 32 | "boxplot.capprops.linestyle": "-", 33 | 34 | "boxplot.medianprops.color": "#9ae1f9", 35 | "boxplot.medianprops.linewidth": 1, 36 | "boxplot.medianprops.linestyle": "-", 37 | 38 | "boxplot.meanprops.color": "C1", 39 | "boxplot.meanprops.marker": "^", 40 | "boxplot.meanprops.markerfacecolor": "C1", 41 | "boxplot.meanprops.markeredgecolor": "C1", 42 | "boxplot.meanprops.markersize": 7, 43 | "boxplot.meanprops.linestyle": "--", 44 | "boxplot.meanprops.linewidth": 1.0, 45 | 46 | "text.color": "#707074", 47 | 48 | "axes.edgecolor": "#D0D0E0", 49 | "axes.grid": True, 50 | "axes.grid.axis": "both", 51 | "axes.titlesize": 18, 52 | "axes.labelsize": 14, 53 | "axes.labelcolor": "#707074", 54 | 55 | "axes.spines.left": False, 56 | "axes.spines.bottom": False, 57 | "axes.spines.top": False, 58 | "axes.spines.right": False, 59 | "cycler-prop-cycles": ['#00BEFF', '#D4CA3A', '#FF6DAE', '#67E1B5', '#EBACFA', '#9E9E9E', '#F1988E', '#5DB15A', '#E28544', '#52B8AA'], 60 | 61 | "xtick.color": "#707074", 62 | "xtick.labelsize": 12, 63 | "ytick.color": "#707074", 64 | "ytick.labelsize": 12, 65 | 66 | "grid.color": "#93939c", 67 | "grid.linestyle": "--", 68 | "grid.alpha": 0.2, 69 | } 70 | -------------------------------------------------------------------------------- /themepy/themes/git_themes_list.log: -------------------------------------------------------------------------------- 1 | blueprint 2 | dark 3 | financial-times-light 4 | fivethirtyeight-grey 5 | fivethirtyeight-white 6 | gadfly 7 | neon 8 | paper 9 | sample-light 10 | sample-light2 11 | sample-dark 12 | sample-dark2 13 | 14 | 15 | -------------------------------------------------------------------------------- /themepy/themes/neon.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "w", 3 | 'ytick.color' : "w", 4 | 'text.color' : "w", 5 | 'figure.facecolor' : "#282c34", 6 | 'figure.edgecolor' : "#282c34", 7 | 'axes.facecolor' : "#282c34", 8 | 'axes.edgecolor' : "w", 9 | 'axes.labelcolor':'w', 10 | 'savefig.edgecolor' : "#282c34", 11 | 'savefig.facecolor' : "#282c34", 12 | 'grid.color' : "lightgrey", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#00FFFF', '#FFFF00', 15 | '#00FF00', '#FF0000', 16 | '#FF00FF', '#9D00FF', 17 | '#FF6600', '#0033FF'], 18 | } -------------------------------------------------------------------------------- /themepy/themes/paper.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "#323034", 3 | 'ytick.color' : "#323034", 4 | 'text.color' : "#323034", 5 | 'figure.facecolor' : "#F3EDDF", 6 | 'figure.edgecolor' : "#F3EDDF", 7 | 'axes.facecolor' : "#F3EDDF", 8 | 'axes.edgecolor' : "black", 9 | 'axes.labelcolor':'black', 10 | 'savefig.edgecolor' : "#F3EDDF", 11 | 'savefig.facecolor' : "#F3EDDF", 12 | 'grid.color' : "#323034", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#000F55', '#D22042', 15 | '#03873C', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | 'font.family': 'Cedarville Cursive' 19 | } 20 | -------------------------------------------------------------------------------- /themepy/themes/sample-dark.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "w", 3 | 'ytick.color' : "w", 4 | 'text.color' : "w", 5 | 'figure.facecolor' : "#404040", 6 | 'figure.edgecolor' : "#404040", 7 | 'axes.facecolor' : "#404040", 8 | 'axes.edgecolor' : "w", 9 | 'axes.labelcolor':'w', 10 | 'savefig.edgecolor' : "#404040", 11 | 'savefig.facecolor' : "#404040", 12 | 'grid.color' : "lightgrey", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#00aeef', '#f7914d', 15 | 'g', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | } -------------------------------------------------------------------------------- /themepy/themes/sample-dark2.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "w", 3 | 'ytick.color' : "w", 4 | 'text.color' : "w", 5 | 'figure.facecolor' : "#282c34", 6 | 'figure.edgecolor' : "#282c34", 7 | 'axes.facecolor' : "#282c34", 8 | 'axes.edgecolor' : "w", 9 | 'axes.labelcolor':'w', 10 | 'savefig.edgecolor' : "#282c34", 11 | 'savefig.facecolor' : "#282c34", 12 | 'grid.color' : "lightgrey", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#00aeef', '#f7914d', 15 | 'g', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | } 19 | -------------------------------------------------------------------------------- /themepy/themes/sample-light.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "black", 3 | 'ytick.color' : "black", 4 | 'text.color' : "black", 5 | 'figure.facecolor' : "#F0F0F0", 6 | 'figure.edgecolor' : "#F0F0F0", 7 | 'axes.facecolor' : "#F0F0F0", 8 | 'axes.edgecolor' : "black", 9 | 'axes.labelcolor':'black', 10 | 'savefig.edgecolor' : "#F0F0F0", 11 | 'savefig.facecolor' : "#F0F0F0", 12 | 'grid.color' : "#083441", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#00aeef', '#f7914d', 15 | 'g', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | } -------------------------------------------------------------------------------- /themepy/themes/sample-light2.txt: -------------------------------------------------------------------------------- 1 | { 2 | 'xtick.color' : "black", 3 | 'ytick.color' : "black", 4 | 'text.color' : "black", 5 | 'figure.facecolor' : "#f5f4e6", 6 | 'figure.edgecolor' : "#f5f4e6", 7 | 'axes.facecolor' : "#f5f4e6", 8 | 'axes.edgecolor' : "black", 9 | 'axes.labelcolor':'black', 10 | 'savefig.edgecolor' : "#f5f4e6", 11 | 'savefig.facecolor' : "#f5f4e6", 12 | 'grid.color' : "#083441", 13 | 'axes.titlesize' : 20, 14 | 'cycler-prop-cycles' : ['#00aeef', '#f7914d', 15 | 'g', 'r', 16 | 'purple', 'y', 17 | 'pink', 'k'], 18 | } --------------------------------------------------------------------------------