├── .bumpversion.cfg ├── .circleci └── config.yml ├── .flake8 ├── .github ├── dependabot.yml └── workflows │ └── main.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE.txt ├── Makefile ├── README.md ├── cheatsheets.tex ├── check-diffs.py ├── check-links.py ├── check-matplotlib-version.py ├── check-num-pages.sh ├── docs ├── Makefile ├── _static │ └── favicon.ico ├── conf.py └── index.rst ├── figures ├── legend.pdf └── legend.svg ├── fonts ├── .gitignore └── Makefile ├── handout-beginner.tex ├── handout-intermediate.tex ├── handout-tips.tex ├── logos ├── logo2.png ├── mpl-logos2.py └── numfocus.png ├── requirements ├── Makefile ├── requirements.in └── requirements.txt ├── scripts ├── adjustements.py ├── advanced-plots.py ├── anatomy.py ├── animation.py ├── annotate.py ├── annotation-arrow-styles.py ├── annotation-connection-styles.py ├── basic-plots.py ├── colorbar.py ├── colormaps.py ├── colornames.py ├── colors.py ├── extents.py ├── fonts.py ├── interpolations.py ├── layouts.py ├── legend.py ├── linestyles.py ├── markers.py ├── performance-tips.py ├── plot-variations.py ├── projections.py ├── scales.py ├── sine.py ├── styles.py ├── text-alignments.py ├── tick-formatters.py ├── tick-locators.py ├── tick-multiple-locator.py ├── tip-color-range.py ├── tip-colorbar.py ├── tip-dotted.py ├── tip-dual-axis.py ├── tip-font-family.py ├── tip-hatched.py ├── tip-multiline.py ├── tip-outline.py ├── tip-post-processing.py └── tip-transparency.py └── styles ├── base.mplstyle ├── plotlet-grid.mplstyle ├── plotlet.mplstyle ├── sine-plot.mplstyle └── ticks.mplstyle /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 3.8.2 3 | 4 | [bumpversion:file:./check-matplotlib-version.py] 5 | search = __version__ == '{current_version}' 6 | replace = __version__ == '{new_version}' 7 | 8 | [bumpversion:glob:./handout-*.tex] 9 | search = Matplotlib {current_version} 10 | replace = Matplotlib {new_version} 11 | 12 | [bumpversion:file:./Makefile] 13 | search = v{current_version} 14 | replace = v{new_version} 15 | 16 | [bumpversion:file:./cheatsheets.tex] 17 | search = Version {current_version} 18 | replace = Version {new_version} 19 | 20 | [bumpversion:file:./requirements/requirements.in] 21 | search = matplotlib=={current_version} 22 | replace = matplotlib=={new_version} 23 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | python: circleci/python@0.2.1 5 | 6 | jobs: 7 | build_docs: 8 | docker: 9 | - image: cimg/python:3.9 10 | steps: 11 | - checkout 12 | - run: 13 | command: echo "placeholder" 14 | 15 | workflows: 16 | main: 17 | jobs: 18 | - build_docs 19 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E20,E22,E501,E701,F401,W 3 | 4 | [pep8] 5 | select = E12,E231,E241,E251,E26,E30 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | groups: 9 | actions: 10 | patterns: 11 | - "*" 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | pre-commit: 7 | runs-on: ubuntu-20.04 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: actions/setup-python@v5 11 | - uses: pre-commit/action@v3.0.1 12 | build: 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-python@v5 17 | with: 18 | python-version: "3.10" 19 | - name: Install dependencies 20 | run: | 21 | sudo apt update 22 | sudo apt install \ 23 | fontconfig \ 24 | imagemagick \ 25 | poppler-utils 26 | python -m pip install --upgrade pip 27 | pip install -r requirements/requirements.txt 28 | - name: Install Tex Live 29 | run: | 30 | sudo apt update 31 | sudo apt install \ 32 | texlive-base \ 33 | texlive-extra-utils \ 34 | texlive-fonts-extra \ 35 | texlive-fonts-recommended \ 36 | texlive-latex-base \ 37 | texlive-latex-extra \ 38 | texlive-latex-recommended \ 39 | texlive-xetex 40 | - name: Build artifacts 41 | run: | 42 | # adjust the ImageMagick policies to convert PDF to PNG 43 | # remove all policies restricting Ghostscript ability to process files 44 | # https://stackoverflow.com/q/52998331 45 | # https://stackoverflow.com/a/59193253 46 | sudo sed -i '/disable ghostscript format types/,+6d' /etc/ImageMagick-6/policy.xml 47 | # 48 | make -C fonts/ 49 | cp -r fonts/ /usr/share/fonts/ 50 | fc-cache 51 | make all 52 | - name: Run checks 53 | run: | 54 | make check 55 | - uses: actions/upload-artifact@v4 56 | if: ${{ always() }} 57 | with: 58 | name: build 59 | path: | 60 | cheatsheets.pdf 61 | handout-*.pdf 62 | ./docs/_build/html/ 63 | - uses: actions/upload-artifact@v4 64 | id: diffs-artifact-upload 65 | if: ${{ always() }} 66 | with: 67 | name: diffs 68 | path: | 69 | diffs/ 70 | - name: Output artifacts URL 71 | run: | 72 | echo 'Artifact URL:' \ 73 | '${{ steps.diffs-artifact-upload.outputs.artifact-url }}' \ 74 | >> $GITHUB_STEP_SUMMARY 75 | - name: Publish cheatsheets and handouts 76 | if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} 77 | uses: peaceiris/actions-gh-pages@v4 78 | with: 79 | github_token: ${{ secrets.GITHUB_TOKEN }} 80 | publish_dir: ./docs/_build/html/ 81 | force_orphan: true 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built cheatsheets and handouts 2 | # ---------------------------------- 3 | cheatsheets*.pdf 4 | cheatsheets*.png 5 | handout-*.pdf 6 | handout-*.png 7 | 8 | # TeX auxiliary files 9 | # ---------------------------------- 10 | *.aux 11 | *.log 12 | *.out 13 | *.upa 14 | 15 | # generated figures 16 | # ---------------------------------- 17 | figures/*.pdf 18 | fonts/**/*.[ot]tf 19 | 20 | # html build 21 | docs/_build/* 22 | 23 | # OS specific 24 | .DS_Store 25 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: | 2 | (?x)^( 3 | .+[.]svg| 4 | )$ 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.0.1 8 | hooks: 9 | - id: check-yaml 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | - repo: https://github.com/pycqa/flake8 13 | rev: 4.0.1 14 | hooks: 15 | - id: flake8 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020, Nicolas P. Rougier 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRC := $(wildcard *.tex) 2 | CONVERTFLAGS = -density 150 -alpha remove -depth 8 3 | 4 | .PHONY: default 5 | default: all 6 | 7 | .PHONY: all 8 | all: figures cheatsheets handouts docs 9 | 10 | .PHONY: figures 11 | figures: 12 | # generate the figures 13 | cd scripts && for script in *.py; do echo $$script; MPLBACKEND="agg" python $$script; done 14 | # crop some of the figures 15 | cd figures && pdfcrop adjustments.pdf adjustments.pdf 16 | cd figures && pdfcrop annotate.pdf annotate.pdf 17 | cd figures && pdfcrop annotation-arrow-styles.pdf annotation-arrow-styles.pdf 18 | cd figures && pdfcrop anatomy.pdf anatomy.pdf 19 | cd figures && pdfcrop colornames.pdf colornames.pdf 20 | cd figures && pdfcrop fonts.pdf fonts.pdf 21 | cd figures && pdfcrop markers.pdf markers.pdf 22 | cd figures && pdfcrop text-alignments.pdf text-alignments.pdf 23 | cd figures && pdfcrop tick-formatters.pdf tick-formatters.pdf 24 | cd figures && pdfcrop tick-locators.pdf tick-locators.pdf 25 | cd figures && pdfcrop tip-font-family.pdf tip-font-family.pdf 26 | cd figures && pdfcrop tip-hatched.pdf tip-hatched.pdf 27 | 28 | .PHONY: cheatsheets 29 | cheatsheets: 30 | xelatex cheatsheets.tex 31 | convert $(CONVERTFLAGS) cheatsheets.pdf -scene 1 cheatsheets.png 32 | 33 | .PHONY: handouts 34 | handouts: 35 | xelatex handout-beginner.tex 36 | xelatex handout-intermediate.tex 37 | xelatex handout-tips.tex 38 | convert $(CONVERTFLAGS) handout-tips.pdf handout-tips.png 39 | convert $(CONVERTFLAGS) handout-beginner.pdf handout-beginner.png 40 | convert $(CONVERTFLAGS) handout-intermediate.pdf handout-intermediate.png 41 | 42 | .PHONY: check 43 | check: 44 | ./check-matplotlib-version.py 45 | ./check-num-pages.sh cheatsheets.pdf 2 46 | ./check-num-pages.sh handout-tips.pdf 1 47 | ./check-num-pages.sh handout-beginner.pdf 1 48 | ./check-num-pages.sh handout-intermediate.pdf 1 49 | ./check-diffs.py 50 | ./check-links.py cheatsheets.pdf 51 | 52 | .PHONY: docs 53 | docs: 54 | make -C docs/ html 55 | cp ./cheatsheets*.p* ./docs/_build/html 56 | cp ./handout-*.p* ./docs/_build/html 57 | 58 | 59 | .PHONY: fonts 60 | fonts: 61 | make -C fonts/ 62 | 63 | .PHONY: clean 64 | clean: $(SRC) 65 | latexmk -c $^ 66 | - rm -rf ./build/ 67 | 68 | .PHONY: clean-all 69 | clean-all: clean 70 | - rm ./logos/mpl-logo2.pdf 71 | git clean -f -X ./figures/ 72 | git clean -f ./scripts/*.pdf 73 | 74 | .PHONY: requirements 75 | requirements: 76 | $(MAKE) -C ./requirements/ 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cheatsheets for Matplotlib users 2 | 3 | ## Cheatsheets 4 | Cheatsheet [(download pdf)](https://matplotlib.org/cheatsheets/cheatsheets.pdf) | | 5 | :------------------------------------------------------------------------------:|:----------------------------------------------------------: 6 | ![](https://matplotlib.org/cheatsheets/cheatsheets-1.png) | ![](https://matplotlib.org/cheatsheets/cheatsheets-2.png) 7 | 8 | ## Handouts 9 | 10 | Beginner handout [(download pdf)](https://matplotlib.org/cheatsheets/handout-beginner.pdf) | Intermediate handout [(download pdf)](https://matplotlib.org/cheatsheets/handout-intermediate.pdf) | Tips handout [(download pdf)](https://matplotlib.org/cheatsheets/handout-tips.pdf) 11 | :-----------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------: 12 | ![](https://matplotlib.org/cheatsheets/handout-beginner.png) | ![](https://matplotlib.org/cheatsheets/handout-intermediate.png) | ![](https://matplotlib.org/cheatsheets/handout-tips.png) 13 | 14 | # For contributors to the cheatsheets 15 | 16 | ## How to compile 17 | 18 | 1. You need to create a `fonts` repository with: 19 | 20 | * `fonts/roboto/*` : See https://fonts.google.com/specimen/Roboto 21 | or https://github.com/googlefonts/roboto/tree/master/src/hinted 22 | * `fonts/roboto-slab/*` : See https://fonts.google.com/specimen/Roboto+Slab 23 | or https://github.com/googlefonts/robotoslab/tree/master/fonts/static 24 | * `fonts/source-code-pro/*` : See https://fonts.google.com/specimen/Source+Code+Pro 25 | or https://github.com/adobe-fonts/source-code-pro/tree/release/OTF 26 | * `fonts/source-sans-pro/*` : See https://fonts.google.com/specimen/Source+Sans+Pro 27 | or https://github.com/adobe-fonts/source-sans-pro/tree/release/OTF 28 | * `fonts/source-serif-pro/*` : See https://fonts.google.com/specimen/Source+Serif+Pro 29 | or https://github.com/adobe-fonts/source-serif-pro/tree/release/OTF 30 | * `fonts/eb-garamond/*` : See https://bitbucket.org/georgd/eb-garamond/src/master 31 | * `fonts/pacifico/*` : See https://fonts.google.com/download?family=Pacifico 32 | 33 | On Linux, with `make` installed, the fonts can be set up with the following command: 34 | ```shell 35 | make -C fonts 36 | ``` 37 | 38 | The fonts can be made discoverable by `matplotlib` (through `fontconfig`) by creating the following in `$HOME/.config/fontconfig/fonts.conf` (see [here](https://www.freedesktop.org/software/fontconfig/fontconfig-user.html)): 39 | 40 | ```xml 41 | 42 | 43 | 44 | /path/to/cheatsheets/fonts/ 45 | ... 46 | 47 | ``` 48 | 49 | 50 | 2. You need to generate all the figures: 51 | 52 | ``` 53 | $ cd scripts 54 | $ for script in *.py; do python $script; done 55 | $ cd .. 56 | ``` 57 | 58 | 3. Compile the sheet 59 | ``` 60 | $ xelatex cheatsheets.tex 61 | $ xelatex cheatsheets.tex 62 | ``` 63 | -------------------------------------------------------------------------------- /check-diffs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | from pathlib import Path 7 | 8 | 9 | ROOT_DIR = Path(__file__).parent 10 | 11 | if os.environ.get('GITHUB_ACTIONS', '') == '': 12 | print('Not running when not in GitHub Actions.') 13 | sys.exit() 14 | summary_file = os.environ.get('GITHUB_STEP_SUMMARY') 15 | if summary_file is None: 16 | sys.exit('$GITHUB_STEP_SUMMARY is not set') 17 | 18 | gh_pages = ROOT_DIR.parent / 'pages' 19 | subprocess.run(['git', 'fetch', 'https://github.com/matplotlib/cheatsheets.git', 20 | 'gh-pages:upstream-gh-pages'], check=True) 21 | subprocess.run(['git', 'worktree', 'add', gh_pages, 'upstream-gh-pages'], 22 | check=True) 23 | 24 | diff_dir = ROOT_DIR / 'diffs' 25 | diff_dir.mkdir(exist_ok=True) 26 | 27 | hashes = {} 28 | for original in gh_pages.glob('*.png'): 29 | result = subprocess.run( 30 | ['compare', '-metric', 'PHASH', 31 | original, 32 | ROOT_DIR / 'docs/_build/html' / original.name, 33 | diff_dir / f'{original.stem}-diff.png'], 34 | text=True, stderr=subprocess.PIPE) 35 | if result.returncode == 2: # Some kind of IO or similar error. 36 | hashes[original] = (float('nan'), result.stderr) 37 | elif result.stderr: # Images were different. 38 | hashes[original] = (float(result.stderr), '') 39 | else: # No differences. 40 | hashes[original] = (0.0, '') 41 | 42 | with open(summary_file, 'w+') as summary: 43 | print('# Cheatsheet image comparison', file=summary) 44 | print('| Filename | Perceptual Hash Difference | Error message |', file=summary) 45 | print('| -------- | -------------------------- | ------------- |', file=summary) 46 | for filename, (hash, message) in sorted(hashes.items()): 47 | message = message.replace('\n', ' ').replace('|', '\\|') 48 | print(f'| {filename.name} | {hash:.05f} | {message}', file=summary) 49 | print(file=summary) 50 | 51 | subprocess.run(['git', 'worktree', 'remove', gh_pages]) 52 | -------------------------------------------------------------------------------- /check-links.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | import pdfx 5 | 6 | 7 | pdf = pdfx.PDFx(sys.argv[1]) 8 | 9 | refs = [ref for ref in pdf.get_references() if ref.reftype == 'url'] 10 | 11 | status_codes = [pdfx.downloader.get_status_code(ref.ref) for ref in refs] 12 | 13 | broken_links = [(ref.ref, code) for ref, code in zip(refs, status_codes) if code != 200] 14 | 15 | # it seems that Twitter does not respond well to the link checker and throws a 400 16 | if all(['twitter.com' in url for url, _ in broken_links]): 17 | sys.exit(0) 18 | else: 19 | print('Broken links:', broken_links) 20 | sys.exit(1) 21 | -------------------------------------------------------------------------------- /check-matplotlib-version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import matplotlib as mpl 3 | 4 | 5 | assert mpl.__version__ == '3.8.2' 6 | -------------------------------------------------------------------------------- /check-num-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Check that a given pdf has a certain number of pages. 4 | # Usage: 5 | # check-num-pages.sh [pdffile] [num_pages] 6 | 7 | set -x 8 | pdffile=$1 9 | num_pages=$2 10 | [[ "$(pdfinfo $pdffile | grep Pages | awk '{print $2}')" == "$num_pages" ]] || exit 1 11 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= -W 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | show: 16 | @python -c "import webbrowser; webbrowser.open_new_tab('file://$(shell pwd)/build/html/index.html')" 17 | 18 | .PHONY: help Makefile 19 | 20 | # Catch-all target: route all unknown targets to Sphinx using the new 21 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 22 | %: Makefile 23 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 24 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matplotlib/cheatsheets/f02ebb5f02abd3c5d5b02bb1f22737ab87e92a08/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | # -- Project information ----------------------------------------------------- 4 | 5 | html_title = 'Visualization with Python' 6 | project = "Matplotlib cheatsheets" 7 | copyright = ( 8 | f"2012 - {datetime.datetime.now().year} The Matplotlib development team" 9 | ) 10 | author = "Matplotlib Developers" 11 | 12 | # -- General configuration --------------------------------------------------- 13 | 14 | # Add any Sphinx extension module names here, as strings. They can be 15 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 16 | # ones. 17 | extensions = ["sphinx_design"] 18 | 19 | # Add any paths that contain templates here, relative to this directory. 20 | 21 | templates_path = [] 22 | 23 | # List of patterns, relative to source directory, that match files and 24 | # directories to ignore when looking for source files. 25 | # This pattern also affects html_static_path and html_extra_path. 26 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 27 | 28 | # -- Options for HTML output ------------------------------------------------- 29 | 30 | html_css_files = ['css/normalize.css', 'css/landing.css'] 31 | html_theme = "mpl_sphinx_theme" 32 | html_favicon = "_static/favicon.ico" 33 | html_theme_options = { 34 | "navbar_links": ("absolute", "server-stable"), 35 | } 36 | html_sidebars = { 37 | "**": [] 38 | } 39 | # Add any paths that contain custom static files (such as style sheets) here, 40 | # relative to this directory. They are copied after the theme static files, 41 | # so a file named "default.css" will overwrite the theme's "default.css". 42 | html_static_path = ["_static"] 43 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. title:: Matplotlib cheatsheets 2 | 3 | *********************************** 4 | Matplotlib cheatsheets and handouts 5 | *********************************** 6 | 7 | Cheatsheets 8 | *********** 9 | 10 | .. grid:: 2 11 | 12 | .. grid-item:: 13 | 14 | .. image:: ../cheatsheets-1.png 15 | :width: 270px 16 | :align: center 17 | :alt: image of first page of cheatsheets 18 | 19 | .. grid-item:: 20 | 21 | .. image:: ../cheatsheets-2.png 22 | :width: 270px 23 | :align: center 24 | :alt: image of second page of cheatsheets 25 | 26 | `Cheatsheets [pdf] <./cheatsheets.pdf>`_ 27 | 28 | 29 | 30 | Handouts 31 | ******** 32 | 33 | .. grid:: 1 2 3 3 34 | 35 | .. grid-item:: 36 | 37 | .. image:: ../handout-beginner.png 38 | :width: 270px 39 | :align: center 40 | :alt: image of beginner handout 41 | 42 | `Beginner [pdf] <./handout-beginner.pdf>`_ 43 | 44 | .. grid-item:: 45 | 46 | .. image:: ../handout-intermediate.png 47 | :width: 270px 48 | :align: center 49 | :alt: image of intermediate handout 50 | 51 | `Intermediate [pdf] <./handout-intermediate.pdf>`_ 52 | 53 | .. grid-item:: 54 | 55 | .. image:: ../handout-tips.png 56 | :width: 270px 57 | :align: center 58 | :alt: image of tips handout 59 | 60 | `Tips [pdf] <./handout-tips.pdf>`_ 61 | 62 | Contribute 63 | ********** 64 | 65 | Issues, suggestions, or pull-requests gratefully accepted at 66 | `matplotlib/cheatsheets `_ 67 | -------------------------------------------------------------------------------- /figures/legend.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matplotlib/cheatsheets/f02ebb5f02abd3c5d5b02bb1f22737ab87e92a08/figures/legend.pdf -------------------------------------------------------------------------------- /figures/legend.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 42 | 44 | 73 | 74 | 76 | 77 | 78 | 107 | 108 | 110 | 111 | 112 | 123 | 125 | 132 | 133 | 134 | 145 | 147 | 154 | 155 | 156 | 185 | 186 | 188 | 189 | 190 | 201 | 203 | 210 | 211 | 212 | 223 | 225 | 232 | 233 | 234 | 245 | 247 | 255 | 256 | 257 | 286 | 287 | 289 | 290 | 291 | 292 | Produced by OmniGraffle 7.11.1 294 | 2019-08-01 08:58:53 +0000 295 | 296 | 298 | image/svg+xml 299 | 301 | 302 | 303 | 304 | 305 | 313 | Canvas 1 315 | 317 | Layer 1 319 | 322 | 331 | 332 | 334 | 345 | 346 | 348 | 359 | 360 | 362 | 373 | 374 | 376 | Legend 387 | 388 | 390 | 400 | 401 | 404 | 411 | 421 | 422 | 425 | 432 | 442 | 443 | 445 | Label 1 456 | 457 | 459 | 469 | 470 | 473 | 480 | 490 | 491 | 494 | 501 | 511 | 512 | 514 | Label 2 525 | 526 | 528 | 538 | 539 | 542 | 549 | 559 | 560 | 563 | 570 | 580 | 581 | 583 | Label 3 594 | 595 | 597 | 607 | 608 | 611 | 618 | 628 | 629 | 632 | 639 | 649 | 650 | 652 | Label 4 663 | 664 | 666 | 678 | 679 | 681 | 693 | 694 | 696 | 708 | 709 | 711 | 723 | 724 | 726 | handletextpad 739 | 740 | 742 | handlelength 755 | 756 | 758 | 769 | 770 | 772 | 783 | 784 | 786 | 796 | 797 | 799 | 810 | 811 | 813 | 824 | 825 | 827 | columnspacing 840 | 841 | 843 | labelspacing 856 | 857 | 859 | 870 | 871 | 873 | 885 | 886 | 888 | borderpad 901 | 902 | 904 | 913 | 914 | 916 | handle 929 | 930 | 932 | 941 | 942 | 944 | label 957 | 958 | 961 | 971 | 972 | 974 | title 987 | 988 | 990 | 999 | 1000 | 1002 | 1014 | 1015 | 1017 | borderaxespad 1030 | 1031 | 1033 | 1042 | 1043 | 1045 | markerfacecolor (mfc) 1058 | 1059 | 1061 | 1070 | 1071 | 1073 | markeredgecolor (mec) 1086 | 1087 | 1089 | 1099 | 1100 | 1102 | 1113 | 1114 | 1116 | numpoints or scatterpoints 1131 | 1132 | 1133 | 1134 | 1135 | -------------------------------------------------------------------------------- /fonts/.gitignore: -------------------------------------------------------------------------------- 1 | .uuid 2 | -------------------------------------------------------------------------------- /fonts/Makefile: -------------------------------------------------------------------------------- 1 | FONT_DIRS := eb-garamond roboto roboto-mono roboto-slab source-code-pro source-sans-pro source-serif-pro pacifico 2 | 3 | EB_GARAMOND_ZIP := https://bitbucket.org/georgd/eb-garamond/downloads/EBGaramond-0.016.zip 4 | ROBOTO_ZIP := https://github.com/googlefonts/roboto/releases/download/v2.138/roboto-unhinted.zip 5 | ROBOTO_MONO_ZIP := https://github.com/googlefonts/RobotoMono/archive/8f651634e746da6df6c2c0be73255721d24f2372.zip 6 | ROBOTO_SLAB_ZIP := https://github.com/googlefonts/robotoslab/archive/a65e6d00d8e3e7ee2fabef844e58fa12690384d2.zip 7 | SOURCE_CODE_PRO_ZIP := https://github.com/adobe-fonts/source-code-pro/releases/download/2.038R-ro%2F1.058R-it%2F1.018R-VAR/OTF-source-code-pro-2.038R-ro-1.058R-it.zip 8 | SOURCE_SANS_PRO_ZIP := https://github.com/adobe-fonts/source-sans/releases/download/2.045R-ro%2F1.095R-it/source-sans-pro-2.045R-ro-1.095R-it.zip 9 | SOURCE_SERIF_PRO_ZIP := https://github.com/adobe-fonts/source-serif/releases/download/3.001R/source-serif-pro-3.001R.zip 10 | PACIFICO := https://raw.githubusercontent.com/googlefonts/Pacifico/refs/heads/main/fonts/ttf/Pacifico-Regular.ttf 11 | 12 | UNZIP_FLAGS := -x "__MACOSX/*" 13 | 14 | 15 | .PHONY: default 16 | default: all 17 | 18 | .PHONY: all 19 | all: sources 20 | mkdir -p $(FONT_DIRS) 21 | cd eb-garamond && unzip -j /tmp/eb-garamond.zip "EBGaramond-0.016/otf/*.otf" $(UNZIP_FLAGS) 22 | cd roboto && unzip -j /tmp/roboto.zip "*.ttf" $(UNZIP_FLAGS) 23 | cd roboto-mono && unzip -j /tmp/roboto-mono.zip "RobotoMono-8f651634e746da6df6c2c0be73255721d24f2372/fonts/ttf/*.ttf" $(UNZIP_FLAGS) 24 | cd roboto-slab && unzip -j /tmp/roboto-slab.zip "robotoslab-a65e6d00d8e3e7ee2fabef844e58fa12690384d2/fonts/static/*.ttf" $(UNZIP_FLAGS) 25 | cd source-code-pro && unzip -j /tmp/source-code-pro.zip "*.otf" $(UNZIP_FLAGS) 26 | cd source-sans-pro && unzip -j /tmp/source-sans-pro.zip "source-sans-pro-2.045R-ro-1.095R-it/OTF/*.otf" $(UNZIP_FLAGS) 27 | cd source-serif-pro && unzip -j /tmp/source-serif-pro.zip "source-serif-pro-3.001R/OTF/*.otf" $(UNZIP_FLAGS) 28 | cd pacifico && cp /tmp/pacifico.ttf . 29 | 30 | .PHONY: sources 31 | sources: 32 | wget $(EB_GARAMOND_ZIP) -O /tmp/eb-garamond.zip 33 | wget $(ROBOTO_ZIP) -O /tmp/roboto.zip 34 | wget $(ROBOTO_MONO_ZIP) -O /tmp/roboto-mono.zip 35 | wget $(ROBOTO_SLAB_ZIP) -O /tmp/roboto-slab.zip 36 | wget $(SOURCE_CODE_PRO_ZIP) -O /tmp/source-code-pro.zip 37 | wget $(SOURCE_SANS_PRO_ZIP) -O /tmp/source-sans-pro.zip 38 | wget $(SOURCE_SERIF_PRO_ZIP) -O /tmp/source-serif-pro.zip 39 | wget $(PACIFICO) -O /tmp/pacifico.ttf 40 | 41 | .PHONY: clean 42 | clean: 43 | - rm $(HOME)/.cache/matplotlib/fontlist* 44 | - rm -rf $(FONT_DIRS) 45 | -------------------------------------------------------------------------------- /handout-beginner.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,landscape,a4paper]{article} 2 | \usepackage[right=10mm, left=10mm, top=10mm, bottom=10mm]{geometry} 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[T1]{fontenc} 5 | \usepackage[english]{babel} 6 | \usepackage[rm,light]{roboto} 7 | \usepackage{xcolor} 8 | \usepackage{graphicx} 9 | \graphicspath{{./figures/}} 10 | \usepackage{multicol} 11 | \usepackage{colortbl} 12 | \usepackage{array} 13 | \setlength\parindent{0pt} 14 | \setlength{\tabcolsep}{2pt} 15 | \baselineskip=0pt 16 | \setlength\columnsep{1em} 17 | \definecolor{Gray}{gray}{0.85} 18 | 19 | % --- Listing ----------------------------------------------------------------- 20 | \usepackage{listings} 21 | \lstset{ 22 | frame=tb, framesep=4pt, framerule=0pt, 23 | backgroundcolor=\color{black!5}, 24 | basicstyle=\ttfamily, 25 | commentstyle=\ttfamily\color{black!50}, 26 | breakatwhitespace=false, 27 | breaklines=true, 28 | extendedchars=true, 29 | keepspaces=true, 30 | language=Python, 31 | rulecolor=\color{black}, 32 | showspaces=false, 33 | showstringspaces=false, 34 | showtabs=false, 35 | tabsize=2, 36 | % 37 | emph = { plot, scatter, imshow, bar, contourf, pie, subplots, show, savefig, 38 | errorbar, boxplot, hist, set_title, set_xlabel, set_ylabel, suptitle, }, 39 | emphstyle = {\ttfamily\bfseries} 40 | } 41 | 42 | % --- Fonts ------------------------------------------------------------------- 43 | \usepackage{fontspec} 44 | \usepackage[babel=true]{microtype} 45 | \defaultfontfeatures{Ligatures = TeX, Mapping = tex-text} 46 | \setsansfont{Roboto} [ Path = fonts/roboto/Roboto-, 47 | Extension = .ttf, 48 | UprightFont = Light, 49 | ItalicFont = LightItalic, 50 | BoldFont = Regular, 51 | BoldItalicFont = Italic ] 52 | \setromanfont{RobotoSlab} [ Path = fonts/roboto-slab/RobotoSlab-, 53 | Extension = .ttf, 54 | UprightFont = Light, 55 | BoldFont = Bold ] 56 | \setmonofont{RobotoMono} [ Path = fonts/roboto-mono/RobotoMono-, 57 | Extension = .ttf, 58 | Scale = 0.90, 59 | UprightFont = Light, 60 | ItalicFont = LightItalic, 61 | BoldFont = Regular, 62 | BoldItalicFont = Italic ] 63 | \renewcommand{\familydefault}{\sfdefault} 64 | 65 | % ----------------------------------------------------------------------------- 66 | \begin{document} 67 | \thispagestyle{empty} 68 | 69 | \section*{\LARGE \rmfamily 70 | Matplotlib \textcolor{orange}{\mdseries for beginners}} 71 | 72 | \begin{multicols*}{3} 73 | 74 | Matplotlib is a library for making 2D plots in Python. It is designed 75 | with the philosophy that you should be able to create simple plots 76 | with just a few commands:\\ 77 | 78 | \fbox{1} \textbf{Initialize} 79 | \begin{lstlisting} 80 | import numpy as np 81 | import matplotlib.pyplot as plt 82 | \end{lstlisting} 83 | % 84 | \fbox{2} \textbf{Prepare} 85 | \begin{lstlisting} 86 | X = np.linspace(0, 10*np.pi, 1000) 87 | Y = np.sin(X) 88 | \end{lstlisting} 89 | % 90 | \fbox{3} \textbf{Render} 91 | \begin{lstlisting} 92 | fig, ax = plt.subplots() 93 | ax.plot(X, Y) 94 | plt.show() 95 | \end{lstlisting} 96 | % 97 | \fbox{4} \textbf{Observe} \medskip\\ 98 | \includegraphics[width=\linewidth]{sine.pdf} 99 | 100 | % ----------------------------------------------------------------------------- 101 | \subsection*{\rmfamily Choose} 102 | % ----------------------------------------------------------------------------- 103 | 104 | Matplotlib offers several kind of plots (see Gallery): \medskip 105 | 106 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 107 | \begin{lstlisting}[belowskip=-\baselineskip] 108 | X = np.random.uniform(0, 1, 100) 109 | Y = np.random.uniform(0, 1, 100) 110 | ax.scatter(X, Y) 111 | \end{lstlisting} 112 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{basic-scatter.pdf}} 113 | \end{tabular} 114 | % ----------------------------------------------------------------------------- 115 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 116 | \begin{lstlisting}[belowskip=-\baselineskip] 117 | X = np.arange(10) 118 | Y = np.random.uniform(1, 10, 10) 119 | ax.bar(X, Y) 120 | \end{lstlisting} 121 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{basic-bar.pdf}} 122 | \end{tabular} 123 | % ----------------------------------------------------------------------------- 124 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 125 | \begin{lstlisting}[belowskip=-\baselineskip] 126 | Z = np.random.uniform(0, 1, (8, 8)) 127 | 128 | ax.imshow(Z) 129 | \end{lstlisting} 130 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{basic-imshow.pdf}} 131 | \end{tabular} 132 | % ----------------------------------------------------------------------------- 133 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 134 | \begin{lstlisting}[belowskip=-\baselineskip] 135 | Z = np.random.uniform(0, 1, (8, 8)) 136 | 137 | ax.contourf(Z) 138 | \end{lstlisting} 139 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{basic-contour.pdf}} 140 | \end{tabular} 141 | % ----------------------------------------------------------------------------- 142 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 143 | \begin{lstlisting}[belowskip=-\baselineskip] 144 | Z = np.random.uniform(0, 1, 4) 145 | 146 | ax.pie(Z) 147 | \end{lstlisting} 148 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{basic-pie.pdf}} 149 | \end{tabular} 150 | % ----------------------------------------------------------------------------- 151 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 152 | \begin{lstlisting}[belowskip=-\baselineskip] 153 | Z = np.random.normal(0, 1, 100) 154 | 155 | ax.hist(Z) 156 | \end{lstlisting} 157 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{advanced-hist.pdf}} 158 | \end{tabular} 159 | % ----------------------------------------------------------------------------- 160 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 161 | \begin{lstlisting}[belowskip=-\baselineskip] 162 | X = np.arange(5) 163 | Y = np.random.uniform(0, 1, 5) 164 | ax.errorbar(X, Y, Y/4) 165 | \end{lstlisting} 166 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{advanced-errorbar.pdf}} 167 | \end{tabular} 168 | % ----------------------------------------------------------------------------- 169 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 170 | \begin{lstlisting}[belowskip=-\baselineskip] 171 | Z = np.random.normal(0, 1, (100, 3)) 172 | 173 | ax.boxplot(Z) 174 | \end{lstlisting} 175 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{advanced-boxplot.pdf}} 176 | \end{tabular} 177 | 178 | 179 | % ----------------------------------------------------------------------------- 180 | \subsection*{\rmfamily Tweak} 181 | % ----------------------------------------------------------------------------- 182 | You can modify pretty much anything in a plot, including limits, 183 | colors, markers, line width and styles, ticks and ticks labels, 184 | titles, etc. \medskip 185 | 186 | % ----------------------------------------------------------------------------- 187 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 188 | \begin{lstlisting}[belowskip=-\baselineskip] 189 | X = np.linspace(0, 10, 100) 190 | Y = np.sin(X) 191 | ax.plot(X, Y, color="black") 192 | \end{lstlisting} 193 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-color.pdf}} 194 | \end{tabular} 195 | % ----------------------------------------------------------------------------- 196 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 197 | \begin{lstlisting}[belowskip=-\baselineskip] 198 | X = np.linspace(0, 10, 100) 199 | Y = np.sin(X) 200 | ax.plot(X, Y, linestyle="--") 201 | \end{lstlisting} 202 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-linestyle.pdf}} 203 | \end{tabular} 204 | % ----------------------------------------------------------------------------- 205 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 206 | \begin{lstlisting}[belowskip=-\baselineskip] 207 | X = np.linspace(0, 10, 100) 208 | Y = np.sin(X) 209 | ax.plot(X, Y, linewidth=5) 210 | \end{lstlisting} 211 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-linewidth.pdf}} 212 | \end{tabular} 213 | % ----------------------------------------------------------------------------- 214 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 215 | \begin{lstlisting}[belowskip=-\baselineskip] 216 | X = np.linspace(0, 10, 100) 217 | Y = np.sin(X) 218 | ax.plot(X, Y, marker="o") 219 | \end{lstlisting} 220 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-marker.pdf}} 221 | \end{tabular} 222 | 223 | 224 | % ----------------------------------------------------------------------------- 225 | \subsection*{\rmfamily Organize} 226 | % ----------------------------------------------------------------------------- 227 | 228 | You can plot several data on the same figure, but you can also split a figure 229 | in several subplots (named {\em Axes}): \medskip 230 | 231 | % ----------------------------------------------------------------------------- 232 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 233 | \begin{lstlisting}[belowskip=-\baselineskip] 234 | X = np.linspace(0, 10, 100) 235 | Y1, Y2 = np.sin(X), np.cos(X) 236 | ax.plot(X, Y1, X, Y2) 237 | \end{lstlisting} 238 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-multi.pdf}} 239 | \end{tabular} 240 | % ----------------------------------------------------------------------------- 241 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 242 | \begin{lstlisting}[belowskip=-\baselineskip] 243 | fig, (ax1, ax2) = plt.subplots(2, 1) 244 | ax1.plot(X, Y1, color="C1") 245 | ax2.plot(X, Y2, color="C0") 246 | \end{lstlisting} 247 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-vsplit.pdf}} 248 | \end{tabular} 249 | % ----------------------------------------------------------------------------- 250 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 251 | \begin{lstlisting}[belowskip=-\baselineskip] 252 | fig, (ax1, ax2) = plt.subplots(1, 2) 253 | ax1.plot(Y1, X, color="C1") 254 | ax2.plot(Y2, X, color="C0") 255 | \end{lstlisting} 256 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-hsplit.pdf}} 257 | \end{tabular} 258 | 259 | % ----------------------------------------------------------------------------- 260 | \subsection*{\rmfamily Label \mdseries (everything)} 261 | % ----------------------------------------------------------------------------- 262 | % ----------------------------------------------------------------------------- 263 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 264 | \begin{lstlisting}[belowskip=-\baselineskip] 265 | ax.plot(X, Y) 266 | fig.suptitle(None) 267 | ax.set_title("A Sine wave") 268 | \end{lstlisting} 269 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-title.pdf}} 270 | \end{tabular} 271 | % ----------------------------------------------------------------------------- 272 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 273 | \begin{lstlisting}[belowskip=-\baselineskip] 274 | ax.plot(X, Y) 275 | ax.set_ylabel(None) 276 | ax.set_xlabel("Time") 277 | \end{lstlisting} 278 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{plot-xlabel.pdf}} 279 | \end{tabular} 280 | 281 | % ----------------------------------------------------------------------------- 282 | \subsection*{\rmfamily Explore} 283 | % ----------------------------------------------------------------------------- 284 | 285 | Figures are shown with a graphical user interface that allows to zoom 286 | and pan the figure, to navigate between the different views and to 287 | show the value under the mouse. 288 | 289 | % ----------------------------------------------------------------------------- 290 | \subsection*{\rmfamily Save \mdseries (bitmap or vector format)} 291 | % ----------------------------------------------------------------------------- 292 | \begin{lstlisting}[belowskip=-\baselineskip] 293 | fig.savefig("my-first-figure.png", dpi=300) 294 | fig.savefig("my-first-figure.pdf") 295 | \end{lstlisting} 296 | % 297 | \vfill 298 | % 299 | {\scriptsize 300 | Matplotlib 3.8.2 handout for beginners. 301 | Copyright (c) 2021 Matplotlib Development Team. 302 | Released under a CC-BY 4.0 International License. 303 | Supported by NumFOCUS. 304 | \par} 305 | 306 | \end{multicols*} 307 | \end{document} 308 | -------------------------------------------------------------------------------- /handout-intermediate.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,landscape,a4paper]{article} 2 | \usepackage[right=10mm, left=10mm, top=10mm, bottom=10mm]{geometry} 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[T1]{fontenc} 5 | \usepackage[english]{babel} 6 | \usepackage[rm,light]{roboto} 7 | \usepackage{xcolor} 8 | \usepackage{graphicx} 9 | \graphicspath{{./figures/}} 10 | \usepackage{multicol} 11 | \usepackage{colortbl} 12 | \usepackage{array} 13 | \setlength\parindent{0pt} 14 | \setlength{\tabcolsep}{2pt} 15 | \baselineskip=0pt 16 | \setlength\columnsep{1em} 17 | \definecolor{Gray}{gray}{0.85} 18 | 19 | % --- Listing ----------------------------------------------------------------- 20 | \usepackage{listings} 21 | \lstset{ 22 | frame=tb, framesep=4pt, framerule=0pt, 23 | backgroundcolor=\color{black!5}, 24 | basicstyle=\ttfamily, 25 | commentstyle=\ttfamily\color{black!50}, 26 | breakatwhitespace=false, 27 | breaklines=true, 28 | extendedchars=true, 29 | keepspaces=true, 30 | language=Python, 31 | rulecolor=\color{black}, 32 | showspaces=false, 33 | showstringspaces=false, 34 | showtabs=false, 35 | tabsize=2, 36 | % 37 | emph = { plot, scatter, imshow, bar, contourf, pie, subplots, spines, 38 | add_gridspec, add_subplot, set_xscale, set_minor_locator, 39 | annotate, set_minor_formatter, tick_params, fill_betweenx, text, legend, 40 | errorbar, boxplot, hist, title, xlabel, ylabel, suptitle }, 41 | emphstyle = {\ttfamily\bfseries} 42 | } 43 | 44 | % --- Fonts ------------------------------------------------------------------- 45 | \usepackage{fontspec} 46 | \usepackage[babel=true]{microtype} 47 | \defaultfontfeatures{Ligatures = TeX, Mapping = tex-text} 48 | \setsansfont{Roboto} [ Path = fonts/roboto/Roboto-, 49 | Extension = .ttf, 50 | UprightFont = Light, 51 | ItalicFont = LightItalic, 52 | BoldFont = Regular, 53 | BoldItalicFont = Italic ] 54 | \setromanfont{RobotoSlab} [ Path = fonts/roboto-slab/RobotoSlab-, 55 | Extension = .ttf, 56 | UprightFont = Light, 57 | BoldFont = Bold ] 58 | \setmonofont{RobotoMono} [ Path = fonts/roboto-mono/RobotoMono-, 59 | Extension = .ttf, 60 | Scale = 0.90, 61 | UprightFont = Light, 62 | ItalicFont = LightItalic, 63 | BoldFont = Regular, 64 | BoldItalicFont = Italic ] 65 | \renewcommand{\familydefault}{\sfdefault} 66 | 67 | % ----------------------------------------------------------------------------- 68 | \begin{document} 69 | \thispagestyle{empty} 70 | 71 | \section*{\LARGE \rmfamily 72 | Matplotlib \textcolor{orange}{\mdseries for intermediate users}} 73 | 74 | \begin{multicols*}{3} 75 | 76 | A matplotlib figure is composed of a hierarchy of elements that forms 77 | the actual figure. Each element can be modified. \medskip 78 | 79 | \includegraphics[width=\linewidth]{anatomy.pdf} 80 | 81 | \subsection*{\rmfamily Figure, axes \& spines} 82 | 83 | % ----------------------------------------------------------------------------- 84 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 85 | \begin{lstlisting}[belowskip=-\baselineskip] 86 | fig, axs = plt.subplots(3, 3) 87 | axs[0, 0].set_facecolor("#ddddff") 88 | axs[2, 2].set_facecolor("#ffffdd") 89 | \end{lstlisting} 90 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{layout-subplot-color.pdf}} 91 | \end{tabular} 92 | 93 | % ----------------------------------------------------------------------------- 94 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 95 | \begin{lstlisting}[belowskip=-\baselineskip] 96 | gs = fig.add_gridspec(3, 3) 97 | ax = fig.add_subplot(gs[0, :]) 98 | ax.set_facecolor("#ddddff") 99 | \end{lstlisting} 100 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{layout-gridspec-color.pdf}} 101 | \end{tabular} 102 | 103 | % ----------------------------------------------------------------------------- 104 | \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} 105 | \begin{lstlisting}[belowskip=-\baselineskip] 106 | fig, ax = plt.subplots() 107 | ax.spines["top"].set_color("None") 108 | ax.spines["right"].set_color("None") 109 | \end{lstlisting} 110 | & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{layout-spines.pdf}} 111 | \end{tabular} 112 | 113 | 114 | 115 | % ----------------------------------------------------------------------------- 116 | \subsection*{\rmfamily Ticks \& labels} 117 | 118 | \begin{lstlisting}[basicstyle=\ttfamily\small] 119 | from mpl.ticker import MultipleLocator as ML 120 | from mpl.ticker import ScalarFormatter as SF 121 | ax.xaxis.set_minor_locator(ML(0.2)) 122 | ax.xaxis.set_minor_formatter(SF()) 123 | ax.tick_params(axis='x',which='minor',rotation=90) 124 | \end{lstlisting} 125 | \includegraphics[width=\linewidth]{tick-multiple-locator.pdf} 126 | 127 | % ----------------------------------------------------------------------------- 128 | \subsection*{\rmfamily Lines \& markers} 129 | 130 | \begin{lstlisting} 131 | X = np.linspace(0.1, 10*np.pi, 1000) 132 | Y = np.sin(X) 133 | ax.plot(X, Y, "C1o:", markevery=50, mec="1.0") 134 | \end{lstlisting} 135 | \includegraphics[width=\linewidth]{sine-marker.pdf} 136 | 137 | % ----------------------------------------------------------------------------- 138 | \subsection*{\rmfamily Scales \& projections} 139 | 140 | \begin{lstlisting} 141 | fig, ax = plt.subplots() 142 | ax.set_xscale("log") 143 | ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") 144 | \end{lstlisting} 145 | \includegraphics[width=\linewidth]{sine-logscale.pdf} 146 | 147 | \subsection*{\rmfamily Text \& ornaments} 148 | \begin{lstlisting}[] 149 | ax.fill_betweenx([-1, 1], [0], [2*np.pi]) 150 | ax.text(0, -1, r" Period $\Phi$") 151 | \end{lstlisting} 152 | \includegraphics[width=\linewidth]{sine-period.pdf} 153 | 154 | 155 | % ----------------------------------------------------------------------------- 156 | \subsection*{\rmfamily Legend} 157 | \begin{lstlisting}[] 158 | ax.plot(X, np.sin(X), "C0", label="Sine") 159 | ax.plot(X, np.cos(X), "C1", label="Cosine") 160 | ax.legend(bbox_to_anchor=(0,1,1,.1), ncol=2, 161 | mode="expand", loc="lower left") 162 | \end{lstlisting} 163 | \includegraphics[width=\linewidth]{sine-legend.pdf} 164 | 165 | % ----------------------------------------------------------------------------- 166 | \subsection*{\rmfamily Annotation} 167 | \begin{lstlisting}[] 168 | ax.annotate("A", (X[250],Y[250]), (X[250],-1), 169 | ha="center", va="center", arrowprops={ 170 | "arrowstyle": "->", "color": "C1"}) 171 | \end{lstlisting} 172 | \includegraphics[width=\linewidth]{sine-annotate.pdf} 173 | 174 | % ----------------------------------------------------------------------------- 175 | \subsection*{\rmfamily Colors} 176 | 177 | Any color can be used, but Matplotlib offers sets of colors:\\ 178 | \includegraphics[width=\linewidth]{colors-cycle.pdf} \smallskip 179 | \includegraphics[width=\linewidth]{colors-grey.pdf}\\ 180 | %As well as nice colormaps (viridis an magma):\\ 181 | %\includegraphics[width=\linewidth]{colormap-viridis.pdf} \smallskip 182 | %\includegraphics[width=\linewidth]{colormap-magma.pdf} \medskip 183 | 184 | % ----------------------------------------------------------------------------- 185 | \vspace{-1em} 186 | \subsection*{\rmfamily Size \& DPI} 187 | 188 | Consider a square figure to be included in a two-column A4 paper with 189 | 2\,cm margins on each side and a column separation of 1\,cm. The width of 190 | a figure is (21 - 2*2 - 1)/2 = 8\,cm. One inch being 2.54\,cm, figure size 191 | should be 3.15$\times$3.15\,in. 192 | \begin{lstlisting}[] 193 | fig = plt.figure(figsize=(3.15, 3.15), dpi=50) 194 | plt.savefig("figure.pdf", dpi=600) 195 | \end{lstlisting} 196 | 197 | 198 | \vfill 199 | % 200 | {\scriptsize 201 | Matplotlib 3.8.2 handout for intermediate users. 202 | Copyright (c) 2021 Matplotlib Development Team. 203 | Released under a CC-BY 4.0 International License. 204 | Supported by NumFOCUS. 205 | \par} 206 | 207 | 208 | 209 | \end{multicols*} 210 | \end{document} 211 | -------------------------------------------------------------------------------- /handout-tips.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,landscape,a4paper]{article} 2 | \usepackage[right=10mm, left=10mm, top=10mm, bottom=10mm]{geometry} 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[T1]{fontenc} 5 | \usepackage[english]{babel} 6 | \usepackage[rm,light]{roboto} 7 | \usepackage{xcolor} 8 | \usepackage{graphicx} 9 | \graphicspath{{./figures/}} 10 | \usepackage{multicol} 11 | \usepackage{colortbl} 12 | \usepackage{array} 13 | \setlength\parindent{0pt} 14 | \setlength{\tabcolsep}{2pt} 15 | \baselineskip=0pt 16 | \setlength\columnsep{1em} 17 | \definecolor{Gray}{gray}{0.85} 18 | 19 | % --- Listing ----------------------------------------------------------------- 20 | \usepackage{listings} 21 | \lstset{ 22 | frame=tb, framesep=4pt, framerule=0pt, 23 | backgroundcolor=\color{black!5}, 24 | basicstyle=\ttfamily\footnotesize, 25 | commentstyle=\ttfamily\color{black!50}, 26 | breakatwhitespace=false, 27 | breaklines=true, 28 | extendedchars=true, 29 | keepspaces=true, 30 | language=Python, 31 | rulecolor=\color{black}, 32 | showspaces=false, 33 | showstringspaces=false, 34 | showtabs=false, 35 | tabsize=2, 36 | % 37 | emph = { 38 | plot, scatter, imshow, bar, contourf, pie, subplots, spines, 39 | add_gridspec, add_subplot, set_xscale, set_minor_locator, linestyle, 40 | dash_capstyle, projection, Stroke, Normal, add_axes, label, savefig, 41 | get_cmap, histtype, annotate, set_minor_formatter, tick_params, 42 | fill_betweenx, text, legend, errorbar, boxplot, hist, title, xlabel, 43 | ylabel, suptitle, fraction, pad, set_fontname, get_xticklabels}, 44 | emphstyle = {\ttfamily\bfseries} 45 | } 46 | 47 | % --- Fonts ------------------------------------------------------------------- 48 | \usepackage{fontspec} 49 | \usepackage[babel=true]{microtype} 50 | \defaultfontfeatures{Ligatures = TeX, Mapping = tex-text} 51 | \setsansfont{Roboto} [ Path = fonts/roboto/Roboto-, 52 | Extension = .ttf, 53 | UprightFont = Light, 54 | ItalicFont = LightItalic, 55 | BoldFont = Regular, 56 | BoldItalicFont = Italic ] 57 | \setromanfont{RobotoSlab} [ Path = fonts/roboto-slab/RobotoSlab-, 58 | Extension = .ttf, 59 | UprightFont = Light, 60 | BoldFont = Bold ] 61 | \setmonofont{RobotoMono} [ Path = fonts/roboto-mono/RobotoMono-, 62 | Extension = .ttf, 63 | Scale = 0.90, 64 | UprightFont = Light, 65 | ItalicFont = LightItalic, 66 | BoldFont = Regular, 67 | BoldItalicFont = Italic ] 68 | \renewcommand{\familydefault}{\sfdefault} 69 | 70 | % ----------------------------------------------------------------------------- 71 | \begin{document} 72 | \thispagestyle{empty} 73 | 74 | \section*{\LARGE \rmfamily 75 | Matplotlib \textcolor{orange}{\mdseries tips \& tricks}} 76 | 77 | \begin{multicols*}{3} 78 | 79 | 80 | % ----------------------------------------------------------------------------- 81 | \subsection*{\rmfamily Transparency} 82 | 83 | Scatter plots can be enhanced by using transparency (alpha) in order 84 | to show area with higher density. Multiple scatter plots can be 85 | used to delineate a frontier. 86 | 87 | \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} 88 | \begin{lstlisting}[belowskip=-\baselineskip] 89 | X = np.random.normal(-1, 1, 500) 90 | Y = np.random.normal(-1, 1, 500) 91 | ax.scatter(X, Y, 50, "0.0", lw=2) # optional 92 | ax.scatter(X, Y, 50, "1.0", lw=0) # optional 93 | ax.scatter(X, Y, 40, "C1", lw=0, alpha=0.1) 94 | \end{lstlisting} & 95 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-transparency.pdf}} 96 | \end{tabular} 97 | 98 | % ----------------------------------------------------------------------------- 99 | \subsection*{\rmfamily Rasterization} 100 | If your figure has many graphical elements, such as a huge 101 | scatter, you can rasterize them to save memory and keep other elements 102 | in vector format. 103 | \begin{lstlisting} 104 | X = np.random.normal(-1, 1, 10_000) 105 | Y = np.random.normal(-1, 1, 10_000) 106 | ax.scatter(X, Y, rasterized=True) 107 | fig.savefig("rasterized-figure.pdf", dpi=600) 108 | \end{lstlisting} 109 | 110 | % ----------------------------------------------------------------------------- 111 | \subsection*{\rmfamily Offline rendering} 112 | 113 | Use the Agg backend to render a figure directly in an array. 114 | \begin{lstlisting} 115 | from matplotlib.backends.backend_agg import FigureCanvas 116 | canvas = FigureCanvas(Figure())) 117 | ... # draw some stuff 118 | canvas.draw() 119 | Z = np.array(canvas.renderer.buffer_rgba()) 120 | \end{lstlisting} 121 | 122 | % ----------------------------------------------------------------------------- 123 | \subsection*{\rmfamily Range of continuous colors} 124 | 125 | You can use colormap to pick from a range of continuous colors. 126 | 127 | \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} 128 | \begin{lstlisting}[belowskip=-\baselineskip] 129 | X = np.random.randn(1000, 4) 130 | cmap = plt.get_cmap("Oranges") 131 | colors = cmap([0.2, 0.4, 0.6, 0.8]) 132 | 133 | ax.hist(X, 2, histtype='bar', color=colors) 134 | \end{lstlisting} & 135 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-color-range.pdf}} 136 | \end{tabular} 137 | 138 | % ----------------------------------------------------------------------------- 139 | \subsection*{\rmfamily Text outline} 140 | Use text outline to make text more visible. 141 | 142 | \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} 143 | \begin{lstlisting}[belowskip=-\baselineskip] 144 | import matplotlib.patheffects as fx 145 | text = ax.text(0.5, 0.1, "Label") 146 | text.set_path_effects([ 147 | fx.Stroke(linewidth=3, foreground='1.0'), 148 | fx.Normal()]) 149 | \end{lstlisting} & 150 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-outline.pdf}} 151 | \end{tabular} 152 | 153 | 154 | % ----------------------------------------------------------------------------- 155 | \subsection*{\rmfamily Multiline plot} 156 | You can plot several lines at once using {\em None} as separator. 157 | 158 | \begin{lstlisting} 159 | X,Y = [], [] 160 | for x in np.linspace(0, 10*np.pi, 100): 161 | X.extend([x, x, None]), Y.extend([0, sin(x), None]) 162 | ax.plot(X, Y, "black") 163 | \end{lstlisting} 164 | \includegraphics[width=\linewidth]{tip-multiline.pdf} 165 | 166 | % ----------------------------------------------------------------------------- 167 | \subsection*{\rmfamily Dotted lines} 168 | To have rounded dotted lines, use a custom {\ttfamily linestyle} and 169 | modify {\ttfamily dash\_capstyle}. 170 | \begin{lstlisting} 171 | ax.plot([0, 1], [0, 0], "C1", 172 | linestyle=(0, (0.01, 1)), dash_capstyle="round") 173 | ax.plot([0, 1], [1, 1], "C1", 174 | linestyle=(0, (0.01, 2)), dash_capstyle="round") 175 | \end{lstlisting} 176 | \includegraphics[width=\linewidth]{tip-dotted.pdf} 177 | 178 | % ----------------------------------------------------------------------------- 179 | \subsection*{\rmfamily Combining axes} 180 | You can use overlaid axes with different projections. 181 | 182 | \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} 183 | \begin{lstlisting}[belowskip=-\baselineskip] 184 | ax1 = fig.add_axes([0, 0, 1, 1], 185 | label="cartesian") 186 | ax2 = fig.add_axes([0, 0, 1, 1], 187 | label="polar", 188 | projection="polar") 189 | \end{lstlisting} & 190 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-dual-axis.pdf}} 191 | \end{tabular} 192 | 193 | \subsection*{\rmfamily Colorbar adjustment} 194 | You can adjust a colorbar's size when adding it. 195 | 196 | \begin{tabular}{@{}m{.754\linewidth}m{.236\linewidth}} 197 | \begin{lstlisting}[belowskip=-\baselineskip] 198 | im = ax.imshow(Z) 199 | 200 | cb = plt.colorbar(im, 201 | fraction=0.046, pad=0.04) 202 | cb.set_ticks([]) 203 | \end{lstlisting} & 204 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-colorbar.pdf}} 205 | \end{tabular} 206 | 207 | \subsection*{\rmfamily Taking advantage of typography} 208 | You can use a condensed font such as Roboto 209 | Condensed to save space on tick labels. 210 | \begin{lstlisting} 211 | for tick in ax.get_xticklabels(which='both'): 212 | tick.set_fontname("Roboto Condensed") 213 | \end{lstlisting} 214 | \includegraphics[width=\linewidth]{tip-font-family.pdf} 215 | 216 | \subsection*{\rmfamily Getting rid of margins} 217 | Once your figure is finished, you can call {\ttfamily tight\_layout()} 218 | to remove white margins. If there are remaining margins, you can use 219 | the {\ttfamily pdfcrop} utility (comes with TeX live). 220 | 221 | 222 | \subsection*{\rmfamily Hatching} 223 | You can achieve a nice visual effect with thick hatch patterns. 224 | 225 | \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} 226 | \begin{lstlisting}[belowskip=-\baselineskip] 227 | cmap = plt.get_cmap("Oranges") 228 | plt.rcParams['hatch.color'] = cmap(0.2) 229 | plt.rcParams['hatch.linewidth'] = 8 230 | ax.bar(X, Y, color=cmap(0.6), hatch="/") 231 | \end{lstlisting} & 232 | \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-hatched.pdf}} 233 | \end{tabular} 234 | 235 | 236 | \subsection*{\rmfamily Read the documentation} 237 | 238 | Matplotlib comes with an extensive documentation explaining the 239 | details of each command and is generally accompanied by examples. 240 | Together with the huge online gallery, this documentation is a 241 | gold-mine. 242 | 243 | \vfill 244 | % 245 | {\scriptsize 246 | Matplotlib 3.8.2 handout for tips \& tricks. 247 | Copyright (c) 2021 Matplotlib Development Team. 248 | Released under a CC-BY 4.0 International License. 249 | Supported by NumFOCUS. 250 | \par} 251 | 252 | 253 | 254 | \end{multicols*} 255 | \end{document} 256 | -------------------------------------------------------------------------------- /logos/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matplotlib/cheatsheets/f02ebb5f02abd3c5d5b02bb1f22737ab87e92a08/logos/logo2.png -------------------------------------------------------------------------------- /logos/mpl-logos2.py: -------------------------------------------------------------------------------- 1 | """ 2 | =============== 3 | Matplotlib logo 4 | =============== 5 | 6 | This example generates the current matplotlib logo. 7 | """ 8 | 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | import matplotlib.cm as cm 12 | import matplotlib.font_manager 13 | from matplotlib.patches import Rectangle, PathPatch 14 | from matplotlib.textpath import TextPath 15 | import matplotlib.transforms as mtrans 16 | 17 | MPL_BLUE = '#11557c' 18 | 19 | 20 | def get_font_properties(): 21 | # The original font is Calibri, if that is not installed, we fall back 22 | # to Carlito, which is metrically equivalent. 23 | if 'Calibri' in matplotlib.font_manager.findfont('Calibri:bold'): 24 | return matplotlib.font_manager.FontProperties(family='Calibri', 25 | weight='bold') 26 | if 'Carlito' in matplotlib.font_manager.findfont('Carlito:bold'): 27 | print('Original font not found. Falling back to Carlito. ' 28 | 'The logo text will not be in the correct font.') 29 | return matplotlib.font_manager.FontProperties(family='Carlito', 30 | weight='bold') 31 | print('Original font not found. ' 32 | 'The logo text will not be in the correct font.') 33 | return None 34 | 35 | 36 | def create_icon_axes(fig, ax_position, lw_bars, lw_grid, lw_border, rgrid): 37 | """ 38 | Create a polar axes containing the matplotlib radar plot. 39 | 40 | Parameters 41 | ---------- 42 | fig : matplotlib.figure.Figure 43 | The figure to draw into. 44 | ax_position : (float, float, float, float) 45 | The position of the created Axes in figure coordinates as 46 | (x, y, width, height). 47 | lw_bars : float 48 | The linewidth of the bars. 49 | lw_grid : float 50 | The linewidth of the grid. 51 | lw_border : float 52 | The linewidth of the Axes border. 53 | rgrid : array-like 54 | Positions of the radial grid. 55 | 56 | Returns 57 | ------- 58 | ax : matplotlib.axes.Axes 59 | The created Axes. 60 | """ 61 | with plt.rc_context({'axes.edgecolor': MPL_BLUE, 62 | 'axes.linewidth': lw_border}): 63 | ax = fig.add_axes(ax_position, projection='polar') 64 | ax.set_axisbelow(True) 65 | 66 | N = 7 67 | arc = 2. * np.pi 68 | theta = np.arange(0.0, arc, arc / N) 69 | radii = np.array([2, 6, 8, 7, 4, 5, 8]) 70 | width = np.pi / 4 * np.array([0.4, 0.4, 0.6, 0.8, 0.2, 0.5, 0.3]) 71 | bars = ax.bar(theta, radii, width=width, bottom=0.0, align='edge', 72 | edgecolor='0.3', lw=lw_bars) 73 | for r, bar in zip(radii, bars): 74 | color = *cm.jet(r / 10.)[:3], 0.6 # color from jet with alpha=0.6 75 | bar.set_facecolor(color) 76 | 77 | ax.tick_params(labelbottom=False, labeltop=False, 78 | labelleft=False, labelright=False) 79 | 80 | ax.grid(lw=lw_grid, color='0.9') 81 | ax.set_rmax(9) 82 | ax.set_yticks(rgrid) 83 | 84 | # the actual visible background - extends a bit beyond the axis 85 | ax.add_patch(Rectangle((0, 0), arc, 9.58, 86 | facecolor='white', zorder=0, 87 | clip_on=False, in_layout=False)) 88 | return ax 89 | 90 | 91 | def create_text_axes(fig, height_px): 92 | """Create an axes in *fig* that contains 'matplotlib' as Text.""" 93 | ax = fig.add_axes((0, 0, 1, 1)) 94 | ax.set_aspect("equal") 95 | ax.set_axis_off() 96 | 97 | path = TextPath((0, 0), "matplotlib", size=height_px * 0.8, 98 | prop=get_font_properties()) 99 | 100 | fp = get_font_properties() 101 | fp.set_weight('light') 102 | path1 = TextPath((80, -13), 'Cheat sheet', size=height_px * 0.12, 103 | prop=fp) 104 | path2 = TextPath((310, -13), f'Version {matplotlib. __version__}', 105 | size=height_px * 0.12, 106 | prop=fp) 107 | 108 | angle = 4.25 # degrees 109 | trans = mtrans.Affine2D().skew_deg(angle, 0) 110 | 111 | patch = PathPatch(path, transform=trans + ax.transData, color=MPL_BLUE, 112 | lw=0) 113 | patch1 = PathPatch(path1, transform=trans + ax.transData, color=MPL_BLUE, 114 | lw=0) 115 | patch2 = PathPatch(path2, color=MPL_BLUE, 116 | lw=0) 117 | 118 | ax.add_patch(patch) 119 | ax.add_patch(patch1) 120 | ax.add_patch(patch2) 121 | ax.autoscale() 122 | 123 | 124 | def make_logo(height_px, lw_bars, lw_grid, lw_border, rgrid, with_text=False): 125 | """ 126 | Create a full figure with the Matplotlib logo. 127 | 128 | Parameters 129 | ---------- 130 | height_px : int 131 | Height of the figure in pixel. 132 | lw_bars : float 133 | The linewidth of the bar border. 134 | lw_grid : float 135 | The linewidth of the grid. 136 | lw_border : float 137 | The linewidth of icon border. 138 | rgrid : sequence of float 139 | The radial grid positions. 140 | with_text : bool 141 | Whether to draw only the icon or to include 'matplotlib' as text. 142 | """ 143 | dpi = 100 144 | height = height_px / dpi 145 | figsize = (5 * height, height) if with_text else (height, height) 146 | fig = plt.figure(figsize=figsize, dpi=dpi) 147 | fig.patch.set_alpha(0) 148 | 149 | if with_text: 150 | create_text_axes(fig, height_px) 151 | ax_pos = (0.535, 0.12, .17, 0.75) if with_text else (0.03, 0.03, .94, .94) 152 | ax = create_icon_axes(fig, ax_pos, lw_bars, lw_grid, lw_border, rgrid) 153 | 154 | fig.savefig('mpl-logo2.pdf') 155 | 156 | return fig, ax 157 | 158 | 159 | ############################################################################## 160 | # A large logo: 161 | 162 | make_logo(height_px=110, lw_bars=0.7, lw_grid=0.5, lw_border=1, 163 | rgrid=[1, 3, 5, 7]) 164 | 165 | ############################################################################## 166 | # A small 32px logo: 167 | 168 | make_logo(height_px=32, lw_bars=0.3, lw_grid=0.3, lw_border=0.3, rgrid=[5]) 169 | 170 | ############################################################################## 171 | # A large logo including text, as used on the matplotlib website. 172 | 173 | make_logo(height_px=110, lw_bars=0.7, lw_grid=0.5, lw_border=1, 174 | rgrid=[1, 3, 5, 7], with_text=True) 175 | # plt.show() 176 | -------------------------------------------------------------------------------- /logos/numfocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matplotlib/cheatsheets/f02ebb5f02abd3c5d5b02bb1f22737ab87e92a08/logos/numfocus.png -------------------------------------------------------------------------------- /requirements/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default 2 | default: all 3 | 4 | .PHONY: all 5 | all: requirements.txt 6 | 7 | .PHONY: install 8 | install: requirements.txt 9 | pip-sync $^ 10 | 11 | %.txt: %.in 12 | pip-compile $< 13 | -------------------------------------------------------------------------------- /requirements/requirements.in: -------------------------------------------------------------------------------- 1 | autopep8 2 | bump2version 3 | cartopy==0.22.0 4 | flake8 5 | matplotlib==3.8.2 6 | pillow>=9 7 | pdfx 8 | pip-tools 9 | pre-commit 10 | scipy 11 | # Docs 12 | mpl-sphinx-theme~=3.8.0 13 | pydata-sphinx-theme==0.13.3 14 | sphinx 15 | sphinx-design 16 | -------------------------------------------------------------------------------- /requirements/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.10 3 | # by the following command: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | accessible-pygments==0.0.4 8 | # via pydata-sphinx-theme 9 | alabaster==0.7.16 10 | # via sphinx 11 | autopep8==2.0.4 12 | # via -r requirements.in 13 | babel==2.14.0 14 | # via 15 | # pydata-sphinx-theme 16 | # sphinx 17 | beautifulsoup4==4.12.3 18 | # via pydata-sphinx-theme 19 | build==1.0.3 20 | # via pip-tools 21 | bump2version==1.0.1 22 | # via -r requirements.in 23 | cartopy==0.22.0 24 | # via -r requirements.in 25 | certifi==2024.7.4 26 | # via 27 | # pyproj 28 | # requests 29 | cffi==1.16.0 30 | # via cryptography 31 | cfgv==3.4.0 32 | # via pre-commit 33 | chardet==4.0.0 34 | # via 35 | # pdfminer-six 36 | # pdfx 37 | charset-normalizer==3.3.2 38 | # via requests 39 | click==8.1.7 40 | # via pip-tools 41 | contourpy==1.2.0 42 | # via matplotlib 43 | cryptography==44.0.1 44 | # via pdfminer-six 45 | cycler==0.12.1 46 | # via matplotlib 47 | distlib==0.3.8 48 | # via virtualenv 49 | docutils==0.20.1 50 | # via 51 | # pydata-sphinx-theme 52 | # sphinx 53 | filelock==3.13.1 54 | # via virtualenv 55 | flake8==7.0.0 56 | # via -r requirements.in 57 | fonttools==4.47.2 58 | # via matplotlib 59 | identify==2.5.33 60 | # via pre-commit 61 | idna==3.7 62 | # via requests 63 | imagesize==1.4.1 64 | # via sphinx 65 | jinja2==3.1.5 66 | # via sphinx 67 | kiwisolver==1.4.5 68 | # via matplotlib 69 | markupsafe==2.1.4 70 | # via jinja2 71 | matplotlib==3.8.2 72 | # via 73 | # -r requirements.in 74 | # cartopy 75 | # mpl-sphinx-theme 76 | mccabe==0.7.0 77 | # via flake8 78 | mpl-sphinx-theme==3.8.0 79 | # via -r requirements.in 80 | nodeenv==1.8.0 81 | # via pre-commit 82 | numpy==1.26.3 83 | # via 84 | # cartopy 85 | # contourpy 86 | # matplotlib 87 | # scipy 88 | # shapely 89 | packaging==23.2 90 | # via 91 | # build 92 | # cartopy 93 | # matplotlib 94 | # pydata-sphinx-theme 95 | # sphinx 96 | pdfminer-six==20201018 97 | # via pdfx 98 | pdfx==1.4.1 99 | # via -r requirements.in 100 | pillow==10.3.0 101 | # via 102 | # -r requirements.in 103 | # matplotlib 104 | pip-tools==7.3.0 105 | # via -r requirements.in 106 | platformdirs==4.2.0 107 | # via virtualenv 108 | pre-commit==3.6.0 109 | # via -r requirements.in 110 | pycodestyle==2.11.1 111 | # via 112 | # autopep8 113 | # flake8 114 | pycparser==2.21 115 | # via cffi 116 | pydata-sphinx-theme==0.13.3 117 | # via 118 | # -r requirements.in 119 | # mpl-sphinx-theme 120 | pyflakes==3.2.0 121 | # via flake8 122 | pygments==2.17.2 123 | # via 124 | # accessible-pygments 125 | # pydata-sphinx-theme 126 | # sphinx 127 | pyparsing==3.1.1 128 | # via matplotlib 129 | pyproj==3.6.1 130 | # via cartopy 131 | pyproject-hooks==1.0.0 132 | # via build 133 | pyshp==2.3.1 134 | # via cartopy 135 | python-dateutil==2.8.2 136 | # via matplotlib 137 | pyyaml==6.0.1 138 | # via pre-commit 139 | requests==2.32.2 140 | # via sphinx 141 | scipy==1.12.0 142 | # via -r requirements.in 143 | shapely==2.0.2 144 | # via cartopy 145 | six==1.16.0 146 | # via python-dateutil 147 | snowballstemmer==2.2.0 148 | # via sphinx 149 | sortedcontainers==2.4.0 150 | # via pdfminer-six 151 | soupsieve==2.5 152 | # via beautifulsoup4 153 | sphinx==7.2.6 154 | # via 155 | # -r requirements.in 156 | # pydata-sphinx-theme 157 | # sphinx-design 158 | sphinx-design==0.5.0 159 | # via -r requirements.in 160 | sphinxcontrib-applehelp==1.0.8 161 | # via sphinx 162 | sphinxcontrib-devhelp==1.0.6 163 | # via sphinx 164 | sphinxcontrib-htmlhelp==2.0.5 165 | # via sphinx 166 | sphinxcontrib-jsmath==1.0.1 167 | # via sphinx 168 | sphinxcontrib-qthelp==1.0.7 169 | # via sphinx 170 | sphinxcontrib-serializinghtml==1.1.10 171 | # via sphinx 172 | tomli==2.0.1 173 | # via 174 | # autopep8 175 | # build 176 | # pip-tools 177 | # pyproject-hooks 178 | typing-extensions==4.9.0 179 | # via pydata-sphinx-theme 180 | urllib3==2.2.2 181 | # via requests 182 | virtualenv==20.26.6 183 | # via pre-commit 184 | wheel==0.42.0 185 | # via pip-tools 186 | 187 | # The following packages are considered to be unsafe in a requirements file: 188 | # pip 189 | # setuptools 190 | -------------------------------------------------------------------------------- /scripts/adjustements.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | import matplotlib.patches as mpatches 11 | from matplotlib.collections import PatchCollection 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ]) 19 | mpl.rc('font', size=4) 20 | mpl.rc('lines', linewidth=0.5) 21 | mpl.rc('patch', linewidth=0.5) 22 | 23 | 24 | subplots_kw = dict( 25 | figsize=(5.7/2.54, 5.7/2.54 * 95/115), 26 | subplot_kw=dict( 27 | frameon=False, 28 | aspect=1, 29 | xlim=(0-5, 100+10), 30 | ylim=(-10, 80+5), 31 | xticks=[], 32 | yticks=[], 33 | ), 34 | ) 35 | 36 | (fig, ax) = plt.subplots(**subplots_kw) 37 | 38 | box = mpatches.FancyBboxPatch( 39 | (0, 0), 100, 83, mpatches.BoxStyle("Round", pad=0, rounding_size=2), 40 | facecolor="0.9", edgecolor="black") 41 | ax.add_artist(box) 42 | 43 | box = mpatches.FancyBboxPatch( 44 | (0, 0), 100, 75, mpatches.BoxStyle("Round", pad=0, rounding_size=0), 45 | facecolor="white", edgecolor="black") 46 | ax.add_artist(box) 47 | 48 | 49 | box = mpatches.Rectangle( 50 | (5, 5), 45, 30, zorder=10, 51 | facecolor="white", edgecolor="black") 52 | ax.add_artist(box) 53 | 54 | box = mpatches.Rectangle( 55 | (5, 40), 45, 30, zorder=10, 56 | facecolor="white", edgecolor="black") 57 | ax.add_artist(box) 58 | 59 | box = mpatches.Rectangle( 60 | (55, 5), 40, 65, zorder=10, 61 | facecolor="white", edgecolor="black") 62 | ax.add_artist(box) 63 | 64 | # Window button 65 | X, Y = [5, 10, 15], [79, 79, 79] 66 | plt.scatter(X, Y, s=20, zorder=10, 67 | edgecolor="black", facecolor="white") 68 | 69 | 70 | # Window size extension 71 | X, Y = [0, 0], [0, -8] 72 | plt.plot(X, Y, color="black", linestyle=":", clip_on=False) 73 | 74 | X, Y = [100, 100], [0, -8] 75 | plt.plot(X, Y, color="black", linestyle=":", clip_on=False) 76 | 77 | X, Y = [100, 108], [0, 0] 78 | plt.plot(X, Y, color="black", linestyle=":", clip_on=False) 79 | 80 | X, Y = [100, 108], [75, 75] 81 | plt.plot(X, Y, color="black", linestyle=":", clip_on=False) 82 | 83 | 84 | def ext_arrow(p0, p1, p2, p3): 85 | p0, p1 = np.asarray(p0), np.asarray(p1) 86 | p2, p3 = np.asarray(p2), np.asarray(p3) 87 | ax.arrow(*p0, *(p1-p0), zorder=20, linewidth=0, 88 | length_includes_head=True, width=.4, 89 | head_width=2, head_length=2, color="black") 90 | ax.arrow(*p3, *(p2-p3), zorder=20, linewidth=0, 91 | length_includes_head=True, width=.4, 92 | head_width=2, head_length=2, color="black") 93 | plt.plot([p1[0], p2[0]], [p1[1], p2[1]], linewidth=.5, color="black") 94 | 95 | 96 | def int_arrow(p0, p1): 97 | p0, p1 = np.asarray(p0), np.asarray(p1) 98 | ax.arrow(*((p0+p1)/2), *((p1-p0)/2), zorder=20, linewidth=0, 99 | length_includes_head=True, width=.4, 100 | head_width=2, head_length=2, color="black") 101 | ax.arrow(*((p0+p1)/2), *(-(p1-p0)/2), zorder=20, linewidth=0, 102 | length_includes_head=True, width=.4, 103 | head_width=2, head_length=2, color="black") 104 | 105 | 106 | x = 0 107 | y = 10 108 | ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) 109 | ax.text(x+9.5, y, "left", ha="left", va="center", zorder=20) 110 | 111 | x += 50 112 | ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) 113 | ax.text(x-4.5, y, "wspace", ha="right", va="center", zorder=20) 114 | 115 | x += 45 116 | ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) 117 | ax.text(x-4.5, y, "right", ha="right", va="center", zorder=20) 118 | 119 | y = 0 120 | x = 25 121 | ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) 122 | ax.text(x, y+9.5, "bottom", ha="center", va="bottom", zorder=20) 123 | 124 | y += 35 125 | ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) 126 | ax.text(x, y-4.5, "hspace", ha="center", va="top", zorder=20) 127 | 128 | y += 35 129 | ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) 130 | ax.text(x, y-4.5, "top", ha="center", va="top", zorder=20) 131 | 132 | int_arrow((0, -5), (100, -5)) 133 | ax.text(50, -5, "figure width", backgroundcolor="white", zorder=30, 134 | ha="center", va="center") 135 | 136 | int_arrow((105, 0), (105, 75)) 137 | ax.text(105, 75/2, "figure height", backgroundcolor="white", zorder=30, 138 | rotation="vertical", ha="center", va="center") 139 | 140 | int_arrow((55, 62.5), (95, 62.5)) 141 | ax.text(75, 62.5, "axes width", backgroundcolor="white", zorder=30, 142 | ha="center", va="center") 143 | 144 | int_arrow((62.5, 5), (62.5, 70)) 145 | ax.text(62.5, 35, "axes height", backgroundcolor="white", zorder=30, 146 | rotation="vertical", ha="center", va="center") 147 | 148 | 149 | fig.savefig(ROOT_DIR / "figures/adjustments.pdf") 150 | -------------------------------------------------------------------------------- /scripts/advanced-plots.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Script to generate all the advanced plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ROOT_DIR / 'styles/plotlet.mplstyle', 19 | ]) 20 | 21 | 22 | subplot_kw = dict( 23 | xlim=(0, 8), xticks=np.arange(1, 8), 24 | ylim=(0, 8), yticks=np.arange(1, 8), 25 | ) 26 | 27 | # Step plot 28 | # ----------------------------------------------------------------------------- 29 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 30 | X = np.linspace(0, 10, 16) 31 | Y = 4 + 2*np.sin(2*X) 32 | ax.step(X, Y, color="C1") 33 | ax.grid() 34 | fig.savefig(ROOT_DIR / "figures/advanced-step.pdf") 35 | 36 | # Violin plot 37 | # ----------------------------------------------------------------------------- 38 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 39 | np.random.seed(10) 40 | D = np.random.normal((3, 5, 4), (0.75, 1.00, 0.75), (200, 3)) 41 | VP = ax.violinplot(D, [2, 4, 6], widths=1.5, 42 | showmeans=False, showmedians=False, showextrema=False) 43 | for body in VP['bodies']: 44 | body.set_facecolor('C1') 45 | body.set_alpha(1) 46 | ax.set_axisbelow(True) 47 | ax.grid() 48 | fig.savefig(ROOT_DIR / "figures/advanced-violin.pdf") 49 | 50 | # Boxplot 51 | # ----------------------------------------------------------------------------- 52 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 53 | np.random.seed(10) 54 | D = np.random.normal((3, 5, 4), (1.25, 1.00, 1.25), (100, 3)) 55 | VP = ax.boxplot(D, positions=[2, 4, 6], widths=1.5, patch_artist=True, 56 | showmeans=False, showfliers=False, 57 | medianprops={"color": "white", 58 | "linewidth": 0.25}, 59 | boxprops={"facecolor": "C1", 60 | "edgecolor": "white", 61 | "linewidth": 0.25}, 62 | whiskerprops={"color": "C1", 63 | "linewidth": 0.75}, 64 | capprops={"color": "C1", 65 | "linewidth": 0.75}) 66 | ax.set_axisbelow(True) 67 | ax.grid() 68 | fig.savefig(ROOT_DIR / "figures/advanced-boxplot.pdf") 69 | 70 | # Barbs plot 71 | # ----------------------------------------------------------------------------- 72 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 73 | np.random.seed(1) 74 | X = [[2, 4, 6]] 75 | Y = [[1.5, 3, 2]] 76 | U = -np.ones((1, 3)) * 0 77 | V = -np.ones((1, 3)) * np.linspace(50, 100, 3) 78 | ax.barbs(X, Y, U, V, barbcolor="C1", flagcolor="C1", length=5, linewidth=0.5) 79 | ax.set_axisbelow(True) 80 | ax.grid() 81 | fig.savefig(ROOT_DIR / "figures/advanced-barbs.pdf") 82 | 83 | # Event plot 84 | # ----------------------------------------------------------------------------- 85 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 86 | np.random.seed(1) 87 | X = [2, 4, 6] 88 | D = np.random.gamma(4, size=(3, 50)) 89 | ax.eventplot(D, colors="C1", orientation="vertical", lineoffsets=X, 90 | linewidth=0.25) 91 | ax.set_axisbelow(True) 92 | ax.grid() 93 | fig.savefig(ROOT_DIR / "figures/advanced-event.pdf") 94 | 95 | # Errorbar plot 96 | # ----------------------------------------------------------------------------- 97 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 98 | np.random.seed(1) 99 | X = [2, 4, 6] 100 | Y = [4, 5, 4] 101 | E = np.random.uniform(0.5, 1.5, 3) 102 | ax.errorbar(X, Y, E, color="C1", linewidth=0.75, capsize=1) 103 | ax.set_axisbelow(True) 104 | ax.grid() 105 | fig.savefig(ROOT_DIR / "figures/advanced-errorbar.pdf") 106 | 107 | # Hexbin plot 108 | # ----------------------------------------------------------------------------- 109 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 110 | np.random.seed(1) 111 | X = np.random.uniform(1.5, 6.5, 100) 112 | Y = np.random.uniform(1.5, 6.5, 100) 113 | C = np.random.uniform(0, 1, 10000) 114 | ax.hexbin(X, Y, C, gridsize=4, linewidth=0.25, edgecolor="white", 115 | cmap=plt.get_cmap("Wistia"), alpha=1.0) 116 | ax.set_axisbelow(True) 117 | ax.grid() 118 | fig.savefig(ROOT_DIR / "figures/advanced-hexbin.pdf") 119 | 120 | # Hist plot 121 | # ----------------------------------------------------------------------------- 122 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 123 | np.random.seed(1) 124 | X = 4 + np.random.normal(0, 1.5, 200) 125 | ax.hist(X, bins=8, facecolor="C1", linewidth=0.25, edgecolor="white") 126 | ax.set_ylim(0, 80), ax.set_yticks(np.arange(1, 80, 10)) 127 | ax.set_axisbelow(True) 128 | ax.grid() 129 | fig.savefig(ROOT_DIR / "figures/advanced-hist.pdf") 130 | 131 | # Xcorr plot 132 | # ----------------------------------------------------------------------------- 133 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 134 | np.random.seed(3) 135 | Y = np.random.uniform(-4, 4, 250) 136 | X = np.random.uniform(-4, 4, 250) 137 | ax.xcorr(X, Y, usevlines=True, maxlags=6, normed=True, lw=1, 138 | color="C1") 139 | ax.set_xlim(-8, 8), ax.set_xticks(np.arange(-8, 8, 2)) 140 | ax.set_ylim(-.25, .25), ax.set_yticks(np.linspace(-.25, .25, 9)) 141 | ax.set_axisbelow(True) 142 | ax.grid() 143 | fig.savefig(ROOT_DIR / "figures/advanced-xcorr.pdf") 144 | -------------------------------------------------------------------------------- /scripts/anatomy.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Title: Scientific Visualisation - Python & Matplotlib 3 | # Author: Nicolas P. Rougier 4 | # License: BSD 5 | # ---------------------------------------------------------------------------- 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ]) 19 | 20 | np.random.seed(123) 21 | 22 | X = np.linspace(0.5, 3.5, 100) 23 | Y1 = 3+np.cos(X) 24 | Y2 = 1+np.cos(1+X/0.75)/2 25 | Y3 = np.random.uniform(Y1, Y2, len(X)) 26 | 27 | (fig, ax) = plt.subplots(figsize=(8, 8), subplot_kw=dict(aspect=1)) 28 | 29 | 30 | def minor_tick(x, pos): 31 | if not x % 1.0: 32 | return "" 33 | return "%.2f" % x 34 | 35 | 36 | ax.xaxis.set_major_locator(MultipleLocator(1.000)) 37 | ax.xaxis.set_minor_locator(AutoMinorLocator(4)) 38 | ax.yaxis.set_major_locator(MultipleLocator(1.000)) 39 | ax.yaxis.set_minor_locator(AutoMinorLocator(4)) 40 | ax.xaxis.set_minor_formatter(FuncFormatter(minor_tick)) 41 | 42 | ax.set_xlim(0, 4) 43 | ax.set_ylim(0, 4) 44 | 45 | ax.tick_params(which='major', width=1.0) 46 | ax.tick_params(which='major', length=10) 47 | ax.tick_params(which='minor', width=1.0, labelsize=10) 48 | ax.tick_params(which='minor', length=5, labelsize=10, labelcolor='0.25') 49 | 50 | ax.grid(linestyle="--", linewidth=0.5, color='.25', zorder=-10) 51 | 52 | ax.plot(X, Y1, c=(0.25, 0.25, 1.00), lw=2, label="Blue signal", zorder=10) 53 | ax.plot(X, Y2, c=(1.00, 0.25, 0.25), lw=2, label="Red signal") 54 | ax.plot(X, Y3, linewidth=0, 55 | marker='o', markerfacecolor='w', markeredgecolor='k') 56 | 57 | ax.set_title("Anatomy of a figure", fontsize=20, verticalalignment='bottom') 58 | ax.set_xlabel("X axis label") 59 | ax.set_ylabel("Y axis label") 60 | 61 | ax.legend(loc="upper right") 62 | 63 | 64 | def circle(x, y, radius=0.15): 65 | from matplotlib.patches import Circle 66 | from matplotlib.patheffects import withStroke 67 | circle = Circle((x, y), radius, clip_on=False, zorder=10, linewidth=1, 68 | edgecolor='black', facecolor=(0, 0, 0, .0125), 69 | path_effects=[withStroke(linewidth=5, foreground='w')]) 70 | ax.add_artist(circle) 71 | 72 | 73 | def text(x, y, text): 74 | ax.text(x, y, text, backgroundcolor="white", 75 | # fontname="Yanone Kaffeesatz", fontsize="large", 76 | ha='center', va='top', weight="regular", color='#000099') 77 | 78 | 79 | # Minor tick 80 | circle(0.50, -0.10) 81 | text(0.50, -0.32, "Minor tick label") 82 | 83 | # Major tick 84 | circle(-0.03, 4.00) 85 | text(0.03, 3.80, "Major tick") 86 | 87 | # Minor tick 88 | circle(0.00, 3.50) 89 | text(0.00, 3.30, "Minor tick") 90 | 91 | # Major tick label 92 | circle(-0.15, 3.00) 93 | text(-0.15, 2.80, "Major tick label") 94 | 95 | # X Label 96 | circle(1.80, -0.27) 97 | text(1.80, -0.45, "X axis label") 98 | 99 | # Y Label 100 | circle(-0.27, 1.80) 101 | text(-0.27, 1.6, "Y axis label") 102 | 103 | # Title 104 | circle(1.60, 4.13) 105 | text(1.60, 3.93, "Title") 106 | 107 | # Blue plot 108 | circle(1.75, 2.80) 109 | text(1.75, 2.60, "Line\n(line plot)") 110 | 111 | # Red plot 112 | circle(1.20, 0.60) 113 | text(1.20, 0.40, "Line\n(line plot)") 114 | 115 | # Scatter plot 116 | circle(3.20, 1.75) 117 | text(3.20, 1.55, "Markers\n(scatter plot)") 118 | 119 | # Grid 120 | circle(3.00, 3.00) 121 | text(3.00, 2.80, "Grid") 122 | 123 | # Legend 124 | circle(3.70, 3.80) 125 | text(3.70, 3.60, "Legend") 126 | 127 | # Axes 128 | circle(0.5, 0.5) 129 | text(0.5, 0.3, "Axes") 130 | 131 | # Figure 132 | circle(-0.3, 0.65) 133 | text(-0.3, 0.45, "Figure") 134 | 135 | color = '#000099' 136 | ax.annotate('Spines', xy=(4.0, 0.35), xytext=(3.3, 0.5), color=color, 137 | weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", 138 | arrowprops=dict(arrowstyle='->', 139 | connectionstyle="arc3", 140 | color=color)) 141 | 142 | ax.annotate('', xy=(3.15, 0.0), xytext=(3.45, 0.45), color=color, 143 | weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", 144 | arrowprops=dict(arrowstyle='->', 145 | connectionstyle="arc3", 146 | color=color)) 147 | 148 | fig.savefig(ROOT_DIR / "figures/anatomy.pdf") 149 | # plt.show() 150 | -------------------------------------------------------------------------------- /scripts/animation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import matplotlib.animation as animation 4 | 5 | T = np.linspace(0, 2*np.pi, 100) 6 | S = np.sin(T) 7 | line, = plt.plot(T, S) 8 | 9 | 10 | def animate(i): 11 | line.set_ydata(np.sin(T+i/50)) 12 | 13 | 14 | a=animation.FuncAnimation( 15 | plt.gcf(), animate, interval=5) 16 | # plt.show() 17 | -------------------------------------------------------------------------------- /scripts/annotate.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | fig = plt.figure(figsize=(6, 1)) 15 | # ax = plt.subplot(111, frameon=False, aspect=.1) 16 | # b = 0.0 17 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) 18 | 19 | 20 | plt.scatter([5.5], [0.75], s=100, c="k") 21 | plt.xlim(0, 6), plt.ylim(0, 1) 22 | plt.xticks([]), plt.yticks([]) 23 | 24 | plt.annotate("text", (5.5, .75), (0.75, .75), size=16, va="center", ha="center", 25 | arrowprops=dict(facecolor='black', shrink=0.05)) 26 | 27 | plt.text( 5.5, 0.6, "xy\nxycoords", size=10, va="top", ha="center", color=".5") 28 | plt.text( .75, 0.6, "xytext\ntextcoords", size=10, va="top", ha="center", color=".5") 29 | 30 | fig.savefig(ROOT_DIR / "figures/annotate.pdf") 31 | # plt.show() 32 | -------------------------------------------------------------------------------- /scripts/annotation-arrow-styles.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import matplotlib.pyplot as plt 4 | import matplotlib.patches as mpatches 5 | 6 | 7 | ROOT_DIR = pathlib.Path(__file__).parent.parent 8 | 9 | styles = mpatches.ArrowStyle.get_styles() 10 | 11 | 12 | def demo_con_style(ax, connectionstyle): 13 | ax.text(.05, .95, connectionstyle.replace(",", ",\n"), 14 | family="Source Code Pro", 15 | transform=ax.transAxes, ha="left", va="top", size="x-small") 16 | 17 | 18 | (fig, axes) = plt.subplots(4, 4, figsize=(4, 2.5), frameon=False) 19 | for ax in axes.flatten(): 20 | ax.axis("off") 21 | for i, (ax, style) in enumerate(zip(axes.flatten(), mpatches.ArrowStyle.get_styles())): 22 | x0, y0 = 0.8, 0.5 23 | x1, y1 = 0.2, 0.5 24 | ax.plot([x0, x1], [y0, y1], ".", color="0.25") 25 | ax.annotate("", 26 | xy=(x0, y0), xycoords='data', 27 | xytext=(x1, y1), textcoords='data', 28 | arrowprops=dict(arrowstyle=style, 29 | color="black", 30 | shrinkA=5, shrinkB=5, 31 | patchA=None, patchB=None, 32 | connectionstyle="arc3,rad=0")) 33 | ax.text( (x1+x0)/2, y0-0.2, style, 34 | transform=ax.transAxes, 35 | family="Source Code Pro", ha="center", va="top") 36 | 37 | fig.savefig(ROOT_DIR / "figures/annotation-arrow-styles.pdf") 38 | # plt.show() 39 | -------------------------------------------------------------------------------- /scripts/annotation-connection-styles.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import matplotlib as mpl 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | ROOT_DIR = pathlib.Path(__file__).parent.parent 8 | 9 | mpl.style.use([ 10 | ROOT_DIR / 'styles/base.mplstyle', 11 | ROOT_DIR / 'styles/plotlet-grid.mplstyle', 12 | ]) 13 | mpl.rc('lines', markersize=3) 14 | 15 | 16 | def demo_con_style(ax, connectionstyle): 17 | x1, y1 = 0.3, 0.2 18 | x2, y2 = 0.8, 0.6 19 | ax.plot([x1, x2], [y1, y2], ".") 20 | ax.annotate("", 21 | xy=(x1, y1), xycoords='data', 22 | xytext=(x2, y2), textcoords='data', 23 | arrowprops=dict(arrowstyle="->", lw=0.5, color="0.5", 24 | shrinkA=3, shrinkB=3, 25 | patchA=None, patchB=None, 26 | connectionstyle=connectionstyle), 27 | ) 28 | ax.text(.05, .95, connectionstyle.replace(",", ",\n"), 29 | transform=ax.transAxes, ha="left", va="top", size=4) 30 | 31 | 32 | fig, axs = plt.subplots(3, 3, figsize=(5.7/2.54, 5.7/2.54)) 33 | demo_con_style(axs[0, 0], "arc3,rad=0") 34 | demo_con_style(axs[0, 1], "arc3,rad=0.3") 35 | demo_con_style(axs[0, 2], "angle3,angleA=0,angleB=90") 36 | demo_con_style(axs[1, 0], "angle,angleA=-90,angleB=180,rad=0") 37 | demo_con_style(axs[1, 1], "angle,angleA=-90,angleB=180,rad=10") 38 | demo_con_style(axs[1, 2], "arc,angleA=-90,angleB=0,armA=0,armB=20,rad=0") 39 | demo_con_style(axs[2, 0], "bar,fraction=0.3") 40 | demo_con_style(axs[2, 1], "bar,fraction=-0.3") 41 | demo_con_style(axs[2, 2], "bar,angle=180,fraction=-0.2") 42 | 43 | for ax in axs.flat: 44 | ax.set(xlim=(0, 1), ylim=(0, 1), xticks=[], yticks=[], aspect=1) 45 | 46 | fig.savefig(ROOT_DIR / "figures/annotation-connection-styles.pdf") 47 | -------------------------------------------------------------------------------- /scripts/basic-plots.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Script to generate all the basic plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ROOT_DIR / 'styles/plotlet.mplstyle', 19 | ]) 20 | 21 | 22 | subplot_kw = dict( 23 | xlim=(0, 8), xticks=np.arange(1, 8), 24 | ylim=(0, 8), yticks=np.arange(1, 8), 25 | ) 26 | 27 | # Basic line plot 28 | # ----------------------------------------------------------------------------- 29 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 30 | X = np.linspace(0, 10, 100) 31 | Y = 4 + 2*np.sin(2*X) 32 | ax.plot(X, Y, color="C1") 33 | ax.grid() 34 | fig.savefig(ROOT_DIR / "figures/basic-plot.pdf") 35 | 36 | # Basic line plot (color) 37 | # ----------------------------------------------------------------------------- 38 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 39 | X = np.linspace(0, 10, 100) 40 | Y = 4 + 2*np.sin(2*X) 41 | ax.plot(X, Y, color="black") 42 | ax.grid() 43 | fig.savefig(ROOT_DIR / "figures/basic-plot-color.pdf") 44 | 45 | # Basic scatter plot 46 | # ----------------------------------------------------------------------------- 47 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 48 | np.random.seed(3) 49 | X = 4 + np.random.normal(0, 1.25, 24) 50 | Y = 4 + np.random.normal(0, 1.25, len(X)) 51 | ax.scatter(X, Y, 5, zorder=10, 52 | edgecolor="white", facecolor="C1", linewidth=0.25) 53 | ax.grid() 54 | fig.savefig(ROOT_DIR / "figures/basic-scatter.pdf") 55 | 56 | # Basic bar plot 57 | # ----------------------------------------------------------------------------- 58 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 59 | np.random.seed(3) 60 | X = 0.5 + np.arange(8) 61 | Y = np.random.uniform(2, 7, len(X)) 62 | ax.bar(X, Y, bottom=0, width=1, 63 | edgecolor="white", facecolor="C1", linewidth=0.25) 64 | ax.set_axisbelow(True) 65 | ax.grid() 66 | fig.savefig(ROOT_DIR / "figures/basic-bar.pdf") 67 | 68 | # Basic imshow plot 69 | # ----------------------------------------------------------------------------- 70 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 71 | np.random.seed(3) 72 | Z = np.zeros((8, 8, 4)) 73 | Z[:, :] = mpl.colors.to_rgba("C1") 74 | Z[..., 3] = np.random.uniform(0.25, 1.0, (8, 8)) 75 | ax.imshow(Z, extent=[0, 8, 0, 8], interpolation="nearest") 76 | ax.grid(linewidth=0.25, color="white") 77 | fig.savefig(ROOT_DIR / "figures/basic-imshow.pdf") 78 | 79 | # Basic pcolormesh plot 80 | # ----------------------------------------------------------------------------- 81 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 82 | np.random.seed(1) 83 | X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256)) 84 | Z = (1 - X/2. + X**5 + Y**3) * np.exp(-X**2 - Y**2) 85 | Z = Z - Z.min() 86 | plt.pcolormesh(X, Y, Z, cmap='Oranges', shading='auto') 87 | ax.set_xlim(-3, 3), ax.set_xticks(np.arange(-3, 4)) 88 | ax.set_ylim(-3, 3), ax.set_yticks(np.arange(-3, 4)) 89 | fig.savefig(ROOT_DIR / "figures/basic-pcolormesh.pdf") 90 | 91 | # Basic contour plot 92 | # ----------------------------------------------------------------------------- 93 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 94 | colors = np.zeros((5, 4)) 95 | colors[:] = mpl.colors.to_rgba("C1") 96 | colors[:, 3] = np.linspace(0.15, 0.85, len(colors)) 97 | plt.contourf(Z, len(colors), extent=[0, 8, 0, 8], colors=colors) 98 | plt.contour(Z, len(colors), extent=[0, 8, 0, 8], colors="white", 99 | linewidths=0.125, nchunk=10) 100 | fig.savefig(ROOT_DIR / "figures/basic-contour.pdf") 101 | 102 | # Basic pie plot 103 | # ----------------------------------------------------------------------------- 104 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 105 | X = [1, 2, 3, 4] 106 | colors = np.zeros((len(X), 4)) 107 | colors[:] = mpl.colors.to_rgba("C1") 108 | colors[:, 3] = np.linspace(0.25, 0.75, len(X)) 109 | ax.set_axisbelow(True) 110 | ax.grid(linewidth=0.25, color="0.75") 111 | ax.pie(X, colors=["white"] * len(X), radius=3, center=(4, 4), 112 | wedgeprops={"linewidth": 0.25, "edgecolor": "white"}, frame=True) 113 | ax.pie(X, colors=colors, radius=3, center=(4, 4), 114 | wedgeprops={"linewidth": 0.25, "edgecolor": "white"}, frame=True) 115 | fig.savefig(ROOT_DIR / "figures/basic-pie.pdf") 116 | 117 | # Basic text plot 118 | # ----------------------------------------------------------------------------- 119 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 120 | ax.set_axisbelow(True) 121 | ax.grid(linewidth=0.25, color="0.75") 122 | ax.text(4, 4, "TEXT", color="C1", size=8, weight="bold", 123 | ha="center", va="center", rotation=25) 124 | fig.savefig(ROOT_DIR / "figures/basic-text.pdf") 125 | 126 | # Basic fill plot 127 | # ----------------------------------------------------------------------------- 128 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 129 | np.random.seed(1) 130 | X = np.linspace(0, 8, 16) 131 | Y1 = 3 + 4*X/8 + np.random.uniform(0.0, 0.5, len(X)) 132 | Y2 = 1 + 2*X/8 + np.random.uniform(0.0, 0.5, len(X)) 133 | plt.fill_between(X, Y1, Y2, color="C1", alpha=.5, linewidth=0) 134 | plt.plot(X, (Y1+Y2)/2, color="C1", linewidth=0.5) 135 | ax.set_axisbelow(True) 136 | ax.grid(color="0.75") 137 | fig.savefig(ROOT_DIR / "figures/basic-fill.pdf") 138 | 139 | # Basic quiver plot 140 | # ----------------------------------------------------------------------------- 141 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 142 | np.random.seed(1) 143 | T = np.linspace(0, 2*np.pi, 8) 144 | X, Y = 4 + np.cos(T), 4 + np.sin(T) 145 | U, V = 1.5*np.cos(T), 1.5*np.sin(T) 146 | plt.quiver(X, Y, U, V, color="C1", 147 | angles='xy', scale_units='xy', scale=0.5, width=.05) 148 | ax.set_axisbelow(True) 149 | ax.grid(color="0.75") 150 | fig.savefig(ROOT_DIR / "figures/basic-quiver.pdf") 151 | -------------------------------------------------------------------------------- /scripts/colorbar.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | fig = plt.figure(figsize=(6, .65)) 16 | # ax = plt.subplot(111, frameon=False, aspect=.1) 17 | b = 0.025 18 | ax = fig.add_axes([b, 10*b, 1-2*b, 1-10*b], frameon=False, aspect=0.05) 19 | 20 | cmap = plt.get_cmap("Oranges") 21 | norm = mpl.colors.Normalize(vmin=0, vmax=1) 22 | sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) 23 | sm.set_array([]) 24 | plt.colorbar(sm, cax=ax, ticks=np.linspace(0, 1, 11), 25 | orientation="horizontal") 26 | 27 | fig.savefig(ROOT_DIR / "figures/colorbar.pdf") 28 | # plt.show() 29 | -------------------------------------------------------------------------------- /scripts/colormaps.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | ROOT_DIR = pathlib.Path(__file__).parent.parent 8 | 9 | figsize = 4.0, 0.25 10 | fig = plt.figure(figsize=figsize) 11 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) 12 | ymin, ymax= 0, 1 13 | xmin, xmax = 0, figsize[0]/figsize[1] 14 | 15 | # Uniform colormaps 16 | # ----------------------------------------------------------------------------- 17 | cmaps = ('viridis', 'plasma', 'inferno', 'magma', 'cividis', 18 | 19 | 'PRGn', 'PiYG', 'RdYlGn', 'BrBG', 'RdGy', 'PuOr', 'RdBu', 20 | 'RdYlBu', 'Spectral', 'coolwarm', 'bwr', 'seismic', 21 | 22 | 'tab10', 'tab20', 'tab20b', 'tab20c', 23 | 'Pastel1', 'Pastel2', 'Paired', 24 | 'Set1', 'Set2', 'Set3', 'Accent', 'Dark2', 25 | 26 | 'Greys', 'Reds', 'Oranges', 'YlOrBr', 'YlOrRd', 'OrRd', 27 | 'PuRd', 'RdPu', 'BuPu', 'Purples', 'YlGnBu', 'Blues', 28 | 'PuBu', 'GnBu', 'PuBuGn', 'BuGn', 'Greens', 'YlGn', 29 | 30 | 'bone', 'gray', 'pink', 'afmhot', 'hot', 'gist_heat', 'copper', 31 | 'Wistia', 'autumn', 'summer', 'spring', 'cool', 'winter', 32 | 33 | 'twilight', 'twilight_shifted', 'hsv', 34 | 35 | 'terrain', 'ocean', 'gist_earth', 'cubehelix', 'rainbow' 36 | ) 37 | 38 | for name in cmaps: 39 | # The maximum number of segments in a cmap is 256, and for anything smaller, 40 | # the cmap will map as a suitably discrete set of colours. 41 | Z = np.linspace(0, 1, 256).reshape(1, 256) 42 | 43 | ax.imshow(Z, extent=[xmin, xmax, ymin, ymax], cmap=name) 44 | ax.set_xlim(xmin, xmax), ax.set_xticks([]) 45 | ax.set_ylim(ymin, ymax), ax.set_yticks([]) 46 | 47 | fig.savefig(ROOT_DIR / f"figures/colormap-{name}.pdf") 48 | ax.clear() 49 | -------------------------------------------------------------------------------- /scripts/colornames.py: -------------------------------------------------------------------------------- 1 | """ 2 | ======================== 3 | Visualizing named colors 4 | ======================== 5 | 6 | Simple plot example with the named colors and its visual representation. 7 | """ 8 | import pathlib 9 | 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ]) 19 | mpl.rc('figure.constrained_layout', h_pad=0, w_pad=0, hspace=0, wspace=0) 20 | 21 | colors = dict(mpl.colors.BASE_COLORS, **mpl.colors.CSS4_COLORS) 22 | 23 | # Sort colors by hue, saturation, value and name. 24 | by_hsv = sorted((tuple(mpl.colors.rgb_to_hsv(mpl.colors.to_rgba(color)[:3])), name) 25 | for name, color in colors.items()) 26 | sorted_names = [name for hsv, name in by_hsv] 27 | 28 | n = len(sorted_names) 29 | ncols = 3 30 | nrows = n // ncols 31 | 32 | fig, ax = plt.subplots(figsize=(4.5, 6)) 33 | 34 | # Get height and width 35 | X, Y = fig.get_dpi() * fig.get_size_inches() 36 | h = Y / (nrows + 1) 37 | w = X / ncols 38 | 39 | for i, name in enumerate(sorted_names): 40 | col = i // nrows 41 | row = i % nrows 42 | y = Y - (row * h) - h 43 | 44 | xi_line = w * (col + 0.05) 45 | xf_line = w * (col + 0.25) 46 | xi_text = w * (col + 0.3) 47 | 48 | ax.text(xi_text, y, name, fontsize=7, 49 | horizontalalignment='left', 50 | verticalalignment='center') 51 | 52 | ax.hlines(y + h * 0.1, xi_line, xf_line, 53 | color=colors[name], linewidth=(h * 0.6)) 54 | 55 | ax.set_xlim(0, X) 56 | ax.set_ylim(0, Y) 57 | ax.set_axis_off() 58 | 59 | fig.savefig(ROOT_DIR / "figures/colornames.pdf") 60 | -------------------------------------------------------------------------------- /scripts/colors.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | figsize = 4.0, 0.25 16 | fig = plt.figure(figsize=figsize) 17 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) 18 | ymin, ymax= 0, 1 19 | xmin, xmax = 0, figsize[0]/figsize[1] 20 | ax.set_xlim(xmin, xmax), ax.set_xticks([]) 21 | ax.set_ylim(ymin, ymax), ax.set_yticks([]) 22 | 23 | # Uniform colormaps 24 | # ----------------------------------------------------------------------------- 25 | palettes = { 26 | 'raw' : ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'], 27 | 'rgba' : [(1, 0, 0), (1, 0, 0, 0.75), (1, 0, 0, 0.50), (1, 0, 0, 0.25)], 28 | 'HexRGBA' : ["#FF0000", "#FF0000BB", "#FF000088", "#FF000044"], 29 | 'cycle' : ["C%d" % i for i in range(10)], 30 | 'grey' : ["%1.1f" % (i/10) for i in range(11)], 31 | 'name' : ["DarkRed", "Firebrick", "Crimson", "IndianRed", "Salmon" ] } 32 | 33 | for name, colors in palettes.items(): 34 | C = mpl.colors.to_rgba_array(colors).reshape((1, len(colors), 4)) 35 | ax.imshow(C, extent=[xmin, xmax, ymin, ymax]) 36 | 37 | # Drop alpha by assuming we're on a white background PDF. 38 | alpha = C[0, :, 3] 39 | rgb = C[0, :, :3] * alpha[:, np.newaxis] + (1 - alpha[:, np.newaxis]) 40 | # Same calculation for luminance as 41 | # https://matplotlib.org/stable/users/explain/colors/colors.html#comparison-between-x11-css4-and-xkcd-colors 42 | luma = 0.299 * rgb[:, 0] + 0.587 * rgb[:, 1] + 0.114 * rgb[:, 2] 43 | 44 | dx = (xmax-xmin)/len(colors) 45 | for i in range(len(colors)): 46 | text_color = "black" if luma[i] > 0.5 else "white" 47 | text = str(colors[i]).replace(' ', '') 48 | ax.text((i+0.5)*dx, (ymin+ymax)/2, text, color=text_color, zorder=10, 49 | family="Source Code Pro", size=9, ha="center", va="center") 50 | 51 | fig.savefig(ROOT_DIR / f"figures/colors-{name}.pdf") 52 | ax.clear() 53 | -------------------------------------------------------------------------------- /scripts/extents.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | mpl.style.use([ 15 | ROOT_DIR / 'styles/base.mplstyle', 16 | ]) 17 | mpl.rc('figure.constrained_layout', wspace=0.05) 18 | 19 | Z = np.arange(5*5).reshape(5, 5) 20 | 21 | (fig, axs) = plt.subplots(figsize=(8, 5), nrows=2, ncols=2) 22 | 23 | ax = axs[0, 0] 24 | ax.imshow(Z, extent=[0, 10, 0, 5], interpolation="nearest", origin="upper") 25 | ax.set_xlim(-1, 11), ax.set_xticks([]) 26 | ax.set_ylim(-1, 6), ax.set_yticks([0, 5]) 27 | ax.text(1, 4.5, "(0,0)", ha="center", va="center", color="white", size="large") 28 | ax.text(9, 0.5, "(4,4)", ha="center", va="center", color="black", size="large") 29 | ax.text(5.0, 5.5, 'origin="upper"', 30 | ha="center", va="center", color="black", size="large") 31 | ax.text(5.0, -0.5, "extent=[0,10,0,5]", 32 | ha="center", va="center", color="black", size="large") 33 | 34 | ax = axs[1, 0] 35 | ax.imshow(Z, extent=[0, 10, 0, 5], interpolation="nearest", origin="lower") 36 | ax.set_xlim(-1, 11), ax.set_xticks([0, 10]) 37 | ax.set_ylim(-1, 6), ax.set_yticks([0, 5]) 38 | ax.text(1, 0.5, "(0,0)", ha="center", va="center", color="white", size="large") 39 | ax.text(9, 4.5, "(4,4)", ha="center", va="center", color="black", size="large") 40 | 41 | ax.text(5.0, 5.5, 'origin="lower"', 42 | ha="center", va="center", color="black", size="large") 43 | ax.text(5.0, -0.5, "extent=[0,10,0,5]", 44 | ha="center", va="center", color="black", size="large") 45 | 46 | ax = axs[1, 1] 47 | ax.imshow(Z, extent=[10, 0, 0, 5], interpolation="nearest", origin="lower") 48 | ax.set_xlim(-1, 11), ax.set_xticks([0, 10]) 49 | ax.set_ylim(-1, 6), ax.set_yticks([]) 50 | ax.text(9, 0.5, "(0,0)", ha="center", va="center", color="white", size="large") 51 | ax.text(1, 4.5, "(4,4)", ha="center", va="center", color="black", size="large") 52 | ax.text(5.0, 5.5, 'origin="lower"', 53 | ha="center", va="center", color="black", size="large") 54 | ax.text(5.0, -0.5, "extent=[10,0,0,5]", 55 | ha="center", va="center", color="black", size="large") 56 | 57 | ax = axs[0, 1] 58 | ax.imshow(Z, extent=[10, 0, 0, 5], interpolation="nearest", origin="upper") 59 | ax.set_xlim(-1, 11), ax.set_xticks([]) 60 | ax.set_ylim(-1, 6), ax.set_yticks([]) 61 | ax.text(9, 4.5, "(0,0)", ha="center", va="center", color="white", size="large") 62 | ax.text(1, 0.5, "(4,4)", ha="center", va="center", color="black", size="large") 63 | ax.text(5.0, 5.5, 'origin="upper"', 64 | ha="center", va="center", color="black", size="large") 65 | ax.text(5.0, -0.5, "extent=[10,0,0,5]", 66 | ha="center", va="center", color="black", size="large") 67 | 68 | fig.savefig(ROOT_DIR / "figures/extents.pdf", dpi=600) 69 | -------------------------------------------------------------------------------- /scripts/fonts.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import matplotlib.pyplot as plt 8 | 9 | 10 | ROOT_DIR = pathlib.Path(__file__).parent.parent 11 | 12 | fig = plt.figure(figsize=(4.25, 3.8)) 13 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, xticks=[], yticks=[], 14 | xlim=[0, 40], ylim=[0, 38]) 15 | 16 | y = 1 17 | 18 | # ----------------------------------------------------------------------------- 19 | variants = { 20 | "normal" : "../fonts/eb-garamond/EBGaramond08-Regular.otf", 21 | "small-caps" : "../fonts/eb-garamond/EBGaramondSC08-Regular.otf" 22 | } 23 | 24 | text = "The quick brown fox jumps over the lazy dog" 25 | for i, (variant, file) in enumerate(variants.items()): 26 | ax.text(1, y, text, size=9, va="center", font=pathlib.Path(file).resolve()) 27 | 28 | ax.text(39, y, variant, 29 | color="0.25", va="center", ha="right", 30 | size="small", family="Source Code Pro", weight=400) 31 | y += 1.65 32 | y += 1 33 | 34 | # ----------------------------------------------------------------------------- 35 | styles = ["normal", "italic"] 36 | 37 | text = "The quick brown fox jumps over the lazy dog" 38 | for i, style in enumerate(styles): 39 | ax.text(1, y, text, size=9, va="center", style=style, 40 | family="Source Sans Pro") 41 | 42 | ax.text(39, y, style, 43 | color="0.25", va="center", ha="right", 44 | size="small", family="Source Code Pro", weight=400) 45 | y += 1.65 46 | y += 1 47 | 48 | 49 | # ----------------------------------------------------------------------------- 50 | families = { 51 | "Pacifico" : "cursive", 52 | "Source Sans Pro" : "sans", 53 | "Source Serif Pro": "serif", 54 | "Source Code Pro" : "monospace" } 55 | 56 | text = "The quick brown fox jumps over the lazy dog" 57 | for i, (family, label) in enumerate(families.items()): 58 | ax.text(1, y, text, 59 | va="center", size=9, family=family, weight="regular") 60 | 61 | ax.text(39, y, label, 62 | color="0.25", va="center", ha="right", 63 | size="small", family="Source Code Pro", weight=400) 64 | y += 1.65 65 | y += 1 66 | 67 | 68 | # ----------------------------------------------------------------------------- 69 | weights = { 70 | 'ultralight' : 100, 71 | 'light' : 200, 72 | 'normal' : 400, 'regular' : 400, 'book' : 400, 73 | 'medium' : 500, 'roman' : 500, 74 | 'semibold' : 600, 'demibold' : 600, 'demi' : 600, 75 | 'bold' : 700, 76 | 'heavy' : 800, 'extra bold' : 800, 77 | 'black' : 900 } 78 | 79 | text = "The quick brown fox jumps over the lazy dog" 80 | for i, weight in enumerate(["ultralight", "normal", "semibold", "bold", "black"]): 81 | ax.text(1, y, text, size=9, 82 | va="center", family="Source Sans Pro", weight=weight) 83 | 84 | ax.text(39, y, f"{weight} ({weights[weight]:d})", 85 | color="0.25", va="center", ha="right", 86 | size="small", family="Source Code Pro", weight=400) 87 | y += 1.65 88 | y += 1 89 | 90 | # ----------------------------------------------------------------------------- 91 | sizes = { "xx-small" : 0.579, 92 | "x-small" : 0.694, 93 | "small" : 0.833, 94 | "medium" : 1.0, 95 | "large" : 1.200, 96 | "x-large" : 1.440, 97 | "xx-large" : 1.728 } 98 | 99 | text = "The quick brown fox" 100 | for i, (size, scaling) in enumerate(sizes.items()): 101 | ax.text(1, y, text, size=size, 102 | ha="left", va="center", family="Source Sans Pro", weight="light") 103 | 104 | ax.text(39, y, f"{size} ({scaling:.2f})", 105 | color="0.25", va="center", ha="right", 106 | size="small", family="Source Code Pro", weight=400) 107 | y += 1.65* max(sizes[size], sizes["small"]) 108 | 109 | 110 | fig.savefig(ROOT_DIR / "figures/fonts.pdf") 111 | # plt.show() 112 | -------------------------------------------------------------------------------- /scripts/interpolations.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import matplotlib as mpl 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | 7 | 8 | ROOT_DIR = pathlib.Path(__file__).parent.parent 9 | 10 | mpl.style.use([ 11 | ROOT_DIR / 'styles/base.mplstyle', 12 | ROOT_DIR / 'styles/plotlet-grid.mplstyle', 13 | ]) 14 | 15 | methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16', 16 | 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 17 | 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'] 18 | 19 | np.random.seed(1) 20 | Z = np.random.uniform(0, 1, (3, 3)) 21 | 22 | 23 | fig, axs = plt.subplots(nrows=6, ncols=3, figsize=(5.7/2.54, 5.7/2.54*2), 24 | # fig, axs = plt.subplots(nrows=6, ncols=3, figsize=(4.5,9), 25 | subplot_kw={'xticks': [], 'yticks': []}) 26 | for ax, interp_method in zip(axs.flat, methods): 27 | ax.imshow(Z, interpolation=interp_method, cmap='viridis', 28 | extent=[0, 1, 0, 1], rasterized=True) 29 | ax.text(0.5, 0.1, str(interp_method), weight="bold", color="white", size=6, 30 | ha="center", va="center") 31 | 32 | fig.savefig(ROOT_DIR / "figures/interpolations.pdf", dpi=600) 33 | # plt.show() 34 | -------------------------------------------------------------------------------- /scripts/layouts.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | from mpl_toolkits.axes_grid1 import make_axes_locatable 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | fig = plt.figure(figsize=(0.4, 0.4)) 16 | margin = 0.01 17 | fig.subplots_adjust(left=margin, right=1-margin, top=1-margin, bottom=margin) 18 | mpl.rc('axes', linewidth=.5) 19 | 20 | # Subplots 21 | # ----------------------------------------------------------------------------- 22 | nrows, ncols = 3, 3 23 | for i in range(nrows*ncols): 24 | ax = plt.subplot(ncols, nrows, i+1) 25 | ax.set_xticks([]), ax.set_yticks([]) 26 | fig.savefig(ROOT_DIR / "figures/layout-subplot.pdf") 27 | fig.clear() 28 | 29 | # Subplots (colored) 30 | # ----------------------------------------------------------------------------- 31 | nrows, ncols = 3, 3 32 | for i in range(nrows*ncols): 33 | ax = plt.subplot(ncols, nrows, i+1) 34 | ax.set_xticks([]), ax.set_yticks([]) 35 | if i == 0: ax.set_facecolor("#ddddff") 36 | if i == 8: ax.set_facecolor("#ffdddd") 37 | fig.savefig(ROOT_DIR / "figures/layout-subplot-color.pdf") 38 | fig.clear() 39 | 40 | # Spines 41 | # ----------------------------------------------------------------------------- 42 | ax = fig.add_subplot(1, 1, 1, xticks=[], yticks=[]) 43 | ax.spines["top"].set_color("None") 44 | ax.spines["right"].set_color("None") 45 | fig.savefig(ROOT_DIR / "figures/layout-spines.pdf") 46 | fig.clear() 47 | 48 | 49 | # Gridspec 50 | # ----------------------------------------------------------------------------- 51 | gs = fig.add_gridspec(3, 3) 52 | ax1 = fig.add_subplot(gs[0, :], xticks=[], yticks=[]) 53 | ax2 = fig.add_subplot(gs[1, :-1], xticks=[], yticks=[]) 54 | ax3 = fig.add_subplot(gs[1:, -1], xticks=[], yticks=[]) 55 | ax4 = fig.add_subplot(gs[-1, 0], xticks=[], yticks=[]) 56 | ax5 = fig.add_subplot(gs[-1, -2], xticks=[], yticks=[]) 57 | fig.savefig(ROOT_DIR / "figures/layout-gridspec.pdf") 58 | fig.clear() 59 | 60 | # Gridspec (colored) 61 | # ----------------------------------------------------------------------------- 62 | gs = fig.add_gridspec(3, 3) 63 | ax1 = fig.add_subplot(gs[0, :], xticks=[], yticks=[]) 64 | ax1.set_facecolor("#ddddff") 65 | ax2 = fig.add_subplot(gs[1, :-1], xticks=[], yticks=[]) 66 | ax3 = fig.add_subplot(gs[1:, -1], xticks=[], yticks=[]) 67 | ax4 = fig.add_subplot(gs[-1, 0], xticks=[], yticks=[]) 68 | ax5 = fig.add_subplot(gs[-1, -2], xticks=[], yticks=[]) 69 | fig.savefig(ROOT_DIR / "figures/layout-gridspec-color.pdf") 70 | fig.clear() 71 | 72 | # Inset axes 73 | # ----------------------------------------------------------------------------- 74 | mpl.rc('axes', linewidth=.5) 75 | margin = 0.0125 76 | ax1 = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin], xticks=[], yticks=[]) 77 | ax2 = ax1.inset_axes([0.5, 0.5, 0.4, 0.4], xticks=[], yticks=[]) 78 | fig.savefig(ROOT_DIR / "figures/layout-inset.pdf") 79 | fig.clear() 80 | 81 | 82 | # Axes divider 83 | # ----------------------------------------------------------------------------- 84 | margin = 0.0125 85 | ax = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin], xticks=[], yticks=[]) 86 | divider = make_axes_locatable(ax) 87 | cax = divider.new_horizontal(size="10%", pad=0.025) 88 | fig.add_axes(cax) 89 | cax.set_xticks([]), cax.set_yticks([]) 90 | fig.savefig(ROOT_DIR / "figures/layout-divider.pdf") 91 | -------------------------------------------------------------------------------- /scripts/legend.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | mpl.style.use([ 15 | ROOT_DIR / 'styles/base.mplstyle', 16 | ]) 17 | mpl.rc('font', size=6) 18 | mpl.rc('lines', markersize=4) 19 | 20 | 21 | subplots_kw = dict( 22 | figsize=(5.7/2.54, 5.7/2.54), 23 | subplot_kw=dict( 24 | aspect=1, frameon=True, 25 | xlim=(0, 1), ylim=(0, 1), 26 | xticks=[], yticks=[], 27 | ), 28 | ) 29 | 30 | (fig, ax) = plt.subplots(**subplots_kw) 31 | 32 | 33 | def text(x, y, _text): 34 | color= "C1" 35 | if not 0 < x < 1 or not 0 < y < 1: color = "C0" 36 | size = 0.15 37 | ax.text(x, y, _text, color="white", # bbox={"color": "C1"}, 38 | size="xx-large", weight="bold", ha="center", va="center") 39 | rect = plt.Rectangle((x-size/2, y-size/2), size, size, facecolor=color, 40 | zorder=-10, clip_on=False) 41 | ax.add_patch(rect) 42 | 43 | 44 | def point(x, y): 45 | ax.scatter([x], [y], facecolor="C0", edgecolor="white", 46 | zorder=10, clip_on=False) 47 | 48 | 49 | d = .1 50 | e = .15/2 51 | 52 | text( d, d, "3"), text( 0.5, d, "8"), text(1-d, d, "4") 53 | text( d, 0.5, "6"), text( 0.5, 0.5, "10"), text(1-d, 0.5, "7") 54 | text( d, 1-d, "2"), text( 0.5, 1-d, "9"), text(1-d, 1-d, "1") 55 | 56 | text( -d, 1-d, "A"), text( -d, 0.5, "B"), text( -d, d, "C") 57 | point(-d+e, 1-d+e), point(-d+e, 0.5), point(-d+e, d-e), 58 | 59 | text( d, -d, "D"), text(0.5, -d, "E"), text( 1-d, -d, "F") 60 | point(d-e, -d+e), point(0.5, -d+e), point(1-d+e, -d+e), 61 | 62 | text(1+d, d, "G"), text(1+d, 0.5, "H"), text( 1+d, 1-d, "I") 63 | point(1+d-e, d-e), point(1+d-e, .5), point(1+d-e, 1-d+e), 64 | 65 | text(1-d, 1+d, "J"), text(0.5, 1+d, "K"), text( d, 1+d, "L") 66 | point(1-d+e, 1+d-e), point(0.5, 1+d-e), point(d-e, 1+d-e), 67 | 68 | fig.savefig(ROOT_DIR / "figures/legend-placement.pdf") 69 | -------------------------------------------------------------------------------- /scripts/linestyles.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | 10 | 11 | ROOT_DIR = pathlib.Path(__file__).parent.parent 12 | 13 | fig = plt.figure(figsize=(4.25, 2*.55)) 14 | ax = fig.add_axes([0, 0, 1, 1], xlim=[0.75, 10.25], ylim=[0.5, 2.5], frameon=False, 15 | xticks=[], yticks=[]) 16 | y = 2 17 | 18 | 19 | def split(n_segment): 20 | width = 9 21 | segment_width = 0.75*(width/n_segment) 22 | segment_pad = (width - n_segment*segment_width)/(n_segment-1) 23 | X0 = 1+np.arange(n_segment)*(segment_width+segment_pad) 24 | X1 = X0 + segment_width 25 | return X0, X1 26 | 27 | 28 | # Line style 29 | # ---------------------------------------------------------------------------- 30 | X0, X1 = split(5) 31 | styles = "-", ":", "--", "-.", (0, (0.01, 2)) 32 | 33 | for x0, x1, style in zip(X0, X1, styles): 34 | ax.plot([x0, x1], [y, y], color="C1", linestyle=style, 35 | solid_capstyle="round", dash_capstyle="round", linewidth=3) 36 | if isinstance(style, str): text = '"%s"' % style 37 | else: text = '%s' % str(style) 38 | text = text.replace(' ', '') 39 | ax.text((x0+x1)/2, y-0.2, text, 40 | size=8, ha="center", va="top", family="Source Code Pro") 41 | ax.text(X0[0]-0.25, y+0.2, "linestyle or ls", family="Source Code Pro", 42 | size=14, ha="left", va="baseline") 43 | y -= 1 44 | 45 | # Dash capstyle 46 | # ---------------------------------------------------------------------------- 47 | X0, X1 = split(3) 48 | styles = "butt", "round", "projecting" 49 | for x0, x1, style in zip(X0, X1, styles): 50 | ax.plot([x0, x1], [y, y], color="C1", dash_capstyle="projecting", 51 | linewidth=7, linestyle="--", alpha=.25) 52 | ax.plot([x0, x1], [y, y], color="C1", linewidth=7, 53 | linestyle="--", dash_capstyle=style) 54 | ax.text((x0+x1)/2, y-0.2, '"%s"' % style, family="Source Code Pro", 55 | size=10, ha="center", va="top") 56 | ax.text(X0[0]-0.25, y+0.2, "capstyle or dash_capstyle", family="Source Code Pro", 57 | size=14, ha="left", va="baseline") 58 | 59 | 60 | fig.savefig(ROOT_DIR / "figures/linestyles.pdf", dpi=200) 61 | # plt.show() 62 | -------------------------------------------------------------------------------- /scripts/markers.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | 10 | 11 | ROOT_DIR = pathlib.Path(__file__).parent.parent 12 | 13 | # Markers 14 | # ----------------------------------------------------------------------------- 15 | fig = plt.figure(figsize=(3.5, 1.5)) 16 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, 17 | xlim=[0.5, 10.5], ylim=[0.0, 4.35], xticks=[], yticks=[]) 18 | X = np.linspace(1, 10, 12) 19 | Y = np.arange(1, 4) 20 | X, Y = np.meshgrid(X, Y) 21 | X , Y = X.ravel(), Y.ravel() 22 | 23 | plt.scatter(X, 1+Y, s=256, marker="s", fc="C1", ec="none", alpha=.25) 24 | markers = [ 25 | "$♠$", "$♣$", "$♥$", "$♦$", "$→$", "$←$", "$↑$", "$↓$", "$◐$", "$◑$", "$◒$", "$◓$", 26 | "1", "2", "3", "4", "+", "x", "|", "_", 4, 5, 6, 7, 27 | ".", "o", "s", "P", "X", "*", "p", "D", "<", ">", "^", "v", ] 28 | for x, y, marker in zip(X, Y, markers): 29 | if y == 3: fc = "white" 30 | else: fc = "C1" 31 | plt.scatter(x, 1+y, s=100, marker=marker, fc=fc, ec="C1", lw=0.5) 32 | 33 | if y == 1: marker = "\$%s\$" % marker 34 | if isinstance(marker, str): text = "'%s'" % marker 35 | else: text = '%s' % marker 36 | plt.text(x, 1+y-0.4, text, 37 | size="x-small", ha="center", va="top", family="Monospace") 38 | 39 | 40 | # Spacing 41 | n_segment = 4 42 | width = 9 43 | segment_width = 0.75*(width/n_segment) 44 | segment_pad = (width - n_segment*segment_width)/(n_segment-1) 45 | X0 = 1+np.arange(n_segment)*(segment_width+segment_pad) 46 | marks = [ 10, [0, -1], (25, 5), [0, 25, -1] ] 47 | y = .6 48 | for x0, mark in zip(X0, marks): 49 | X = np.linspace(x0, x0+segment_width, 50) 50 | Y = y*np.ones(len(X)) 51 | ax.plot(X, Y, linewidth=1, color="black", 52 | marker=".", mfc="white", mec="black", mew="1", markevery=mark) 53 | ax.text((X[0]+X[-1])/2, y-0.2, '%s' % str(mark), 54 | size="x-small", ha="center", va="top") 55 | 56 | plt.text(.7, 1, "markevery", 57 | size="medium", ha="left", va="center", family="Source Code Pro") 58 | fig.savefig(ROOT_DIR / "figures/markers.pdf", dpi=600) 59 | -------------------------------------------------------------------------------- /scripts/performance-tips.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import time 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | 9 | 10 | fig, ax = plt.subplots() 11 | 12 | n = 10_000_000 13 | np.random.seed(1) 14 | X = np.random.uniform(0, 1, n) 15 | Y = np.random.uniform(0, 1, n) 16 | 17 | start = time.perf_counter() 18 | ax.plot(X, Y, marker="o", ls="") 19 | end = time.perf_counter() 20 | print(f"Time: {end-start}s") 21 | 22 | ax.clear() 23 | 24 | start = time.perf_counter() 25 | ax.scatter(X, Y) 26 | end = time.perf_counter() 27 | print(f"Time: {end-start}s") 28 | 29 | ax.clear() 30 | 31 | n = 1_000 32 | np.random.seed(1) 33 | X = [] 34 | for i in range(n): 35 | X.append(np.random.uniform(0, 1, 10)) 36 | # np.random.uniform(0,1,n) 37 | # Y = np.random.uniform(0,1,n) 38 | 39 | start = time.perf_counter() 40 | # for i in range(0,n,2): plt.plot(X[i:i+2], Y[i:i+2]) 41 | for i in range(n): plt.plot(X[i]) 42 | end = time.perf_counter() 43 | print(f"Time: {end-start}s") 44 | 45 | ax.clear() 46 | 47 | start = time.perf_counter() 48 | ax.plot(sum([list(x)+[None] for x in X], [])) 49 | # X0,Y0 = X[0::2], Y[0::2] 50 | # X1,Y1 = X[1::2], Y[1::2] 51 | # S = [None]*len(X) 52 | # X = [v for t in zip(X0,X1,S) for v in t] 53 | # Y = [v for t in zip(Y0,Y1,S) for v in t] 54 | # plt.plot(X,Y) 55 | end = time.perf_counter() 56 | print(f"Time: {end-start}s") 57 | -------------------------------------------------------------------------------- /scripts/plot-variations.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | # Scripts to generate all the basic plots 8 | import numpy as np 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | mpl.style.use([ 16 | ROOT_DIR / 'styles/base.mplstyle', 17 | ROOT_DIR / 'styles/plotlet.mplstyle', 18 | ]) 19 | mpl.rc('axes', titlepad=1) 20 | 21 | 22 | subplot_kw = dict( 23 | xlim=(0, 8), xticks=np.arange(1, 8), 24 | ylim=(0, 8), yticks=np.arange(1, 8), 25 | ) 26 | 27 | # Basic line plot (color) 28 | # ----------------------------------------------------------------------------- 29 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 30 | X = np.linspace(0, 10, 100) 31 | Y = 4+2*np.sin(2*X) 32 | ax.plot(X, Y, color="black", linewidth=0.75) 33 | ax.grid() 34 | fig.savefig(ROOT_DIR / "figures/plot-color.pdf") 35 | 36 | # Basic line plot (linestyle) 37 | # ----------------------------------------------------------------------------- 38 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 39 | X = np.linspace(0, 10, 100) 40 | Y = 4+2*np.sin(2*X) 41 | ax.plot(X, Y, color="C1", linewidth=0.75, linestyle="--") 42 | ax.grid() 43 | fig.savefig(ROOT_DIR / "figures/plot-linestyle.pdf") 44 | 45 | # Basic line plot (linewidth) 46 | # ----------------------------------------------------------------------------- 47 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 48 | X = np.linspace(0, 10, 100) 49 | Y = 4+2*np.sin(2*X) 50 | ax.plot(X, Y, color="C1", linewidth=1.5) 51 | ax.grid() 52 | fig.savefig("../figures/plot-linewidth.pdf") 53 | fig.savefig(ROOT_DIR / "figures/plot-linewidth.pdf") 54 | 55 | # Basic line plot (marker) 56 | # ----------------------------------------------------------------------------- 57 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 58 | X = np.linspace(0, 10, 100) 59 | Y = 4+2*np.sin(2*X) 60 | ax.plot(X, Y, color="C1", linewidth=0.75, marker="o", markevery=5, markersize=2) 61 | ax.grid() 62 | fig.savefig(ROOT_DIR / "figures/plot-marker.pdf") 63 | 64 | # Basic line plot (multi) 65 | # ----------------------------------------------------------------------------- 66 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 67 | X = np.linspace(0, 10, 100) 68 | Y1 = 4+2*np.sin(2*X) 69 | Y2 = 4+2*np.cos(2*X) 70 | ax.plot(X, Y1, color="C1", linewidth=0.75) 71 | ax.plot(X, Y2, color="C0", linewidth=0.75) 72 | ax.grid() 73 | fig.savefig(ROOT_DIR / "figures/plot-multi.pdf") 74 | 75 | # Basic line plot (vsplit) 76 | # ----------------------------------------------------------------------------- 77 | (fig, [ax2, ax1]) = plt.subplots(nrows=2, gridspec_kw=dict(hspace=0.2), subplot_kw=subplot_kw) 78 | 79 | X = np.linspace(0, 10, 100) 80 | Y1 = 2+1*np.sin(2*X) 81 | ax1.plot(X, Y1, color="C1", linewidth=0.75) 82 | ax1.set_ylim(0, 4), ax1.set_yticks(np.arange(1, 4)) 83 | ax1.grid() 84 | ax1.tick_params(axis=u'both', which=u'both', length=0) 85 | 86 | Y2 = 2+1*np.cos(2*X) 87 | ax2.plot(X, Y2, color="C0", linewidth=0.75) 88 | ax2.set_ylim(0, 4), ax2.set_yticks(np.arange(1, 4)) 89 | ax2.grid() 90 | ax2.tick_params(axis=u'both', which=u'both', length=0) 91 | fig.savefig(ROOT_DIR / "figures/plot-vsplit.pdf") 92 | 93 | # Basic line plot (hsplit) 94 | # ----------------------------------------------------------------------------- 95 | (fig, [ax1, ax2]) = plt.subplots(ncols=2, gridspec_kw=dict(wspace=0.2), subplot_kw=subplot_kw) 96 | 97 | X = np.linspace(0, 10, 100) 98 | Y1 = 2+1*np.sin(2*X) 99 | ax1.plot(Y1, X, color="C1", linewidth=0.75) 100 | ax1.set_xlim(0, 4), ax1.set_xticks(np.arange(1, 4)) 101 | ax1.grid() 102 | ax1.tick_params(axis=u'both', which=u'both', length=0) 103 | 104 | Y2 = 2+1*np.cos(2*X) 105 | ax2.plot(Y2, X, color="C0", linewidth=0.75) 106 | ax2.set_xlim(0, 4), ax2.set_xticks(np.arange(1, 4)) 107 | ax2.grid() 108 | ax2.tick_params(axis=u'both', which=u'both', length=0) 109 | fig.savefig(ROOT_DIR / "figures/plot-hsplit.pdf") 110 | 111 | # Basic line plot (title) 112 | # ----------------------------------------------------------------------------- 113 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 114 | X = np.linspace(0, 10, 100) 115 | Y = 3+2*np.sin(2*X) 116 | ax.plot(X, Y, color="C1", linewidth=0.75) 117 | ax.set_ylim(0, 6), ax.set_yticks(np.arange(1, 6)) 118 | ax.grid() 119 | ax.set_title("A Sine wave", size=4, weight="bold") 120 | fig.savefig(ROOT_DIR / "figures/plot-title.pdf") 121 | 122 | # Basic line plot (xlabel) 123 | # ----------------------------------------------------------------------------- 124 | (fig, ax) = plt.subplots(subplot_kw=subplot_kw) 125 | X = np.linspace(0, 10, 100) 126 | Y = 3+2*np.sin(2*X) 127 | ax.plot(X, Y, color="C1", linewidth=0.75), ax.set_xticklabels([]) 128 | ax.set_ylim(0, 6), ax.set_yticks(np.arange(1, 6)), ax.set_yticklabels([]) 129 | ax.grid() 130 | ax.text(4, -1, "Time", transform=ax.transData, clip_on=False, 131 | size=3.5, ha="center", va="center") 132 | fig.savefig(ROOT_DIR / "figures/plot-xlabel.pdf") 133 | -------------------------------------------------------------------------------- /scripts/projections.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import cartopy 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | mpl.style.use([ 16 | ROOT_DIR / 'styles/base.mplstyle', 17 | ROOT_DIR / 'styles/plotlet.mplstyle', 18 | ]) 19 | 20 | CARTOPY_SOURCE_TEMPLATE = 'https://naturalearth.s3.amazonaws.com/{resolution}_{category}/ne_{resolution}_{name}.zip' 21 | 22 | 23 | # Configures cartopy to download NaturalEarth shapefiles from S3 instead of naciscdn 24 | # Taken from https://github.com/SciTools/cartopy/issues/1325#issuecomment-904343657 25 | target_path_template = cartopy.io.shapereader.NEShpDownloader.default_downloader().target_path_template 26 | downloader = cartopy.io.shapereader.NEShpDownloader(url_template=CARTOPY_SOURCE_TEMPLATE, 27 | target_path_template=target_path_template) 28 | cartopy.config['downloaders'][('shapefiles', 'natural_earth')] = downloader 29 | 30 | 31 | # Polar plot 32 | # ----------------------------------------------------------------------------- 33 | (fig, ax) = plt.subplots(subplot_kw={'projection': 'polar'}) 34 | T = np.linspace(0, 3*2*np.pi, 500) 35 | R = np.linspace(0, 2, len(T)) 36 | ax.plot(T, R, color="C1") 37 | ax.set_xticks(np.linspace(0, 2*np.pi, 2*8)) 38 | ax.set_xticklabels([]) 39 | ax.set_yticks(np.linspace(0, 2, 8)) 40 | ax.set_yticklabels([]) 41 | ax.set_ylim(0, 2) 42 | ax.grid(linewidth=0.2) 43 | fig.savefig(ROOT_DIR / "figures/projection-polar.pdf") 44 | fig.clear() 45 | 46 | # 3D plot 47 | # ----------------------------------------------------------------------------- 48 | (fig, ax) = plt.subplots(subplot_kw={'projection': '3d'}) 49 | r = np.linspace(0, 1.25, 50) 50 | p = np.linspace(0, 2*np.pi, 50) 51 | R, P = np.meshgrid(r, p) 52 | Z = ((R**2 - 1)**2) 53 | X, Y = R*np.cos(P), R*np.sin(P) 54 | 55 | # Plot the surface. 56 | ax.plot_surface(X, Y, Z, color="C1", antialiased=False) 57 | ax.set_zlim(0, 1) 58 | ax.set_xticks([]) 59 | ax.set_yticks([]) 60 | ax.set_zticks([]) 61 | fig.savefig(ROOT_DIR / "figures/projection-3d.pdf") 62 | fig.clear() 63 | 64 | # Cartopy plot 65 | # ----------------------------------------------------------------------------- 66 | fig = plt.figure() 67 | ax = fig.add_subplot(frameon=False, 68 | projection=cartopy.crs.Orthographic()) 69 | ax.add_feature(cartopy.feature.LAND, zorder=0, 70 | facecolor="C1", edgecolor="0.0", linewidth=0) 71 | fig.savefig(ROOT_DIR / "figures/projection-cartopy.pdf") 72 | -------------------------------------------------------------------------------- /scripts/scales.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | ROOT_DIR = pathlib.Path(__file__).parent.parent 8 | 9 | fig = plt.figure(figsize=(0.4, 2/3*0.4)) 10 | ax = fig.add_axes([0, 0, 1, 1], frameon=False) 11 | ax.tick_params(axis='both', which='both', length=0) 12 | ax.set_xlim(-2, 2) 13 | X = np.linspace(-2, +2, 1001) 14 | Y = np.sin(X*2.5*2*np.pi) 15 | 16 | 17 | # Linear scale 18 | # ----------------------------------------------------------------------------- 19 | ax.set_xlim(X.min(), X.max()) 20 | ax.set_xscale("linear") 21 | ax.plot(X, Y, color="C1", linewidth=0.75) 22 | ax.set_ylim(-2.5, 1.5) 23 | ax.text(0, 0.12, "-∞", ha="left", va="bottom", size=3, transform=ax.transAxes) 24 | ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) 25 | ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) 26 | ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) 27 | fig.savefig(ROOT_DIR / "figures/scale-linear.pdf") 28 | ax.clear() 29 | 30 | # Log scale 31 | # ----------------------------------------------------------------------------- 32 | ax.set_xscale("log", base=10) 33 | ax.plot(X, Y, color="C1", linewidth=0.75) 34 | ax.set_ylim(-2.5, 1.5) 35 | ax.text(0, 0.12, "0", ha="left", va="bottom", size=3, transform=ax.transAxes) 36 | ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) 37 | ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) 38 | ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) 39 | fig.savefig(ROOT_DIR / "figures/scale-log.pdf") 40 | ax.clear() 41 | 42 | # Symlog scale 43 | # ----------------------------------------------------------------------------- 44 | ax.set_xscale("symlog", base=10, linthresh=1) 45 | ax.plot(X, Y, color="C1", linewidth=0.75) 46 | ax.set_ylim(-2.5, 1.5) 47 | ax.text(0, 0.12, "-∞", ha="left", va="bottom", size=3, transform=ax.transAxes) 48 | ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) 49 | ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) 50 | ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) 51 | fig.savefig(ROOT_DIR / "figures/scale-symlog.pdf") 52 | ax.clear() 53 | 54 | # Symlog scale 55 | # ----------------------------------------------------------------------------- 56 | ax.set_xscale("logit") 57 | ax.plot(X, Y, color="C1", linewidth=0.75) 58 | ax.set_ylim(-2.5, 1.5) 59 | ax.text(0, 0.12, "0", ha="left", va="bottom", size=3, transform=ax.transAxes) 60 | ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) 61 | ax.text(1, 0.12, "1", ha="right", va="bottom", size=3, transform=ax.transAxes) 62 | ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) 63 | fig.savefig(ROOT_DIR / "figures/scale-logit.pdf") 64 | ax.clear() 65 | -------------------------------------------------------------------------------- /scripts/sine.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Author: Nicolas P. Rougier 3 | # License: BSD 4 | # ---------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | mpl.style.use([ 15 | ROOT_DIR / 'styles/base.mplstyle', 16 | ROOT_DIR / 'styles/sine-plot.mplstyle', 17 | ]) 18 | 19 | X = np.linspace(0, 10*np.pi, 1000) 20 | Y = np.sin(X) 21 | 22 | 23 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.2/2.54)) 24 | ax.set_yticks(np.linspace(-1, 1, 5)) 25 | ax.plot(X, Y, color="C1") 26 | fig.savefig(ROOT_DIR / "figures/sine.pdf") 27 | 28 | 29 | X = np.linspace(0.1, 10*np.pi, 1000) 30 | Y = np.sin(X) 31 | 32 | 33 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) 34 | ax.plot(X, Y, "C1o:", markevery=50, mec="1.0") 35 | ax.set_ylim(-1.5, 1.5) 36 | fig.savefig(ROOT_DIR / "figures/sine-marker.pdf") 37 | 38 | 39 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) 40 | ax.set_xscale("log") 41 | ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") 42 | ax.set_ylim(-1.5, 1.5) 43 | fig.savefig(ROOT_DIR / "figures/sine-logscale.pdf") 44 | 45 | 46 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) 47 | ax.plot(X, Y, "C1") 48 | ax.fill_betweenx([-1.5, 1.5], [0], [2*np.pi], color=".9") 49 | ax.text(0, -1, r" Period $\Phi$", va="top") 50 | ax.set_ylim(-1.5, 1.5) 51 | fig.savefig(ROOT_DIR / "figures/sine-period.pdf") 52 | 53 | 54 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) 55 | ax.plot(X, np.sin(X), "C0", label="Sine") 56 | ax.plot(X, np.cos(X), "C1", label="Cosine") 57 | ax.legend(bbox_to_anchor=(0.0, .9, 1.02, 0.1), 58 | frameon=False, mode="expand", ncol=2, loc="lower left") 59 | ax.set_title("Sine and Cosine") 60 | ax.set_xticks([]), ax.set_yticks([]) 61 | ax.set_ylim(-1.25, 1.25) 62 | fig.savefig(ROOT_DIR / "figures/sine-legend.pdf") 63 | 64 | 65 | fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) 66 | X = np.linspace(0, 10*np.pi, 1000) 67 | Y = np.sin(X) 68 | ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") 69 | ax.set_ylim(-1.5, 1.5) 70 | ax.annotate(" ", (X[200], Y[200]), (X[250], -1), ha="center", va="center", 71 | arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) 72 | ax.annotate("A", (X[250], Y[250]), (X[250], -1), ha="center", va="center", 73 | arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) 74 | ax.annotate(" ", (X[300], Y[300]), (X[250], -1), ha="center", va="center", 75 | arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) 76 | fig.savefig(ROOT_DIR / "figures/sine-annotate.pdf") 77 | -------------------------------------------------------------------------------- /scripts/styles.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | for style in ['default'] + plt.style.available: 15 | with plt.style.context(style): 16 | fig = plt.figure(figsize=(5, 3), dpi=100) 17 | ax = plt.subplot(1, 1, 1) 18 | X = np.linspace(0, 2*np.pi, 256) 19 | Y = np.cos(X) 20 | ax.plot(X, Y) 21 | plt.title(style, family="Source Serif Pro", size=32) 22 | plt.tight_layout() 23 | fig.savefig(ROOT_DIR / f"figures/style-{style}.pdf") 24 | plt.close(fig) 25 | -------------------------------------------------------------------------------- /scripts/text-alignments.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | 10 | 11 | ROOT_DIR = pathlib.Path(__file__).parent.parent 12 | 13 | dpi = 100 14 | fig = plt.figure(figsize=(4.25, 1.5), dpi=dpi) 15 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, 16 | xlim=(0, 4.25), ylim=(0, 1.5), xticks=[], yticks=[]) 17 | 18 | fontsize = 48 19 | renderer = fig.canvas.get_renderer() 20 | horizontalalignment = "left" 21 | verticalalignment = "center" 22 | position = (0.25, 1.5/2) 23 | color = "0.25" 24 | 25 | # Compute vertical and horizontal alignment offsets 26 | text = ax.text(0, 0, "Matplotlib", fontsize=fontsize) 27 | yoffset = {} 28 | for alignment in ["top", "center", "baseline", "bottom"]: 29 | text.set_verticalalignment(alignment) 30 | y = text.get_window_extent(renderer).y0/dpi 31 | yoffset[alignment] = y 32 | 33 | xoffset = {} 34 | for alignment in ["left", "center", "right"]: 35 | text.set_horizontalalignment(alignment) 36 | x = text.get_window_extent(renderer).x0/dpi 37 | xoffset[alignment] = x 38 | 39 | # Actual positioning of the text 40 | text.set_horizontalalignment(horizontalalignment) 41 | text.set_verticalalignment(verticalalignment) 42 | text.set_position(position) 43 | 44 | 45 | for name, y in yoffset.items(): 46 | y = position[1] - y + yoffset[verticalalignment] 47 | plt.plot([0.1, 3.75], [y, y], linewidth=0.5, color=color) 48 | plt.text(3.75, y, " "+name, color=color, 49 | ha="left", va="center", size="x-small") 50 | 51 | for name, x in xoffset.items(): 52 | x = position[0] - x + xoffset[horizontalalignment] 53 | plt.plot([x, x], [0.25, 1.25], linewidth=0.5, color=color) 54 | plt.text(x, 0.24, name, color=color, 55 | ha="center", va="top", size="x-small") 56 | 57 | P = [] 58 | for x in xoffset.values(): 59 | x = position[0] - x + xoffset[horizontalalignment] 60 | for y in yoffset.values(): 61 | y = position[1] - y + yoffset[verticalalignment] 62 | P.append((x, y)) 63 | P = np.array(P) 64 | 65 | ax.scatter(P[:, 0], P[:, 1], s=10, zorder=10, 66 | facecolor="white", edgecolor=color, linewidth=0.75) 67 | 68 | epsilon = 0.05 69 | plt.text(P[3, 0]+epsilon, P[3, 1]-epsilon, "(0,0)", 70 | color=color, ha="left", va="top", size="x-small") 71 | plt.text(P[8, 0]-epsilon, P[8, 1]+epsilon, "(1,1)", 72 | color=color, ha="right", va="bottom", size="x-small") 73 | 74 | fig.savefig(ROOT_DIR / "figures/text-alignments.pdf") 75 | # plt.show() 76 | -------------------------------------------------------------------------------- /scripts/tick-formatters.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Title: Scientific Visualisation - Python & Matplotlib 3 | # Author: Nicolas P. Rougier 4 | # License: BSD 5 | # ---------------------------------------------------------------------------- 6 | import pathlib 7 | 8 | import matplotlib.pyplot as plt 9 | import matplotlib.ticker as ticker 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | 15 | # Setup a plot such that only the bottom spine is shown 16 | def setup(ax): 17 | """Set up Axes with just an x-Axis.""" 18 | ax.spines['right'].set_color('none') 19 | ax.spines['left'].set_color('none') 20 | ax.yaxis.set_major_locator(ticker.NullLocator()) 21 | ax.spines['top'].set_color('none') 22 | ax.xaxis.set_ticks_position('bottom') 23 | ax.tick_params(which='major', width=1.00, length=5) 24 | ax.tick_params(which='minor', width=0.75, length=2.5, labelsize=10) 25 | ax.set_xlim(0, 5) 26 | ax.set_ylim(0, 1) 27 | ax.patch.set_alpha(0.0) 28 | 29 | 30 | fig = plt.figure(figsize=(8, 5)) 31 | fig.patch.set_alpha(0.0) 32 | n = 7 33 | 34 | fontsize = 18 35 | family = "Source Code Pro" 36 | 37 | # Null formatter 38 | ax = fig.add_subplot(n, 1, 1) 39 | setup(ax) 40 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00)) 41 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 42 | ax.xaxis.set_major_formatter(ticker.NullFormatter()) 43 | ax.xaxis.set_minor_formatter(ticker.NullFormatter()) 44 | ax.text(0.0, 0.1, "ticker.NullFormatter()", family=family, 45 | fontsize=fontsize, transform=ax.transAxes) 46 | 47 | # Fixed formatter 48 | ax = fig.add_subplot(n, 1, 2) 49 | setup(ax) 50 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 51 | ax.xaxis.set_major_locator(ticker.FixedLocator(range(6))) 52 | majors = ["zero", "one", "two", "three", "four", "five"] 53 | ax.xaxis.set_major_formatter(ticker.FixedFormatter(majors)) 54 | ax.text(0.0, 0.1, "ticker.FixedFormatter(['zero', 'one', 'two', …])", 55 | family=family, fontsize=fontsize, transform=ax.transAxes) 56 | 57 | 58 | # FuncFormatter can be used as a decorator 59 | @ticker.FuncFormatter 60 | def major_formatter(x, pos): 61 | """Return formatted value with 2 decimal places.""" 62 | return "[%.2f]" % x 63 | 64 | 65 | ax = fig.add_subplot(n, 1, 3) 66 | setup(ax) 67 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00)) 68 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 69 | ax.xaxis.set_major_formatter(major_formatter) 70 | ax.text(0.0, 0.1, 'ticker.FuncFormatter(lambda x, pos: "[%.2f]" % x)', 71 | family=family, fontsize=fontsize, transform=ax.transAxes) 72 | 73 | 74 | # FormatStr formatter 75 | ax = fig.add_subplot(n, 1, 4) 76 | setup(ax) 77 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00)) 78 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 79 | ax.xaxis.set_major_formatter(ticker.FormatStrFormatter(">%d<")) 80 | ax.text(0.0, 0.1, "ticker.FormatStrFormatter('>%d<')", 81 | family=family, fontsize=fontsize, transform=ax.transAxes) 82 | 83 | # Scalar formatter 84 | ax = fig.add_subplot(n, 1, 5) 85 | setup(ax) 86 | ax.xaxis.set_major_locator(ticker.AutoLocator()) 87 | ax.xaxis.set_minor_locator(ticker.AutoMinorLocator()) 88 | ax.xaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True)) 89 | ax.text(0.0, 0.1, "ticker.ScalarFormatter()", 90 | family=family, fontsize=fontsize, transform=ax.transAxes) 91 | 92 | # StrMethod formatter 93 | ax = fig.add_subplot(n, 1, 6) 94 | setup(ax) 95 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00)) 96 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 97 | ax.xaxis.set_major_formatter(ticker.StrMethodFormatter("{x}")) 98 | ax.text(0.0, 0.1, "ticker.StrMethodFormatter('{x}')", 99 | family=family, fontsize=fontsize, transform=ax.transAxes) 100 | 101 | # Percent formatter 102 | ax = fig.add_subplot(n, 1, 7) 103 | setup(ax) 104 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00)) 105 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) 106 | ax.xaxis.set_major_formatter(ticker.PercentFormatter(xmax=5)) 107 | ax.text(0.0, 0.1, "ticker.PercentFormatter(xmax=5)", 108 | family=family, fontsize=fontsize, transform=ax.transAxes) 109 | 110 | # Push the top of the top axes outside the figure because we only show the 111 | # bottom spine. 112 | fig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05) 113 | 114 | fig.savefig(ROOT_DIR / "figures/tick-formatters.pdf", transparent=True) 115 | # plt.show() 116 | -------------------------------------------------------------------------------- /scripts/tick-locators.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Title: Scientific Visualisation - Python & Matplotlib 3 | # Author: Nicolas P. Rougier 4 | # License: BSD 5 | # ---------------------------------------------------------------------------- 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | import matplotlib.ticker as ticker 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | 16 | # Setup a plot such that only the bottom spine is shown 17 | def setup(ax): 18 | ax.spines['right'].set_color('none') 19 | ax.spines['left'].set_color('none') 20 | ax.yaxis.set_major_locator(ticker.NullLocator()) 21 | ax.spines['top'].set_color('none') 22 | ax.xaxis.set_ticks_position('bottom') 23 | ax.tick_params(which='major', width=1.00) 24 | ax.tick_params(which='major', length=5) 25 | ax.tick_params(which='minor', width=0.75) 26 | ax.tick_params(which='minor', length=2.5) 27 | ax.set_xlim(0, 5) 28 | ax.set_ylim(0, 1) 29 | ax.patch.set_alpha(0.0) 30 | 31 | 32 | fig = plt.figure(figsize=(8, 5)) 33 | fig.patch.set_alpha(0.0) 34 | n = 8 35 | 36 | fontsize = 18 37 | family = "Source Code Pro" 38 | 39 | # Null Locator 40 | ax = plt.subplot(n, 1, 1) 41 | setup(ax) 42 | ax.xaxis.set_major_locator(ticker.NullLocator()) 43 | ax.xaxis.set_minor_locator(ticker.NullLocator()) 44 | ax.text(0.0, 0.1, "ticker.NullLocator()", 45 | family=family, fontsize=fontsize, transform=ax.transAxes) 46 | 47 | # Multiple Locator 48 | ax = plt.subplot(n, 1, 2) 49 | setup(ax) 50 | ax.xaxis.set_major_locator(ticker.MultipleLocator(0.5)) 51 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.1)) 52 | ax.text(0.0, 0.1, "ticker.MultipleLocator(0.5)", 53 | family=family, fontsize=fontsize, transform=ax.transAxes) 54 | 55 | # Fixed Locator 56 | ax = plt.subplot(n, 1, 3) 57 | setup(ax) 58 | majors = [0, 1, 5] 59 | ax.xaxis.set_major_locator(ticker.FixedLocator(majors)) 60 | minors = np.linspace(0, 1, 11)[1:-1] 61 | ax.xaxis.set_minor_locator(ticker.FixedLocator(minors)) 62 | ax.text(0.0, 0.1, "ticker.FixedLocator([0, 1, 5])", 63 | family=family, fontsize=fontsize, transform=ax.transAxes) 64 | 65 | # Linear Locator 66 | ax = plt.subplot(n, 1, 4) 67 | setup(ax) 68 | ax.xaxis.set_major_locator(ticker.LinearLocator(3)) 69 | ax.xaxis.set_minor_locator(ticker.LinearLocator(31)) 70 | ax.text(0.0, 0.1, "ticker.LinearLocator(numticks=3)", 71 | family=family, fontsize=fontsize, transform=ax.transAxes) 72 | 73 | # Index Locator 74 | ax = plt.subplot(n, 1, 5) 75 | setup(ax) 76 | ax.plot(range(0, 5), [0]*5, color='white') 77 | ax.xaxis.set_major_locator(ticker.IndexLocator(base=.5, offset=.25)) 78 | ax.text(0.0, 0.1, "ticker.IndexLocator(base=0.5, offset=0.25)", 79 | family=family, fontsize=fontsize, transform=ax.transAxes) 80 | 81 | # Auto Locator 82 | ax = plt.subplot(n, 1, 6) 83 | setup(ax) 84 | ax.xaxis.set_major_locator(ticker.AutoLocator()) 85 | ax.xaxis.set_minor_locator(ticker.AutoMinorLocator()) 86 | ax.text(0.0, 0.1, "ticker.AutoLocator()", 87 | family=family, fontsize=fontsize, transform=ax.transAxes) 88 | 89 | # MaxN Locator 90 | ax = plt.subplot(n, 1, 7) 91 | setup(ax) 92 | ax.xaxis.set_major_locator(ticker.MaxNLocator(4)) 93 | ax.xaxis.set_minor_locator(ticker.MaxNLocator(40)) 94 | ax.text(0.0, 0.1, "ticker.MaxNLocator(n=4)", 95 | family=family, fontsize=fontsize, transform=ax.transAxes) 96 | 97 | # Log Locator 98 | ax = plt.subplot(n, 1, 8) 99 | setup(ax) 100 | ax.set_xlim(10**3, 10**10) 101 | ax.set_xscale('log') 102 | ax.xaxis.set_major_locator(ticker.LogLocator(base=10.0, numticks=15)) 103 | ax.text(0.0, 0.1, "ticker.LogLocator(base=10, numticks=15)", 104 | family=family, fontsize=fontsize, transform=ax.transAxes) 105 | 106 | # Push the top of the top axes outside the figure because we only show the 107 | # bottom spine. 108 | plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05) 109 | 110 | fig.savefig(ROOT_DIR / "figures/tick-locators.pdf", transparent=True) 111 | # plt.show() 112 | -------------------------------------------------------------------------------- /scripts/tick-multiple-locator.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Title: Scientific Visualisation - Python & Matplotlib 3 | # Author: Nicolas P. Rougier 4 | # License: BSD 5 | # ---------------------------------------------------------------------------- 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | import matplotlib.ticker as ticker 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | mpl.style.use([ 17 | ROOT_DIR / 'styles/base.mplstyle', 18 | ROOT_DIR / 'styles/ticks.mplstyle', 19 | ]) 20 | 21 | 22 | subplots_kw = dict( 23 | figsize=(5.7/2.54, 0.4/2.54), 24 | subplot_kw=dict(xlim=(0, 5), ylim=(0, 1)), 25 | ) 26 | 27 | (fig, ax) = plt.subplots(**subplots_kw) 28 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.0)) 29 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.2)) 30 | ax.xaxis.set_major_formatter(ticker.ScalarFormatter()) 31 | ax.xaxis.set_minor_formatter(ticker.ScalarFormatter()) 32 | ax.tick_params(axis='both', which='major', labelsize=5) 33 | ax.tick_params(axis='x', which='minor', rotation=90) 34 | 35 | fig.savefig(ROOT_DIR / "figures/tick-multiple-locator.pdf", transparent=True) 36 | -------------------------------------------------------------------------------- /scripts/tip-color-range.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Scripts to generate all the basic plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | fig = plt.figure(figsize=(2, 2)) 17 | mpl.rcParams['axes.linewidth'] = 1.5 18 | d = 0.01 19 | 20 | ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) 21 | 22 | X = np.random.seed(1) 23 | X = np.random.randn(1000, 4) 24 | cmap = plt.get_cmap("Oranges") 25 | colors = [cmap(i) for i in [.1, .3, .5, .7]] 26 | ax.hist(X, 2, density=True, histtype='bar', color=colors) 27 | 28 | fig.savefig(ROOT_DIR / "figures/tip-color-range.pdf") 29 | # plt.show() 30 | -------------------------------------------------------------------------------- /scripts/tip-colorbar.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Scripts to generate all the basic plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | import matplotlib.patheffects as path_effects 13 | 14 | 15 | ROOT_DIR = pathlib.Path(__file__).parent.parent 16 | 17 | fig = plt.figure(figsize=(2.15, 2)) 18 | mpl.rcParams['axes.linewidth'] = 1.5 19 | d = 0.01 20 | ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) 21 | 22 | np.random.seed(1) 23 | Z = np.random.uniform(0, 1, (8, 8)) 24 | cmap = plt.get_cmap("Oranges") 25 | im = ax.imshow(Z, interpolation="nearest", cmap=cmap, vmin=0, vmax=2) 26 | cb = fig.colorbar(im, fraction=0.046, pad=0.04) 27 | cb.set_ticks([]) 28 | 29 | fig.savefig(ROOT_DIR / "figures/tip-colorbar.pdf") 30 | # plt.show() 31 | -------------------------------------------------------------------------------- /scripts/tip-dotted.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Scripts to generate all the basic plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | ROOT_DIR = pathlib.Path(__file__).parent.parent 15 | 16 | fig = plt.figure(figsize=(5, .25)) 17 | 18 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, 19 | xticks=[], yticks=[], xlim=[0, 1], ylim=[-.5, 1.5]) 20 | 21 | epsilon=1e-12 22 | plt.plot([0, 1], [0, 0], "black", clip_on=False, lw=8, 23 | ls=(.5, (epsilon, 1)), dash_capstyle="round") 24 | plt.plot([0, 1], [1, 1], "black", clip_on=False, lw=8, 25 | ls=(-.5, (epsilon, 2)), dash_capstyle="round") 26 | fig.savefig(ROOT_DIR / "figures/tip-dotted.pdf") 27 | # plt.show() 28 | -------------------------------------------------------------------------------- /scripts/tip-dual-axis.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import numpy as np 4 | import matplotlib as mpl 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | ROOT_DIR = pathlib.Path(__file__).parent.parent 9 | 10 | mpl.rcParams['axes.linewidth'] = 1.5 11 | 12 | fig = plt.figure(figsize=(2, 2)) 13 | d = 0.01 14 | ax1 = fig.add_axes([d, d, 1-2*d, 1-2*d], label="cartesian") 15 | ax2 = fig.add_axes([d, d, 1-2*d, 1-2*d], projection="polar", label="polar") 16 | 17 | ax1.set_xticks([]) # np.linspace(0.0, 0.4, 5)) 18 | ax1.set_yticks([]) # np.linspace(0.0, 1.0, 11)) 19 | 20 | ax2.set_rorigin(0) 21 | ax2.set_thetamax(90) 22 | ax2.set_ylim(0.5, 1.0) 23 | ax2.set_xticks(np.linspace(0, np.pi/2, 10)) 24 | ax2.set_yticks(np.linspace(0.5, 1.0, 5)) 25 | 26 | ax2.set_xticklabels([]) 27 | ax2.set_yticklabels([]) 28 | 29 | fig.savefig(ROOT_DIR / "figures/tip-dual-axis.pdf") 30 | # plt.show() 31 | -------------------------------------------------------------------------------- /scripts/tip-font-family.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Title: Scientific Visualisation - Python & Matplotlib 3 | # Author: Nicolas P. Rougier 4 | # License: BSD 5 | # ---------------------------------------------------------------------------- 6 | import pathlib 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | import matplotlib.ticker as ticker 11 | 12 | 13 | ROOT_DIR = pathlib.Path(__file__).parent.parent 14 | 15 | 16 | # Setup a plot such that only the bottom spine is shown 17 | def setup(ax): 18 | ax.spines['right'].set_color('none') 19 | ax.spines['left'].set_color('none') 20 | ax.yaxis.set_major_locator(ticker.NullLocator()) 21 | ax.spines['top'].set_color('none') 22 | 23 | ax.spines['bottom'].set_position("center") 24 | 25 | ax.xaxis.set_ticks_position('bottom') 26 | ax.tick_params(which='major', width=1.00) 27 | ax.tick_params(which='major', length=5) 28 | ax.tick_params(which='minor', width=0.75) 29 | ax.tick_params(which='minor', length=2.5) 30 | ax.set_xlim(0, 5) 31 | ax.set_ylim(0, 1) 32 | ax.patch.set_alpha(0.0) 33 | 34 | 35 | fig = plt.figure(figsize=(5, .5)) 36 | fig.patch.set_alpha(0.0) 37 | n = 1 38 | 39 | fontsize = 18 40 | ax = plt.subplot(n, 1, 1) 41 | ax.tick_params(axis='both', which='minor', labelsize=6) 42 | setup(ax) 43 | ax.xaxis.set_major_locator(ticker.MultipleLocator(1.0)) 44 | ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.2)) 45 | ax.xaxis.set_major_formatter(ticker.ScalarFormatter()) 46 | ax.xaxis.set_minor_formatter(ticker.ScalarFormatter()) 47 | ax.tick_params(axis='x', which='minor', rotation=0) 48 | 49 | for tick in ax.get_xticklabels(which='both'): 50 | tick.set_fontname("Roboto Condensed") 51 | 52 | plt.tight_layout() 53 | fig.savefig(ROOT_DIR / "figures/tip-font-family.pdf", transparent=True) 54 | # plt.show() 55 | -------------------------------------------------------------------------------- /scripts/tip-hatched.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | ROOT_DIR = pathlib.Path(__file__).parent.parent 8 | 9 | cmap = plt.get_cmap("Oranges") 10 | color1, color2 = cmap(0.3), cmap(0.5) 11 | 12 | plt.rcParams['hatch.color'] = color1 13 | plt.rcParams['hatch.linewidth'] = 8 14 | 15 | fig = plt.figure(figsize=(2, 2)) 16 | ax = plt.subplot() 17 | np.random.seed(123) 18 | 19 | x1, y1 = 3*np.arange(2), np.random.randint(25, 50, 2) 20 | x2, y2 = x1+1, np.random.randint(25, 75, 2) 21 | 22 | ax.bar(x1, y1, color=color2) 23 | for x, y in zip(x1, y1): 24 | plt.annotate(f"{y:d}%", (x, y), xytext=(0, 1), 25 | fontsize="x-small", color=color2, 26 | textcoords="offset points", va="bottom", ha="center") 27 | 28 | ax.bar(x2, y2, color=color2, hatch="/" ) 29 | for x, y in zip(x2, y2): 30 | plt.annotate(f"{y:d}%", (x, y), xytext=(0, 1), 31 | fontsize="x-small", color=color2, 32 | textcoords="offset points", va="bottom", ha="center") 33 | 34 | ax.set_yticks([]) 35 | ax.set_xticks(0.5+np.arange(0, 6, 3)) 36 | ax.set_xticklabels(["2018", "2019"]) 37 | ax.tick_params('x', length=0, labelsize="small", which='major') 38 | 39 | ax.spines['right'].set_visible(False) 40 | ax.spines['left'].set_visible(False) 41 | ax.spines['top'].set_visible(False) 42 | 43 | plt.tight_layout() 44 | fig.savefig(ROOT_DIR / "figures/tip-hatched.pdf") 45 | # plt.show() 46 | -------------------------------------------------------------------------------- /scripts/tip-multiline.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Author: Nicolas P. Rougier 3 | # License: BSD 4 | # ---------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | ROOT_DIR = pathlib.Path(__file__).parent.parent 13 | 14 | mpl.rcParams['axes.linewidth'] = 1.5 15 | 16 | fig = plt.figure(figsize=(8, 1.5)) 17 | dx, dy = 0.0025, 0.01 18 | ax = fig.add_axes([dx, dy, 1-2*dx, 1-2*dy], frameon=False) 19 | X, Y = [], [] 20 | for x in np.linspace(0.01, 10*np.pi-0.01, 100): 21 | X.extend([x, x, None]) 22 | Y.extend([0, np.sin(x), None]) 23 | print(X[:10], Y[:10]) 24 | plt.plot(X, Y, "black") 25 | plt.xticks([]), plt.yticks([]) 26 | plt.xlim(-0.25, 10*np.pi+.25) 27 | plt.ylim(-1.5, 1.5) 28 | plt.tight_layout() 29 | fig.savefig(ROOT_DIR / "figures/tip-multiline.pdf", dpi=100) 30 | # plt.show() 31 | -------------------------------------------------------------------------------- /scripts/tip-outline.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | 6 | # Scripts to generate all the basic plots 7 | import pathlib 8 | 9 | import numpy as np 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | import matplotlib.patheffects as path_effects 13 | 14 | 15 | ROOT_DIR = pathlib.Path(__file__).parent.parent 16 | 17 | fig = plt.figure(figsize=(2, 2)) 18 | mpl.rcParams['axes.linewidth'] = 1.5 19 | d = 0.01 20 | 21 | ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) 22 | 23 | np.random.seed(1) 24 | Z = np.random.uniform(0, 1, (8, 8)) 25 | cmap = plt.get_cmap("Oranges") 26 | ax.imshow(Z, interpolation="nearest", cmap=cmap, vmin=0, vmax=2) 27 | 28 | text = ax.text(0.5, 0.1, "Label", transform=ax.transAxes, 29 | color=cmap(0.9), size=32, weight="bold", ha="center", va="bottom") 30 | text.set_path_effects([path_effects.Stroke(linewidth=5, foreground='white'), 31 | path_effects.Normal()]) 32 | fig.savefig(ROOT_DIR / "figures/tip-outline.pdf") 33 | -------------------------------------------------------------------------------- /scripts/tip-post-processing.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from matplotlib.figure import Figure 6 | from matplotlib.backends.backend_agg import FigureCanvas 7 | from scipy.ndimage import gaussian_filter 8 | 9 | 10 | ROOT_DIR = pathlib.Path(__file__).parent.parent 11 | 12 | # First pass for drop-shadow 13 | fig = Figure(figsize=(6, 1.5)) 14 | canvas = FigureCanvas(fig) 15 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, 16 | xlim=[0, 1], xticks=[], ylim=[0, 1], yticks=[]) 17 | ax.text(0.5, 0.5, "Matplotlib", transform=ax.transAxes, 18 | ha="center", va="center", size=64, color="black") 19 | canvas.draw() 20 | Z = np.array(canvas.renderer.buffer_rgba())[:, :, 0] 21 | Z = gaussian_filter(Z, sigma=9) 22 | 23 | # Second pass for text + drop-shadow 24 | fig = plt.figure(figsize=(6, 1.5)) 25 | ax = fig.add_axes([0, 0, 1, 1], frameon=False, 26 | xlim=[0, 1], xticks=[], ylim=[0, 1], yticks=[]) 27 | ax.imshow(Z, extent=[0, 1, 0, 1], cmap=plt.cm.gray, alpha=0.65, aspect='auto') 28 | ax.text(0.5, 0.5, "Matplotlib", transform=ax.transAxes, 29 | ha="center", va="center", size=64, color="black") 30 | 31 | fig.savefig(ROOT_DIR / "figures/tip-post-processing.pdf", dpi=600) 32 | # plt.show() 33 | -------------------------------------------------------------------------------- /scripts/tip-transparency.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------- 2 | # Matplotlib cheat sheet 3 | # Released under the BSD License 4 | # ----------------------------------------------------------------------------- 5 | import pathlib 6 | 7 | import numpy as np 8 | import matplotlib as mpl 9 | import matplotlib.pyplot as plt 10 | 11 | ROOT_DIR = pathlib.Path(__file__).parent.parent 12 | 13 | mpl.rc('axes', linewidth=1.5) 14 | 15 | np.random.seed(123) 16 | 17 | fig = plt.figure(figsize=(2, 2), dpi=100) 18 | margin = 0.01 19 | ax = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin]) 20 | n = 500 21 | X = np.random.normal(0, 0.25, n) 22 | Y = np.random.normal(0, 0.25, n) 23 | ax.scatter(X, Y, s=50, c="k", lw=2) 24 | ax.scatter(X, Y, s=50, c="w", lw=0) 25 | ax.scatter(X, Y, s=40, c="C1", lw=0, alpha=0.1) 26 | 27 | ax.set_xlim([-1, 1]), ax.set_xticks([]), 28 | ax.set_ylim([-1, 1]), ax.set_yticks([]) 29 | fig.savefig(ROOT_DIR / "figures/tip-transparency.pdf") 30 | # plt.show() 31 | -------------------------------------------------------------------------------- /styles/base.mplstyle: -------------------------------------------------------------------------------- 1 | figure.constrained_layout.use: True 2 | figure.constrained_layout.h_pad: 0.01 3 | figure.constrained_layout.w_pad: 0.01 4 | figure.constrained_layout.hspace: 0.1 5 | figure.constrained_layout.wspace: 0.1 6 | -------------------------------------------------------------------------------- /styles/plotlet-grid.mplstyle: -------------------------------------------------------------------------------- 1 | font.family: Source Code Pro 2 | font.size: 5 3 | 4 | axes.linewidth: 0.5 5 | 6 | xtick.major.size: 0.0 7 | ytick.major.size: 0.0 8 | -------------------------------------------------------------------------------- /styles/plotlet.mplstyle: -------------------------------------------------------------------------------- 1 | figure.figsize: 0.4, 0.4 2 | 3 | figure.constrained_layout.h_pad: 0.01 4 | figure.constrained_layout.w_pad: 0.01 5 | figure.constrained_layout.hspace: 0.01 6 | figure.constrained_layout.wspace: 0.01 7 | 8 | axes.linewidth: 0.5 9 | 10 | grid.linewidth: 0.2 11 | 12 | lines.linewidth: 0.75 13 | 14 | xtick.major.size: 0.0 15 | ytick.major.size: 0.0 16 | 17 | xtick.labeltop: False 18 | xtick.labelbottom: False 19 | 20 | ytick.labelleft: False 21 | ytick.labelright: False 22 | -------------------------------------------------------------------------------- /styles/sine-plot.mplstyle: -------------------------------------------------------------------------------- 1 | font.size: 4 2 | 3 | axes.titlesize: 4 4 | axes.titlepad: 2 5 | axes.linewidth: 0.2 6 | 7 | lines.linewidth: 0.5 8 | lines.markersize: 3 9 | 10 | xtick.labelsize: 3 11 | xtick.major.pad: 1 12 | xtick.major.width: 0.2 13 | xtick.major.size: 1 14 | xtick.minor.width: 0.1 15 | xtick.minor.size: 0.5 16 | 17 | ytick.labelsize: 3 18 | ytick.major.pad: 1 19 | ytick.major.width: 0.2 20 | ytick.major.size: 1 21 | ytick.minor.width: 0.1 22 | ytick.minor.size: 0.5 23 | 24 | legend.fontsize: 3 25 | -------------------------------------------------------------------------------- /styles/ticks.mplstyle: -------------------------------------------------------------------------------- 1 | savefig.transparent: True 2 | 3 | font.size: 5 4 | 5 | axes.linewidth: 0.5 6 | axes.spines.right: False 7 | axes.spines.top: False 8 | axes.spines.left: False 9 | axes.spines.bottom: True 10 | 11 | xtick.labelsize: 3 12 | xtick.major.size: 2 13 | xtick.major.width: 0.2 14 | xtick.major.pad: 2 15 | xtick.minor.size: 1 16 | xtick.minor.width: 0.2 17 | xtick.minor.pad: 2 18 | 19 | ytick.left: False 20 | ytick.labelleft: False 21 | --------------------------------------------------------------------------------