The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .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 | <?xml version="1.0"?>
42 | <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
43 | <fontconfig>
44 | <dir>/path/to/cheatsheets/fonts/</dir>
45 | ...
46 | </fontconfig>
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 <https://github.com/matplotlib/cheatsheets>`_
67 | 


--------------------------------------------------------------------------------
/figures/legend.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matplotlib/cheatsheets/f02ebb5f02abd3c5d5b02bb1f22737ab87e92a08/figures/legend.pdf


--------------------------------------------------------------------------------
/figures/legend.svg:
--------------------------------------------------------------------------------
   1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?>
   2 | <svg
   3 |    xmlns:dc="http://purl.org/dc/elements/1.1/"
   4 |    xmlns:cc="http://creativecommons.org/ns#"
   5 |    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   6 |    xmlns:svg="http://www.w3.org/2000/svg"
   7 |    xmlns="http://www.w3.org/2000/svg"
   8 |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   9 |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  10 |    version="1.1"
  11 |    viewBox="327 239 402.28339 201.5"
  12 |    width="402.28339"
  13 |    height="201.5"
  14 |    id="svg272"
  15 |    sodipodi:docname="legend.svg"
  16 |    inkscape:version="1.0beta2 (2b71d25, 2019-12-03)">
  17 |   <sodipodi:namedview
  18 |      fit-margin-bottom="0"
  19 |      fit-margin-right="0"
  20 |      fit-margin-left="0"
  21 |      fit-margin-top="0"
  22 |      pagecolor="#ffffff"
  23 |      bordercolor="#666666"
  24 |      inkscape:document-rotation="0"
  25 |      borderopacity="1"
  26 |      objecttolerance="10"
  27 |      gridtolerance="10"
  28 |      guidetolerance="10"
  29 |      inkscape:pageopacity="0"
  30 |      inkscape:pageshadow="2"
  31 |      inkscape:window-width="1673"
  32 |      inkscape:window-height="838"
  33 |      id="namedview274"
  34 |      showgrid="false"
  35 |      inkscape:zoom="2.7965361"
  36 |      inkscape:cx="269.97685"
  37 |      inkscape:cy="100.75"
  38 |      inkscape:window-x="0"
  39 |      inkscape:window-y="0"
  40 |      inkscape:window-maximized="0"
  41 |      inkscape:current-layer="Canvas_1: Layer 1" />
  42 |   <defs
  43 |      id="defs43">
  44 |     <font-face
  45 |        overline-thickness="0"
  46 |        overline-position="0"
  47 |        strikethrough-thickness="0"
  48 |        strikethrough-position="0"
  49 |        v-hanging="0"
  50 |        v-mathematical="0"
  51 |        v-alphabetic="0"
  52 |        v-ideographic="0"
  53 |        hanging="0"
  54 |        mathematical="0"
  55 |        alphabetic="0"
  56 |        ideographic="0"
  57 |        accent-height="0"
  58 |        stemh="0"
  59 |        stemv="0"
  60 |        font-family="Source Serif Pro"
  61 |        font-size="32"
  62 |        panose-1="2 4 6 3 5 4 5 2 2 4"
  63 |        units-per-em="1000"
  64 |        underline-position="-75"
  65 |        underline-thickness="50"
  66 |        slope="0"
  67 |        x-height="475"
  68 |        cap-height="670"
  69 |        ascent="1036.0021"
  70 |        descent="-335.00068"
  71 |        font-weight="400"
  72 |        id="font-face10">
  73 |       <font-face-src>
  74 |         <font-face-name
  75 |            name="SourceSerifPro-Regular" />
  76 |       </font-face-src>
  77 |     </font-face>
  78 |     <font-face
  79 |        overline-thickness="0"
  80 |        overline-position="0"
  81 |        strikethrough-thickness="0"
  82 |        strikethrough-position="0"
  83 |        v-hanging="0"
  84 |        v-mathematical="0"
  85 |        v-alphabetic="0"
  86 |        v-ideographic="0"
  87 |        hanging="0"
  88 |        mathematical="0"
  89 |        alphabetic="0"
  90 |        ideographic="0"
  91 |        accent-height="0"
  92 |        stemh="0"
  93 |        stemv="0"
  94 |        font-family="Helvetica Neue"
  95 |        font-size="24"
  96 |        panose-1="2 0 4 3 0 0 0 2 0 4"
  97 |        units-per-em="1000"
  98 |        underline-position="-100"
  99 |        underline-thickness="50"
 100 |        slope="0"
 101 |        x-height="523"
 102 |        cap-height="721"
 103 |        ascent="966.9952"
 104 |        descent="-212.99744"
 105 |        font-weight="300"
 106 |        id="font-face12">
 107 |       <font-face-src>
 108 |         <font-face-name
 109 |            name="HelveticaNeue-Light" />
 110 |       </font-face-src>
 111 |     </font-face>
 112 |     <marker
 113 |        orient="auto"
 114 |        overflow="visible"
 115 |        markerUnits="strokeWidth"
 116 |        id="DimensionArrow_Marker"
 117 |        stroke-linejoin="miter"
 118 |        stroke-miterlimit="10"
 119 |        viewBox="-1 -6 10 12"
 120 |        markerWidth="10"
 121 |        markerHeight="12"
 122 |        color="black">
 123 |       <g
 124 |          id="g16">
 125 |         <path
 126 |            inkscape:connector-curvature="0"
 127 |            d="M 0,0 H 8 M 8,5 V -5 M 0,2 7,0 0,-2"
 128 |            fill="none"
 129 |            stroke="currentColor"
 130 |            stroke-width="1"
 131 |            id="path14" />
 132 |       </g>
 133 |     </marker>
 134 |     <marker
 135 |        orient="auto"
 136 |        overflow="visible"
 137 |        markerUnits="strokeWidth"
 138 |        id="DimensionArrow_Marker_2"
 139 |        stroke-linejoin="miter"
 140 |        stroke-miterlimit="10"
 141 |        viewBox="-9 -6 10 12"
 142 |        markerWidth="10"
 143 |        markerHeight="12"
 144 |        color="black">
 145 |       <g
 146 |          id="g21">
 147 |         <path
 148 |            inkscape:connector-curvature="0"
 149 |            d="m 0,0 h -8 m 0,-5 V 5 m 8,-7 -7,2 7,2"
 150 |            fill="none"
 151 |            stroke="currentColor"
 152 |            stroke-width="1"
 153 |            id="path19" />
 154 |       </g>
 155 |     </marker>
 156 |     <font-face
 157 |        overline-thickness="0"
 158 |        overline-position="0"
 159 |        strikethrough-thickness="0"
 160 |        strikethrough-position="0"
 161 |        v-hanging="0"
 162 |        v-mathematical="0"
 163 |        v-alphabetic="0"
 164 |        v-ideographic="0"
 165 |        hanging="0"
 166 |        mathematical="0"
 167 |        alphabetic="0"
 168 |        ideographic="0"
 169 |        accent-height="0"
 170 |        stemh="0"
 171 |        stemv="0"
 172 |        font-family="Helvetica Neue"
 173 |        font-size="10"
 174 |        panose-1="2 0 4 3 0 0 0 2 0 4"
 175 |        units-per-em="1000"
 176 |        underline-position="-100"
 177 |        underline-thickness="50"
 178 |        slope="0"
 179 |        x-height="523"
 180 |        cap-height="721"
 181 |        ascent="966.9952"
 182 |        descent="-212.99744"
 183 |        font-weight="300"
 184 |        id="font-face24">
 185 |       <font-face-src>
 186 |         <font-face-name
 187 |            name="HelveticaNeue-Light" />
 188 |       </font-face-src>
 189 |     </font-face>
 190 |     <marker
 191 |        orient="auto"
 192 |        overflow="visible"
 193 |        markerUnits="strokeWidth"
 194 |        id="FilledArrow_Marker"
 195 |        stroke-linejoin="miter"
 196 |        stroke-miterlimit="10"
 197 |        viewBox="-1 -4 8 8"
 198 |        markerWidth="8"
 199 |        markerHeight="8"
 200 |        color="black">
 201 |       <g
 202 |          id="g28">
 203 |         <path
 204 |            inkscape:connector-curvature="0"
 205 |            d="M 6,0 0,-2.25 v 4.5 z"
 206 |            fill="currentColor"
 207 |            stroke="currentColor"
 208 |            stroke-width="1"
 209 |            id="path26" />
 210 |       </g>
 211 |     </marker>
 212 |     <marker
 213 |        orient="auto"
 214 |        overflow="visible"
 215 |        markerUnits="strokeWidth"
 216 |        id="FilledArrow_Marker_2"
 217 |        stroke-linejoin="miter"
 218 |        stroke-miterlimit="10"
 219 |        viewBox="-1 -3 6 6"
 220 |        markerWidth="6"
 221 |        markerHeight="6"
 222 |        color="black">
 223 |       <g
 224 |          id="g33">
 225 |         <path
 226 |            inkscape:connector-curvature="0"
 227 |            d="M 4,0 0,-1.5 v 3 z"
 228 |            fill="currentColor"
 229 |            stroke="currentColor"
 230 |            stroke-width="1"
 231 |            id="path31" />
 232 |       </g>
 233 |     </marker>
 234 |     <marker
 235 |        orient="auto"
 236 |        overflow="visible"
 237 |        markerUnits="strokeWidth"
 238 |        id="FilledBall_Marker"
 239 |        stroke-linejoin="miter"
 240 |        stroke-miterlimit="10"
 241 |        viewBox="-4 -3 5 6"
 242 |        markerWidth="5"
 243 |        markerHeight="6"
 244 |        color="black">
 245 |       <g
 246 |          id="g38">
 247 |         <circle
 248 |            cx="-1.4999993"
 249 |            cy="0"
 250 |            r="1.4999987"
 251 |            fill="currentColor"
 252 |            stroke="currentColor"
 253 |            stroke-width="1"
 254 |            id="circle36" />
 255 |       </g>
 256 |     </marker>
 257 |     <font-face
 258 |        overline-thickness="0"
 259 |        overline-position="0"
 260 |        strikethrough-thickness="0"
 261 |        strikethrough-position="0"
 262 |        v-hanging="0"
 263 |        v-mathematical="0"
 264 |        v-alphabetic="0"
 265 |        v-ideographic="0"
 266 |        hanging="0"
 267 |        mathematical="0"
 268 |        alphabetic="0"
 269 |        ideographic="0"
 270 |        accent-height="0"
 271 |        stemh="0"
 272 |        stemv="0"
 273 |        font-family="Helvetica Neue"
 274 |        font-size="8"
 275 |        panose-1="2 0 4 3 0 0 0 2 0 4"
 276 |        units-per-em="1000"
 277 |        underline-position="-100"
 278 |        underline-thickness="50"
 279 |        slope="0"
 280 |        x-height="523"
 281 |        cap-height="721"
 282 |        ascent="966.9952"
 283 |        descent="-212.99744"
 284 |        font-weight="300"
 285 |        id="font-face41">
 286 |       <font-face-src>
 287 |         <font-face-name
 288 |            name="HelveticaNeue-Light" />
 289 |       </font-face-src>
 290 |     </font-face>
 291 |   </defs>
 292 |   <metadata
 293 |      id="metadata45"> Produced by OmniGraffle 7.11.1 
 294 |     <dc:date>2019-08-01 08:58:53 +0000</dc:date>
 295 | <rdf:RDF>
 296 |   <cc:Work
 297 |      rdf:about="">
 298 |     <dc:format>image/svg+xml</dc:format>
 299 |     <dc:type
 300 |        rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 301 |     <dc:title></dc:title>
 302 |   </cc:Work>
 303 | </rdf:RDF>
 304 | </metadata>
 305 |   <g
 306 |      transform="translate(-31.52199,-8.25)"
 307 |      id="Canvas_1"
 308 |      stroke-opacity="1"
 309 |      stroke-dasharray="none"
 310 |      fill="none"
 311 |      fill-opacity="1"
 312 |      stroke="none">
 313 |     <title
 314 |        id="title47">Canvas 1</title>
 315 |     <g
 316 |        id="Canvas_1: Layer 1">
 317 |       <title
 318 |          id="title49">Layer 1</title>
 319 |       <g
 320 |          style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
 321 |          id="Graphic_4">
 322 |         <path
 323 |            style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
 324 |            inkscape:connector-curvature="0"
 325 |            d="m 365,248 h 390 c 2.7614,0 5,2.23858 5,5 v 158 c 0,2.7614 -2.2386,5 -5,5 H 365 c -2.76142,0 -5,-2.2386 -5,-5 V 253 c 0,-2.76142 2.23858,-5 5,-5 z"
 326 |            stroke="black"
 327 |            stroke-linecap="round"
 328 |            stroke-linejoin="round"
 329 |            stroke-width="1"
 330 |            id="path51" />
 331 |       </g>
 332 |       <g
 333 |          id="Line_28">
 334 |         <line
 335 |            x1="448"
 336 |            y1="320"
 337 |            x2="448"
 338 |            y2="352"
 339 |            stroke="black"
 340 |            stroke-linecap="round"
 341 |            stroke-linejoin="round"
 342 |            stroke-dasharray="1.0,1.0"
 343 |            stroke-width=".5"
 344 |            id="line54" />
 345 |       </g>
 346 |       <g
 347 |          id="Line_29">
 348 |         <line
 349 |            x1="472"
 350 |            y1="320"
 351 |            x2="472"
 352 |            y2="400"
 353 |            stroke="black"
 354 |            stroke-linecap="round"
 355 |            stroke-linejoin="round"
 356 |            stroke-dasharray="1.0,1.0"
 357 |            stroke-width=".5"
 358 |            id="line57" />
 359 |       </g>
 360 |       <g
 361 |          id="Line_30">
 362 |         <line
 363 |            x1="384"
 364 |            y1="320"
 365 |            x2="384"
 366 |            y2="352"
 367 |            stroke="black"
 368 |            stroke-linecap="round"
 369 |            stroke-linejoin="round"
 370 |            stroke-dasharray="1.0,1.0"
 371 |            stroke-width=".5"
 372 |            id="line60" />
 373 |       </g>
 374 |       <g
 375 |          id="Graphic_3">
 376 |         <text
 377 |            transform="translate(381.896,257.5)"
 378 |            fill="black"
 379 |            id="text65"><tspan
 380 |              font-family="Source Serif Pro"
 381 |              font-size="32"
 382 |              font-weight="400"
 383 |              fill="black"
 384 |              x="4.1211479e-13"
 385 |              y="33"
 386 |              id="tspan63">Legend</tspan></text>
 387 |       </g>
 388 |       <g
 389 |          id="Line_8">
 390 |         <line
 391 |            x1="384"
 392 |            y1="339.5"
 393 |            x2="448"
 394 |            y2="339.5"
 395 |            stroke="black"
 396 |            stroke-linecap="butt"
 397 |            stroke-linejoin="round"
 398 |            stroke-width="2"
 399 |            id="line68" />
 400 |       </g>
 401 |       <g
 402 |          id="Graphic_6"
 403 |          style="fill:#ff7f00;fill-opacity:1">
 404 |         <circle
 405 |            cx="400"
 406 |            cy="339.5"
 407 |            r="8.0000124"
 408 |            fill="#ffc0c0"
 409 |            id="circle71"
 410 |            style="fill:#ff7f00;fill-opacity:1" />
 411 |         <circle
 412 |            cx="400"
 413 |            cy="339.5"
 414 |            r="8.0000124"
 415 |            stroke="black"
 416 |            stroke-linecap="round"
 417 |            stroke-linejoin="round"
 418 |            stroke-width="2"
 419 |            id="circle73"
 420 |            style="fill:#ff7f00;fill-opacity:1" />
 421 |       </g>
 422 |       <g
 423 |          id="Graphic_7"
 424 |          style="fill:#ff7f00;fill-opacity:1">
 425 |         <circle
 426 |            cx="432"
 427 |            cy="339.5"
 428 |            r="8.0000124"
 429 |            fill="#ffc0c0"
 430 |            id="circle76"
 431 |            style="fill:#ff7f00;fill-opacity:1" />
 432 |         <circle
 433 |            cx="432"
 434 |            cy="339.5"
 435 |            r="8.0000124"
 436 |            stroke="black"
 437 |            stroke-linecap="round"
 438 |            stroke-linejoin="round"
 439 |            stroke-width="2"
 440 |            id="circle78"
 441 |            style="fill:#ff7f00;fill-opacity:1" />
 442 |       </g>
 443 |       <g
 444 |          id="Graphic_10">
 445 |         <text
 446 |            transform="translate(470.184,324.5)"
 447 |            fill="black"
 448 |            id="text83"><tspan
 449 |              font-family="Helvetica Neue"
 450 |              font-size="24"
 451 |              font-weight="300"
 452 |              fill="black"
 453 |              x="0"
 454 |              y="23"
 455 |              id="tspan81">Label 1</tspan></text>
 456 |       </g>
 457 |       <g
 458 |          id="Line_14">
 459 |         <line
 460 |            x1="384"
 461 |            y1="383"
 462 |            x2="448"
 463 |            y2="383"
 464 |            stroke="black"
 465 |            stroke-linecap="butt"
 466 |            stroke-linejoin="round"
 467 |            stroke-width="2"
 468 |            id="line86" />
 469 |       </g>
 470 |       <g
 471 |          id="Graphic_13"
 472 |          style="fill:#ffb100;fill-opacity:1">
 473 |         <circle
 474 |            cx="400"
 475 |            cy="383"
 476 |            r="8.0000124"
 477 |            fill="#ff8080"
 478 |            id="circle89"
 479 |            style="fill:#ffb100;fill-opacity:1" />
 480 |         <circle
 481 |            cx="400"
 482 |            cy="383"
 483 |            r="8.0000124"
 484 |            stroke="black"
 485 |            stroke-linecap="round"
 486 |            stroke-linejoin="round"
 487 |            stroke-width="2"
 488 |            id="circle91"
 489 |            style="fill:#ffb100;fill-opacity:1" />
 490 |       </g>
 491 |       <g
 492 |          id="Graphic_12"
 493 |          style="fill:#ffb100;fill-opacity:1">
 494 |         <circle
 495 |            cx="432"
 496 |            cy="383"
 497 |            r="8.0000124"
 498 |            fill="#ff8080"
 499 |            id="circle94"
 500 |            style="fill:#ffb100;fill-opacity:1" />
 501 |         <circle
 502 |            cx="432"
 503 |            cy="383"
 504 |            r="8.0000124"
 505 |            stroke="black"
 506 |            stroke-linecap="round"
 507 |            stroke-linejoin="round"
 508 |            stroke-width="2"
 509 |            id="circle96"
 510 |            style="fill:#ffb100;fill-opacity:1" />
 511 |       </g>
 512 |       <g
 513 |          id="Graphic_11">
 514 |         <text
 515 |            transform="translate(470.184,368)"
 516 |            fill="black"
 517 |            id="text101"><tspan
 518 |              font-family="Helvetica Neue"
 519 |              font-size="24"
 520 |              font-weight="300"
 521 |              fill="black"
 522 |              x="0"
 523 |              y="23"
 524 |              id="tspan99">Label 2</tspan></text>
 525 |       </g>
 526 |       <g
 527 |          id="Line_22">
 528 |         <line
 529 |            x1="576"
 530 |            y1="339.5"
 531 |            x2="640"
 532 |            y2="339.5"
 533 |            stroke="black"
 534 |            stroke-linecap="butt"
 535 |            stroke-linejoin="round"
 536 |            stroke-width="2"
 537 |            id="line104" />
 538 |       </g>
 539 |       <g
 540 |          id="Graphic_21"
 541 |          style="fill:#ffd100;fill-opacity:1">
 542 |         <circle
 543 |            cx="592"
 544 |            cy="339.5"
 545 |            r="8.0000124"
 546 |            fill="#ff4040"
 547 |            id="circle107"
 548 |            style="fill:#ffd100;fill-opacity:1" />
 549 |         <circle
 550 |            cx="592"
 551 |            cy="339.5"
 552 |            r="8.0000124"
 553 |            stroke="black"
 554 |            stroke-linecap="round"
 555 |            stroke-linejoin="round"
 556 |            stroke-width="2"
 557 |            id="circle109"
 558 |            style="fill:#ffd100;fill-opacity:1" />
 559 |       </g>
 560 |       <g
 561 |          id="Graphic_20"
 562 |          style="fill:#ffd100;fill-opacity:1">
 563 |         <circle
 564 |            cx="624"
 565 |            cy="339.5"
 566 |            r="8.0000124"
 567 |            fill="#ff4040"
 568 |            id="circle112"
 569 |            style="fill:#ffd100;fill-opacity:1" />
 570 |         <circle
 571 |            cx="624"
 572 |            cy="339.5"
 573 |            r="8.0000124"
 574 |            stroke="black"
 575 |            stroke-linecap="round"
 576 |            stroke-linejoin="round"
 577 |            stroke-width="2"
 578 |            id="circle114"
 579 |            style="fill:#ffd100;fill-opacity:1" />
 580 |       </g>
 581 |       <g
 582 |          id="Graphic_19">
 583 |         <text
 584 |            transform="translate(662.184,324.5)"
 585 |            fill="black"
 586 |            id="text119"><tspan
 587 |              font-family="Helvetica Neue"
 588 |              font-size="24"
 589 |              font-weight="300"
 590 |              fill="black"
 591 |              x="0"
 592 |              y="23"
 593 |              id="tspan117">Label 3</tspan></text>
 594 |       </g>
 595 |       <g
 596 |          id="Line_18">
 597 |         <line
 598 |            x1="576"
 599 |            y1="383"
 600 |            x2="640"
 601 |            y2="383"
 602 |            stroke="black"
 603 |            stroke-linecap="butt"
 604 |            stroke-linejoin="round"
 605 |            stroke-width="2"
 606 |            id="line122" />
 607 |       </g>
 608 |       <g
 609 |          id="Graphic_17"
 610 |          style="fill:#ffe700;fill-opacity:1">
 611 |         <circle
 612 |            cx="592"
 613 |            cy="383"
 614 |            r="8.0000124"
 615 |            fill="red"
 616 |            id="circle125"
 617 |            style="fill:#ffe700;fill-opacity:1" />
 618 |         <circle
 619 |            cx="592"
 620 |            cy="383"
 621 |            r="8.0000124"
 622 |            stroke="black"
 623 |            stroke-linecap="round"
 624 |            stroke-linejoin="round"
 625 |            stroke-width="2"
 626 |            id="circle127"
 627 |            style="fill:#ffe700;fill-opacity:1" />
 628 |       </g>
 629 |       <g
 630 |          id="Graphic_16"
 631 |          style="fill:#ffe700;fill-opacity:1">
 632 |         <circle
 633 |            cx="624"
 634 |            cy="383"
 635 |            r="8.0000124"
 636 |            fill="red"
 637 |            id="circle130"
 638 |            style="fill:#ffe700;fill-opacity:1" />
 639 |         <circle
 640 |            cx="624"
 641 |            cy="383"
 642 |            r="8.0000124"
 643 |            stroke="black"
 644 |            stroke-linecap="round"
 645 |            stroke-linejoin="round"
 646 |            stroke-width="2"
 647 |            id="circle132"
 648 |            style="fill:#ffe700;fill-opacity:1" />
 649 |       </g>
 650 |       <g
 651 |          id="Graphic_15">
 652 |         <text
 653 |            transform="translate(662.184,368)"
 654 |            fill="black"
 655 |            id="text137"><tspan
 656 |              font-family="Helvetica Neue"
 657 |              font-size="24"
 658 |              font-weight="300"
 659 |              fill="black"
 660 |              x="0"
 661 |              y="23"
 662 |              id="tspan135">Label 4</tspan></text>
 663 |       </g>
 664 |       <g
 665 |          id="Line_23">
 666 |         <line
 667 |            x1="388"
 668 |            y1="328"
 669 |            x2="444"
 670 |            y2="328"
 671 |            marker-end="url(#DimensionArrow_Marker)"
 672 |            marker-start="url(#DimensionArrow_Marker_2)"
 673 |            stroke="black"
 674 |            stroke-linecap="round"
 675 |            stroke-linejoin="round"
 676 |            stroke-width=".5"
 677 |            id="line140" />
 678 |       </g>
 679 |       <g
 680 |          id="Line_24">
 681 |         <line
 682 |            x1="452"
 683 |            y1="328"
 684 |            x2="468"
 685 |            y2="328"
 686 |            marker-end="url(#DimensionArrow_Marker)"
 687 |            marker-start="url(#DimensionArrow_Marker_2)"
 688 |            stroke="black"
 689 |            stroke-linecap="round"
 690 |            stroke-linejoin="round"
 691 |            stroke-width=".5"
 692 |            id="line143" />
 693 |       </g>
 694 |       <g
 695 |          id="Line_25">
 696 |         <line
 697 |            x1="550"
 698 |            y1="400"
 699 |            x2="572"
 700 |            y2="400"
 701 |            marker-end="url(#DimensionArrow_Marker)"
 702 |            marker-start="url(#DimensionArrow_Marker_2)"
 703 |            stroke="black"
 704 |            stroke-linecap="round"
 705 |            stroke-linejoin="round"
 706 |            stroke-width=".5"
 707 |            id="line146" />
 708 |       </g>
 709 |       <g
 710 |          id="Line_26">
 711 |         <line
 712 |            x1="367.96469"
 713 |            y1="353"
 714 |            x2="367.92679"
 715 |            y2="370"
 716 |            marker-end="url(#DimensionArrow_Marker)"
 717 |            marker-start="url(#DimensionArrow_Marker_2)"
 718 |            stroke="black"
 719 |            stroke-linecap="round"
 720 |            stroke-linejoin="round"
 721 |            stroke-width=".5"
 722 |            id="line149" />
 723 |       </g>
 724 |       <g
 725 |          id="Graphic_27">
 726 |         <text
 727 |            transform="translate(429.077,298.5)"
 728 |            fill="black"
 729 |            id="text154"
 730 |            style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000"><tspan
 731 |              font-family="Helvetica Neue"
 732 |              font-size="10"
 733 |              font-weight="300"
 734 |              fill="black"
 735 |              x="0"
 736 |              y="10"
 737 |              id="tspan152"
 738 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">handletextpad</tspan></text>
 739 |       </g>
 740 |       <g
 741 |          id="Graphic_31">
 742 |         <text
 743 |            transform="translate(388.722,312)"
 744 |            fill="black"
 745 |            id="text159"
 746 |            style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000"><tspan
 747 |              font-family="Helvetica Neue"
 748 |              font-size="10"
 749 |              font-weight="300"
 750 |              fill="black"
 751 |              x="0"
 752 |              y="10"
 753 |              id="tspan157"
 754 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">handlelength</tspan></text>
 755 |       </g>
 756 |       <g
 757 |          id="Line_32">
 758 |         <line
 759 |            x1="546"
 760 |            y1="364"
 761 |            x2="546"
 762 |            y2="404"
 763 |            stroke="black"
 764 |            stroke-linecap="round"
 765 |            stroke-linejoin="round"
 766 |            stroke-dasharray="1.0,1.0"
 767 |            stroke-width=".5"
 768 |            id="line162" />
 769 |       </g>
 770 |       <g
 771 |          id="Line_33">
 772 |         <line
 773 |            x1="576"
 774 |            y1="364"
 775 |            x2="576"
 776 |            y2="400"
 777 |            stroke="black"
 778 |            stroke-linecap="round"
 779 |            stroke-linejoin="round"
 780 |            stroke-dasharray="1.0,1.0"
 781 |            stroke-width=".5"
 782 |            id="line165" />
 783 |       </g>
 784 |       <g
 785 |          id="Line_34">
 786 |         <line
 787 |            x1="459.7233"
 788 |            y1="312.5"
 789 |            x2="459.7157"
 790 |            y2="328"
 791 |            stroke="black"
 792 |            stroke-linecap="butt"
 793 |            stroke-linejoin="round"
 794 |            stroke-width=".5"
 795 |            id="line168" />
 796 |       </g>
 797 |       <g
 798 |          id="Line_35">
 799 |         <line
 800 |            x1="361"
 801 |            y1="349"
 802 |            x2="401"
 803 |            y2="349"
 804 |            stroke="black"
 805 |            stroke-linecap="round"
 806 |            stroke-linejoin="round"
 807 |            stroke-dasharray="1.0,1.0"
 808 |            stroke-width=".5"
 809 |            id="line171" />
 810 |       </g>
 811 |       <g
 812 |          id="Line_36">
 813 |         <line
 814 |            x1="361"
 815 |            y1="374"
 816 |            x2="401"
 817 |            y2="374"
 818 |            stroke="black"
 819 |            stroke-linecap="round"
 820 |            stroke-linejoin="round"
 821 |            stroke-dasharray="1.0,1.0"
 822 |            stroke-width=".5"
 823 |            id="line174" />
 824 |       </g>
 825 |       <g
 826 |          id="Graphic_37">
 827 |         <text
 828 |            transform="translate(512.761,401.5)"
 829 |            fill="black"
 830 |            id="text179"
 831 |            style="fill:#000000"><tspan
 832 |              font-family="Helvetica Neue"
 833 |              font-size="10"
 834 |              font-weight="300"
 835 |              fill="black"
 836 |              x="5.1159082e-13"
 837 |              y="10"
 838 |              id="tspan177"
 839 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">columnspacing</tspan></text>
 840 |       </g>
 841 |       <g
 842 |          id="Graphic_38">
 843 |         <text
 844 |            transform="translate(373,354.5)"
 845 |            fill="black"
 846 |            id="text184"
 847 |            style="fill:#000000"><tspan
 848 |              font-family="Helvetica Neue"
 849 |              font-size="10"
 850 |              font-weight="300"
 851 |              fill="black"
 852 |              x="0"
 853 |              y="10"
 854 |              id="tspan182"
 855 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">labelspacing</tspan></text>
 856 |       </g>
 857 |       <g
 858 |          id="Line_41">
 859 |         <line
 860 |            x1="377"
 861 |            y1="392"
 862 |            x2="401"
 863 |            y2="392"
 864 |            stroke="black"
 865 |            stroke-linecap="round"
 866 |            stroke-linejoin="round"
 867 |            stroke-dasharray="1.0,1.0"
 868 |            stroke-width=".5"
 869 |            id="line187" />
 870 |       </g>
 871 |       <g
 872 |          id="Line_42">
 873 |         <line
 874 |            x1="384.04642"
 875 |            y1="396"
 876 |            x2="384.00931"
 877 |            y2="412"
 878 |            marker-end="url(#DimensionArrow_Marker)"
 879 |            marker-start="url(#DimensionArrow_Marker_2)"
 880 |            stroke="black"
 881 |            stroke-linecap="round"
 882 |            stroke-linejoin="round"
 883 |            stroke-width=".5"
 884 |            id="line190" />
 885 |       </g>
 886 |       <g
 887 |          id="Graphic_43">
 888 |         <text
 889 |            transform="translate(389,397.5)"
 890 |            fill="black"
 891 |            id="text195"
 892 |            style="fill:#000000"><tspan
 893 |              font-family="Helvetica Neue"
 894 |              font-size="10"
 895 |              font-weight="300"
 896 |              fill="black"
 897 |              x="0"
 898 |              y="10"
 899 |              id="tspan193"
 900 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">borderpad</tspan></text>
 901 |       </g>
 902 |       <g
 903 |          id="Line_46">
 904 |         <path
 905 |            inkscape:connector-curvature="0"
 906 |            d="m 598.873,311 c 0.3784,0.32023 0.7545,0.6534 1.127,1 3.0322,2.82113 5.2479,5.99215 6.8099,8.7626"
 907 |            marker-end="url(#FilledArrow_Marker)"
 908 |            stroke="black"
 909 |            stroke-linecap="square"
 910 |            stroke-linejoin="round"
 911 |            stroke-width="1"
 912 |            id="path198" />
 913 |       </g>
 914 |       <g
 915 |          id="Graphic_47">
 916 |         <text
 917 |            transform="translate(569.29,297)"
 918 |            fill="black"
 919 |            id="text203"
 920 |            style="fill:#000000"><tspan
 921 |              font-family="Helvetica Neue"
 922 |              font-size="10"
 923 |              font-weight="300"
 924 |              fill="black"
 925 |              x="0"
 926 |              y="10"
 927 |              id="tspan201"
 928 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">handle</tspan></text>
 929 |       </g>
 930 |       <g
 931 |          id="Line_49">
 932 |         <path
 933 |            inkscape:connector-curvature="0"
 934 |            d="m 528,296 c 0,0 -10.39056,3.67623 -16,16 -0.70953,1.55883 -1.3004,3.1633 -1.7912,4.7769"
 935 |            marker-end="url(#FilledArrow_Marker)"
 936 |            stroke="black"
 937 |            stroke-linecap="square"
 938 |            stroke-linejoin="round"
 939 |            stroke-width="1"
 940 |            id="path206" />
 941 |       </g>
 942 |       <g
 943 |          id="Graphic_48">
 944 |         <text
 945 |            transform="translate(530.423,289.5)"
 946 |            fill="black"
 947 |            id="text211"
 948 |            style="fill:#000000"><tspan
 949 |              font-family="Helvetica Neue"
 950 |              font-size="10"
 951 |              font-weight="300"
 952 |              fill="black"
 953 |              x="0"
 954 |              y="10"
 955 |              id="tspan209"
 956 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">label</tspan></text>
 957 |       </g>
 958 |       <g
 959 |          style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
 960 |          id="Line_50">
 961 |         <path
 962 |            style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
 963 |            sodipodi:nodetypes="cc"
 964 |            inkscape:connector-curvature="0"
 965 |            d="M 359.27199,448 H 760.05537"
 966 |            stroke="black"
 967 |            stroke-linecap="round"
 968 |            stroke-linejoin="round"
 969 |            stroke-width="1"
 970 |            id="path214" />
 971 |       </g>
 972 |       <g
 973 |          id="Graphic_53">
 974 |         <text
 975 |            transform="translate(528.928,254.5)"
 976 |            fill="black"
 977 |            id="text225"
 978 |            style="fill:#000000"><tspan
 979 |              font-family="Helvetica Neue"
 980 |              font-size="10"
 981 |              font-weight="300"
 982 |              fill="black"
 983 |              x="6.5369932e-13"
 984 |              y="10"
 985 |              id="tspan223"
 986 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">title</tspan></text>
 987 |       </g>
 988 |       <g
 989 |          id="Line_54">
 990 |         <path
 991 |            inkscape:connector-curvature="0"
 992 |            d="m 532.7271,268.5 c -2.55994,4.073 -6.64004,8.81268 -12.7271,11.5 -6.5416,2.888 -13.7507,2.67704 -19.028,1.8611"
 993 |            marker-end="url(#FilledArrow_Marker)"
 994 |            stroke="black"
 995 |            stroke-linecap="square"
 996 |            stroke-linejoin="round"
 997 |            stroke-width="1"
 998 |            id="path228" />
 999 |       </g>
1000 |       <g
1001 |          id="Line_55">
1002 |         <line
1003 |            x1="448.04874"
1004 |            y1="420"
1005 |            x2="448.00696"
1006 |            y2="444"
1007 |            marker-end="url(#DimensionArrow_Marker)"
1008 |            marker-start="url(#DimensionArrow_Marker_2)"
1009 |            stroke="black"
1010 |            stroke-linecap="round"
1011 |            stroke-linejoin="round"
1012 |            stroke-width=".5"
1013 |            id="line231" />
1014 |       </g>
1015 |       <g
1016 |          id="Graphic_56">
1017 |         <text
1018 |            transform="translate(453,426.5)"
1019 |            fill="black"
1020 |            id="text236"
1021 |            style="fill:#000000"><tspan
1022 |              font-family="Helvetica Neue"
1023 |              font-size="10"
1024 |              font-weight="300"
1025 |              fill="black"
1026 |              x="0"
1027 |              y="10"
1028 |              id="tspan234"
1029 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">borderaxespad</tspan></text>
1030 |       </g>
1031 |       <g
1032 |          id="Line_57">
1033 |         <path
1034 |            inkscape:connector-curvature="0"
1035 |            d="m 648,312 c 0,0 -9.2007,0.62993 -16,8 -2.9641,3.2129 -4.8642,7.04807 -6.0647,10.3524"
1036 |            marker-end="url(#FilledArrow_Marker)"
1037 |            stroke="black"
1038 |            stroke-linecap="square"
1039 |            stroke-linejoin="round"
1040 |            stroke-width="1"
1041 |            id="path239" />
1042 |       </g>
1043 |       <g
1044 |          id="Graphic_58">
1045 |         <text
1046 |            transform="translate(650,305.5)"
1047 |            fill="black"
1048 |            id="text244"
1049 |            style="fill:#000000"><tspan
1050 |              font-family="Helvetica Neue"
1051 |              font-size="10"
1052 |              font-weight="300"
1053 |              fill="black"
1054 |              x="0"
1055 |              y="10"
1056 |              id="tspan242"
1057 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">markerfacecolor (mfc)</tspan></text>
1058 |       </g>
1059 |       <g
1060 |          id="Line_59">
1061 |         <path
1062 |            inkscape:connector-curvature="0"
1063 |            d="m 640,371 c 0,0 -11.0027,3.7993 -16,-3 -2.5221,-3.43153 -2.91595,-8.74826 -2.6874,-13.17327"
1064 |            marker-end="url(#FilledArrow_Marker)"
1065 |            stroke="black"
1066 |            stroke-linecap="square"
1067 |            stroke-linejoin="round"
1068 |            stroke-width="1"
1069 |            id="path247" />
1070 |       </g>
1071 |       <g
1072 |          id="Graphic_60">
1073 |         <text
1074 |            transform="translate(634,358.5)"
1075 |            fill="black"
1076 |            id="text252"
1077 |            style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000"><tspan
1078 |              font-family="Helvetica Neue"
1079 |              font-size="10"
1080 |              font-weight="300"
1081 |              fill="black"
1082 |              x="0"
1083 |              y="10"
1084 |              id="tspan250"
1085 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">markeredgecolor (mec)</tspan></text>
1086 |       </g>
1087 |       <g
1088 |          id="Line_61">
1089 |         <path
1090 |            inkscape:connector-curvature="0"
1091 |            d="M 592,395.5 V 408 h 42.1"
1092 |            marker-end="url(#FilledArrow_Marker_2)"
1093 |            marker-start="url(#FilledBall_Marker)"
1094 |            stroke="black"
1095 |            stroke-linecap="round"
1096 |            stroke-linejoin="round"
1097 |            stroke-width="1"
1098 |            id="path255" />
1099 |       </g>
1100 |       <g
1101 |          id="Line_62">
1102 |         <line
1103 |            x1="623.98108"
1104 |            y1="395.49994"
1105 |            x2="623.91357"
1106 |            y2="408"
1107 |            marker-start="url(#FilledBall_Marker)"
1108 |            stroke="black"
1109 |            stroke-linecap="round"
1110 |            stroke-linejoin="round"
1111 |            stroke-width="1"
1112 |            id="line258" />
1113 |       </g>
1114 |       <g
1115 |          id="Graphic_63">
1116 |         <text
1117 |            transform="translate(643,401)"
1118 |            fill="black"
1119 |            id="text267"
1120 |            style="fill:#000000"><tspan
1121 |              font-family="Helvetica Neue"
1122 |              font-size="10"
1123 |              font-weight="300"
1124 |              fill="black"
1125 |              x="0"
1126 |              y="10"
1127 |              id="tspan261"
1128 |              style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.33333px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">numpoints <tspan
1129 |    style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.66667px;font-family:'Source Serif Pro';-inkscape-font-specification:'Source Serif Pro Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
1130 |    id="tspan278">or</tspan> scatterpoints</tspan></text>
1131 |       </g>
1132 |     </g>
1133 |   </g>
1134 | </svg>
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
quot;)
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 
lt;
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 |     "$♠
quot;, "$♣
quot;, "$♥
quot;, "$♦
quot;, "$→
quot;, "$←
quot;, "$↑
quot;, "$↓
quot;, "$◐
quot;, "$◑
quot;, "$◒
quot;, "$◓
quot;,
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\
quot; % 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
quot;, 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 | 


--------------------------------------------------------------------------------