diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 12463a8..67c3723 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -9,3 +9,45 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 - uses: pre-commit/action@v2.0.0 + build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.6 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install \ + fontconfig \ + libgeos++-dev \ + libproj-dev + python -m pip install --upgrade pip + pip install -r requirements/requirements-base.txt + pip install -r requirements/requirements.txt + - name: Install Tex Live + run: | + sudo apt-get update + sudo apt-get install \ + texlive-base \ + texlive-extra-utils \ + texlive-fonts-extra \ + texlive-fonts-recommended \ + texlive-latex-base \ + texlive-latex-extra \ + texlive-latex-recommended \ + texlive-xetex + - name: Build artifacts + run: | + rm *.pdf + make -C fonts/ + cp -r fonts/ /usr/share/fonts/ + fc-cache + make figures cheatsheets handouts + - uses: actions/upload-artifact@v2 + with: + name: build + path: | + cheatsheets.pdf + handout-*.pdf diff --git a/.gitignore b/.gitignore index ff77218..bf16396 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -fonts/* -*.upa +*.aux *.log *.out -*.aux +*.upa figures/*.pdf +fonts/**/*.[ot]tf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bbe1368 --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +SRC := $(wildcard *.tex) + +.PHONY: default +default: all + +.PHONY: all +all: figures cheatsheets + +.PHONY: figures +figures: + # generate the figures + cd scripts && for script in *.py; do echo $$script; 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 && python styles.py + +.PHONY: cheatsheets +cheatsheets: + xelatex cheatsheets.tex + +.PHONY: handouts +handouts: + xelatex handout-beginner.tex + xelatex handout-intermediate.tex + xelatex handout-tips.tex + +.PHONY: fonts +fonts: + make -C fonts/ + +.PHONY: clean +clean: $(SRC) + git clean -f -X ./figures/ + git clean -f ./scripts/*.pdf + latexmk -c $^ + +.PHONY: requirements +requirements: + $(MAKE) -C ./requirements/ diff --git a/README.md b/README.md index e67d49d..1d425a0 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,21 @@ or https://github.com/adobe-fonts/source-serif-pro/tree/release/OTF * `fonts/delicious-123/*` : See https://www.exljbris.com/delicious.html +On Linux, with `make` installed, the fonts can be set up with the following command: +```shell +make -C fonts +``` +The fonts can be made discoverable by `matplotlib` (through `fontconfig`) by creating the following in `$HOME/.config/fontconfig/fonts.conf` (see [here](https://www.freedesktop.org/software/fontconfig/fontconfig-user.html)): +```xml + + + +/path/to/cheatsheets/fonts/ +... + +``` 2. You need to generate all the figures: diff --git a/fonts/.gitignore b/fonts/.gitignore new file mode 100644 index 0000000..637df79 --- /dev/null +++ b/fonts/.gitignore @@ -0,0 +1 @@ +.uuid diff --git a/fonts/Makefile b/fonts/Makefile new file mode 100644 index 0000000..2d3c142 --- /dev/null +++ b/fonts/Makefile @@ -0,0 +1,43 @@ +FONT_DIRS := delicious-123 roboto roboto-mono roboto-slab source-code-pro source-sans-pro source-serif-pro + +DELICIOUS_ZIP := http://www.exljbris.com/dl/DELICIOUS_21_OTF.zip +ROBOTO_ZIP := https://github.com/googlefonts/roboto/releases/download/v2.138/roboto-unhinted.zip +ROBOTO_MONO_ZIP := https://github.com/googlefonts/RobotoMono/archive/8f651634e746da6df6c2c0be73255721d24f2372.zip +ROBOTO_SLAB_ZIP := https://github.com/googlefonts/robotoslab/archive/a65e6d00d8e3e7ee2fabef844e58fa12690384d2.zip +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 + +UNZIP_FLAGS := -x "__MACOSX/*" + + +.PHONY: default +default: all + +.PHONY: all +all: sources + mkdir -p $(FONT_DIRS) + cd delicious-123 && unzip -j /tmp/delicious.zip "DELICIOUS_21_OTF/*.otf" $(UNZIP_FLAGS) + cd delicious-123 && ln -sf Delicious_R_2021.otf Delicious-Roman.otf + cd delicious-123 && ln -sf Delicious_SC_2021.otf Delicious-SmallCaps.otf + cd roboto && unzip -j /tmp/roboto.zip "*.ttf" $(UNZIP_FLAGS) + cd roboto-mono && unzip -j /tmp/roboto-mono.zip "RobotoMono-8f651634e746da6df6c2c0be73255721d24f2372/fonts/ttf/*.ttf" $(UNZIP_FLAGS) + cd roboto-slab && unzip -j /tmp/roboto-slab.zip "robotoslab-a65e6d00d8e3e7ee2fabef844e58fa12690384d2/fonts/static/*.ttf" $(UNZIP_FLAGS) + 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) + +.PHONY: sources +sources: + wget $(DELICIOUS_ZIP) -O /tmp/delicious.zip + wget $(ROBOTO_ZIP) -O /tmp/roboto.zip + wget $(ROBOTO_MONO_ZIP) -O /tmp/roboto-mono.zip + wget $(ROBOTO_SLAB_ZIP) -O /tmp/roboto-slab.zip + 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 + +.PHONY: clean +clean: + - rm $(HOME)/.cache/matplotlib/fontlist* + - rm -rf $(FONT_DIRS) diff --git a/handout-intermediate.tex b/handout-intermediate.tex index 55e46e7..140fd90 100644 --- a/handout-intermediate.tex +++ b/handout-intermediate.tex @@ -76,7 +76,7 @@ \section*{\LARGE \rmfamily A matplotlib figure is composed of a hierarchy of elements that forms the actual figure. Each element can be modified. \medskip -\includegraphics[width=\linewidth]{anatomy-cropped.pdf} +\includegraphics[width=\linewidth]{anatomy.pdf} \subsection*{\rmfamily Figure, axes \& spines} diff --git a/handout-tips.tex b/handout-tips.tex index 8a2f3a3..197fb68 100644 --- a/handout-tips.tex +++ b/handout-tips.tex @@ -121,7 +121,9 @@ \subsection*{\rmfamily Offline rendering} % ----------------------------------------------------------------------------- \subsection*{\rmfamily Range of continuous colors} + You can use colormap to pick from a range of continuous colors. + \begin{tabular}{@{}m{.774\linewidth}m{.216\linewidth}} \begin{lstlisting}[belowskip=-\baselineskip] X = np.random.randn(1000, 4) diff --git a/requirements/Makefile b/requirements/Makefile new file mode 100644 index 0000000..d55dfbc --- /dev/null +++ b/requirements/Makefile @@ -0,0 +1,14 @@ +.PHONY: default +default: all + +.PHONY: all +all: requirements-base.txt requirements.txt + +.PHONY: install +install: requirements-base.txt requirements.txt + pip-sync $^ + +requirements.txt: requirements-base.txt + +%.txt: %.in + pip-compile $< diff --git a/requirements/requirements-base.in b/requirements/requirements-base.in new file mode 100644 index 0000000..2f2d856 --- /dev/null +++ b/requirements/requirements-base.in @@ -0,0 +1,2 @@ +numpy +pip-tools diff --git a/requirements/requirements-base.txt b/requirements/requirements-base.txt new file mode 100644 index 0000000..948596c --- /dev/null +++ b/requirements/requirements-base.txt @@ -0,0 +1,27 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements-base.in +# +click==7.1.2 + # via pip-tools +importlib-metadata==3.9.0 + # via pep517 +numpy==1.19.5 + # via -r requirements-base.in +pep517==0.10.0 + # via pip-tools +pip-tools==6.0.1 + # via -r requirements-base.in +toml==0.10.2 + # via pep517 +typing-extensions==3.7.4.3 + # via importlib-metadata +zipp==3.4.1 + # via + # importlib-metadata + # pep517 + +# The following packages are considered to be unsafe in a requirements file: +# pip diff --git a/requirements/requirements.in b/requirements/requirements.in new file mode 100644 index 0000000..d523250 --- /dev/null +++ b/requirements/requirements.in @@ -0,0 +1,9 @@ +-c ./requirements-base.txt + +cartopy +fonttools[woff] +matplotlib +pre-commit +scipy + +--no-binary shapely diff --git a/requirements/requirements.txt b/requirements/requirements.txt new file mode 100644 index 0000000..5bec37b --- /dev/null +++ b/requirements/requirements.txt @@ -0,0 +1,89 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +--no-binary shapely + +appdirs==1.4.4 + # via virtualenv +brotli==1.0.9 + # via fonttools +cartopy==0.18.0 + # via -r requirements.in +cfgv==3.2.0 + # via pre-commit +cycler==0.10.0 + # via matplotlib +distlib==0.3.1 + # via virtualenv +filelock==3.0.12 + # via virtualenv +fonttools[woff]==4.21.1 + # via -r requirements.in +identify==2.2.2 + # via pre-commit +importlib-metadata==3.9.0 + # via + # -c ./requirements-base.txt + # pre-commit + # virtualenv +importlib-resources==5.1.2 + # via + # pre-commit + # virtualenv +kiwisolver==1.3.1 + # via matplotlib +matplotlib==3.3.4 + # via -r requirements.in +nodeenv==1.5.0 + # via pre-commit +numpy==1.19.5 + # via + # -c ./requirements-base.txt + # cartopy + # matplotlib + # scipy +pillow==8.1.2 + # via matplotlib +pre-commit==2.11.1 + # via -r requirements.in +pyparsing==2.4.7 + # via matplotlib +pyshp==2.1.3 + # via cartopy +python-dateutil==2.8.1 + # via matplotlib +pyyaml==5.4.1 + # via pre-commit +scipy==1.5.4 + # via -r requirements.in +shapely==1.7.1 + # via cartopy +six==1.15.0 + # via + # cartopy + # cycler + # python-dateutil + # virtualenv +toml==0.10.2 + # via + # -c ./requirements-base.txt + # pre-commit +typing-extensions==3.7.4.3 + # via + # -c ./requirements-base.txt + # importlib-metadata +virtualenv==20.4.3 + # via pre-commit +zipp==3.4.1 + # via + # -c ./requirements-base.txt + # importlib-metadata + # importlib-resources +zopfli==0.1.8 + # via fonttools + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/scripts/anatomy.py b/scripts/anatomy.py index 19d69ce..c188381 100644 --- a/scripts/anatomy.py +++ b/scripts/anatomy.py @@ -136,4 +136,4 @@ def text(x, y, text): color=color)) plt.savefig("../figures/anatomy.pdf") -plt.show() +# plt.show() diff --git a/scripts/animation.py b/scripts/animation.py index 991906e..ace8d48 100644 --- a/scripts/animation.py +++ b/scripts/animation.py @@ -9,4 +9,4 @@ def animate(i): line.set_ydata(np.sin(T+i/50)) a=animation.FuncAnimation( plt.gcf(), animate, interval=5) -plt.show() +# plt.show() diff --git a/scripts/extents.py b/scripts/extents.py index 5b2aaa1..33bccd5 100644 --- a/scripts/extents.py +++ b/scripts/extents.py @@ -63,4 +63,4 @@ plt.savefig("../figures/extents.pdf", dpi=600) -plt.show() +# plt.show() diff --git a/scripts/figure.py b/scripts/figure.py index a4e0940..b0a90d6 100644 --- a/scripts/figure.py +++ b/scripts/figure.py @@ -125,4 +125,4 @@ def int_arrow(p0,p1): rotation = "vertical", ha="center", va="center", size="x-small") plt.savefig("figure.pdf") -plt.show() +# plt.show() diff --git a/scripts/interpolations.py b/scripts/interpolations.py index f9aa59a..eb4f6a4 100644 --- a/scripts/interpolations.py +++ b/scripts/interpolations.py @@ -19,4 +19,4 @@ plt.tight_layout() plt.savefig("../figures/interpolations.pdf", dpi=600) -plt.show() +# plt.show() diff --git a/scripts/line.py b/scripts/line.py index fd49750..456f414 100644 --- a/scripts/line.py +++ b/scripts/line.py @@ -82,4 +82,4 @@ def split(n_segment): y -= 1 plt.savefig("line.pdf", dpi=200) -plt.show() +# plt.show() diff --git a/scripts/sine.py b/scripts/sine.py index 1e7ef28..bf39a71 100644 --- a/scripts/sine.py +++ b/scripts/sine.py @@ -8,50 +8,50 @@ X = np.linspace(0.1, 10*np.pi, 10000) Y = np.sin(X) -# fig = plt.figure(figsize=(8,2)) -# plt.plot(X, Y, color="orange", linewidth=2) +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) +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 = 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=(7,1.5)) -# 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, ax = plt.subplots(figsize=(7,1.5)) +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) +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) +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() diff --git a/scripts/tick-locators-single.py b/scripts/tick-locators-single.py index f9c9801..3652e6a 100644 --- a/scripts/tick-locators-single.py +++ b/scripts/tick-locators-single.py @@ -36,4 +36,4 @@ def setup(ax): ax.xaxis.set_major_locator(ticker.MultipleLocator(1)) ax.xaxis.set_minor_locator(ticker.MultipleLocator(.1)) plt.savefig("../figures/tick-multiple-locator.pdf", transparent=True) -plt.show() +# plt.show() diff --git a/scripts/tick-multiple-locator.py b/scripts/tick-multiple-locator.py index b94c481..51110ff 100644 --- a/scripts/tick-multiple-locator.py +++ b/scripts/tick-multiple-locator.py @@ -48,4 +48,4 @@ def setup(ax): plt.tight_layout() plt.savefig("../figures/tick-multiple-locator.pdf", transparent=True) -plt.show() +# plt.show() diff --git a/scripts/tip-dotted.py b/scripts/tip-dotted.py index 57ff616..f5781aa 100644 --- a/scripts/tip-dotted.py +++ b/scripts/tip-dotted.py @@ -18,4 +18,4 @@ 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.show() +# plt.show() diff --git a/scripts/tip-dual-axis.py b/scripts/tip-dual-axis.py index 1afe015..0d60963 100644 --- a/scripts/tip-dual-axis.py +++ b/scripts/tip-dual-axis.py @@ -22,4 +22,4 @@ ax2.set_yticklabels([]) plt.savefig("../figures/tip-dual-axis.pdf") -plt.show() +# plt.show() diff --git a/scripts/tip-multiline.py b/scripts/tip-multiline.py index 0c421b8..06c1dbf 100644 --- a/scripts/tip-multiline.py +++ b/scripts/tip-multiline.py @@ -21,4 +21,4 @@ plt.ylim(-1.5, 1.5) plt.tight_layout() plt.savefig("../figures/tip-multiline.pdf", dpi=100) -plt.show() +# plt.show() diff --git a/scripts/tip-transparency.py b/scripts/tip-transparency.py index aca7c74..3a2c820 100644 --- a/scripts/tip-transparency.py +++ b/scripts/tip-transparency.py @@ -20,4 +20,4 @@ ax.set_xlim([-1, 1]), ax.set_xticks([]), ax.set_ylim([-1, 1]), ax.set_yticks([]) plt.savefig("../figures/tip-transparency.pdf") -plt.show() +# plt.show()