diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c192f5b..7e284e4 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,9 @@ [bumpversion] -current_version = 3.4.2 +current_version = 3.8.2 + +[bumpversion:file:./check-matplotlib-version.py] +search = __version__ == '{current_version}' +replace = __version__ == '{new_version}' [bumpversion:glob:./handout-*.tex] search = Matplotlib {current_version} diff --git a/.circleci/config.yml b/.circleci/config.yml index 799c53f..a8d9e77 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,12 +6,12 @@ orbs: jobs: build_docs: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.9 steps: - checkout - run: command: echo "placeholder" - + workflows: main: jobs: diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..a2292e8 --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +ignore = E20,E22,E501,E701,F401,W + +[pep8] +select = E12,E231,E241,E251,E26,E30 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..34902e5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + actions: + patterns: + - "*" diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 447fbc6..8ea3441 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -6,24 +6,22 @@ jobs: pre-commit: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - uses: pre-commit/action@v2.0.0 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: pre-commit/action@v3.0.1 build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: "3.10" - name: Install dependencies run: | sudo apt update sudo apt install \ fontconfig \ imagemagick \ - libgeos++-dev \ - libproj-dev \ poppler-utils python -m pip install --upgrade pip pip install -r requirements/requirements.txt @@ -54,7 +52,7 @@ jobs: - name: Run checks run: | make check - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 if: ${{ always() }} with: name: build @@ -62,9 +60,21 @@ jobs: cheatsheets.pdf handout-*.pdf ./docs/_build/html/ + - uses: actions/upload-artifact@v4 + id: diffs-artifact-upload + if: ${{ always() }} + with: + name: diffs + path: | + diffs/ + - name: Output artifacts URL + run: | + echo 'Artifact URL:' \ + '${{ steps.diffs-artifact-upload.outputs.artifact-url }}' \ + >> $GITHUB_STEP_SUMMARY - name: Publish cheatsheets and handouts if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/_build/html/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27c2048..b940132 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,3 +9,7 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace + - repo: https://github.com/pycqa/flake8 + rev: 4.0.1 + hooks: + - id: flake8 diff --git a/Makefile b/Makefile index 114d87e..aa863ad 100644 --- a/Makefile +++ b/Makefile @@ -1,44 +1,52 @@ SRC := $(wildcard *.tex) +CONVERTFLAGS = -density 150 -alpha remove -depth 8 .PHONY: default default: all .PHONY: all -all: logos figures cheatsheets handouts docs - -.PHONY: logos -logos: - wget https://github.com/matplotlib/matplotlib/raw/v3.4.2/doc/_static/logo2.png -O ./logos/logo2.png +all: figures cheatsheets handouts docs .PHONY: figures figures: # generate the figures cd scripts && for script in *.py; do echo $$script; MPLBACKEND="agg" python $$script; done - # crop the figures - cd figures && for figure in *.pdf; do echo $$figure; pdfcrop $$figure $$figure; done - # regenerate some figures that should not be cropped - cd scripts && MPLBACKEND="agg" python styles.py + # crop some of the figures + cd figures && pdfcrop adjustments.pdf adjustments.pdf + cd figures && pdfcrop annotate.pdf annotate.pdf + cd figures && pdfcrop annotation-arrow-styles.pdf annotation-arrow-styles.pdf + cd figures && pdfcrop anatomy.pdf anatomy.pdf + cd figures && pdfcrop colornames.pdf colornames.pdf + cd figures && pdfcrop fonts.pdf fonts.pdf + cd figures && pdfcrop markers.pdf markers.pdf + cd figures && pdfcrop text-alignments.pdf text-alignments.pdf + cd figures && pdfcrop tick-formatters.pdf tick-formatters.pdf + cd figures && pdfcrop tick-locators.pdf tick-locators.pdf + cd figures && pdfcrop tip-font-family.pdf tip-font-family.pdf + cd figures && pdfcrop tip-hatched.pdf tip-hatched.pdf .PHONY: cheatsheets cheatsheets: xelatex cheatsheets.tex - convert -density 150 cheatsheets.pdf -scene 1 cheatsheets.png + convert $(CONVERTFLAGS) cheatsheets.pdf -scene 1 cheatsheets.png .PHONY: handouts handouts: xelatex handout-beginner.tex xelatex handout-intermediate.tex xelatex handout-tips.tex - convert -density 150 handout-tips.pdf handout-tips.png - convert -density 150 handout-beginner.pdf handout-beginner.png - convert -density 150 handout-intermediate.pdf handout-intermediate.png + convert $(CONVERTFLAGS) handout-tips.pdf handout-tips.png + convert $(CONVERTFLAGS) handout-beginner.pdf handout-beginner.png + convert $(CONVERTFLAGS) handout-intermediate.pdf handout-intermediate.png .PHONY: check check: + ./check-matplotlib-version.py ./check-num-pages.sh cheatsheets.pdf 2 ./check-num-pages.sh handout-tips.pdf 1 ./check-num-pages.sh handout-beginner.pdf 1 ./check-num-pages.sh handout-intermediate.pdf 1 + ./check-diffs.py ./check-links.py cheatsheets.pdf .PHONY: docs diff --git a/README.md b/README.md index d956a69..a9d07d5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ Beginner handout [(download pdf)](https://matplotlib.org/cheatsheets/handout-beg or https://github.com/adobe-fonts/source-sans-pro/tree/release/OTF * `fonts/source-serif-pro/*` : See https://fonts.google.com/specimen/Source+Serif+Pro or https://github.com/adobe-fonts/source-serif-pro/tree/release/OTF -* `fonts/delicious-123/*` : See https://www.exljbris.com/delicious.html +* `fonts/eb-garamond/*` : See https://bitbucket.org/georgd/eb-garamond/src/master +* `fonts/pacifico/*` : See https://fonts.google.com/download?family=Pacifico On Linux, with `make` installed, the fonts can be set up with the following command: ```shell diff --git a/cheatsheets.tex b/cheatsheets.tex index 5666a60..c6a5257 100644 --- a/cheatsheets.tex +++ b/cheatsheets.tex @@ -104,7 +104,7 @@ \setlength\parindent{0pt} \setlength{\tabcolsep}{2pt} \baselineskip=0pt -\setlength\columnsep{0.5em} +\setlength\columnsep{1.75mm} % --- Macros ------------------------------------------------------------------ @@ -264,7 +264,7 @@ \begin{multicols*}{5} \begin{overpic}[width=\columnwidth,tics=6,trim=12 6 18 6, clip]{logo2.png} \put (16.5,1.5) {\scriptsize\RobotoCon \textcolor[HTML]{11557c}{Cheat sheet}} - \put (80,1.5) {\tiny\Roboto \textcolor[HTML]{11557c}{Version 3.4.2}} + \put (80,1.5) {\tiny\Roboto \textcolor[HTML]{11557c}{Version 3.8.2}} \end{overpic} %\textbf{\Large \RobotoCon Matplotlib 3.2 cheat sheet}\\ %{\ttfamily https://matplotlib.org} \hfill CC-BY 4.0 @@ -286,10 +286,10 @@ Y = np.cos(X)\\ \\ fig, ax = plt.subplots()\\ - ax.plot(X,Y,color='C1')\\ + ax.plot(X, Y, color='green')\\ \\ fig.savefig(``figure.pdf'')\\ - fig.show() } + plt.show() } \end{myboxed} \vspace{\fill} @@ -301,19 +301,19 @@ % --- Layout --------------------------------------------------------------- \begin{myboxed}{Subplots layout \hfill \API{https://matplotlib.org/tutorials/intermediate/gridspec.html} } - \plot{layout-subplot.pdf}{\textbf{subplot[s]}(rows,cols,…)} + \plot{layout-subplot.pdf}{\textbf{subplot[s]}(rows, cols, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html} - {\ttfamily fig, axs = plt.subplots(3,3)} + {\ttfamily fig, axs = plt.subplots(3, 3)} {} - \plot{layout-gridspec.pdf}{G = \textbf{gridspec}(rows,cols,…)} + \plot{layout-gridspec.pdf}{G = \textbf{gridspec}(rows,cols, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.gridspec.GridSpec.html} - {\ttfamily ax = G[0,:]}{} + {\ttfamily ax = G[0, :]}{} \plot{layout-inset.pdf}{ax.\textbf{inset\_axes}(extent)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.inset_axes.html} {}{} \plot{layout-divider.pdf}{d=\textbf{make\_axes\_locatable}(ax)} {https://matplotlib.org/mpl_toolkits/axes_grid/users/axes_divider.html} - {\ttfamily ax=d.new\_horizontal('10\%')}{} + {\ttfamily ax = d.new\_horizontal('10\%')}{} \end{myboxed} \vspace{\fill} @@ -328,7 +328,7 @@ \href{https://stackoverflow.com/questions/tagged/matplotlib} {\faIcon{stack-overflow}\,stackoverflow.com/questions/tagged/matplotlib}\\ \href{https://gitter.im/matplotlib/matplotlib} - {\faIcon{gitter}\,gitter.im/matplotlib}\\ + {\faIcon{gitter}\,{https://gitter.im/matplotlib/matplotlib}}\\ \href{https://twitter.com/matplotlib} {\faIcon{twitter}\,twitter.com/matplotlib}\\ \href{https://mail.python.org/mailman/listinfo/matplotlib-users} @@ -338,7 +338,7 @@ % --- Basic plots ----------------------------------------------------------- \begin{myboxed}{Basic plots} - \plot{basic-plot.pdf}{\textbf{plot}([X],Y,[fmt],…)} + \plot{basic-plot.pdf}{\textbf{plot}([X], Y, [fmt], …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html} {\optional{X}, \mandatory{Y}, @@ -347,7 +347,7 @@ \optional{marker}, \optional{linestyle}} {} - \plot{basic-scatter.pdf}{\textbf{scatter}(X,Y,…)} + \plot{basic-scatter.pdf}{\textbf{scatter}(X, Y, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html} {\mandatory{X}, \mandatory{Y}, @@ -356,7 +356,7 @@ \optional{marker}, \optional{cmap}} {} - \plot{basic-bar.pdf}{\textbf{bar[h]}(x,height,…)} + \plot{basic-bar.pdf}{\textbf{bar[h]}(x, height, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar.html} { \mandatory{x}, \mandatory{height}, @@ -364,7 +364,7 @@ \optional{bottom}, \optional{align}, \optional{color} }{} - \plot{basic-imshow.pdf}{\textbf{imshow}(Z,[cmap],…)} + \plot{basic-imshow.pdf}{\textbf{imshow}(Z, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html} { \mandatory{Z}, \optional{cmap}, @@ -372,7 +372,7 @@ \optional{extent}, \optional{origin} } {} - \plot{basic-contour.pdf}{\textbf{contour[f]}([X],[Y],Z,,…)} + \plot{basic-contour.pdf}{\textbf{contour[f]}([X], [Y], Z, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contour.html} { \optional{X}, \optional{Y}, @@ -382,7 +382,16 @@ \optional{extent}, \optional{origin} } {} - \plot{basic-quiver.pdf}{\textbf{quiver}([X],[Y],U,V,…)} + \plot{basic-pcolormesh.pdf}{\textbf{pcolormesh}([X], [Y], Z, …)} + {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.pcolormesh.html} + { \optional{X}, + \optional{Y}, + \mandatory{Z}, + \optional{vmin}, + \optional{vmax}, + \optional{cmap}} + {} + \plot{basic-quiver.pdf}{\textbf{quiver}([X], [Y], U, V, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html} { \optional{X}, \optional{Y}, @@ -392,7 +401,7 @@ \optional{units}, \optional{angles} } {} - \plot{basic-pie.pdf}{\textbf{pie}(X,[explode],…)} + \plot{basic-pie.pdf}{\textbf{pie}(X, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.pie.html} {\mandatory{Z}, \optional{explode}, @@ -400,7 +409,7 @@ \optional{colors}, \optional{radius}} {} - \plot{basic-text.pdf}{\textbf{text}(x,y,text,…)} + \plot{basic-text.pdf}{\textbf{text}(x, y, text, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html} {\mandatory{x}, \mandatory{y}, @@ -411,7 +420,7 @@ \optional{weight}, \optional{transform} } {} - \plot{basic-fill.pdf}{\textbf{fill[\_between][x]}( … )} + \plot{basic-fill.pdf}{\textbf{fill[\_between][x]}(…)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.fill.html} {\mandatory{X}, \optional{Y1}, @@ -423,7 +432,7 @@ \vspace{\fill} % --- Advanced plots -------------------------------------------------------- \begin{myboxed}{Advanced plots} - \plot{advanced-step.pdf}{\textbf{step}(X,Y,[fmt],…)} + \plot{advanced-step.pdf}{\textbf{step}(X, Y, [fmt], …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.step.html} {\mandatory{X}, \mandatory{Y}, @@ -432,7 +441,7 @@ \optional{marker}, \optional{where} } {} - \plot{advanced-boxplot.pdf}{\textbf{boxplot}(X,…)} + \plot{advanced-boxplot.pdf}{\textbf{boxplot}(X, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.boxplot.html} { \mandatory{X}, \optional{notch}, @@ -440,7 +449,7 @@ \optional{bootstrap}, \optional{widths} } {} - \plot{advanced-errorbar.pdf}{\textbf{errorbar}(X,Y,xerr,yerr,…)} + \plot{advanced-errorbar.pdf}{\textbf{errorbar}(X,Y,xerr,yerr, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.errorbar.html} { \mandatory{X}, \mandatory{Y}, @@ -456,14 +465,14 @@ \optional{density}, \optional{weights}} {} - \plot{advanced-violin.pdf}{\textbf{violinplot}(D,…)} + \plot{advanced-violin.pdf}{\textbf{violinplot}(D, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.violinplot.html} {\mandatory{D}, \optional{positions}, \optional{widths}, \optional{vert} } {} - \plot{advanced-barbs.pdf}{\textbf{barbs}([X],[Y], U, V, …)} + \plot{advanced-barbs.pdf}{\textbf{barbs}([X], [Y], U, V, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.barbs.html} { \optional{X}, \optional{Y}, @@ -474,13 +483,13 @@ \optional{pivot}, \optional{sizes} } {} - \plot{advanced-event.pdf}{\textbf{eventplot}(positions,…)} + \plot{advanced-event.pdf}{\textbf{eventplot}(positions, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.eventplot.html} {\mandatory{positions}, \optional{orientation}, \optional{lineoffsets} } {} - \plot{advanced-hexbin.pdf}{\textbf{hexbin}(X,Y,C,…)} + \plot{advanced-hexbin.pdf}{\textbf{hexbin}(X, Y, C, …)} {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hexbin.html} {\mandatory{X}, \mandatory{Y}, @@ -488,20 +497,13 @@ \optional{gridsize}, \optional{bins} } {} - \plot{advanced-xcorr.pdf}{\textbf{xcorr}(X,Y,…)} - {https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.xcorr.html} - {\mandatory{X}, - \mandatory{Y}, - \optional{normed}, - \optional{detrend} } - {} \end{myboxed} % --- Scale --------------------------------------------------------------- \begin{myboxed}{Scales \hfill \API{https://matplotlib.org/stable/api/scale_api.html}} - {\ttfamily ax.\textbf{set\_[xy]scale}(scale,…)} + {\ttfamily ax.\textbf{set\_[xy]scale}(scale, …)} \smallskip \scale{scale-linear.pdf}{\textbf{linear}}{any values} \scale{scale-log.pdf}{\textbf{log}}{values > 0} @@ -514,20 +516,14 @@ % --- Projections ----------------------------------------------------------- \begin{myboxed}{Projections \hfill \API{https://matplotlib.org/stable/api/projections_api.html}} - {\ttfamily \textbf{subplot}(…,projection=p)} + {\ttfamily \textbf{subplot}(…, projection=p)} \smallskip \scale{projection-polar.pdf}{p='polar'}{} - \scale{projection-3d.pdf}{p='3d'}{} -% {https://matplotlib.org/stable/api/projections_api.html} -% {} -% {} - %% \plot{projection-3d.pdf}{p='3d'} - %% {https://matplotlib.org/stable/api/toolkits/mplot3d.html} - %% {} - %% {} - \plot{projection-cartopy.pdf}{p=Orthographic()} - {https://matplotlib.org/stable/api/toolkits/mplot3d.html} - {from cartopy.crs import Cartographic} + \scale{projection-3d.pdf} + {p='3d'\hfill\api{https://matplotlib.org/stable/api/toolkits/mplot3d.html}}{} + \plot{projection-cartopy.pdf}{p=ccrs.Orthographic()} + {https://scitools.org.uk/cartopy/docs/latest/reference/projections.html} + {import cartopy.crs as ccrs} {} \end{myboxed} % @@ -664,13 +660,13 @@ {\ttfamily \scriptsize import matplotlib.animation as mpla\par ~\par - T = np.linspace(0,2*np.pi,100)\par + T = np.linspace(0, 2*np.pi, 100)\par S = np.sin(T)\par line, = plt.plot(T, S)\par def animate(i):\par - ~~line.set\_ydata(np.sin(T+i/50))\par + ~~~~line.set\_ydata(np.sin(T+i/50))\par anim = mpla.FuncAnimation(\par - ~~plt.gcf(), animate, interval=5)\par + ~~~~plt.gcf(), animate, interval=5)\par plt.show()\par } \end{myboxed} @@ -686,19 +682,11 @@ \fbox{\includegraphics[width=.32\columnwidth]{style-classic.pdf}} \fbox{\includegraphics[width=.32\columnwidth]{style-grayscale.pdf}} \fbox{\includegraphics[width=.32\columnwidth]{style-ggplot.pdf}} - \fbox{\includegraphics[width=.32\columnwidth]{style-seaborn.pdf}} + \fbox{\includegraphics[width=.32\columnwidth]{style-seaborn-v0_8.pdf}} \fbox{\includegraphics[width=.32\columnwidth]{style-fast.pdf}} \fbox{\includegraphics[width=.32\columnwidth]{style-bmh.pdf}} \fbox{\includegraphics[width=.32\columnwidth]{style-Solarize_Light2.pdf}} - \fbox{\includegraphics[width=.32\columnwidth]{style-seaborn-notebook.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-default.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-classic.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-grayscale.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-ggplot.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-seaborn.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-fast.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-bmh.pdf}} - %% \fbox{\includegraphics[width=.24\columnwidth]{style-Solarize_Light2.pdf}} + \fbox{\includegraphics[width=.32\columnwidth]{style-seaborn-v0_8-notebook.pdf}} \end{myboxed} % \vspace{\fill} @@ -706,19 +694,19 @@ \begin{myboxed}{Quick reminder} {\ttfamily ax.\textbf{grid}()\\ - ax.patch.\textbf{set\_alpha}(0)\\ ax.\textbf{set\_[xy]lim}(vmin, vmax)\\ ax.\textbf{set\_[xy]label}(label)\\ - ax.\textbf{set\_[xy]ticks}(list)\\ - ax.\textbf{set\_[xy]ticklabels}(list)\\ - ax.\textbf{set\_[sup]title}(title)\\ + ax.\textbf{set\_[xy]ticks}(ticks, [labels])\\ + ax.\textbf{set\_[xy]ticklabels}(labels)\\ + ax.\textbf{set\_title}(title)\\ ax.\textbf{tick\_params}(width=10, …)\\ ax.\textbf{set\_axis\_[on|off]}()\\ \\ + fig.\textbf{suptitle}(title)\\ fig.\textbf{tight\_layout}()\\ plt.\textbf{gcf}(), plt.\textbf{gca}()\\ mpl.\textbf{rc}('axes', linewidth=1, …)\\ - fig.patch.\textbf{set\_alpha}(0)\\ + {[fig|ax]}.patch.\textbf{set\_alpha}(0)\\ \verb|text=r'$\frac{-e^{i\pi}}{2^n}$'|} \end{myboxed} % @@ -758,16 +746,16 @@ % \begin{myboxed}{Ten simple rules \hfill \READ{https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1003833}} - 1. Know Your Audience\\ - 2. Identify Your Message\\ - 3. Adapt the Figure\\ - 4. Captions Are Not Optional\\ - 5. Do Not Trust the Defaults\\ - 6. Use Color Effectively\\ - 7. Do Not Mislead the Reader\\ - 8. Avoid “Chartjunk”\\ - 9. Message Trumps Beauty\\ - 10. Get the Right Tool + 1. Know your audience\\ + 2. Identify your message\\ + 3. Adapt the figure\\ + 4. Captions are not optional\\ + 5. Do not trust the defaults\\ + 6. Use color effectively\\ + 7. Do not mislead the reader\\ + 8. Avoid “chartjunk”\\ + 9. Message trumps beauty\\ + 10. Get the right tool \end{myboxed} \end{multicols*} @@ -792,7 +780,7 @@ % \begin{myboxed}{Text alignments \hfill \API{https://matplotlib.org/tutorials/text/text_props.html} } - ax.\textbf{text}( …, ha=… , va=…, … )\\ + ax.\textbf{text}( …, ha=… , va=…, …)\\ \includegraphics[width=\columnwidth]{text-alignments.pdf} \end{myboxed} @@ -801,8 +789,8 @@ % \begin{myboxed}{Text parameters \hfill \API{https://matplotlib.org/tutorials/text/text_props.html}} - ax.\textbf{text}( …, family=… , size=…, weight = …)\\ - ax.\textbf{text}( …, fontproperties = … )\\ + ax.\textbf{text}(…, family=…, size=…, weight=…)\\ + ax.\textbf{text}(…, fontproperties=…)\\ \includegraphics[width=\columnwidth]{fonts.pdf} \end{myboxed} @@ -918,7 +906,7 @@ \begin{myboxed}{Legend placement} \includegraphics[width=\columnwidth]{legend-placement.pdf} - ax.\textbf{legend}(loc="string", bbox\_to\_anchor=(x,y))\\ + ax.\textbf{legend}(loc="string", bbox\_to\_anchor=(x, y))\\ \begin{tabular}{@{}p{0.33\columnwidth} p{0.33\columnwidth} p{0.33\columnwidth}@{}} @@ -931,12 +919,12 @@ \begin{tabular}{@{}p{0.495\columnwidth} p{0.495\columnwidth}@{}} \scriptsize \rule{0pt}{1.25em}\noindent - \tiny A: upper right / {\ttfamily (-0.1,0.9)} & \tiny B: center right / {\ttfamily (-0.1,0.5)}\\ - \tiny C: lower right / {\ttfamily (-0.1,0.1)} & \tiny D: upper left / {\ttfamily (0.1,-0.1)}\\ - \tiny E: upper center / {\ttfamily (0.5,-0.1)} & \tiny F: upper right / {\ttfamily (0.9,-0.1)}\\ - \tiny G: lower left / {\ttfamily (1.1,0.1)} & \tiny H: center left / {\ttfamily (1.1,0.5)}\\ - \tiny I: upper left / {\ttfamily (1.1,0.9)} & \tiny J: lower right / {\ttfamily (0.9,1.1)}\\ - \tiny K: lower center / {\ttfamily (0.5,1.1)} & \tiny L: lower left / {\ttfamily (0.1,1.1)} + \tiny A: upper right / {\ttfamily (-0.1, 0.9)} & \tiny B: center right / {\ttfamily (-0.1, 0.5)}\\ + \tiny C: lower right / {\ttfamily (-0.1, 0.1)} & \tiny D: upper left / {\ttfamily (0.1, -0.1)}\\ + \tiny E: upper center / {\ttfamily (0.5, -0.1)} & \tiny F: upper right / {\ttfamily (0.9, -0.1)}\\ + \tiny G: lower left / {\ttfamily (1.1, 0.1)} & \tiny H: center left / {\ttfamily (1.1, 0.5)}\\ + \tiny I: upper left / {\ttfamily (1.1, 0.9)} & \tiny J: lower right / {\ttfamily (0.9, 1.1)}\\ + \tiny K: lower center / {\ttfamily (0.5, 1.1)} & \tiny L: lower left / {\ttfamily (0.1, 1.1)} \end{tabular} \end{myboxed} % @@ -961,21 +949,21 @@ % \begin{myboxed}{How do I …} \textbf{… resize a figure?}\\ - \hspace*{2.5mm}~$\rightarrow$ fig.set\_size\_inches(w,h)\\ + \hspace*{2.5mm}~$\rightarrow$ fig.set\_size\_inches(w, h)\\ \textbf{… save a figure?}\\ \hspace*{2.5mm}~$\rightarrow$ fig.savefig("figure.pdf")\\ \textbf{… save a transparent figure?}\\ \hspace*{2.5mm}~$\rightarrow$ fig.savefig("figure.pdf", transparent=True)\\ - \textbf{… clear a figure?}\\ - \hspace*{2.5mm}~$\rightarrow$ ax.clear()\\ + \textbf{… clear a figure/an axes?}\\ + \hspace*{2.5mm}~$\rightarrow$ fig.clear() $\rightarrow$ ax.clear()\\ \textbf{… close all figures?}\\ \hspace*{2.5mm}~$\rightarrow$ plt.close("all")\\ \textbf{… remove ticks?}\\ - \hspace*{2.5mm}~$\rightarrow$ ax.set\_xticks([])\\ + \hspace*{2.5mm}~$\rightarrow$ ax.set\_[xy]ticks([])\\ \textbf{… remove tick labels ?}\\ \hspace*{2.5mm}~$\rightarrow$ ax.set\_[xy]ticklabels([])\\ \textbf{… rotate tick labels ?}\\ - \hspace*{2.5mm}~$\rightarrow$ ax.set\_[xy]ticks(rotation=90)\\ + \hspace*{2.5mm}~$\rightarrow$ ax.tick\_params(axis="x", rotation=90)\\ \textbf{… hide top spine?}\\ \hspace*{2.5mm}~$\rightarrow$ ax.spines['top'].set\_visible(False)\\ \textbf{… hide legend border?}\\ @@ -983,7 +971,7 @@ \textbf{… show error as shaded region?}\\ \hspace*{2.5mm}~$\rightarrow$ ax.fill\_between(X, Y+error, Y-error)\\ \textbf{… draw a rectangle?}\\ - \hspace*{2.5mm}~$\rightarrow$ ax.add\_patch(plt.Rectangle((0, 0),1,1)\\ + \hspace*{2.5mm}~$\rightarrow$ ax.add\_patch(plt.Rectangle((0, 0), 1, 1)\\ \textbf{… draw a vertical line?}\\ \hspace*{2.5mm}~$\rightarrow$ ax.axvline(x=0.5)\\ \textbf{… draw outside frame?}\\ @@ -991,7 +979,7 @@ \textbf{… use transparency?}\\ \hspace*{2.5mm}~$\rightarrow$ ax.plot(…, alpha=0.25)\\ \textbf{… convert an RGB image into a gray image? }\\ - \hspace*{2.5mm}~$\rightarrow$ gray = 0.2989*R+0.5870*G+0.1140*B\\ + \hspace*{2.5mm}~$\rightarrow$ gray = 0.2989*R + 0.5870*G + 0.1140*B\\ \textbf{… set figure background color?}\\ \hspace*{2.5mm}~$\rightarrow$ fig.patch.set\_facecolor(``grey'')\\ \textbf{… get a reversed colormap?}\\ @@ -1012,12 +1000,12 @@ plot(X, Y, marker="o", ls="") \hfill fast% \vskip.5\baselineskip % - \textcolor{red}{for i in range(n): plot(X[i]) \hfill slow}\\ - plot(sum([x+[None] for x in X],[])) \hfill fast% + \textcolor{red}{for i in range(n): plot(i, X[i], "o") \hfill slow}\\ + plot(X, marker="o", ls="") \hfill fast% \vskip.5\baselineskip % - \textcolor{red}{cla(), imshow(…), canvas.draw() \hfill slow}\\ - im.set\_data(…), canvas.draw() \hfill fast% + \textcolor{red}{cla(); imshow(…); canvas.draw() \hfill slow}\\ + im.set\_data(…); canvas.draw() \hfill fast% \vskip.1\baselineskip } \end{myboxed} @@ -1026,12 +1014,12 @@ % \begin{myboxed}{Beyond Matplotlib} \smallskip - \href{https://seaborn.pydata.org/}{\textbf{Seaborn}}: Statistical Data Visualization\\ - \href{https://scitools.org.uk/cartopy/docs/latest/}{\textbf{Cartopy}}: Geospatial Data Processing\\ - \href{https://yt-project.org/doc/index.html}{\textbf{yt}}: Volumetric data Visualization\\ + \href{https://seaborn.pydata.org/}{\textbf{Seaborn}}: Statistical data visualization\\ + \href{https://scitools.org.uk/cartopy/docs/latest/}{\textbf{Cartopy}}: Geospatial data processing\\ + \href{https://yt-project.org/doc/index.html}{\textbf{yt}}: Volumetric data visualization\\ \href{https://mpld3.github.io}{\textbf{mpld3}}: Bringing Matplotlib to the browser\\ \href{https://datashader.org/}{\textbf{Datashader}}: Large data processing pipeline\\ - \href{https://plotnine.readthedocs.io/en/latest/}{\textbf{plotnine}}: A Grammar of Graphics for Python + \href{https://plotnine.org/}{\textbf{plotnine}}: A grammar of graphics for Python \end{myboxed} % \begin{center} diff --git a/check-diffs.py b/check-diffs.py new file mode 100755 index 0000000..e68c0d6 --- /dev/null +++ b/check-diffs.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +import os +import subprocess +import sys +from pathlib import Path + + +ROOT_DIR = Path(__file__).parent + +if os.environ.get('GITHUB_ACTIONS', '') == '': + print('Not running when not in GitHub Actions.') + sys.exit() +summary_file = os.environ.get('GITHUB_STEP_SUMMARY') +if summary_file is None: + sys.exit('$GITHUB_STEP_SUMMARY is not set') + +gh_pages = ROOT_DIR.parent / 'pages' +subprocess.run(['git', 'fetch', 'https://github.com/matplotlib/cheatsheets.git', + 'gh-pages:upstream-gh-pages'], check=True) +subprocess.run(['git', 'worktree', 'add', gh_pages, 'upstream-gh-pages'], + check=True) + +diff_dir = ROOT_DIR / 'diffs' +diff_dir.mkdir(exist_ok=True) + +hashes = {} +for original in gh_pages.glob('*.png'): + result = subprocess.run( + ['compare', '-metric', 'PHASH', + original, + ROOT_DIR / 'docs/_build/html' / original.name, + diff_dir / f'{original.stem}-diff.png'], + text=True, stderr=subprocess.PIPE) + if result.returncode == 2: # Some kind of IO or similar error. + hashes[original] = (float('nan'), result.stderr) + elif result.stderr: # Images were different. + hashes[original] = (float(result.stderr), '') + else: # No differences. + hashes[original] = (0.0, '') + +with open(summary_file, 'w+') as summary: + print('# Cheatsheet image comparison', file=summary) + print('| Filename | Perceptual Hash Difference | Error message |', file=summary) + print('| -------- | -------------------------- | ------------- |', file=summary) + for filename, (hash, message) in sorted(hashes.items()): + message = message.replace('\n', ' ').replace('|', '\\|') + print(f'| {filename.name} | {hash:.05f} | {message}', file=summary) + print(file=summary) + +subprocess.run(['git', 'worktree', 'remove', gh_pages]) diff --git a/check-links.py b/check-links.py index 3a3e797..aa6f449 100755 --- a/check-links.py +++ b/check-links.py @@ -8,12 +8,12 @@ refs = [ref for ref in pdf.get_references() if ref.reftype == 'url'] -status_codes = list(map(lambda ref: pdfx.downloader.get_status_code(ref.ref), refs)) +status_codes = [pdfx.downloader.get_status_code(ref.ref) for ref in refs] -broken_links = [refs[idx].ref for idx in range(len(refs)) if status_codes[idx] != 200] +broken_links = [(ref.ref, code) for ref, code in zip(refs, status_codes) if code != 200] # it seems that Twitter does not respond well to the link checker and throws a 400 -if all(['twitter.com' in url for url in broken_links]): +if all(['twitter.com' in url for url, _ in broken_links]): sys.exit(0) else: print('Broken links:', broken_links) diff --git a/check-matplotlib-version.py b/check-matplotlib-version.py new file mode 100755 index 0000000..1430429 --- /dev/null +++ b/check-matplotlib-version.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +import matplotlib as mpl + + +assert mpl.__version__ == '3.8.2' diff --git a/docs/conf.py b/docs/conf.py index f4c70d1..6a558b0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -5,8 +5,8 @@ html_title = 'Visualization with Python' project = "Matplotlib cheatsheets" copyright = ( - f"2012 - {datetime.datetime.now().year} The Matplotlib development team" - ) + f"2012 - {datetime.datetime.now().year} The Matplotlib development team" +) author = "Matplotlib Developers" # -- General configuration --------------------------------------------------- @@ -14,7 +14,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] +extensions = ["sphinx_design"] # Add any paths that contain templates here, relative to this directory. @@ -31,8 +31,7 @@ html_theme = "mpl_sphinx_theme" html_favicon = "_static/favicon.ico" html_theme_options = { - "logo_link": "https://matplotlib.org/stable/", - "native_site": False, + "navbar_links": ("absolute", "server-stable"), } html_sidebars = { "**": [] diff --git a/docs/index.rst b/docs/index.rst index b9993ca..1024ddd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,23 +7,21 @@ Matplotlib cheatsheets and handouts Cheatsheets *********** -.. container:: twocol +.. grid:: 2 - .. container:: + .. grid-item:: - .. image:: ../cheatsheets-1.png - :width: 270px - :align: center - :alt: image of first page of cheatsheets + .. image:: ../cheatsheets-1.png + :width: 270px + :align: center + :alt: image of first page of cheatsheets + .. grid-item:: - .. container:: - - .. image:: ../cheatsheets-2.png - :width: 270px - :align: center - :alt: image of second page of cheatsheets - + .. image:: ../cheatsheets-2.png + :width: 270px + :align: center + :alt: image of second page of cheatsheets `Cheatsheets [pdf] <./cheatsheets.pdf>`_ @@ -32,36 +30,34 @@ Cheatsheets Handouts ******** -.. container:: twocol - - .. container:: - - .. image:: ../handout-beginner.png - :width: 270px - :align: center - :alt: image of beginner handout +.. grid:: 1 2 3 3 - `Beginner [pdf] <./handout-beginner.pdf>`_ + .. grid-item:: + .. image:: ../handout-beginner.png + :width: 270px + :align: center + :alt: image of beginner handout - .. container:: + `Beginner [pdf] <./handout-beginner.pdf>`_ - .. image:: ../handout-intermediate.png - :width: 270px - :align: center - :alt: image of intermediate handout + .. grid-item:: - `Intermediate [pdf] <./handout-intermediate.pdf>`_ + .. image:: ../handout-intermediate.png + :width: 270px + :align: center + :alt: image of intermediate handout + `Intermediate [pdf] <./handout-intermediate.pdf>`_ - .. container:: + .. grid-item:: - .. image:: ../handout-tips.png - :width: 270px - :align: center - :alt: image of tips handout + .. image:: ../handout-tips.png + :width: 270px + :align: center + :alt: image of tips handout - `Tips [pdf] <./handout-tips.pdf>`_ + `Tips [pdf] <./handout-tips.pdf>`_ Contribute ********** diff --git a/figures/legend.pdf b/figures/legend.pdf index a2fd28b..7cc56ee 100644 Binary files a/figures/legend.pdf and b/figures/legend.pdf differ diff --git a/fonts/Makefile b/fonts/Makefile index baa450e..96d20ee 100644 --- a/fonts/Makefile +++ b/fonts/Makefile @@ -1,4 +1,4 @@ -FONT_DIRS := eb-garamond roboto roboto-mono roboto-slab source-code-pro source-sans-pro source-serif-pro +FONT_DIRS := eb-garamond roboto roboto-mono roboto-slab source-code-pro source-sans-pro source-serif-pro pacifico EB_GARAMOND_ZIP := https://bitbucket.org/georgd/eb-garamond/downloads/EBGaramond-0.016.zip ROBOTO_ZIP := https://github.com/googlefonts/roboto/releases/download/v2.138/roboto-unhinted.zip @@ -7,6 +7,7 @@ ROBOTO_SLAB_ZIP := https://github.com/googlefonts/robotoslab/archive/a65e6d 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 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 SOURCE_SERIF_PRO_ZIP := https://github.com/adobe-fonts/source-serif/releases/download/3.001R/source-serif-pro-3.001R.zip +PACIFICO := https://raw.githubusercontent.com/googlefonts/Pacifico/refs/heads/main/fonts/ttf/Pacifico-Regular.ttf UNZIP_FLAGS := -x "__MACOSX/*" @@ -24,6 +25,7 @@ all: sources cd source-code-pro && unzip -j /tmp/source-code-pro.zip "*.otf" $(UNZIP_FLAGS) cd source-sans-pro && unzip -j /tmp/source-sans-pro.zip "source-sans-pro-2.045R-ro-1.095R-it/OTF/*.otf" $(UNZIP_FLAGS) cd source-serif-pro && unzip -j /tmp/source-serif-pro.zip "source-serif-pro-3.001R/OTF/*.otf" $(UNZIP_FLAGS) + cd pacifico && cp /tmp/pacifico.ttf . .PHONY: sources sources: @@ -34,6 +36,7 @@ sources: wget $(SOURCE_CODE_PRO_ZIP) -O /tmp/source-code-pro.zip wget $(SOURCE_SANS_PRO_ZIP) -O /tmp/source-sans-pro.zip wget $(SOURCE_SERIF_PRO_ZIP) -O /tmp/source-serif-pro.zip + wget $(PACIFICO) -O /tmp/pacifico.ttf .PHONY: clean clean: diff --git a/handout-beginner.tex b/handout-beginner.tex index f9d7394..58be029 100644 --- a/handout-beginner.tex +++ b/handout-beginner.tex @@ -83,7 +83,7 @@ \section*{\LARGE \rmfamily % \fbox{2} \textbf{Prepare} \begin{lstlisting} - X = np.linspace(0, 4*np.pi, 1000) + X = np.linspace(0, 10*np.pi, 1000) Y = np.sin(X) \end{lstlisting} % @@ -91,7 +91,7 @@ \section*{\LARGE \rmfamily \begin{lstlisting} fig, ax = plt.subplots() ax.plot(X, Y) - fig.show() + plt.show() \end{lstlisting} % \fbox{4} \textbf{Observe} \medskip\\ @@ -123,7 +123,7 @@ \subsection*{\rmfamily Choose} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - Z = np.random.uniform(0, 1, (8,8)) + Z = np.random.uniform(0, 1, (8, 8)) ax.imshow(Z) \end{lstlisting} @@ -132,7 +132,7 @@ \subsection*{\rmfamily Choose} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - Z = np.random.uniform(0, 1, (8,8)) + Z = np.random.uniform(0, 1, (8, 8)) ax.contourf(Z) \end{lstlisting} @@ -168,7 +168,7 @@ \subsection*{\rmfamily Choose} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - Z = np.random.normal(0, 1, (100,3)) + Z = np.random.normal(0, 1, (100, 3)) ax.boxplot(Z) \end{lstlisting} @@ -225,8 +225,8 @@ \subsection*{\rmfamily Tweak} \subsection*{\rmfamily Organize} % ----------------------------------------------------------------------------- -You can plot several data on the the same figure, but you can also -split a figure in several subplots (named {\em Axes}): \medskip +You can plot several data on the same figure, but you can also split a figure +in several subplots (named {\em Axes}): \medskip % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} @@ -240,7 +240,7 @@ \subsection*{\rmfamily Organize} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - fig, (ax1, ax2) = plt.subplots((2,1)) + fig, (ax1, ax2) = plt.subplots(2, 1) ax1.plot(X, Y1, color="C1") ax2.plot(X, Y2, color="C0") \end{lstlisting} @@ -249,7 +249,7 @@ \subsection*{\rmfamily Organize} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - fig, (ax1, ax2) = plt.subplots((1,2)) + fig, (ax1, ax2) = plt.subplots(1, 2) ax1.plot(Y1, X, color="C1") ax2.plot(Y2, X, color="C0") \end{lstlisting} @@ -297,7 +297,7 @@ \subsection*{\rmfamily Save \mdseries (bitmap or vector format)} \vfill % {\scriptsize - Matplotlib 3.4.2 handout for beginners. + Matplotlib 3.8.2 handout for beginners. Copyright (c) 2021 Matplotlib Development Team. Released under a CC-BY 4.0 International License. Supported by NumFOCUS. diff --git a/handout-intermediate.tex b/handout-intermediate.tex index d04971b..93d7b68 100644 --- a/handout-intermediate.tex +++ b/handout-intermediate.tex @@ -83,9 +83,9 @@ \subsection*{\rmfamily Figure, axes \& spines} % ----------------------------------------------------------------------------- \begin{tabular}{@{}m{.821\linewidth}m{.169\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - fig, axs = plt.subplots((3,3)) - axs[0,0].set_facecolor("#ddddff") - axs[2,2].set_facecolor("#ffffdd") + fig, axs = plt.subplots(3, 3) + axs[0, 0].set_facecolor("#ddddff") + axs[2, 2].set_facecolor("#ffffdd") \end{lstlisting} & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{layout-subplot-color.pdf}} \end{tabular} @@ -130,7 +130,7 @@ \subsection*{\rmfamily Lines \& markers} \begin{lstlisting} X = np.linspace(0.1, 10*np.pi, 1000) Y = np.sin(X) - ax.plot(X, Y, "C1o:", markevery=25, mec="1.0") + ax.plot(X, Y, "C1o:", markevery=50, mec="1.0") \end{lstlisting} \includegraphics[width=\linewidth]{sine-marker.pdf} @@ -140,13 +140,13 @@ \subsection*{\rmfamily Scales \& projections} \begin{lstlisting} fig, ax = plt.subplots() ax.set_xscale("log") - ax.plot(X, Y, "C1o-", markevery=25, mec="1.0") + ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") \end{lstlisting} \includegraphics[width=\linewidth]{sine-logscale.pdf} \subsection*{\rmfamily Text \& ornaments} \begin{lstlisting}[] - ax.fill_betweenx([-1,1],[0],[2*np.pi]) + ax.fill_betweenx([-1, 1], [0], [2*np.pi]) ax.text(0, -1, r" Period $\Phi$") \end{lstlisting} \includegraphics[width=\linewidth]{sine-period.pdf} @@ -157,17 +157,17 @@ \subsection*{\rmfamily Legend} \begin{lstlisting}[] ax.plot(X, np.sin(X), "C0", label="Sine") ax.plot(X, np.cos(X), "C1", label="Cosine") - ax.legend(bbox_to_anchor=(0,1,1,.1),ncol=2, - mode="expand", loc="lower left") + ax.legend(bbox_to_anchor=(0,1,1,.1), ncol=2, + mode="expand", loc="lower left") \end{lstlisting} \includegraphics[width=\linewidth]{sine-legend.pdf} % ----------------------------------------------------------------------------- \subsection*{\rmfamily Annotation} \begin{lstlisting}[] - ax.annotate("A", (X[250],Y[250]),(X[250],-1), - ha="center", va="center",arrowprops = - {"arrowstyle" : "->", "color": "C1"}) + ax.annotate("A", (X[250],Y[250]), (X[250],-1), + ha="center", va="center", arrowprops={ + "arrowstyle": "->", "color": "C1"}) \end{lstlisting} \includegraphics[width=\linewidth]{sine-annotate.pdf} @@ -185,12 +185,12 @@ \subsection*{\rmfamily Colors} \vspace{-1em} \subsection*{\rmfamily Size \& DPI} -Consider a square figure to be included in a two-columns A4 paper with -2cm margins on each side and a column separation of 1cm. The width of -a figure is (21 - 2*2 - 1)/2 = 8cm. One inch being 2.54cm, figure size -should be 3.15$\times$3.15 in. +Consider a square figure to be included in a two-column A4 paper with +2\,cm margins on each side and a column separation of 1\,cm. The width of +a figure is (21 - 2*2 - 1)/2 = 8\,cm. One inch being 2.54\,cm, figure size +should be 3.15$\times$3.15\,in. \begin{lstlisting}[] - fig = plt.figure(figsize=(3.15,3.15), dpi=50) + fig = plt.figure(figsize=(3.15, 3.15), dpi=50) plt.savefig("figure.pdf", dpi=600) \end{lstlisting} @@ -198,7 +198,7 @@ \subsection*{\rmfamily Size \& DPI} \vfill % {\scriptsize - Matplotlib 3.4.2 handout for intermediate users. + Matplotlib 3.8.2 handout for intermediate users. Copyright (c) 2021 Matplotlib Development Team. Released under a CC-BY 4.0 International License. Supported by NumFOCUS. diff --git a/handout-tips.tex b/handout-tips.tex index 864dc56..84ddede 100644 --- a/handout-tips.tex +++ b/handout-tips.tex @@ -114,7 +114,7 @@ \subsection*{\rmfamily Offline rendering} \begin{lstlisting} from matplotlib.backends.backend_agg import FigureCanvas canvas = FigureCanvas(Figure())) - ... # draw som stuff + ... # draw some stuff canvas.draw() Z = np.array(canvas.renderer.buffer_rgba()) \end{lstlisting} @@ -153,7 +153,7 @@ \subsection*{\rmfamily Text outline} % ----------------------------------------------------------------------------- \subsection*{\rmfamily Multiline plot} -You can plot several lines at once using None as separator. +You can plot several lines at once using {\em None} as separator. \begin{lstlisting} X,Y = [], [] @@ -168,10 +168,10 @@ \subsection*{\rmfamily Dotted lines} To have rounded dotted lines, use a custom {\ttfamily linestyle} and modify {\ttfamily dash\_capstyle}. \begin{lstlisting} - ax.plot([0,1], [0,0], "C1", - linestyle = (0, (0.01, 1)), dash_capstyle="round") - ax.plot([0,1], [1,1], "C1", - linestyle = (0, (0.01, 2)), dash_capstyle="round") + ax.plot([0, 1], [0, 0], "C1", + linestyle=(0, (0.01, 1)), dash_capstyle="round") + ax.plot([0, 1], [1, 1], "C1", + linestyle=(0, (0.01, 2)), dash_capstyle="round") \end{lstlisting} \includegraphics[width=\linewidth]{tip-dotted.pdf} @@ -181,9 +181,9 @@ \subsection*{\rmfamily Combining axes} \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] - ax1 = fig.add_axes([0,0,1,1], + ax1 = fig.add_axes([0, 0, 1, 1], label="cartesian") - ax2 = fig.add_axes([0,0,1,1], + ax2 = fig.add_axes([0, 0, 1, 1], label="polar", projection="polar") \end{lstlisting} & @@ -227,7 +227,7 @@ \subsection*{\rmfamily Hatching} cmap = plt.get_cmap("Oranges") plt.rcParams['hatch.color'] = cmap(0.2) plt.rcParams['hatch.linewidth'] = 8 - ax.bar(X, Y, color=cmap(0.6), hatch="/" ) + ax.bar(X, Y, color=cmap(0.6), hatch="/") \end{lstlisting} & \raisebox{-0.75em}{\includegraphics[width=\linewidth]{tip-hatched.pdf}} \end{tabular} @@ -243,7 +243,7 @@ \subsection*{\rmfamily Read the documentation} \vfill % {\scriptsize - Matplotlib 3.4.2 handout for tips \& tricks. + Matplotlib 3.8.2 handout for tips \& tricks. Copyright (c) 2021 Matplotlib Development Team. Released under a CC-BY 4.0 International License. Supported by NumFOCUS. diff --git a/logos/logo2.png b/logos/logo2.png new file mode 100644 index 0000000..72843ab Binary files /dev/null and b/logos/logo2.png differ diff --git a/logos/mpl-logos2.py b/logos/mpl-logos2.py index 9ae6b5d..5547a06 100644 --- a/logos/mpl-logos2.py +++ b/logos/mpl-logos2.py @@ -155,6 +155,7 @@ def make_logo(height_px, lw_bars, lw_grid, lw_border, rgrid, with_text=False): return fig, ax + ############################################################################## # A large logo: diff --git a/requirements/requirements.in b/requirements/requirements.in index 00cad75..2b1dd17 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -1,11 +1,15 @@ +autopep8 bump2version -cartopy==0.19.0.post1 -matplotlib==3.4.2 +cartopy==0.22.0 +flake8 +matplotlib==3.8.2 +pillow>=9 pdfx pip-tools pre-commit scipy +# Docs +mpl-sphinx-theme~=3.8.0 +pydata-sphinx-theme==0.13.3 sphinx -mpl-sphinx-theme - ---no-binary shapely +sphinx-design diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 52e79e2..d157b29 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,145 +1,188 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # # pip-compile requirements.in # ---no-binary shapely - -alabaster==0.7.12 - # via sphinx -appdirs==1.4.4 - # via virtualenv -babel==2.9.1 +accessible-pygments==0.0.4 + # via pydata-sphinx-theme +alabaster==0.7.16 # via sphinx -beautifulsoup4==4.9.3 +autopep8==2.0.4 + # via -r requirements.in +babel==2.14.0 + # via + # pydata-sphinx-theme + # sphinx +beautifulsoup4==4.12.3 # via pydata-sphinx-theme +build==1.0.3 + # via pip-tools bump2version==1.0.1 # via -r requirements.in -cartopy==0.19.0.post1 +cartopy==0.22.0 # via -r requirements.in -certifi==2021.10.8 - # via requests -cffi==1.15.0 +certifi==2024.7.4 + # via + # pyproj + # requests +cffi==1.16.0 # via cryptography -cfgv==3.2.0 +cfgv==3.4.0 # via pre-commit chardet==4.0.0 # via - # pdfminer.six + # pdfminer-six # pdfx -charset-normalizer==2.0.7 +charset-normalizer==3.3.2 # via requests -click==8.0.0 +click==8.1.7 # via pip-tools -cryptography==35.0.0 - # via pdfminer.six -cycler==0.10.0 +contourpy==1.2.0 # via matplotlib -distlib==0.3.1 +cryptography==44.0.1 + # via pdfminer-six +cycler==0.12.1 + # via matplotlib +distlib==0.3.8 # via virtualenv -docutils==0.17.1 +docutils==0.20.1 # via # pydata-sphinx-theme # sphinx -filelock==3.0.12 +filelock==3.13.1 # via virtualenv -identify==2.2.2 +flake8==7.0.0 + # via -r requirements.in +fonttools==4.47.2 + # via matplotlib +identify==2.5.33 # via pre-commit -idna==3.3 +idna==3.7 # via requests -imagesize==1.2.0 +imagesize==1.4.1 # via sphinx -jinja2==3.0.2 +jinja2==3.1.5 # via sphinx -kiwisolver==1.3.1 +kiwisolver==1.4.5 # via matplotlib -markupsafe==2.0.1 +markupsafe==2.1.4 # via jinja2 -matplotlib==3.4.2 - # via -r requirements.in -mpl-sphinx-theme==0.0.6 +matplotlib==3.8.2 + # via + # -r requirements.in + # cartopy + # mpl-sphinx-theme +mccabe==0.7.0 + # via flake8 +mpl-sphinx-theme==3.8.0 # via -r requirements.in -nodeenv==1.5.0 +nodeenv==1.8.0 # via pre-commit -numpy==1.19.5 +numpy==1.26.3 # via # cartopy + # contourpy # matplotlib # scipy -packaging==21.2 - # via sphinx -pdfminer.six==20201018 + # shapely +packaging==23.2 + # via + # build + # cartopy + # matplotlib + # pydata-sphinx-theme + # sphinx +pdfminer-six==20201018 # via pdfx pdfx==1.4.1 # via -r requirements.in -pep517==0.10.0 - # via pip-tools -pillow==8.1.2 - # via matplotlib -pip-tools==6.1.0 +pillow==10.3.0 + # via + # -r requirements.in + # matplotlib +pip-tools==7.3.0 # via -r requirements.in -pre-commit==2.11.1 +platformdirs==4.2.0 + # via virtualenv +pre-commit==3.6.0 # via -r requirements.in -pycparser==2.20 +pycodestyle==2.11.1 + # via + # autopep8 + # flake8 +pycparser==2.21 # via cffi -pydata-sphinx-theme==0.7.1 - # via mpl-sphinx-theme -pygments==2.10.0 - # via sphinx -pyparsing==2.4.7 +pydata-sphinx-theme==0.13.3 # via - # matplotlib - # packaging -pyshp==2.1.3 + # -r requirements.in + # mpl-sphinx-theme +pyflakes==3.2.0 + # via flake8 +pygments==2.17.2 + # via + # accessible-pygments + # pydata-sphinx-theme + # sphinx +pyparsing==3.1.1 + # via matplotlib +pyproj==3.6.1 # via cartopy -python-dateutil==2.8.1 +pyproject-hooks==1.0.0 + # via build +pyshp==2.3.1 + # via cartopy +python-dateutil==2.8.2 # via matplotlib -pytz==2021.3 - # via babel -pyyaml==5.4.1 +pyyaml==6.0.1 # via pre-commit -requests==2.26.0 +requests==2.32.2 # via sphinx -scipy==1.5.4 +scipy==1.12.0 # via -r requirements.in -shapely==1.7.1 +shapely==2.0.2 # via cartopy -six==1.15.0 - # via - # cycler - # python-dateutil - # virtualenv -snowballstemmer==2.1.0 +six==1.16.0 + # via python-dateutil +snowballstemmer==2.2.0 # via sphinx sortedcontainers==2.4.0 - # via pdfminer.six -soupsieve==2.3 + # via pdfminer-six +soupsieve==2.5 # via beautifulsoup4 -sphinx==4.2.0 +sphinx==7.2.6 # via # -r requirements.in # pydata-sphinx-theme -sphinxcontrib-applehelp==1.0.2 + # sphinx-design +sphinx-design==0.5.0 + # via -r requirements.in +sphinxcontrib-applehelp==1.0.8 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.6 # via sphinx -sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-htmlhelp==2.0.5 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.7 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.10 # via sphinx -toml==0.10.2 +tomli==2.0.1 # via - # pep517 - # pre-commit -urllib3==1.26.7 + # autopep8 + # build + # pip-tools + # pyproject-hooks +typing-extensions==4.9.0 + # via pydata-sphinx-theme +urllib3==2.2.2 # via requests -virtualenv==20.4.3 +virtualenv==20.26.6 # via pre-commit +wheel==0.42.0 + # via pip-tools # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/scripts/adjustements.py b/scripts/adjustements.py index 8d4577c..26f9559 100644 --- a/scripts/adjustements.py +++ b/scripts/adjustements.py @@ -2,65 +2,86 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib import numpy as np +import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.collections import PatchCollection -fig = plt.figure(figsize=(4.25, 4.25 * 95/115)) -ax = fig.add_axes([0,0,1,1], frameon=False, aspect=1, - xlim=(0-5,100+10), ylim=(-10,80+5), xticks=[], yticks=[]) +ROOT_DIR = pathlib.Path(__file__).parent.parent +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', +]) +mpl.rc('font', size=4) +mpl.rc('lines', linewidth=0.5) +mpl.rc('patch', linewidth=0.5) + + +subplots_kw = dict( + figsize=(5.7/2.54, 5.7/2.54 * 95/115), + subplot_kw=dict( + frameon=False, + aspect=1, + xlim=(0-5, 100+10), + ylim=(-10, 80+5), + xticks=[], + yticks=[], + ), +) + +(fig, ax) = plt.subplots(**subplots_kw) box = mpatches.FancyBboxPatch( - (0,0), 100, 83, mpatches.BoxStyle("Round", pad=0, rounding_size=2), - linewidth=1., facecolor="0.9", edgecolor="black") + (0, 0), 100, 83, mpatches.BoxStyle("Round", pad=0, rounding_size=2), + facecolor="0.9", edgecolor="black") ax.add_artist(box) box = mpatches.FancyBboxPatch( - (0,0), 100, 75, mpatches.BoxStyle("Round", pad=0, rounding_size=0), - linewidth=1., facecolor="white", edgecolor="black") + (0, 0), 100, 75, mpatches.BoxStyle("Round", pad=0, rounding_size=0), + facecolor="white", edgecolor="black") ax.add_artist(box) box = mpatches.Rectangle( - (5,5), 45, 30, zorder=10, - linewidth=1.0, facecolor="white", edgecolor="black") + (5, 5), 45, 30, zorder=10, + facecolor="white", edgecolor="black") ax.add_artist(box) box = mpatches.Rectangle( - (5,40), 45, 30, zorder=10, - linewidth=1.0, facecolor="white", edgecolor="black") + (5, 40), 45, 30, zorder=10, + facecolor="white", edgecolor="black") ax.add_artist(box) box = mpatches.Rectangle( - (55,5), 40, 65, zorder=10, - linewidth=1.0, facecolor="white", edgecolor="black") + (55, 5), 40, 65, zorder=10, + facecolor="white", edgecolor="black") ax.add_artist(box) # Window button -X, Y = [5,10,15], [79,79,79] -plt.scatter(X, Y, s=75, zorder=10, - edgecolor="black", facecolor="white", linewidth=1) +X, Y = [5, 10, 15], [79, 79, 79] +plt.scatter(X, Y, s=20, zorder=10, + edgecolor="black", facecolor="white") # Window size extension X, Y = [0, 0], [0, -8] -plt.plot(X, Y, color="black", linestyle=":", linewidth=1, clip_on=False) +plt.plot(X, Y, color="black", linestyle=":", clip_on=False) X, Y = [100, 100], [0, -8] -plt.plot(X, Y, color="black", linestyle=":", linewidth=1, clip_on=False) +plt.plot(X, Y, color="black", linestyle=":", clip_on=False) X, Y = [100, 108], [0, 0] -plt.plot(X, Y, color="black", linestyle=":", linewidth=1, clip_on=False) +plt.plot(X, Y, color="black", linestyle=":", clip_on=False) X, Y = [100, 108], [75, 75] -plt.plot(X, Y, color="black", linestyle=":", linewidth=1, clip_on=False) +plt.plot(X, Y, color="black", linestyle=":", clip_on=False) -def ext_arrow(p0,p1,p2,p3): +def ext_arrow(p0, p1, p2, p3): p0, p1 = np.asarray(p0), np.asarray(p1) p2, p3 = np.asarray(p2), np.asarray(p3) ax.arrow(*p0, *(p1-p0), zorder=20, linewidth=0, @@ -69,9 +90,10 @@ def ext_arrow(p0,p1,p2,p3): ax.arrow(*p3, *(p2-p3), zorder=20, linewidth=0, length_includes_head=True, width=.4, head_width=2, head_length=2, color="black") - plt.plot([p1[0],p2[0]], [p1[1],p2[1]], linewidth=.9, color="black") + plt.plot([p1[0], p2[0]], [p1[1], p2[1]], linewidth=.5, color="black") -def int_arrow(p0,p1): + +def int_arrow(p0, p1): p0, p1 = np.asarray(p0), np.asarray(p1) ax.arrow(*((p0+p1)/2), *((p1-p0)/2), zorder=20, linewidth=0, length_includes_head=True, width=.4, @@ -81,49 +103,47 @@ def int_arrow(p0,p1): head_width=2, head_length=2, color="black") - x = 0 y = 10 -ext_arrow( (x-4,y), (x,y), (x+5,y), (x+9,y) ) -ax.text(x+9.5, y, "left", ha="left", va="center", size="x-small", zorder=20) +ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) +ax.text(x+9.5, y, "left", ha="left", va="center", zorder=20) x += 50 -ext_arrow( (x-4,y), (x,y), (x+5,y), (x+9,y) ) -ax.text(x-4.5, y, "wspace", ha="right", va="center", size="x-small", zorder=20) +ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) +ax.text(x-4.5, y, "wspace", ha="right", va="center", zorder=20) x += 45 -ext_arrow( (x-4,y), (x,y), (x+5,y), (x+9,y) ) -ax.text(x-4.5, y, "right", ha="right", va="center", size="x-small", zorder=20) +ext_arrow( (x-4, y), (x, y), (x+5, y), (x+9, y) ) +ax.text(x-4.5, y, "right", ha="right", va="center", zorder=20) y = 0 x = 25 -ext_arrow( (x,y-4), (x,y), (x,y+5), (x,y+9) ) -ax.text(x, y+9.5, "bottom", ha="center", va="bottom", size="x-small", zorder=20) +ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) +ax.text(x, y+9.5, "bottom", ha="center", va="bottom", zorder=20) y += 35 -ext_arrow( (x,y-4), (x,y), (x,y+5), (x,y+9) ) -ax.text(x, y-4.5, "hspace", ha="center", va="top", size="x-small", zorder=20) +ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) +ax.text(x, y-4.5, "hspace", ha="center", va="top", zorder=20) y += 35 -ext_arrow( (x,y-4), (x,y), (x,y+5), (x,y+9) ) -ax.text(x, y-4.5, "top", ha="center", va="top", size="x-small", zorder=20) +ext_arrow( (x, y-4), (x, y), (x, y+5), (x, y+9) ) +ax.text(x, y-4.5, "top", ha="center", va="top", zorder=20) -int_arrow((0,-5), (100,-5)) +int_arrow((0, -5), (100, -5)) ax.text(50, -5, "figure width", backgroundcolor="white", zorder=30, - ha="center", va="center", size="x-small") + ha="center", va="center") -int_arrow((105,0), (105,75)) +int_arrow((105, 0), (105, 75)) ax.text(105, 75/2, "figure height", backgroundcolor="white", zorder=30, - rotation = "vertical", ha="center", va="center", size="x-small") + rotation="vertical", ha="center", va="center") -int_arrow((55,62.5), (95,62.5)) +int_arrow((55, 62.5), (95, 62.5)) ax.text(75, 62.5, "axes width", backgroundcolor="white", zorder=30, - ha="center", va="center", size="x-small") + ha="center", va="center") -int_arrow((62.5,5), (62.5,70)) +int_arrow((62.5, 5), (62.5, 70)) ax.text(62.5, 35, "axes height", backgroundcolor="white", zorder=30, - rotation = "vertical", ha="center", va="center", size="x-small") + rotation="vertical", ha="center", va="center") -plt.savefig("../figures/adjustments.pdf") -# plt.show() +fig.savefig(ROOT_DIR / "figures/adjustments.pdf") diff --git a/scripts/advanced-plots.py b/scripts/advanced-plots.py index 34bf1ab..f598087 100644 --- a/scripts/advanced-plots.py +++ b/scripts/advanced-plots.py @@ -3,149 +3,141 @@ # Released under the BSD License # ----------------------------------------------------------------------------- -# Scripts to generate all the basic plots +# Script to generate all the advanced plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(0.4,0.4)) -mpl.rcParams['axes.linewidth'] = 0.5 -mpl.rcParams['xtick.major.size'] = 0.0 -mpl.rcParams['ytick.major.size'] = 0.0 -d = 0.01 -ax = fig.add_axes([d,d,1-2*d,1-2*d]) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet.mplstyle', +]) +subplot_kw = dict( + xlim=(0, 8), xticks=np.arange(1, 8), + ylim=(0, 8), yticks=np.arange(1, 8), +) + # Step plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 16) -Y = 4+2*np.sin(2*X) -ax.step(X, Y, color="C1", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-step.pdf") -ax.clear() +Y = 4 + 2*np.sin(2*X) +ax.step(X, Y, color="C1") +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-step.pdf") # Violin plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(10) -D = np.random.normal((3,5,4), (0.75, 1.00, 0.75), (200,3)) -VP = ax.violinplot(D, [2,4,6], widths=1.5, +D = np.random.normal((3, 5, 4), (0.75, 1.00, 0.75), (200, 3)) +VP = ax.violinplot(D, [2, 4, 6], widths=1.5, showmeans=False, showmedians=False, showextrema=False) for body in VP['bodies']: body.set_facecolor('C1') body.set_alpha(1) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-violin.pdf") -ax.clear() - +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-violin.pdf") # Boxplot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(10) -D = np.random.normal((3,5,4), (1.25, 1.00, 1.25), (100,3)) -VP = ax.boxplot(D, positions=[2,4,6], widths=1.5, patch_artist=True, +D = np.random.normal((3, 5, 4), (1.25, 1.00, 1.25), (100, 3)) +VP = ax.boxplot(D, positions=[2, 4, 6], widths=1.5, patch_artist=True, showmeans=False, showfliers=False, - medianprops = {"color": "white", - "linewidth": 0.25}, - boxprops = {"facecolor": "C1", - "edgecolor": "white", - "linewidth": 0.25}, - whiskerprops = {"color": "C1", - "linewidth": 0.75}, - capprops = {"color": "C1", - "linewidth": 0.75}) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) + medianprops={"color": "white", + "linewidth": 0.25}, + boxprops={"facecolor": "C1", + "edgecolor": "white", + "linewidth": 0.25}, + whiskerprops={"color": "C1", + "linewidth": 0.75}, + capprops={"color": "C1", + "linewidth": 0.75}) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-boxplot.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-boxplot.pdf") # Barbs plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) -X = [[2,4,6]] -Y = [[1.5,3,2]] -U = -np.ones((1,3))*0 -V = -np.ones((1,3))*np.linspace(50,100,3) -ax.barbs(X,Y,U,V, barbcolor="C1", flagcolor="C1", length=5, linewidth=0.5) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) +X = [[2, 4, 6]] +Y = [[1.5, 3, 2]] +U = -np.ones((1, 3)) * 0 +V = -np.ones((1, 3)) * np.linspace(50, 100, 3) +ax.barbs(X, Y, U, V, barbcolor="C1", flagcolor="C1", length=5, linewidth=0.5) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-barbs.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-barbs.pdf") # Event plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) -X = [2,4,6] +X = [2, 4, 6] D = np.random.gamma(4, size=(3, 50)) -ax.eventplot(D, colors="C1", orientation="vertical", lineoffsets=X, linewidth=0.25) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) +ax.eventplot(D, colors="C1", orientation="vertical", lineoffsets=X, + linewidth=0.25) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-event.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-event.pdf") # Errorbar plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) -X = [2,4,6] -Y = [4,5,4] +X = [2, 4, 6] +Y = [4, 5, 4] E = np.random.uniform(0.5, 1.5, 3) ax.errorbar(X, Y, E, color="C1", linewidth=0.75, capsize=1) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-errorbar.pdf") -ax.clear() - +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-errorbar.pdf") # Hexbin plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) -X = np.random.uniform(1.5,6.5,100) -Y = np.random.uniform(1.5,6.5,100) -C = np.random.uniform(0,1,10000) +X = np.random.uniform(1.5, 6.5, 100) +Y = np.random.uniform(1.5, 6.5, 100) +C = np.random.uniform(0, 1, 10000) ax.hexbin(X, Y, C, gridsize=4, linewidth=0.25, edgecolor="white", cmap=plt.get_cmap("Wistia"), alpha=1.0) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-hexbin.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-hexbin.pdf") # Hist plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) -X = 4 + np.random.normal(0,1.5,200) -ax.hist(X, bins=8, facecolor="C1", linewidth=0.25, edgecolor="white",) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 80), ax.set_yticks(np.arange(1,80,10)) +X = 4 + np.random.normal(0, 1.5, 200) +ax.hist(X, bins=8, facecolor="C1", linewidth=0.25, edgecolor="white") +ax.set_ylim(0, 80), ax.set_yticks(np.arange(1, 80, 10)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-hist.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-hist.pdf") # Xcorr plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(3) Y = np.random.uniform(-4, 4, 250) X = np.random.uniform(-4, 4, 250) ax.xcorr(X, Y, usevlines=True, maxlags=6, normed=True, lw=1, color="C1") -ax.set_xlim(-8, 8), ax.set_xticks(np.arange(-8,8,2)) -ax.set_ylim(-.25, .25), ax.set_yticks(np.linspace(-.25,.25,9)) +ax.set_xlim(-8, 8), ax.set_xticks(np.arange(-8, 8, 2)) +ax.set_ylim(-.25, .25), ax.set_yticks(np.linspace(-.25, .25, 9)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/advanced-xcorr.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/advanced-xcorr.pdf") diff --git a/scripts/anatomy.py b/scripts/anatomy.py index c188381..e8f95cc 100644 --- a/scripts/anatomy.py +++ b/scripts/anatomy.py @@ -3,10 +3,20 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np +import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', +]) + np.random.seed(123) X = np.linspace(0.5, 3.5, 100) @@ -14,8 +24,7 @@ Y2 = 1+np.cos(1+X/0.75)/2 Y3 = np.random.uniform(Y1, Y2, len(X)) -fig = plt.figure(figsize=(8, 8)) -ax = fig.add_subplot(1, 1, 1, aspect=1) +(fig, ax) = plt.subplots(figsize=(8, 8), subplot_kw=dict(aspect=1)) def minor_tick(x, pos): @@ -23,6 +32,7 @@ def minor_tick(x, pos): return "" return "%.2f" % x + ax.xaxis.set_major_locator(MultipleLocator(1.000)) ax.xaxis.set_minor_locator(AutoMinorLocator(4)) ax.yaxis.set_major_locator(MultipleLocator(1.000)) @@ -48,7 +58,7 @@ def minor_tick(x, pos): ax.set_xlabel("X axis label") ax.set_ylabel("Y axis label") -ax.legend() +ax.legend(loc="upper right") def circle(x, y, radius=0.15): @@ -124,16 +134,16 @@ def text(x, y, text): color = '#000099' ax.annotate('Spines', xy=(4.0, 0.35), xytext=(3.3, 0.5), color=color, - weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", + weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", arrowprops=dict(arrowstyle='->', connectionstyle="arc3", color=color)) ax.annotate('', xy=(3.15, 0.0), xytext=(3.45, 0.45), color=color, - weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", + weight='regular', # fontsize="large", fontname="Yanone Kaffeesatz", arrowprops=dict(arrowstyle='->', connectionstyle="arc3", color=color)) -plt.savefig("../figures/anatomy.pdf") +fig.savefig(ROOT_DIR / "figures/anatomy.pdf") # plt.show() diff --git a/scripts/animation.py b/scripts/animation.py index ace8d48..353808c 100644 --- a/scripts/animation.py +++ b/scripts/animation.py @@ -2,11 +2,15 @@ import matplotlib.pyplot as plt import matplotlib.animation as animation -T = np.linspace(0,2*np.pi,100) +T = np.linspace(0, 2*np.pi, 100) S = np.sin(T) line, = plt.plot(T, S) + + def animate(i): line.set_ydata(np.sin(T+i/50)) + + a=animation.FuncAnimation( plt.gcf(), animate, interval=5) # plt.show() diff --git a/scripts/annotate.py b/scripts/annotate.py index a544bc9..6535368 100644 --- a/scripts/annotate.py +++ b/scripts/annotate.py @@ -2,27 +2,30 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(6,1)) -#ax = plt.subplot(111, frameon=False, aspect=.1) -# b = 0.0 -ax = fig.add_axes([0,0,1,1], frameon=False, aspect=1) +ROOT_DIR = pathlib.Path(__file__).parent.parent +fig = plt.figure(figsize=(6, 1)) +# ax = plt.subplot(111, frameon=False, aspect=.1) +# b = 0.0 +ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) -plt.scatter([5.5],[0.75], s=100, c="k") -plt.xlim(0,6), plt.ylim(0,1) +plt.scatter([5.5], [0.75], s=100, c="k") +plt.xlim(0, 6), plt.ylim(0, 1) plt.xticks([]), plt.yticks([]) -plt.annotate("Annotation", (5.5,.75), (0.1,.75), size=16, va="center", +plt.annotate("text", (5.5, .75), (0.75, .75), size=16, va="center", ha="center", arrowprops=dict(facecolor='black', shrink=0.05)) -plt.text( 5.5, 0.6, "xy\nycoords", size=10, va="top", ha="center", color=".5") +plt.text( 5.5, 0.6, "xy\nxycoords", size=10, va="top", ha="center", color=".5") plt.text( .75, 0.6, "xytext\ntextcoords", size=10, va="top", ha="center", color=".5") -plt.savefig("../figures/annotate.pdf") +fig.savefig(ROOT_DIR / "figures/annotate.pdf") # plt.show() diff --git a/scripts/annotation-arrow-styles.py b/scripts/annotation-arrow-styles.py index cb01a81..26ac950 100644 --- a/scripts/annotation-arrow-styles.py +++ b/scripts/annotation-arrow-styles.py @@ -1,16 +1,24 @@ +import pathlib + import matplotlib.pyplot as plt import matplotlib.patches as mpatches + +ROOT_DIR = pathlib.Path(__file__).parent.parent + styles = mpatches.ArrowStyle.get_styles() + + def demo_con_style(ax, connectionstyle): ax.text(.05, .95, connectionstyle.replace(",", ",\n"), family="Source Code Pro", transform=ax.transAxes, ha="left", va="top", size="x-small") -(fig, axes) = plt.subplots(5, 3, figsize=(4, 2.5), frameon=False) + +(fig, axes) = plt.subplots(4, 4, figsize=(4, 2.5), frameon=False) for ax in axes.flatten(): ax.axis("off") -for i,(ax,style) in enumerate(zip(axes.flatten(), mpatches.ArrowStyle.get_styles())): +for i, (ax, style) in enumerate(zip(axes.flatten(), mpatches.ArrowStyle.get_styles())): x0, y0 = 0.8, 0.5 x1, y1 = 0.2, 0.5 ax.plot([x0, x1], [y0, y1], ".", color="0.25") @@ -24,7 +32,7 @@ def demo_con_style(ax, connectionstyle): connectionstyle="arc3,rad=0")) ax.text( (x1+x0)/2, y0-0.2, style, transform=ax.transAxes, - family = "Source Code Pro", ha="center", va="top") + family="Source Code Pro", ha="center", va="top") -plt.savefig("../figures/annotation-arrow-styles.pdf") +fig.savefig(ROOT_DIR / "figures/annotation-arrow-styles.pdf") # plt.show() diff --git a/scripts/annotation-connection-styles.py b/scripts/annotation-connection-styles.py index 87c1198..057b5cd 100644 --- a/scripts/annotation-connection-styles.py +++ b/scripts/annotation-connection-styles.py @@ -1,5 +1,18 @@ +import pathlib + +import matplotlib as mpl import matplotlib.pyplot as plt + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet-grid.mplstyle', +]) +mpl.rc('lines', markersize=3) + + def demo_con_style(ax, connectionstyle): x1, y1 = 0.3, 0.2 x2, y2 = 0.8, 0.6 @@ -7,29 +20,27 @@ def demo_con_style(ax, connectionstyle): ax.annotate("", xy=(x1, y1), xycoords='data', xytext=(x2, y2), textcoords='data', - arrowprops=dict(arrowstyle="->", color="0.5", - shrinkA=5, shrinkB=5, + arrowprops=dict(arrowstyle="->", lw=0.5, color="0.5", + shrinkA=3, shrinkB=3, patchA=None, patchB=None, connectionstyle=connectionstyle), ) ax.text(.05, .95, connectionstyle.replace(",", ",\n"), - family="Source Code Pro", - transform=ax.transAxes, ha="left", va="top", size="x-small") + transform=ax.transAxes, ha="left", va="top", size=4) + -fig, axs = plt.subplots(3, 3, figsize=(5, 5)) +fig, axs = plt.subplots(3, 3, figsize=(5.7/2.54, 5.7/2.54)) demo_con_style(axs[0, 0], "arc3,rad=0") demo_con_style(axs[0, 1], "arc3,rad=0.3") demo_con_style(axs[0, 2], "angle3,angleA=0,angleB=90") demo_con_style(axs[1, 0], "angle,angleA=-90,angleB=180,rad=0") -demo_con_style(axs[1, 1], "angle,angleA=-90,angleB=180,rad=25") -demo_con_style(axs[1, 2], "arc,angleA=-90,angleB=0,armA=0,armB=40,rad=0") +demo_con_style(axs[1, 1], "angle,angleA=-90,angleB=180,rad=10") +demo_con_style(axs[1, 2], "arc,angleA=-90,angleB=0,armA=0,armB=20,rad=0") demo_con_style(axs[2, 0], "bar,fraction=0.3") demo_con_style(axs[2, 1], "bar,fraction=-0.3") demo_con_style(axs[2, 2], "bar,angle=180,fraction=-0.2") for ax in axs.flat: ax.set(xlim=(0, 1), ylim=(0, 1), xticks=[], yticks=[], aspect=1) -fig.tight_layout(pad=0.2) -plt.savefig("../figures/annotation-connection-styles.pdf") -# plt.show() +fig.savefig(ROOT_DIR / "figures/annotation-connection-styles.pdf") diff --git a/scripts/basic-plots.py b/scripts/basic-plots.py index e044728..8350326 100644 --- a/scripts/basic-plots.py +++ b/scripts/basic-plots.py @@ -3,158 +3,148 @@ # Released under the BSD License # ----------------------------------------------------------------------------- -# Scripts to generate all the basic plots +# Script to generate all the basic plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(0.4,0.4)) -mpl.rcParams['axes.linewidth'] = 0.5 -mpl.rcParams['xtick.major.size'] = 0.0 -mpl.rcParams['ytick.major.size'] = 0.0 -d = 0.01 -ax = fig.add_axes([d,d,1-2*d,1-2*d]) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet.mplstyle', +]) + + +subplot_kw = dict( + xlim=(0, 8), xticks=np.arange(1, 8), + ylim=(0, 8), yticks=np.arange(1, 8), +) # Basic line plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) -Y = 4+2*np.sin(2*X) -ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/basic-plot.pdf") -ax.clear() - +Y = 4 + 2*np.sin(2*X) +ax.plot(X, Y, color="C1") +ax.grid() +fig.savefig(ROOT_DIR / "figures/basic-plot.pdf") # Basic line plot (color) # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) -Y = 4+2*np.sin(2*X) -ax.plot(X, Y, color="black", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/basic-plot-color.pdf") -ax.clear() +Y = 4 + 2*np.sin(2*X) +ax.plot(X, Y, color="black") +ax.grid() +fig.savefig(ROOT_DIR / "figures/basic-plot-color.pdf") # Basic scatter plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(3) -X = 4+np.random.normal(0, 1.25, 24) -Y = 4+np.random.normal(0, 1.25, len(X)) +X = 4 + np.random.normal(0, 1.25, 24) +Y = 4 + np.random.normal(0, 1.25, len(X)) ax.scatter(X, Y, 5, zorder=10, edgecolor="white", facecolor="C1", linewidth=0.25) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/basic-scatter.pdf") -ax.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/basic-scatter.pdf") # Basic bar plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(3) X = 0.5 + np.arange(8) Y = np.random.uniform(2, 7, len(X)) ax.bar(X, Y, bottom=0, width=1, edgecolor="white", facecolor="C1", linewidth=0.25) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125) -plt.savefig("../figures/basic-bar.pdf") -ax.clear() - +ax.grid() +fig.savefig(ROOT_DIR / "figures/basic-bar.pdf") # Basic imshow plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(3) -I = np.zeros((8,8,4)) -I[:,:] = mpl.colors.to_rgba("C1") -I[...,3] = np.random.uniform(0.25,1.0,(8,8)) -ax.imshow(I, extent=[0,8,0,8], interpolation="nearest") -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) +Z = np.zeros((8, 8, 4)) +Z[:, :] = mpl.colors.to_rgba("C1") +Z[..., 3] = np.random.uniform(0.25, 1.0, (8, 8)) +ax.imshow(Z, extent=[0, 8, 0, 8], interpolation="nearest") ax.grid(linewidth=0.25, color="white") -plt.savefig("../figures/basic-imshow.pdf") -ax.clear() +fig.savefig(ROOT_DIR / "figures/basic-imshow.pdf") - -# Basic contour plot +# Basic pcolormesh plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256)) -Z = (1 - X/2. + X**5 + Y**3)*np.exp(-X**2-Y**2) +Z = (1 - X/2. + X**5 + Y**3) * np.exp(-X**2 - Y**2) Z = Z - Z.min() -colors = np.zeros((5,4)) -colors[:] = mpl.colors.to_rgba("C1") -colors[:,3] = np.linspace(0.15, 0.85, len(colors)) -plt.contourf(Z, len(colors), extent=[0,8,0,8], colors=colors) -plt.contour(Z, len(colors), extent=[0,8,0,8], colors="white", linewidths=0.125, - nchunk=10) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -# ax.set_axisbelow(True) -# ax.grid(linewidth=0.125, color="0.75") -plt.savefig("../figures/basic-contour.pdf") -ax.clear() +plt.pcolormesh(X, Y, Z, cmap='Oranges', shading='auto') +ax.set_xlim(-3, 3), ax.set_xticks(np.arange(-3, 4)) +ax.set_ylim(-3, 3), ax.set_yticks(np.arange(-3, 4)) +fig.savefig(ROOT_DIR / "figures/basic-pcolormesh.pdf") +# Basic contour plot +# ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) +colors = np.zeros((5, 4)) +colors[:] = mpl.colors.to_rgba("C1") +colors[:, 3] = np.linspace(0.15, 0.85, len(colors)) +plt.contourf(Z, len(colors), extent=[0, 8, 0, 8], colors=colors) +plt.contour(Z, len(colors), extent=[0, 8, 0, 8], colors="white", + linewidths=0.125, nchunk=10) +fig.savefig(ROOT_DIR / "figures/basic-contour.pdf") # Basic pie plot # ----------------------------------------------------------------------------- -X = 1,2,3,4 -colors = np.zeros((len(X),4)) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) +X = [1, 2, 3, 4] +colors = np.zeros((len(X), 4)) colors[:] = mpl.colors.to_rgba("C1") -colors[:,3] = np.linspace(0.25, 0.75, len(X)) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) +colors[:, 3] = np.linspace(0.25, 0.75, len(X)) ax.set_axisbelow(True) ax.grid(linewidth=0.25, color="0.75") -ax.pie(X, colors=["white",]*len(X), radius=3, center=(4,4), - wedgeprops = {"linewidth": 0.25, "edgecolor": "white"}, frame=True) -ax.pie(X, colors=colors, radius=3, center=(4,4), - wedgeprops = {"linewidth": 0.25, "edgecolor": "white"}, frame=True) -plt.savefig("../figures/basic-pie.pdf") -ax.clear() - +ax.pie(X, colors=["white"] * len(X), radius=3, center=(4, 4), + wedgeprops={"linewidth": 0.25, "edgecolor": "white"}, frame=True) +ax.pie(X, colors=colors, radius=3, center=(4, 4), + wedgeprops={"linewidth": 0.25, "edgecolor": "white"}, frame=True) +fig.savefig(ROOT_DIR / "figures/basic-pie.pdf") # Basic text plot # ----------------------------------------------------------------------------- -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) ax.set_axisbelow(True) ax.grid(linewidth=0.25, color="0.75") ax.text(4, 4, "TEXT", color="C1", size=8, weight="bold", ha="center", va="center", rotation=25) -plt.savefig("../figures/basic-text.pdf") -ax.clear() +fig.savefig(ROOT_DIR / "figures/basic-text.pdf") # Basic fill plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) X = np.linspace(0, 8, 16) Y1 = 3 + 4*X/8 + np.random.uniform(0.0, 0.5, len(X)) Y2 = 1 + 2*X/8 + np.random.uniform(0.0, 0.5, len(X)) plt.fill_between(X, Y1, Y2, color="C1", alpha=.5, linewidth=0) plt.plot(X, (Y1+Y2)/2, color="C1", linewidth=0.5) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125, color="0.75") -plt.savefig("../figures/basic-fill.pdf") -ax.clear() +ax.grid(color="0.75") +fig.savefig(ROOT_DIR / "figures/basic-fill.pdf") # Basic quiver plot # ----------------------------------------------------------------------------- +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) np.random.seed(1) T = np.linspace(0, 2*np.pi, 8) -X, Y = 4 + 1*np.cos(T), 4 + 1*np.sin(T) +X, Y = 4 + np.cos(T), 4 + np.sin(T) U, V = 1.5*np.cos(T), 1.5*np.sin(T) plt.quiver(X, Y, U, V, color="C1", angles='xy', scale_units='xy', scale=0.5, width=.05) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) ax.set_axisbelow(True) -ax.grid(linewidth=0.125, color="0.75") -plt.savefig("../figures/basic-quiver.pdf") -ax.clear() +ax.grid(color="0.75") +fig.savefig(ROOT_DIR / "figures/basic-quiver.pdf") diff --git a/scripts/colorbar.py b/scripts/colorbar.py index 1a252be..6ffba8f 100644 --- a/scripts/colorbar.py +++ b/scripts/colorbar.py @@ -2,22 +2,27 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- + +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(6,.65)) -#ax = plt.subplot(111, frameon=False, aspect=.1) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(6, .65)) +# ax = plt.subplot(111, frameon=False, aspect=.1) b = 0.025 -ax = fig.add_axes([b,10*b,1-2*b,1-10*b], frameon=False, aspect=0.05) +ax = fig.add_axes([b, 10*b, 1-2*b, 1-10*b], frameon=False, aspect=0.05) cmap = plt.get_cmap("Oranges") -norm = mpl.colors.Normalize(vmin=0,vmax=1) +norm = mpl.colors.Normalize(vmin=0, vmax=1) sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) sm.set_array([]) -plt.colorbar(sm, cax=ax, ticks=np.linspace(0,1,11), +plt.colorbar(sm, cax=ax, ticks=np.linspace(0, 1, 11), orientation="horizontal") -plt.savefig("../figures/colorbar.pdf") +fig.savefig(ROOT_DIR / "figures/colorbar.pdf") # plt.show() diff --git a/scripts/colormaps.py b/scripts/colormaps.py index 6d7ce45..1ccdea8 100644 --- a/scripts/colormaps.py +++ b/scripts/colormaps.py @@ -1,10 +1,14 @@ +import pathlib + import numpy as np import matplotlib.pyplot as plt +ROOT_DIR = pathlib.Path(__file__).parent.parent + figsize = 4.0, 0.25 fig = plt.figure(figsize=figsize) -ax = fig.add_axes([0,0,1,1], frameon=False, aspect=1) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) ymin, ymax= 0, 1 xmin, xmax = 0, figsize[0]/figsize[1] @@ -13,15 +17,15 @@ cmaps = ('viridis', 'plasma', 'inferno', 'magma', 'cividis', 'PRGn', 'PiYG', 'RdYlGn', 'BrBG', 'RdGy', 'PuOr', 'RdBu', - 'RdYlBu', 'Spectral', 'coolwarm', 'bwr', 'seismic', + 'RdYlBu', 'Spectral', 'coolwarm', 'bwr', 'seismic', 'tab10', 'tab20', 'tab20b', 'tab20c', 'Pastel1', 'Pastel2', 'Paired', 'Set1', 'Set2', 'Set3', 'Accent', 'Dark2', - 'Greys', 'Reds','Oranges', 'YlOrBr', 'YlOrRd', 'OrRd', + 'Greys', 'Reds', 'Oranges', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'Purples', 'YlGnBu', 'Blues', - 'PuBu', 'GnBu', 'PuBuGn', 'BuGn','Greens', 'YlGn', + 'PuBu', 'GnBu', 'PuBuGn', 'BuGn', 'Greens', 'YlGn', 'bone', 'gray', 'pink', 'afmhot', 'hot', 'gist_heat', 'copper', 'Wistia', 'autumn', 'summer', 'spring', 'cool', 'winter', @@ -29,38 +33,16 @@ 'twilight', 'twilight_shifted', 'hsv', 'terrain', 'ocean', 'gist_earth', 'cubehelix', 'rainbow' -) - -for cmap in cmaps: - n = 512 + ) - if cmap in ['tab10']: n = 10 - if cmap in ['tab20', 'tab20b', 'tab20c']: n = 20 - if cmap in ['Pastel1', 'Set1']: n = 9 - if cmap in ['Pastel2', 'Accent', 'Dark2', 'Set2']: n = 8 - if cmap in ['Set3']: n = 12 - if cmap in ['Greys']: n = 11 - Z = np.linspace(0,1,n).reshape(1,n) +for name in cmaps: + # The maximum number of segments in a cmap is 256, and for anything smaller, + # the cmap will map as a suitably discrete set of colours. + Z = np.linspace(0, 1, 256).reshape(1, 256) - ax.imshow(Z, extent=[xmin, xmax, ymin, ymax], cmap=plt.get_cmap(cmap)) + ax.imshow(Z, extent=[xmin, xmax, ymin, ymax], cmap=name) ax.set_xlim(xmin, xmax), ax.set_xticks([]) ax.set_ylim(ymin, ymax), ax.set_yticks([]) - """ - if cmap == "tab10": - x = np.linspace(xmin, xmax, 11, endpoint=True) + 0.5*(xmax-xmin)/11 - for i in range(10): - ax.text(x[i], (ymin+ymax)/2, "C%d"%i, color="white", zorder=10, - family = "Source Pro Serif", size=10, ha="center", va="center") - - if cmap == "Greys": - x = np.linspace(xmin, xmax, 12, endpoint=True) + 0.5*(xmax-xmin)/12 - for i in range(11): - color = "%.1f"%(i/10) - text = "%.1f"%(1-i/10) - ax.text(x[i], (ymin+ymax)/2, text, color=color, zorder=10, - family = "Source Pro Serif", size=10, ha="center", va="center") - """ - - plt.savefig("../figures/colormap-%s.pdf" % cmap) + fig.savefig(ROOT_DIR / f"figures/colormap-{name}.pdf") ax.clear() diff --git a/scripts/colornames.py b/scripts/colornames.py index 0f0260e..a059787 100644 --- a/scripts/colornames.py +++ b/scripts/colornames.py @@ -5,22 +5,29 @@ Simple plot example with the named colors and its visual representation. """ -from __future__ import division +import pathlib +import matplotlib as mpl import matplotlib.pyplot as plt -from matplotlib import colors as mcolors -colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', +]) +mpl.rc('figure.constrained_layout', h_pad=0, w_pad=0, hspace=0, wspace=0) + +colors = dict(mpl.colors.BASE_COLORS, **mpl.colors.CSS4_COLORS) # Sort colors by hue, saturation, value and name. -by_hsv = sorted((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name) +by_hsv = sorted((tuple(mpl.colors.rgb_to_hsv(mpl.colors.to_rgba(color)[:3])), name) for name, color in colors.items()) sorted_names = [name for hsv, name in by_hsv] n = len(sorted_names) ncols = 3 -nrows = n // ncols +1 +nrows = n // ncols fig, ax = plt.subplots(figsize=(4.5, 6)) @@ -30,8 +37,8 @@ w = X / ncols for i, name in enumerate(sorted_names): - col = i // (nrows-1) - row = i % (nrows-1) + col = i // nrows + row = i % nrows y = Y - (row * h) - h xi_line = w * (col + 0.05) @@ -49,9 +56,4 @@ ax.set_ylim(0, Y) ax.set_axis_off() -fig.subplots_adjust(left=0, right=1, - top=1, bottom=0, - hspace=0, wspace=0) - -plt.savefig("../figures/colornames.pdf") -# plt.show() +fig.savefig(ROOT_DIR / "figures/colornames.pdf") diff --git a/scripts/colors.py b/scripts/colors.py index a55f9db..c72d1d9 100644 --- a/scripts/colors.py +++ b/scripts/colors.py @@ -2,14 +2,19 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- + +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt +ROOT_DIR = pathlib.Path(__file__).parent.parent + figsize = 4.0, 0.25 fig = plt.figure(figsize=figsize) -ax = fig.add_axes([0,0,1,1], frameon=False, aspect=1) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) ymin, ymax= 0, 1 xmin, xmax = 0, figsize[0]/figsize[1] ax.set_xlim(xmin, xmax), ax.set_xticks([]) @@ -19,22 +24,29 @@ # ----------------------------------------------------------------------------- palettes = { 'raw' : ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'], - 'rgba' : [(1,0,0), (1,0,0,0.75), (1,0,0,0.50), (1,0,0,0.25)], + 'rgba' : [(1, 0, 0), (1, 0, 0, 0.75), (1, 0, 0, 0.50), (1, 0, 0, 0.25)], 'HexRGBA' : ["#FF0000", "#FF0000BB", "#FF000088", "#FF000044"], 'cycle' : ["C%d" % i for i in range(10)], 'grey' : ["%1.1f" % (i/10) for i in range(11)], 'name' : ["DarkRed", "Firebrick", "Crimson", "IndianRed", "Salmon" ] } for name, colors in palettes.items(): - C = mpl.colors.to_rgba_array(colors).reshape((1,len(colors),4)) + C = mpl.colors.to_rgba_array(colors).reshape((1, len(colors), 4)) ax.imshow(C, extent=[xmin, xmax, ymin, ymax]) + + # Drop alpha by assuming we're on a white background PDF. + alpha = C[0, :, 3] + rgb = C[0, :, :3] * alpha[:, np.newaxis] + (1 - alpha[:, np.newaxis]) + # Same calculation for luminance as + # https://matplotlib.org/stable/users/explain/colors/colors.html#comparison-between-x11-css4-and-xkcd-colors + luma = 0.299 * rgb[:, 0] + 0.587 * rgb[:, 1] + 0.114 * rgb[:, 2] + dx = (xmax-xmin)/len(colors) for i in range(len(colors)): - color = "white" - if colors[i] in ['1.0', 'w']: color = "black" + text_color = "black" if luma[i] > 0.5 else "white" text = str(colors[i]).replace(' ', '') - ax.text((i+0.5)*dx, (ymin+ymax)/2, text, color=color, zorder=10, - family = "Source Code Pro", size=9, ha="center", va="center") + ax.text((i+0.5)*dx, (ymin+ymax)/2, text, color=text_color, zorder=10, + family="Source Code Pro", size=9, ha="center", va="center") - plt.savefig("../figures/colors-%s.pdf" % name) + fig.savefig(ROOT_DIR / f"figures/colors-{name}.pdf") ax.clear() diff --git a/scripts/extents.py b/scripts/extents.py index 33bccd5..2eab814 100644 --- a/scripts/extents.py +++ b/scripts/extents.py @@ -2,20 +2,28 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib -# Scripts to generate all the basic plots import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -Z = np.arange(5*5).reshape(5,5) -fig = plt.figure(figsize=(8,5)) +ROOT_DIR = pathlib.Path(__file__).parent.parent -ax = fig.add_subplot(2,2,1) -ax.imshow(Z, extent=[0,10,0,5], interpolation="nearest", origin="upper") +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', +]) +mpl.rc('figure.constrained_layout', wspace=0.05) + +Z = np.arange(5*5).reshape(5, 5) + +(fig, axs) = plt.subplots(figsize=(8, 5), nrows=2, ncols=2) + +ax = axs[0, 0] +ax.imshow(Z, extent=[0, 10, 0, 5], interpolation="nearest", origin="upper") ax.set_xlim(-1, 11), ax.set_xticks([]) -ax.set_ylim(-1, 6), ax.set_yticks([0,5]) +ax.set_ylim(-1, 6), ax.set_yticks([0, 5]) ax.text(1, 4.5, "(0,0)", ha="center", va="center", color="white", size="large") ax.text(9, 0.5, "(4,4)", ha="center", va="center", color="black", size="large") ax.text(5.0, 5.5, 'origin="upper"', @@ -23,10 +31,10 @@ ax.text(5.0, -0.5, "extent=[0,10,0,5]", ha="center", va="center", color="black", size="large") -ax = fig.add_subplot(2,2,3) -ax.imshow(Z, extent=[0,10,0,5], interpolation="nearest", origin="lower") -ax.set_xlim(-1, 11), ax.set_xticks([0,10]) -ax.set_ylim(-1, 6), ax.set_yticks([0,5]) +ax = axs[1, 0] +ax.imshow(Z, extent=[0, 10, 0, 5], interpolation="nearest", origin="lower") +ax.set_xlim(-1, 11), ax.set_xticks([0, 10]) +ax.set_ylim(-1, 6), ax.set_yticks([0, 5]) ax.text(1, 0.5, "(0,0)", ha="center", va="center", color="white", size="large") ax.text(9, 4.5, "(4,4)", ha="center", va="center", color="black", size="large") @@ -35,10 +43,9 @@ ax.text(5.0, -0.5, "extent=[0,10,0,5]", ha="center", va="center", color="black", size="large") - -ax = fig.add_subplot(2,2,4) -ax.imshow(Z, extent=[10,0,0,5], interpolation="nearest", origin="lower") -ax.set_xlim(-1, 11), ax.set_xticks([0,10]) +ax = axs[1, 1] +ax.imshow(Z, extent=[10, 0, 0, 5], interpolation="nearest", origin="lower") +ax.set_xlim(-1, 11), ax.set_xticks([0, 10]) ax.set_ylim(-1, 6), ax.set_yticks([]) ax.text(9, 0.5, "(0,0)", ha="center", va="center", color="white", size="large") ax.text(1, 4.5, "(4,4)", ha="center", va="center", color="black", size="large") @@ -46,11 +53,9 @@ ha="center", va="center", color="black", size="large") ax.text(5.0, -0.5, "extent=[10,0,0,5]", ha="center", va="center", color="black", size="large") -plt.tight_layout() - -ax = fig.add_subplot(2,2,2) -ax.imshow(Z, extent=[10,0,0,5], interpolation="nearest", origin="upper") +ax = axs[0, 1] +ax.imshow(Z, extent=[10, 0, 0, 5], interpolation="nearest", origin="upper") ax.set_xlim(-1, 11), ax.set_xticks([]) ax.set_ylim(-1, 6), ax.set_yticks([]) ax.text(9, 4.5, "(0,0)", ha="center", va="center", color="white", size="large") @@ -59,8 +64,5 @@ ha="center", va="center", color="black", size="large") ax.text(5.0, -0.5, "extent=[10,0,0,5]", ha="center", va="center", color="black", size="large") -plt.tight_layout() - -plt.savefig("../figures/extents.pdf", dpi=600) -# plt.show() +fig.savefig(ROOT_DIR / "figures/extents.pdf", dpi=600) diff --git a/scripts/fonts.py b/scripts/fonts.py index 385286f..7d39e10 100644 --- a/scripts/fonts.py +++ b/scripts/fonts.py @@ -7,9 +7,11 @@ import matplotlib.pyplot as plt +ROOT_DIR = pathlib.Path(__file__).parent.parent + fig = plt.figure(figsize=(4.25, 3.8)) -ax = fig.add_axes([0,0,1,1], frameon=False, xticks=[], yticks=[], - xlim=[0,40], ylim=[0,38]) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, xticks=[], yticks=[], + xlim=[0, 40], ylim=[0, 38]) y = 1 @@ -20,13 +22,12 @@ } text = "The quick brown fox jumps over the lazy dog" -for i,variant in enumerate(variants.keys()): - ax.text(1, y, text, size=9, va="center", - font=pathlib.Path(variants[variant]).resolve()) +for i, (variant, file) in enumerate(variants.items()): + ax.text(1, y, text, size=9, va="center", font=pathlib.Path(file).resolve()) ax.text(39, y, variant, color="0.25", va="center", ha="right", - size="small", family = "Source Code Pro", weight = 400) + size="small", family="Source Code Pro", weight=400) y += 1.65 y += 1 @@ -34,13 +35,13 @@ styles = ["normal", "italic"] text = "The quick brown fox jumps over the lazy dog" -for i,style in enumerate(styles): +for i, style in enumerate(styles): ax.text(1, y, text, size=9, va="center", style=style, - family = "Source Sans Pro") + family="Source Sans Pro") ax.text(39, y, style, color="0.25", va="center", ha="right", - size="small", family = "Source Code Pro", weight = 400) + size="small", family="Source Code Pro", weight=400) y += 1.65 y += 1 @@ -53,14 +54,13 @@ "Source Code Pro" : "monospace" } text = "The quick brown fox jumps over the lazy dog" -for i,family in enumerate(families): +for i, (family, label) in enumerate(families.items()): ax.text(1, y, text, - va="center", size=9, family = family, weight = "regular") + va="center", size=9, family=family, weight="regular") - ax.text(39, y, - "%s" % (families[family]), + ax.text(39, y, label, color="0.25", va="center", ha="right", - size="small", family = "Source Code Pro", weight = 400) + size="small", family="Source Code Pro", weight=400) y += 1.65 y += 1 @@ -77,13 +77,13 @@ 'black' : 900 } text = "The quick brown fox jumps over the lazy dog" -for i,weight in enumerate(["ultralight","normal","semibold","bold","black"]): +for i, weight in enumerate(["ultralight", "normal", "semibold", "bold", "black"]): ax.text(1, y, text, size=9, - va="center", family = "Source Sans Pro", weight = weight) + va="center", family="Source Sans Pro", weight=weight) - ax.text(39, y, "%s (%d)" % (weight, weights[weight]), + ax.text(39, y, f"{weight} ({weights[weight]:d})", color="0.25", va="center", ha="right", - size="small", family = "Source Code Pro", weight = 400) + size="small", family="Source Code Pro", weight=400) y += 1.65 y += 1 @@ -97,15 +97,15 @@ "xx-large" : 1.728 } text = "The quick brown fox" -for i,size in enumerate(sizes.keys()): +for i, (size, scaling) in enumerate(sizes.items()): ax.text(1, y, text, size=size, - ha="left", va="center", family = "Source Sans Pro", weight="light") + ha="left", va="center", family="Source Sans Pro", weight="light") - ax.text(39, y, "%s (%.2f)" % (size, sizes[size]), + ax.text(39, y, f"{size} ({scaling:.2f})", color="0.25", va="center", ha="right", - size="small", family = "Source Code Pro", weight = 400) + size="small", family="Source Code Pro", weight=400) y += 1.65* max(sizes[size], sizes["small"]) -plt.savefig("../figures/fonts.pdf") +fig.savefig(ROOT_DIR / "figures/fonts.pdf") # plt.show() diff --git a/scripts/interpolations.py b/scripts/interpolations.py index 8083b72..3cd1308 100644 --- a/scripts/interpolations.py +++ b/scripts/interpolations.py @@ -1,22 +1,33 @@ +import pathlib + +import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet-grid.mplstyle', +]) + methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'] np.random.seed(1) -Z = np.random.uniform(0,1,(3,3)) +Z = np.random.uniform(0, 1, (3, 3)) -fig, axs = plt.subplots(nrows=6, ncols=3, figsize=(4.5,9), +fig, axs = plt.subplots(nrows=6, ncols=3, figsize=(5.7/2.54, 5.7/2.54*2), + # fig, axs = plt.subplots(nrows=6, ncols=3, figsize=(4.5,9), subplot_kw={'xticks': [], 'yticks': []}) for ax, interp_method in zip(axs.flat, methods): ax.imshow(Z, interpolation=interp_method, cmap='viridis', - extent=[0,9,0,9], rasterized=True) - ax.text(4.5, 1, str(interp_method), weight="bold", color="white", size=12, - transform=ax.transData, ha="center", va="center") + extent=[0, 1, 0, 1], rasterized=True) + ax.text(0.5, 0.1, str(interp_method), weight="bold", color="white", size=6, + ha="center", va="center") -plt.tight_layout() -plt.savefig("../figures/interpolations.pdf", dpi=600) +fig.savefig(ROOT_DIR / "figures/interpolations.pdf", dpi=600) # plt.show() diff --git a/scripts/layouts.py b/scripts/layouts.py index 25388f2..49f7340 100644 --- a/scripts/layouts.py +++ b/scripts/layouts.py @@ -2,41 +2,47 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid1 import make_axes_locatable + -fig = plt.figure(figsize=(0.4,0.4)) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(0.4, 0.4)) margin = 0.01 fig.subplots_adjust(left=margin, right=1-margin, top=1-margin, bottom=margin) mpl.rc('axes', linewidth=.5) # Subplots # ----------------------------------------------------------------------------- -nrows, ncols = 3,3 +nrows, ncols = 3, 3 for i in range(nrows*ncols): ax = plt.subplot(ncols, nrows, i+1) ax.set_xticks([]), ax.set_yticks([]) -plt.savefig("../figures/layout-subplot.pdf") +fig.savefig(ROOT_DIR / "figures/layout-subplot.pdf") fig.clear() # Subplots (colored) # ----------------------------------------------------------------------------- -nrows, ncols = 3,3 +nrows, ncols = 3, 3 for i in range(nrows*ncols): ax = plt.subplot(ncols, nrows, i+1) ax.set_xticks([]), ax.set_yticks([]) if i == 0: ax.set_facecolor("#ddddff") if i == 8: ax.set_facecolor("#ffdddd") -plt.savefig("../figures/layout-subplot-color.pdf") +fig.savefig(ROOT_DIR / "figures/layout-subplot-color.pdf") fig.clear() # Spines # ----------------------------------------------------------------------------- -ax = fig.add_subplot(1,1,1, xticks=[], yticks=[]) +ax = fig.add_subplot(1, 1, 1, xticks=[], yticks=[]) ax.spines["top"].set_color("None") ax.spines["right"].set_color("None") -plt.savefig("../figures/layout-spines.pdf") +fig.savefig(ROOT_DIR / "figures/layout-spines.pdf") fig.clear() @@ -48,7 +54,7 @@ ax3 = fig.add_subplot(gs[1:, -1], xticks=[], yticks=[]) ax4 = fig.add_subplot(gs[-1, 0], xticks=[], yticks=[]) ax5 = fig.add_subplot(gs[-1, -2], xticks=[], yticks=[]) -plt.savefig("../figures/layout-gridspec.pdf") +fig.savefig(ROOT_DIR / "figures/layout-gridspec.pdf") fig.clear() # Gridspec (colored) @@ -60,26 +66,25 @@ ax3 = fig.add_subplot(gs[1:, -1], xticks=[], yticks=[]) ax4 = fig.add_subplot(gs[-1, 0], xticks=[], yticks=[]) ax5 = fig.add_subplot(gs[-1, -2], xticks=[], yticks=[]) -plt.savefig("../figures/layout-gridspec-color.pdf") +fig.savefig(ROOT_DIR / "figures/layout-gridspec-color.pdf") fig.clear() # Inset axes # ----------------------------------------------------------------------------- mpl.rc('axes', linewidth=.5) margin = 0.0125 -ax1 = fig.add_axes([margin,margin,1-2*margin,1-2*margin], xticks=[], yticks=[]) +ax1 = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin], xticks=[], yticks=[]) ax2 = ax1.inset_axes([0.5, 0.5, 0.4, 0.4], xticks=[], yticks=[]) -plt.savefig("../figures/layout-inset.pdf") +fig.savefig(ROOT_DIR / "figures/layout-inset.pdf") fig.clear() # Axes divider # ----------------------------------------------------------------------------- -from mpl_toolkits.axes_grid1 import make_axes_locatable margin = 0.0125 -ax = fig.add_axes([margin,margin,1-2*margin,1-2*margin], xticks=[], yticks=[]) +ax = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin], xticks=[], yticks=[]) divider = make_axes_locatable(ax) cax = divider.new_horizontal(size="10%", pad=0.025) fig.add_axes(cax) cax.set_xticks([]), cax.set_yticks([]) -plt.savefig("../figures/layout-divider.pdf") +fig.savefig(ROOT_DIR / "figures/layout-divider.pdf") diff --git a/scripts/legend.py b/scripts/legend.py index 32f01ed..5faf885 100644 --- a/scripts/legend.py +++ b/scripts/legend.py @@ -2,49 +2,67 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(4,4)) -ax = fig.add_axes([0.15,0.15,.7,.7], frameon=True, aspect=1, - xticks=[], yticks=[]) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', +]) +mpl.rc('font', size=6) +mpl.rc('lines', markersize=4) + + +subplots_kw = dict( + figsize=(5.7/2.54, 5.7/2.54), + subplot_kw=dict( + aspect=1, frameon=True, + xlim=(0, 1), ylim=(0, 1), + xticks=[], yticks=[], + ), +) + +(fig, ax) = plt.subplots(**subplots_kw) + def text(x, y, _text): color= "C1" - if not 0 < x < 1 or not 0 < y < 1: color = "C0" + if not 0 < x < 1 or not 0 < y < 1: color = "C0" size = 0.15 - ax.text(x, y, _text, color="white", #bbox={"color": "C1"}, + ax.text(x, y, _text, color="white", # bbox={"color": "C1"}, size="xx-large", weight="bold", ha="center", va="center") rect = plt.Rectangle((x-size/2, y-size/2), size, size, facecolor=color, zorder=-10, clip_on=False) ax.add_patch(rect) + def point(x, y): ax.scatter([x], [y], facecolor="C0", edgecolor="white", zorder=10, clip_on=False) + d = .1 e = .15/2 -text( d, d, "3"), text( 0.5, d, "8"), text(1-d, d, "4") +text( d, d, "3"), text( 0.5, d, "8"), text(1-d, d, "4") text( d, 0.5, "6"), text( 0.5, 0.5, "10"), text(1-d, 0.5, "7") text( d, 1-d, "2"), text( 0.5, 1-d, "9"), text(1-d, 1-d, "1") -text( -d, 1-d, "A"), text( -d, 0.5, "B"), text( -d, d, "C") +text( -d, 1-d, "A"), text( -d, 0.5, "B"), text( -d, d, "C") point(-d+e, 1-d+e), point(-d+e, 0.5), point(-d+e, d-e), -text( d, -d, "D"), text(0.5, -d, "E"), text( 1-d, -d, "F") +text( d, -d, "D"), text(0.5, -d, "E"), text( 1-d, -d, "F") point(d-e, -d+e), point(0.5, -d+e), point(1-d+e, -d+e), -text(1+d, d, "G"), text(1+d, 0.5, "H"), text( 1+d, 1-d, "I") +text(1+d, d, "G"), text(1+d, 0.5, "H"), text( 1+d, 1-d, "I") point(1+d-e, d-e), point(1+d-e, .5), point(1+d-e, 1-d+e), text(1-d, 1+d, "J"), text(0.5, 1+d, "K"), text( d, 1+d, "L") point(1-d+e, 1+d-e), point(0.5, 1+d-e), point(d-e, 1+d-e), -plt.xlim(0,1), plt.ylim(0,1) - -plt.savefig("../figures/legend-placement.pdf") -# plt.show() +fig.savefig(ROOT_DIR / "figures/legend-placement.pdf") diff --git a/scripts/linestyles.py b/scripts/linestyles.py index 7826085..6f9deaa 100644 --- a/scripts/linestyles.py +++ b/scripts/linestyles.py @@ -2,15 +2,20 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib.pyplot as plt -fig = plt.figure(figsize=(4.25,2*.55)) -ax = fig.add_axes([0,0,1,1], xlim=[0.75,10.25], ylim=[0.5,2.5], frameon=False, - xticks=[], yticks=[]) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(4.25, 2*.55)) +ax = fig.add_axes([0, 0, 1, 1], xlim=[0.75, 10.25], ylim=[0.5, 2.5], frameon=False, + xticks=[], yticks=[]) y = 2 + def split(n_segment): width = 9 segment_width = 0.75*(width/n_segment) @@ -23,17 +28,17 @@ def split(n_segment): # Line style # ---------------------------------------------------------------------------- X0, X1 = split(5) -styles = "-", ":", "--", "-.", (0,(0.01,2)) +styles = "-", ":", "--", "-.", (0, (0.01, 2)) -for x0,x1,style in zip(X0,X1,styles): - ax.plot([x0,x1],[y,y], color="C1", linestyle=style, +for x0, x1, style in zip(X0, X1, styles): + ax.plot([x0, x1], [y, y], color="C1", linestyle=style, solid_capstyle="round", dash_capstyle="round", linewidth=3) - if isinstance(style,str): text = '"%s"' % style - else: text = '%s' % str(style) - text = text.replace(' ','') + if isinstance(style, str): text = '"%s"' % style + else: text = '%s' % str(style) + text = text.replace(' ', '') ax.text((x0+x1)/2, y-0.2, text, size=8, ha="center", va="top", family="Source Code Pro") -ax.text(X0[0]-0.25, y+0.2, "linestyle or ls", family = "Source Code Pro", +ax.text(X0[0]-0.25, y+0.2, "linestyle or ls", family="Source Code Pro", size=14, ha="left", va="baseline") y -= 1 @@ -41,16 +46,16 @@ def split(n_segment): # ---------------------------------------------------------------------------- X0, X1 = split(3) styles = "butt", "round", "projecting" -for x0,x1,style in zip(X0,X1,styles): - ax.plot([x0,x1],[y,y], color="C1", dash_capstyle="projecting", +for x0, x1, style in zip(X0, X1, styles): + ax.plot([x0, x1], [y, y], color="C1", dash_capstyle="projecting", linewidth=7, linestyle="--", alpha=.25) - ax.plot([x0,x1],[y,y], color="C1", linewidth=7, + ax.plot([x0, x1], [y, y], color="C1", linewidth=7, linestyle="--", dash_capstyle=style) - ax.text((x0+x1)/2, y-0.2, '"%s"' % style, family = "Source Code Pro", + ax.text((x0+x1)/2, y-0.2, '"%s"' % style, family="Source Code Pro", size=10, ha="center", va="top") -ax.text(X0[0]-0.25, y+0.2, "capstyle or dash_capstyle", family = "Source Code Pro", +ax.text(X0[0]-0.25, y+0.2, "capstyle or dash_capstyle", family="Source Code Pro", size=14, ha="left", va="baseline") -plt.savefig("../figures/linestyles.pdf", dpi=200) +fig.savefig(ROOT_DIR / "figures/linestyles.pdf", dpi=200) # plt.show() diff --git a/scripts/markers.py b/scripts/markers.py index d4ce894..0780d12 100644 --- a/scripts/markers.py +++ b/scripts/markers.py @@ -2,36 +2,39 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib.pyplot as plt +ROOT_DIR = pathlib.Path(__file__).parent.parent + # Markers # ----------------------------------------------------------------------------- -fig = plt.figure(figsize=(3.5,1.5)) -ax = fig.add_axes([0,0,1,1], frameon=False, - xlim=[0.5,10.5], ylim=[0.0,4.35], xticks=[], yticks=[]) -X = np.linspace(1,10,12) -Y = np.arange(1,4) -X, Y = np.meshgrid(X,Y) -X ,Y = X.ravel(), Y.ravel() +fig = plt.figure(figsize=(3.5, 1.5)) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, + xlim=[0.5, 10.5], ylim=[0.0, 4.35], xticks=[], yticks=[]) +X = np.linspace(1, 10, 12) +Y = np.arange(1, 4) +X, Y = np.meshgrid(X, Y) +X , Y = X.ravel(), Y.ravel() plt.scatter(X, 1+Y, s=256, marker="s", fc="C1", ec="none", alpha=.25) markers = [ - "$♠$", "$♣$", "$♥$","$♦$", "$→$","$←$","$↑$","$↓$", "$◐$","$◑$","$◒$","$◓$", + "$♠$", "$♣$", "$♥$", "$♦$", "$→$", "$←$", "$↑$", "$↓$", "$◐$", "$◑$", "$◒$", "$◓$", "1", "2", "3", "4", "+", "x", "|", "_", 4, 5, 6, 7, ".", "o", "s", "P", "X", "*", "p", "D", "<", ">", "^", "v", ] -for x,y,marker in zip(X,Y,markers): - if y == 3: fc = "white" - elif y == 2: fc = "None" - else: fc = "C1" +for x, y, marker in zip(X, Y, markers): + if y == 3: fc = "white" + else: fc = "C1" plt.scatter(x, 1+y, s=100, marker=marker, fc=fc, ec="C1", lw=0.5) if y == 1: marker = "\$%s\$" % marker - if isinstance(marker,str): text = "'%s'" % marker - else: text = '%s' % marker + if isinstance(marker, str): text = "'%s'" % marker + else: text = '%s' % marker plt.text(x, 1+y-0.4, text, - size="x-small", ha="center", va="top", family="Monospace") + size="x-small", ha="center", va="top", family="Monospace") # Spacing @@ -40,9 +43,9 @@ segment_width = 0.75*(width/n_segment) segment_pad = (width - n_segment*segment_width)/(n_segment-1) X0 = 1+np.arange(n_segment)*(segment_width+segment_pad) -marks = [ 10, [0,-1], (25, 5), [0,25,-1] ] +marks = [ 10, [0, -1], (25, 5), [0, 25, -1] ] y = .6 -for x0, mark in zip(X0,marks): +for x0, mark in zip(X0, marks): X = np.linspace(x0, x0+segment_width, 50) Y = y*np.ones(len(X)) ax.plot(X, Y, linewidth=1, color="black", @@ -52,4 +55,4 @@ plt.text(.7, 1, "markevery", size="medium", ha="left", va="center", family="Source Code Pro") -plt.savefig("../figures/markers.pdf", dpi=600) +fig.savefig(ROOT_DIR / "figures/markers.pdf", dpi=600) diff --git a/scripts/performance-tips.py b/scripts/performance-tips.py index 0094a1b..adbfaa1 100644 --- a/scripts/performance-tips.py +++ b/scripts/performance-tips.py @@ -11,8 +11,8 @@ n = 10_000_000 np.random.seed(1) -X = np.random.uniform(0,1,n) -Y = np.random.uniform(0,1,n) +X = np.random.uniform(0, 1, n) +Y = np.random.uniform(0, 1, n) start = time.perf_counter() ax.plot(X, Y, marker="o", ls="") @@ -32,8 +32,8 @@ np.random.seed(1) X = [] for i in range(n): - X.append(np.random.uniform(0,1,10)) -#np.random.uniform(0,1,n) + X.append(np.random.uniform(0, 1, 10)) +# np.random.uniform(0,1,n) # Y = np.random.uniform(0,1,n) start = time.perf_counter() @@ -45,7 +45,7 @@ ax.clear() start = time.perf_counter() -ax.plot(sum([list(x)+[None] for x in X],[])) +ax.plot(sum([list(x)+[None] for x in X], [])) # X0,Y0 = X[0::2], Y[0::2] # X1,Y1 = X[1::2], Y[1::2] # S = [None]*len(X) diff --git a/scripts/plot-variations.py b/scripts/plot-variations.py index bbcb9a1..65b9ff1 100644 --- a/scripts/plot-variations.py +++ b/scripts/plot-variations.py @@ -2,150 +2,131 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib # Scripts to generate all the basic plots import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(0.4,0.4)) -mpl.rcParams['axes.linewidth'] = 0.5 -mpl.rcParams['xtick.major.size'] = 0.0 -mpl.rcParams['ytick.major.size'] = 0.0 -d = 0.01 + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet.mplstyle', +]) +mpl.rc('axes', titlepad=1) + + +subplot_kw = dict( + xlim=(0, 8), xticks=np.arange(1, 8), + ylim=(0, 8), yticks=np.arange(1, 8), +) # Basic line plot (color) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,1-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 4+2*np.sin(2*X) ax.plot(X, Y, color="black", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/plot-color.pdf") -fig.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/plot-color.pdf") # Basic line plot (linestyle) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,1-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 4+2*np.sin(2*X) ax.plot(X, Y, color="C1", linewidth=0.75, linestyle="--") -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/plot-linestyle.pdf") -fig.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/plot-linestyle.pdf") # Basic line plot (linewidth) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,1-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 4+2*np.sin(2*X) ax.plot(X, Y, color="C1", linewidth=1.5) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/plot-linewidth.pdf") -fig.clear() +ax.grid() +fig.savefig("../figures/plot-linewidth.pdf") +fig.savefig(ROOT_DIR / "figures/plot-linewidth.pdf") # Basic line plot (marker) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,1-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 4+2*np.sin(2*X) ax.plot(X, Y, color="C1", linewidth=0.75, marker="o", markevery=5, markersize=2) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/plot-marker.pdf") -fig.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/plot-marker.pdf") # Basic line plot (multi) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,1-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y1 = 4+2*np.sin(2*X) Y2 = 4+2*np.cos(2*X) ax.plot(X, Y1, color="C1", linewidth=0.75) ax.plot(X, Y2, color="C0", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 8), ax.set_yticks(np.arange(1,8)) -ax.grid(linewidth=0.125) -plt.savefig("../figures/plot-multi.pdf") -fig.clear() +ax.grid() +fig.savefig(ROOT_DIR / "figures/plot-multi.pdf") # Basic line plot (vsplit) # ----------------------------------------------------------------------------- -ax1 = fig.add_axes([d, d, 1-2*d,.45-d]) -ax2 = fig.add_axes([d, .55-d, 1-2*d,.45-d]) +(fig, [ax2, ax1]) = plt.subplots(nrows=2, gridspec_kw=dict(hspace=0.2), subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y1 = 2+1*np.sin(2*X) ax1.plot(X, Y1, color="C1", linewidth=0.75) -ax1.set_xlim(0, 8), ax1.set_xticks(np.arange(1,8)), ax1.set_xticklabels([]) -ax1.set_ylim(0, 4), ax1.set_yticks(np.arange(1,4)), ax1.set_yticklabels([]) -ax1.grid(linewidth=0.125) -ax1.tick_params(axis=u'both', which=u'both',length=0) +ax1.set_ylim(0, 4), ax1.set_yticks(np.arange(1, 4)) +ax1.grid() +ax1.tick_params(axis=u'both', which=u'both', length=0) Y2 = 2+1*np.cos(2*X) ax2.plot(X, Y2, color="C0", linewidth=0.75) -ax2.set_xlim(0, 8), ax2.set_xticks(np.arange(1,8)), ax2.set_xticklabels([]) -ax2.set_ylim(0, 4), ax2.set_yticks(np.arange(1,4)), ax2.set_yticklabels([]) -ax2.grid(linewidth=0.125) -ax2.tick_params(axis=u'both', which=u'both',length=0) -plt.savefig("../figures/plot-vsplit.pdf") -fig.clear() +ax2.set_ylim(0, 4), ax2.set_yticks(np.arange(1, 4)) +ax2.grid() +ax2.tick_params(axis=u'both', which=u'both', length=0) +fig.savefig(ROOT_DIR / "figures/plot-vsplit.pdf") # Basic line plot (hsplit) # ----------------------------------------------------------------------------- -ax1 = fig.add_axes([d, d, .45-d, 1-2*d]) -ax2 = fig.add_axes([.55-d, d, .45-d, 1-2*d]) +(fig, [ax1, ax2]) = plt.subplots(ncols=2, gridspec_kw=dict(wspace=0.2), subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y1 = 2+1*np.sin(2*X) ax1.plot(Y1, X, color="C1", linewidth=0.75) -ax1.set_xlim(0, 4), ax1.set_xticks(np.arange(1,4)), ax1.set_xticklabels([]) -ax1.set_ylim(0, 8), ax1.set_yticks(np.arange(1,8)), ax1.set_yticklabels([]) -ax1.grid(linewidth=0.125) -ax1.tick_params(axis=u'both', which=u'both',length=0) +ax1.set_xlim(0, 4), ax1.set_xticks(np.arange(1, 4)) +ax1.grid() +ax1.tick_params(axis=u'both', which=u'both', length=0) Y2 = 2+1*np.cos(2*X) ax2.plot(Y2, X, color="C0", linewidth=0.75) -ax2.set_xlim(0, 4), ax2.set_xticks(np.arange(1,4)), ax2.set_xticklabels([]) -ax2.set_ylim(0, 8), ax2.set_yticks(np.arange(1,8)), ax2.set_yticklabels([]) -ax2.grid(linewidth=0.125) -ax2.tick_params(axis=u'both', which=u'both',length=0) -plt.savefig("../figures/plot-hsplit.pdf") -fig.clear() +ax2.set_xlim(0, 4), ax2.set_xticks(np.arange(1, 4)) +ax2.grid() +ax2.tick_params(axis=u'both', which=u'both', length=0) +fig.savefig(ROOT_DIR / "figures/plot-hsplit.pdf") # Basic line plot (title) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,d,1-2*d,.8-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 3+2*np.sin(2*X) ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)) -ax.set_ylim(0, 6), ax.set_yticks(np.arange(1,6)) -ax.grid(linewidth=0.125) -ax.text(4, 6.75, "A Sine wave", transform=ax.transData, clip_on=False, - weight="bold", size=4, ha="center", va="center") -plt.savefig("../figures/plot-title.pdf") -fig.clear() - +ax.set_ylim(0, 6), ax.set_yticks(np.arange(1, 6)) +ax.grid() +ax.set_title("A Sine wave", size=4, weight="bold") +fig.savefig(ROOT_DIR / "figures/plot-title.pdf") # Basic line plot (xlabel) # ----------------------------------------------------------------------------- -ax = fig.add_axes([d,.2-d,1-2*d,.8-2*d]) +(fig, ax) = plt.subplots(subplot_kw=subplot_kw) X = np.linspace(0, 10, 100) Y = 3+2*np.sin(2*X) -ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_xlim(0, 8), ax.set_xticks(np.arange(1,8)), ax.set_xticklabels([]) -ax.set_ylim(0, 6), ax.set_yticks(np.arange(1,6)), ax.set_yticklabels([]) -ax.grid(linewidth=0.125) +ax.plot(X, Y, color="C1", linewidth=0.75), ax.set_xticklabels([]) +ax.set_ylim(0, 6), ax.set_yticks(np.arange(1, 6)), ax.set_yticklabels([]) +ax.grid() ax.text(4, -1, "Time", transform=ax.transData, clip_on=False, size=3.5, ha="center", va="center") -# plt.show() -plt.savefig("../figures/plot-xlabel.pdf") -fig.clear() +fig.savefig(ROOT_DIR / "figures/plot-xlabel.pdf") diff --git a/scripts/projections.py b/scripts/projections.py index f659ff1..1f623a9 100644 --- a/scripts/projections.py +++ b/scripts/projections.py @@ -2,12 +2,21 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import cartopy import matplotlib as mpl import matplotlib.pyplot as plt +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/plotlet.mplstyle', +]) + CARTOPY_SOURCE_TEMPLATE = 'https://naturalearth.s3.amazonaws.com/%7Bresolution%7D_%7Bcategory%7D/ne_%7Bresolution%7D_%7Bname%7D.zip' @@ -15,32 +24,28 @@ # Taken from https://github.com/SciTools/cartopy/issues/1325#issuecomment-904343657 target_path_template = cartopy.io.shapereader.NEShpDownloader.default_downloader().target_path_template downloader = cartopy.io.shapereader.NEShpDownloader(url_template=CARTOPY_SOURCE_TEMPLATE, - target_path_template=target_path_template) + target_path_template=target_path_template) cartopy.config['downloaders'][('shapefiles', 'natural_earth')] = downloader # Polar plot # ----------------------------------------------------------------------------- -mpl.rc('axes', linewidth=4.0) -fig = plt.figure(figsize=(4,4)) -b = 0.025 -ax = fig.add_axes([b,b,1-2*b,1-2*b], projection="polar") +(fig, ax) = plt.subplots(subplot_kw={'projection': 'polar'}) T = np.linspace(0, 3*2*np.pi, 500) R = np.linspace(0, 2, len(T)) -ax.plot(T, R, color="C1", linewidth=6) +ax.plot(T, R, color="C1") ax.set_xticks(np.linspace(0, 2*np.pi, 2*8)) ax.set_xticklabels([]) ax.set_yticks(np.linspace(0, 2, 8)) ax.set_yticklabels([]) -ax.set_ylim(0,2) -ax.grid(linewidth=1) -plt.savefig("../figures/projection-polar.pdf") +ax.set_ylim(0, 2) +ax.grid(linewidth=0.2) +fig.savefig(ROOT_DIR / "figures/projection-polar.pdf") fig.clear() # 3D plot # ----------------------------------------------------------------------------- -mpl.rc('axes', linewidth=2.0) -ax = fig.add_axes([0,.1,1,.9], projection="3d") +(fig, ax) = plt.subplots(subplot_kw={'projection': '3d'}) r = np.linspace(0, 1.25, 50) p = np.linspace(0, 2*np.pi, 50) R, P = np.meshgrid(r, p) @@ -53,15 +58,14 @@ ax.set_xticks([]) ax.set_yticks([]) ax.set_zticks([]) -plt.savefig("../figures/projection-3d.pdf") +fig.savefig(ROOT_DIR / "figures/projection-3d.pdf") fig.clear() # Cartopy plot # ----------------------------------------------------------------------------- -mpl.rc('axes', linewidth=3.0) -b = 0.025 -ax = fig.add_axes([b,b,1-2*b,1-2*b], frameon=False, - projection=cartopy.crs.Orthographic()) +fig = plt.figure() +ax = fig.add_subplot(frameon=False, + projection=cartopy.crs.Orthographic()) ax.add_feature(cartopy.feature.LAND, zorder=0, facecolor="C1", edgecolor="0.0", linewidth=0) -plt.savefig("../figures/projection-cartopy.pdf") +fig.savefig(ROOT_DIR / "figures/projection-cartopy.pdf") diff --git a/scripts/scales.py b/scripts/scales.py index 508bb4c..70192ca 100644 --- a/scripts/scales.py +++ b/scripts/scales.py @@ -1,11 +1,16 @@ +import pathlib + import numpy as np import matplotlib.pyplot as plt -fig = plt.figure(figsize=(0.4,2/3*0.4)) -ax = fig.add_axes([0,0,1,1], frameon=False) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(0.4, 2/3*0.4)) +ax = fig.add_axes([0, 0, 1, 1], frameon=False) ax.tick_params(axis='both', which='both', length=0) -ax.set_xlim(-2,2) -X = np.linspace(-2,+2,1001) +ax.set_xlim(-2, 2) +X = np.linspace(-2, +2, 1001) Y = np.sin(X*2.5*2*np.pi) @@ -14,46 +19,46 @@ ax.set_xlim(X.min(), X.max()) ax.set_xscale("linear") ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_ylim(-2.5,1.5) +ax.set_ylim(-2.5, 1.5) ax.text(0, 0.12, "-∞", ha="left", va="bottom", size=3, transform=ax.transAxes) -ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) +ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) -ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) -plt.savefig("../figures/scale-linear.pdf") +ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) +fig.savefig(ROOT_DIR / "figures/scale-linear.pdf") ax.clear() # Log scale # ----------------------------------------------------------------------------- ax.set_xscale("log", base=10) ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_ylim(-2.5,1.5) +ax.set_ylim(-2.5, 1.5) ax.text(0, 0.12, "0", ha="left", va="bottom", size=3, transform=ax.transAxes) -ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) +ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) -ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) -plt.savefig("../figures/scale-log.pdf") +ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) +fig.savefig(ROOT_DIR / "figures/scale-log.pdf") ax.clear() # Symlog scale # ----------------------------------------------------------------------------- ax.set_xscale("symlog", base=10, linthresh=1) ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_ylim(-2.5,1.5) +ax.set_ylim(-2.5, 1.5) ax.text(0, 0.12, "-∞", ha="left", va="bottom", size=3, transform=ax.transAxes) -ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) +ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) ax.text(1, 0.12, "+∞", ha="right", va="bottom", size=3, transform=ax.transAxes) -ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) -plt.savefig("../figures/scale-symlog.pdf") +ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) +fig.savefig(ROOT_DIR / "figures/scale-symlog.pdf") ax.clear() # Symlog scale # ----------------------------------------------------------------------------- ax.set_xscale("logit") ax.plot(X, Y, color="C1", linewidth=0.75) -ax.set_ylim(-2.5,1.5) +ax.set_ylim(-2.5, 1.5) ax.text(0, 0.12, "0", ha="left", va="bottom", size=3, transform=ax.transAxes) -ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) +ax.text(0, 0.15, "⇤", ha="left", va="top", size=4, transform=ax.transAxes) ax.text(1, 0.12, "1", ha="right", va="bottom", size=3, transform=ax.transAxes) -ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) -plt.savefig("../figures/scale-logit.pdf") +ax.text(1, 0.15, "⇥", ha="right", va="top", size=4, transform=ax.transAxes) +fig.savefig(ROOT_DIR / "figures/scale-logit.pdf") ax.clear() diff --git a/scripts/sine.py b/scripts/sine.py index bf39a71..6307629 100644 --- a/scripts/sine.py +++ b/scripts/sine.py @@ -2,71 +2,75 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np +import matplotlib as mpl import matplotlib.pyplot as plt -X = np.linspace(0.1, 10*np.pi, 10000) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/sine-plot.mplstyle', +]) + +X = np.linspace(0, 10*np.pi, 1000) Y = np.sin(X) -fig = plt.figure(figsize=(8,2)) -plt.plot(X, Y, color="orange", linewidth=2) -# plt.xticks([]), plt.yticks([]) -plt.tight_layout() -plt.savefig("../figures/sine.pdf", dpi=100) -fig = plt.figure(figsize=(7,1.5)) -plt.plot(X, Y, "C1o:", markevery=500, mec="1.0", lw=2, ms=8.5, mew=2) -# plt.xticks([]), plt.yticks([]) -plt.ylim(-1.5, 1.5) -plt.tight_layout() -plt.savefig("../figures/sine-marker.pdf", dpi=100) +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.2/2.54)) +ax.set_yticks(np.linspace(-1, 1, 5)) +ax.plot(X, Y, color="C1") +fig.savefig(ROOT_DIR / "figures/sine.pdf") + + +X = np.linspace(0.1, 10*np.pi, 1000) +Y = np.sin(X) + -fig, ax = plt.subplots(figsize=(7,1.5)) +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) +ax.plot(X, Y, "C1o:", markevery=50, mec="1.0") +ax.set_ylim(-1.5, 1.5) +fig.savefig(ROOT_DIR / "figures/sine-marker.pdf") + + +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) ax.set_xscale("log") -ax.plot(X, Y, "-") -plt.plot(X, Y, "C1o-", markevery=500, mec="1.0", lw=2, ms=8.5, mew=2) -#plt.xticks([]), plt.yticks([]) -plt.ylim(-1.5, 1.5) -plt.tight_layout() -plt.savefig("../figures/sine-logscale.pdf", dpi=100) - - -fig = plt.figure(figsize=(7,1.5)) -plt.plot(X, Y, "C1", lw=2) -plt.fill_betweenx([-1.5,1.5],[0],[2*np.pi], color=".9") -plt.text(0, -1, r" Period $\Phi$") -# plt.xticks([]), plt.yticks([]) -plt.ylim(-1.5, 1.5) -plt.tight_layout() -plt.savefig("../figures/sine-period.pdf", dpi=100) -# plt.show() - - -fig = plt.figure(figsize=(7,1.5)) -plt.plot(X, np.sin(X), "C0", lw=2, label="Sine") -plt.plot(X, np.cos(X), "C1", lw=2, label="Cosine") -plt.legend(bbox_to_anchor = (0.0, .9, 1.02, 0.1), - frameon=False, mode="expand", ncol=2, loc="lower left") -plt.title("Sine and Cosine") -plt.xticks([]), plt.yticks([]) -plt.ylim(-1.25, 1.25) -plt.tight_layout() -plt.savefig("../figures/sine-legend.pdf", dpi=100) -# plt.show() - - -fig = plt.figure(figsize=(7,1.5)) +ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") +ax.set_ylim(-1.5, 1.5) +fig.savefig(ROOT_DIR / "figures/sine-logscale.pdf") + + +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) +ax.plot(X, Y, "C1") +ax.fill_betweenx([-1.5, 1.5], [0], [2*np.pi], color=".9") +ax.text(0, -1, r" Period $\Phi$", va="top") +ax.set_ylim(-1.5, 1.5) +fig.savefig(ROOT_DIR / "figures/sine-period.pdf") + + +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) +ax.plot(X, np.sin(X), "C0", label="Sine") +ax.plot(X, np.cos(X), "C1", label="Cosine") +ax.legend(bbox_to_anchor=(0.0, .9, 1.02, 0.1), + frameon=False, mode="expand", ncol=2, loc="lower left") +ax.set_title("Sine and Cosine") +ax.set_xticks([]), ax.set_yticks([]) +ax.set_ylim(-1.25, 1.25) +fig.savefig(ROOT_DIR / "figures/sine-legend.pdf") + + +fig, ax = plt.subplots(figsize=(5.7/2.54, 1.0/2.54)) X = np.linspace(0, 10*np.pi, 1000) Y = np.sin(X) -plt.plot(X, Y, "C1o-", markevery=50, mec="1.0", lw=2, ms=8.5, mew=2) -# plt.xticks([]), plt.yticks([]) -plt.ylim(-1.5, 1.5) -plt.annotate(" ", (X[200],Y[200]), (X[250], -1), ha="center", va="center", - arrowprops = {"arrowstyle" : "->", "color": "C1"}) -plt.annotate("A", (X[250],Y[250]), (X[250], -1), ha="center", va="center", - arrowprops = {"arrowstyle" : "->", "color": "C1"}) -plt.annotate(" ", (X[300],Y[300]), (X[250], -1), ha="center", va="center", - arrowprops = {"arrowstyle" : "->", "color": "C1"}) -plt.tight_layout() -plt.savefig("../figures/sine-annotate.pdf", dpi=100) -# plt.show() +ax.plot(X, Y, "C1o-", markevery=50, mec="1.0") +ax.set_ylim(-1.5, 1.5) +ax.annotate(" ", (X[200], Y[200]), (X[250], -1), ha="center", va="center", + arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) +ax.annotate("A", (X[250], Y[250]), (X[250], -1), ha="center", va="center", + arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) +ax.annotate(" ", (X[300], Y[300]), (X[250], -1), ha="center", va="center", + arrowprops=dict(arrowstyle="->", color="C1", linewidth=0.5, patchA=None, shrinkA=4, shrinkB=0.5)) +fig.savefig(ROOT_DIR / "figures/sine-annotate.pdf") diff --git a/scripts/styles.py b/scripts/styles.py index bf5109a..bedf9d9 100644 --- a/scripts/styles.py +++ b/scripts/styles.py @@ -2,18 +2,23 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt + +ROOT_DIR = pathlib.Path(__file__).parent.parent + for style in ['default'] + plt.style.available: with plt.style.context(style): - fig = plt.figure(figsize=(5,3), dpi=100) - ax = plt.subplot(1,1,1) - X = np.linspace(0,2*np.pi, 256) + fig = plt.figure(figsize=(5, 3), dpi=100) + ax = plt.subplot(1, 1, 1) + X = np.linspace(0, 2*np.pi, 256) Y = np.cos(X) - ax.plot(X,Y) + ax.plot(X, Y) plt.title(style, family="Source Serif Pro", size=32) plt.tight_layout() - plt.savefig("../figures/style-%s.pdf" % style) + fig.savefig(ROOT_DIR / f"figures/style-{style}.pdf") plt.close(fig) diff --git a/scripts/text-alignments.py b/scripts/text-alignments.py index 2470ab7..0d653b9 100644 --- a/scripts/text-alignments.py +++ b/scripts/text-alignments.py @@ -2,13 +2,18 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib.pyplot as plt + +ROOT_DIR = pathlib.Path(__file__).parent.parent + dpi = 100 fig = plt.figure(figsize=(4.25, 1.5), dpi=dpi) -ax = fig.add_axes([0,0,1,1], frameon=False, - xlim=(0,4.25), ylim=(0,1.5), xticks=[], yticks=[]) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, + xlim=(0, 4.25), ylim=(0, 1.5), xticks=[], yticks=[]) fontsize = 48 renderer = fig.canvas.get_renderer() @@ -37,16 +42,16 @@ text.set_position(position) -for name,y in yoffset.items(): +for name, y in yoffset.items(): y = position[1] - y + yoffset[verticalalignment] plt.plot([0.1, 3.75], [y, y], linewidth=0.5, color=color) plt.text(3.75, y, " "+name, color=color, ha="left", va="center", size="x-small") -for name,x in xoffset.items(): +for name, x in xoffset.items(): x = position[0] - x + xoffset[horizontalalignment] - plt.plot([x,x], [0.25, 1.25], linewidth=0.5, color=color) - plt.text(x, 0.24, name, color = color, + plt.plot([x, x], [0.25, 1.25], linewidth=0.5, color=color) + plt.text(x, 0.24, name, color=color, ha="center", va="top", size="x-small") P = [] @@ -54,17 +59,17 @@ x = position[0] - x + xoffset[horizontalalignment] for y in yoffset.values(): y = position[1] - y + yoffset[verticalalignment] - P.append((x,y)) + P.append((x, y)) P = np.array(P) -ax.scatter(P[:,0], P[:,1], s=10, zorder=10, +ax.scatter(P[:, 0], P[:, 1], s=10, zorder=10, facecolor="white", edgecolor=color, linewidth=0.75) epsilon = 0.05 -plt.text(P[3,0]+epsilon, P[3,1]-epsilon, "(0,0)", +plt.text(P[3, 0]+epsilon, P[3, 1]-epsilon, "(0,0)", color=color, ha="left", va="top", size="x-small") -plt.text(P[8,0]-epsilon, P[8,1]+epsilon, "(1,1)", +plt.text(P[8, 0]-epsilon, P[8, 1]+epsilon, "(1,1)", color=color, ha="right", va="bottom", size="x-small") -plt.savefig("../figures/text-alignments.pdf") +fig.savefig(ROOT_DIR / "figures/text-alignments.pdf") # plt.show() diff --git a/scripts/tick-formatters.py b/scripts/tick-formatters.py index 3df9ee7..bcdce04 100644 --- a/scripts/tick-formatters.py +++ b/scripts/tick-formatters.py @@ -3,12 +3,18 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- -import numpy as np +import pathlib + import matplotlib.pyplot as plt import matplotlib.ticker as ticker + +ROOT_DIR = pathlib.Path(__file__).parent.parent + + # Setup a plot such that only the bottom spine is shown def setup(ax): + """Set up Axes with just an x-Axis.""" ax.spines['right'].set_color('none') ax.spines['left'].set_color('none') ax.yaxis.set_major_locator(ticker.NullLocator()) @@ -41,20 +47,18 @@ def setup(ax): # Fixed formatter ax = fig.add_subplot(n, 1, 2) setup(ax) -ax.xaxis.set_major_locator(ticker.MultipleLocator(1.0)) ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.25)) -majors = ["", "0", "1", "2", "3", "4", "5"] +ax.xaxis.set_major_locator(ticker.FixedLocator(range(6))) +majors = ["zero", "one", "two", "three", "four", "five"] ax.xaxis.set_major_formatter(ticker.FixedFormatter(majors)) -minors = [""] + ["%.2f" % (x-int(x)) if (x-int(x)) - else "" for x in np.arange(0, 5, 0.25)] -ax.xaxis.set_minor_formatter(ticker.FixedFormatter(minors)) -ax.text(0.0, 0.1, "ticker.FixedFormatter(['', '0', '1', ...])", +ax.text(0.0, 0.1, "ticker.FixedFormatter(['zero', 'one', 'two', …])", family=family, fontsize=fontsize, transform=ax.transAxes) # FuncFormatter can be used as a decorator @ticker.FuncFormatter def major_formatter(x, pos): + """Return formatted value with 2 decimal places.""" return "[%.2f]" % x @@ -107,5 +111,5 @@ def major_formatter(x, pos): # bottom spine. fig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05) -plt.savefig("../figures/tick-formatters.pdf", transparent=True) +fig.savefig(ROOT_DIR / "figures/tick-formatters.pdf", transparent=True) # plt.show() diff --git a/scripts/tick-locators.py b/scripts/tick-locators.py index 6803738..4c0985c 100644 --- a/scripts/tick-locators.py +++ b/scripts/tick-locators.py @@ -3,10 +3,16 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as ticker + +ROOT_DIR = pathlib.Path(__file__).parent.parent + + # Setup a plot such that only the bottom spine is shown def setup(ax): ax.spines['right'].set_color('none') @@ -101,5 +107,5 @@ def setup(ax): # bottom spine. plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05) -plt.savefig("../figures/tick-locators.pdf", transparent=True) +fig.savefig(ROOT_DIR / "figures/tick-locators.pdf", transparent=True) # plt.show() diff --git a/scripts/tick-multiple-locator.py b/scripts/tick-multiple-locator.py index 51110ff..2976a63 100644 --- a/scripts/tick-multiple-locator.py +++ b/scripts/tick-multiple-locator.py @@ -3,49 +3,33 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np +import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.ticker as ticker -# Setup a plot such that only the bottom spine is shown -def setup(ax): - ax.spines['right'].set_color('none') - ax.spines['left'].set_color('none') - ax.yaxis.set_major_locator(ticker.NullLocator()) - ax.spines['top'].set_color('none') - - ax.spines['bottom'].set_position("center") - - ax.xaxis.set_ticks_position('bottom') - ax.tick_params(which='major', width=1.00) - ax.tick_params(which='major', length=5) - ax.tick_params(which='minor', width=0.75) - ax.tick_params(which='minor', length=2.5) - ax.set_xlim(0, 5) - ax.set_ylim(0, 1) - ax.patch.set_alpha(0.0) +ROOT_DIR = pathlib.Path(__file__).parent.parent -fig = plt.figure(figsize=(5, .5)) -fig.patch.set_alpha(0.0) -n = 1 +mpl.style.use([ + ROOT_DIR / 'styles/base.mplstyle', + ROOT_DIR / 'styles/ticks.mplstyle', +]) -fontsize = 18 -family = "Source Code Pro" -# Null Locator -ax = plt.subplot(n, 1, 1) -# ax.tick_params(axis='both', which='major', -# labelsize=10, family="Roboto Condensed") -ax.tick_params(axis='both', which='minor', labelsize=6) +subplots_kw = dict( + figsize=(5.7/2.54, 0.4/2.54), + subplot_kw=dict(xlim=(0, 5), ylim=(0, 1)), +) -setup(ax) +(fig, ax) = plt.subplots(**subplots_kw) ax.xaxis.set_major_locator(ticker.MultipleLocator(1.0)) ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.2)) ax.xaxis.set_major_formatter(ticker.ScalarFormatter()) ax.xaxis.set_minor_formatter(ticker.ScalarFormatter()) +ax.tick_params(axis='both', which='major', labelsize=5) ax.tick_params(axis='x', which='minor', rotation=90) -plt.tight_layout() -plt.savefig("../figures/tick-multiple-locator.pdf", transparent=True) -# plt.show() +fig.savefig(ROOT_DIR / "figures/tick-multiple-locator.pdf", transparent=True) diff --git a/scripts/tip-color-range.py b/scripts/tip-color-range.py index 01d0c7e..5743940 100644 --- a/scripts/tip-color-range.py +++ b/scripts/tip-color-range.py @@ -4,21 +4,26 @@ # ----------------------------------------------------------------------------- # Scripts to generate all the basic plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(2,2)) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(2, 2)) mpl.rcParams['axes.linewidth'] = 1.5 d = 0.01 -ax = fig.add_axes([d,d,1-2*d,1-2*d], xticks=[], yticks=[]) +ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) X = np.random.seed(1) X = np.random.randn(1000, 4) cmap = plt.get_cmap("Oranges") -colors = [cmap(i) for i in [.1,.3,.5,.7]] +colors = [cmap(i) for i in [.1, .3, .5, .7]] ax.hist(X, 2, density=True, histtype='bar', color=colors) -plt.savefig("../figures/tip-color-range.pdf") +fig.savefig(ROOT_DIR / "figures/tip-color-range.pdf") # plt.show() diff --git a/scripts/tip-colorbar.py b/scripts/tip-colorbar.py index 5e7bf50..9e8da79 100644 --- a/scripts/tip-colorbar.py +++ b/scripts/tip-colorbar.py @@ -4,22 +4,27 @@ # ----------------------------------------------------------------------------- # Scripts to generate all the basic plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.patheffects as path_effects -fig = plt.figure(figsize=(2.15,2)) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(2.15, 2)) mpl.rcParams['axes.linewidth'] = 1.5 d = 0.01 -ax = fig.add_axes([d,d,1-2*d,1-2*d], xticks=[], yticks=[]) +ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) np.random.seed(1) -Z = np.random.uniform(0,1,(8,8)) +Z = np.random.uniform(0, 1, (8, 8)) cmap = plt.get_cmap("Oranges") im = ax.imshow(Z, interpolation="nearest", cmap=cmap, vmin=0, vmax=2) cb = fig.colorbar(im, fraction=0.046, pad=0.04) cb.set_ticks([]) -plt.savefig("../figures/tip-colorbar.pdf") +fig.savefig(ROOT_DIR / "figures/tip-colorbar.pdf") # plt.show() diff --git a/scripts/tip-dotted.py b/scripts/tip-dotted.py index f5781aa..8f52a2c 100644 --- a/scripts/tip-dotted.py +++ b/scripts/tip-dotted.py @@ -4,18 +4,24 @@ # ----------------------------------------------------------------------------- # Scripts to generate all the basic plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -fig = plt.figure(figsize=(5,.25)) -ax = fig.add_axes([0,0,1,1], frameon=False, - xticks=[], yticks=[], xlim=[0,1], ylim=[-.5,1.5]) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(5, .25)) + +ax = fig.add_axes([0, 0, 1, 1], frameon=False, + xticks=[], yticks=[], xlim=[0, 1], ylim=[-.5, 1.5]) epsilon=1e-12 -plt.plot([0,1], [0,0], "black", clip_on=False, lw=8, - ls=(.5,(epsilon, 1)), dash_capstyle="round") -plt.plot([0,1], [1,1], "black", clip_on=False, lw=8, - ls=(-.5,(epsilon, 2)), dash_capstyle="round") -plt.savefig("../figures/tip-dotted.pdf") +plt.plot([0, 1], [0, 0], "black", clip_on=False, lw=8, + ls=(.5, (epsilon, 1)), dash_capstyle="round") +plt.plot([0, 1], [1, 1], "black", clip_on=False, lw=8, + ls=(-.5, (epsilon, 2)), dash_capstyle="round") +fig.savefig(ROOT_DIR / "figures/tip-dotted.pdf") # plt.show() diff --git a/scripts/tip-dual-axis.py b/scripts/tip-dual-axis.py index 0d60963..9d72f34 100644 --- a/scripts/tip-dual-axis.py +++ b/scripts/tip-dual-axis.py @@ -1,25 +1,30 @@ +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt -mpl.rcParams['axes.linewidth'] = 1.5 -fig = plt.figure(figsize=(2,2)) +ROOT_DIR = pathlib.Path(__file__).parent.parent + +mpl.rcParams['axes.linewidth'] = 1.5 + +fig = plt.figure(figsize=(2, 2)) d = 0.01 -ax1 = fig.add_axes([d,d,1-2*d,1-2*d], label="cartesian") -ax2 = fig.add_axes([d,d,1-2*d,1-2*d], projection="polar", label="polar") +ax1 = fig.add_axes([d, d, 1-2*d, 1-2*d], label="cartesian") +ax2 = fig.add_axes([d, d, 1-2*d, 1-2*d], projection="polar", label="polar") -ax1.set_xticks([]) #np.linspace(0.0, 0.4, 5)) -ax1.set_yticks([]) #np.linspace(0.0, 1.0, 11)) +ax1.set_xticks([]) # np.linspace(0.0, 0.4, 5)) +ax1.set_yticks([]) # np.linspace(0.0, 1.0, 11)) ax2.set_rorigin(0) ax2.set_thetamax(90) -ax2.set_ylim(0.5,1.0) +ax2.set_ylim(0.5, 1.0) ax2.set_xticks(np.linspace(0, np.pi/2, 10)) ax2.set_yticks(np.linspace(0.5, 1.0, 5)) ax2.set_xticklabels([]) ax2.set_yticklabels([]) -plt.savefig("../figures/tip-dual-axis.pdf") +fig.savefig(ROOT_DIR / "figures/tip-dual-axis.pdf") # plt.show() diff --git a/scripts/tip-font-family.py b/scripts/tip-font-family.py index c98a7dc..53564ac 100644 --- a/scripts/tip-font-family.py +++ b/scripts/tip-font-family.py @@ -3,10 +3,16 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as ticker + +ROOT_DIR = pathlib.Path(__file__).parent.parent + + # Setup a plot such that only the bottom spine is shown def setup(ax): ax.spines['right'].set_color('none') @@ -44,5 +50,5 @@ def setup(ax): tick.set_fontname("Roboto Condensed") plt.tight_layout() -plt.savefig("../figures/tip-font-family.pdf", transparent=True) +fig.savefig(ROOT_DIR / "figures/tip-font-family.pdf", transparent=True) # plt.show() diff --git a/scripts/tip-hatched.py b/scripts/tip-hatched.py index 9e33ae3..f1a38d4 100644 --- a/scripts/tip-hatched.py +++ b/scripts/tip-hatched.py @@ -1,33 +1,38 @@ +import pathlib + import numpy as np import matplotlib.pyplot as plt + +ROOT_DIR = pathlib.Path(__file__).parent.parent + cmap = plt.get_cmap("Oranges") color1, color2 = cmap(0.3), cmap(0.5) plt.rcParams['hatch.color'] = color1 plt.rcParams['hatch.linewidth'] = 8 -fig = plt.figure(figsize=(2,2)) +fig = plt.figure(figsize=(2, 2)) ax = plt.subplot() np.random.seed(123) -x1,y1 = 3*np.arange(2), np.random.randint(25,50,2) -x2,y2 = x1+1, np.random.randint(25,75,2) +x1, y1 = 3*np.arange(2), np.random.randint(25, 50, 2) +x2, y2 = x1+1, np.random.randint(25, 75, 2) ax.bar(x1, y1, color=color2) -for i in range(len(x1)): - plt.annotate("%d%%" % y1[i], (x1[i], y1[i]), xytext=(0,1), +for x, y in zip(x1, y1): + plt.annotate(f"{y:d}%", (x, y), xytext=(0, 1), fontsize="x-small", color=color2, textcoords="offset points", va="bottom", ha="center") ax.bar(x2, y2, color=color2, hatch="/" ) -for i in range(len(x2)): - plt.annotate("%d%%" % y2[i], (x2[i], y2[i]), xytext=(0,1), +for x, y in zip(x2, y2): + plt.annotate(f"{y:d}%", (x, y), xytext=(0, 1), fontsize="x-small", color=color2, textcoords="offset points", va="bottom", ha="center") ax.set_yticks([]) -ax.set_xticks(0.5+np.arange(0,6,3)) +ax.set_xticks(0.5+np.arange(0, 6, 3)) ax.set_xticklabels(["2018", "2019"]) ax.tick_params('x', length=0, labelsize="small", which='major') @@ -36,5 +41,5 @@ ax.spines['top'].set_visible(False) plt.tight_layout() -plt.savefig("../figures/tip-hatched.pdf") +fig.savefig(ROOT_DIR / "figures/tip-hatched.pdf") # plt.show() diff --git a/scripts/tip-multiline.py b/scripts/tip-multiline.py index 06c1dbf..99d704c 100644 --- a/scripts/tip-multiline.py +++ b/scripts/tip-multiline.py @@ -2,17 +2,23 @@ # Author: Nicolas P. Rougier # License: BSD # ---------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt + + +ROOT_DIR = pathlib.Path(__file__).parent.parent + mpl.rcParams['axes.linewidth'] = 1.5 -fig = plt.figure(figsize=(8,1.5)) -dx,dy = 0.0025, 0.01 +fig = plt.figure(figsize=(8, 1.5)) +dx, dy = 0.0025, 0.01 ax = fig.add_axes([dx, dy, 1-2*dx, 1-2*dy], frameon=False) -X,Y = [], [] +X, Y = [], [] for x in np.linspace(0.01, 10*np.pi-0.01, 100): - X.extend([x, x,None]) + X.extend([x, x, None]) Y.extend([0, np.sin(x), None]) print(X[:10], Y[:10]) plt.plot(X, Y, "black") @@ -20,5 +26,5 @@ plt.xlim(-0.25, 10*np.pi+.25) plt.ylim(-1.5, 1.5) plt.tight_layout() -plt.savefig("../figures/tip-multiline.pdf", dpi=100) +fig.savefig(ROOT_DIR / "figures/tip-multiline.pdf", dpi=100) # plt.show() diff --git a/scripts/tip-outline.py b/scripts/tip-outline.py index e34ad89..6fe1a6f 100644 --- a/scripts/tip-outline.py +++ b/scripts/tip-outline.py @@ -4,24 +4,29 @@ # ----------------------------------------------------------------------------- # Scripts to generate all the basic plots +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.patheffects as path_effects -fig = plt.figure(figsize=(2,2)) + +ROOT_DIR = pathlib.Path(__file__).parent.parent + +fig = plt.figure(figsize=(2, 2)) mpl.rcParams['axes.linewidth'] = 1.5 d = 0.01 -ax = fig.add_axes([d,d,1-2*d,1-2*d], xticks=[], yticks=[]) +ax = fig.add_axes([d, d, 1-2*d, 1-2*d], xticks=[], yticks=[]) np.random.seed(1) -Z = np.random.uniform(0,1,(8,8)) +Z = np.random.uniform(0, 1, (8, 8)) cmap = plt.get_cmap("Oranges") ax.imshow(Z, interpolation="nearest", cmap=cmap, vmin=0, vmax=2) text = ax.text(0.5, 0.1, "Label", transform=ax.transAxes, - color=cmap(0.9), size=32, weight="bold", ha="center", va="bottom") + color=cmap(0.9), size=32, weight="bold", ha="center", va="bottom") text.set_path_effects([path_effects.Stroke(linewidth=5, foreground='white'), path_effects.Normal()]) -plt.savefig("../figures/tip-outline.pdf") +fig.savefig(ROOT_DIR / "figures/tip-outline.pdf") diff --git a/scripts/tip-post-processing.py b/scripts/tip-post-processing.py index 1bf7238..3280efe 100644 --- a/scripts/tip-post-processing.py +++ b/scripts/tip-post-processing.py @@ -1,27 +1,32 @@ +import pathlib + import numpy as np import matplotlib.pyplot as plt from matplotlib.figure import Figure from matplotlib.backends.backend_agg import FigureCanvas from scipy.ndimage import gaussian_filter + +ROOT_DIR = pathlib.Path(__file__).parent.parent + # First pass for drop-shadow -fig = Figure(figsize=(6,1.5)) +fig = Figure(figsize=(6, 1.5)) canvas = FigureCanvas(fig) -ax = fig.add_axes([0,0,1,1], frameon=False, - xlim=[0,1], xticks=[], ylim=[0,1], yticks=[]) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, + xlim=[0, 1], xticks=[], ylim=[0, 1], yticks=[]) ax.text(0.5, 0.5, "Matplotlib", transform=ax.transAxes, ha="center", va="center", size=64, color="black") canvas.draw() -Z = np.array(canvas.renderer.buffer_rgba())[:,:,0] +Z = np.array(canvas.renderer.buffer_rgba())[:, :, 0] Z = gaussian_filter(Z, sigma=9) # Second pass for text + drop-shadow -fig = plt.figure(figsize=(6,1.5)) -ax = fig.add_axes([0,0,1,1], frameon=False, - xlim=[0,1], xticks=[], ylim=[0,1], yticks=[]) -ax.imshow(Z, extent=[0,1,0,1], cmap=plt.cm.gray, alpha=0.65, aspect='auto') +fig = plt.figure(figsize=(6, 1.5)) +ax = fig.add_axes([0, 0, 1, 1], frameon=False, + xlim=[0, 1], xticks=[], ylim=[0, 1], yticks=[]) +ax.imshow(Z, extent=[0, 1, 0, 1], cmap=plt.cm.gray, alpha=0.65, aspect='auto') ax.text(0.5, 0.5, "Matplotlib", transform=ax.transAxes, ha="center", va="center", size=64, color="black") -plt.savefig("../figures/tip-post-processing.pdf", dpi=600) +fig.savefig(ROOT_DIR / "figures/tip-post-processing.pdf", dpi=600) # plt.show() diff --git a/scripts/tip-transparency.py b/scripts/tip-transparency.py index 3a2c820..320ea0c 100644 --- a/scripts/tip-transparency.py +++ b/scripts/tip-transparency.py @@ -2,22 +2,29 @@ # Matplotlib cheat sheet # Released under the BSD License # ----------------------------------------------------------------------------- +import pathlib + import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt + +ROOT_DIR = pathlib.Path(__file__).parent.parent + mpl.rc('axes', linewidth=1.5) +np.random.seed(123) + fig = plt.figure(figsize=(2, 2), dpi=100) margin = 0.01 ax = fig.add_axes([margin, margin, 1-2*margin, 1-2*margin]) n = 500 X = np.random.normal(0, 0.25, n) Y = np.random.normal(0, 0.25, n) -ax.scatter(X, Y, s=50, c="k", lw=2) -ax.scatter(X, Y, s=50, c="w", lw=0) +ax.scatter(X, Y, s=50, c="k", lw=2) +ax.scatter(X, Y, s=50, c="w", lw=0) ax.scatter(X, Y, s=40, c="C1", lw=0, alpha=0.1) ax.set_xlim([-1, 1]), ax.set_xticks([]), ax.set_ylim([-1, 1]), ax.set_yticks([]) -plt.savefig("../figures/tip-transparency.pdf") +fig.savefig(ROOT_DIR / "figures/tip-transparency.pdf") # plt.show() diff --git a/styles/base.mplstyle b/styles/base.mplstyle new file mode 100644 index 0000000..ea0c81e --- /dev/null +++ b/styles/base.mplstyle @@ -0,0 +1,5 @@ +figure.constrained_layout.use: True +figure.constrained_layout.h_pad: 0.01 +figure.constrained_layout.w_pad: 0.01 +figure.constrained_layout.hspace: 0.1 +figure.constrained_layout.wspace: 0.1 diff --git a/styles/plotlet-grid.mplstyle b/styles/plotlet-grid.mplstyle new file mode 100644 index 0000000..e637a9c --- /dev/null +++ b/styles/plotlet-grid.mplstyle @@ -0,0 +1,7 @@ +font.family: Source Code Pro +font.size: 5 + +axes.linewidth: 0.5 + +xtick.major.size: 0.0 +ytick.major.size: 0.0 diff --git a/styles/plotlet.mplstyle b/styles/plotlet.mplstyle new file mode 100644 index 0000000..ff46026 --- /dev/null +++ b/styles/plotlet.mplstyle @@ -0,0 +1,21 @@ +figure.figsize: 0.4, 0.4 + +figure.constrained_layout.h_pad: 0.01 +figure.constrained_layout.w_pad: 0.01 +figure.constrained_layout.hspace: 0.01 +figure.constrained_layout.wspace: 0.01 + +axes.linewidth: 0.5 + +grid.linewidth: 0.2 + +lines.linewidth: 0.75 + +xtick.major.size: 0.0 +ytick.major.size: 0.0 + +xtick.labeltop: False +xtick.labelbottom: False + +ytick.labelleft: False +ytick.labelright: False diff --git a/styles/sine-plot.mplstyle b/styles/sine-plot.mplstyle new file mode 100644 index 0000000..9829f21 --- /dev/null +++ b/styles/sine-plot.mplstyle @@ -0,0 +1,24 @@ +font.size: 4 + +axes.titlesize: 4 +axes.titlepad: 2 +axes.linewidth: 0.2 + +lines.linewidth: 0.5 +lines.markersize: 3 + +xtick.labelsize: 3 +xtick.major.pad: 1 +xtick.major.width: 0.2 +xtick.major.size: 1 +xtick.minor.width: 0.1 +xtick.minor.size: 0.5 + +ytick.labelsize: 3 +ytick.major.pad: 1 +ytick.major.width: 0.2 +ytick.major.size: 1 +ytick.minor.width: 0.1 +ytick.minor.size: 0.5 + +legend.fontsize: 3 diff --git a/styles/ticks.mplstyle b/styles/ticks.mplstyle new file mode 100644 index 0000000..ba56aa8 --- /dev/null +++ b/styles/ticks.mplstyle @@ -0,0 +1,20 @@ +savefig.transparent: True + +font.size: 5 + +axes.linewidth: 0.5 +axes.spines.right: False +axes.spines.top: False +axes.spines.left: False +axes.spines.bottom: True + +xtick.labelsize: 3 +xtick.major.size: 2 +xtick.major.width: 0.2 +xtick.major.pad: 2 +xtick.minor.size: 1 +xtick.minor.width: 0.2 +xtick.minor.pad: 2 + +ytick.left: False +ytick.labelleft: False