[
  {
    "path": ".devcontainer/README.md",
    "content": "# Remote: Containers for VSCode\n\nThis directory contains all files required to enable [working *inside* of containers](https://code.visualstudio.com/docs/remote/containers) in VSCode.\nThe entire workspace/IDE will work from *within* the context of a container of an image of your choice.\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "{\n    \"name\": \"LaTeX\",\n    // Instead of *building* the accompanying Dockerfile and its whole context, like:\n    //\n    // \"build\": {\n    //     \"context\": \"..\",\n    //     \"dockerfile\": \"image/Dockerfile\"\n    // },\n    //\n    // simply download the prepared image the author has already uploaded, based on\n    // what's found inside the `image/` directory.\n    // Advantages:\n    // - build process is slow (downloads from TeX servers), each user doing it every\n    //   time is too much. It can take *hours* in worst-cases\n    // - build might fail for various reasons\n    // It is much easier to download the ready-made image.\n    // Disadvantages:\n    // - cannot easily iterate on the Docker image, need to go through Docker Hub.\n    //   Recourse: simply change the below to use the *local image temporarily*\n    // - Upstream image on Docker Hub might not be the latest\n    \"image\": \"alexpovel/latex\",\n    \"customizations\": {\n        \"vscode\": {\n            // Set *default* container specific settings.json values on container create.\n            \"settings\": {\n                \"terminal.integrated.defaultProfile.linux\": \"bash\"\n            },\n            // Add the IDs of extensions you want installed when the container is created.\n            // Browse for extensions here: https://marketplace.visualstudio.com/\n            // then look for 'Unique Identifier' on the extension's page.\n            \"extensions\": [\n                \"James-Yu.latex-workshop\",\n                \"streetsidesoftware.code-spell-checker\",\n                \"streetsidesoftware.code-spell-checker-german\"\n            ]\n        }\n    },\n    \"containerEnv\": {\n        // Inside the container, act as though we're in CI. Important for the Makefile.\n        \"CI\": \"true\",\n        // The base image has this locale:\n        //     $ docker run --rm --entrypoint=\"locale\" alexpovel/latex\n        //     LANG=\n        //     LANGUAGE=\n        //     LC_CTYPE=\"POSIX\"\n        //     LC_NUMERIC=\"POSIX\"\n        //     LC_TIME=\"POSIX\"\n        //     LC_COLLATE=\"POSIX\"\n        //     LC_MONETARY=\"POSIX\"\n        //     LC_MESSAGES=\"POSIX\"\n        //     LC_PAPER=\"POSIX\"\n        //     LC_NAME=\"POSIX\"\n        //     LC_ADDRESS=\"POSIX\"\n        //     LC_TELEPHONE=\"POSIX\"\n        //     LC_MEASUREMENT=\"POSIX\"\n        //     LC_IDENTIFICATION=\"POSIX\"\n        //     LC_ALL=\n        // *However*, starting this very same container in VSCode's Remote Containers,\n        // the locale changes to:\n        //     $ locale\n        //     locale: Cannot set LC_CTYPE to default locale: No such file or directory\n        //     locale: Cannot set LC_MESSAGES to default locale: No such file or directory\n        //     locale: Cannot set LC_ALL to default locale: No such file or directory\n        //     LANG=en_US.UTF-8\n        //     LANGUAGE=\n        //     LC_CTYPE=\"en_US.UTF-8\"\n        //     LC_NUMERIC=\"en_US.UTF-8\"\n        //     LC_TIME=\"en_US.UTF-8\"\n        //     LC_COLLATE=\"en_US.UTF-8\"\n        //     LC_MONETARY=\"en_US.UTF-8\"\n        //     LC_MESSAGES=\"en_US.UTF-8\"\n        //     LC_PAPER=\"en_US.UTF-8\"\n        //     LC_NAME=\"en_US.UTF-8\"\n        //     LC_ADDRESS=\"en_US.UTF-8\"\n        //     LC_TELEPHONE=\"en_US.UTF-8\"\n        //     LC_MEASUREMENT=\"en_US.UTF-8\"\n        //     LC_IDENTIFICATION=\"en_US.UTF-8\"\n        //     LC_ALL=\n        // There's three errors because the container doesn't seem to have the correct\n        // locale files:\n        //     $ locale -a\n        //     locale: Cannot set LC_CTYPE to default locale: No such file or directory\n        //     locale: Cannot set LC_MESSAGES to default locale: No such file or directory\n        //     locale: Cannot set LC_COLLATE to default locale: No such file or directory\n        //     C\n        //     C.UTF-8\n        //     POSIX\n        // This leads to `lualatex` erroring out, see also https://tex.stackexchange.com/q/374303/120853\n        // Using \"POSIX\" is possible and brings us back to vanilla container locale:\n        \"LC_ALL\": \"POSIX\"\n    }\n}\n"
  },
  {
    "path": ".devcontainer/image/Dockerfile",
    "content": "# ARGs before the first FROM are global and usable in all stages\n\nARG BASE_OS=\"debian\"\n\n# Tag of the base OS image\nARG OS_VERSION=\"testing\"\n\n# TeXLive version. This will be used by the `texlive.sh` script to determine what to\n# download and install. `latest` will fetch the latest version available on their servers.\n# Alternatively, you can specify *a past year* and it will download that version\n# from the TeXLive archives and use it (can take a long time).\n# For available years, see ftp://tug.org/historic/systems/texlive/ .\nARG TL_VERSION=\"latest\"\n\nARG _BUILD_CONTEXT_PREFIX=\".devcontainer/image/\"\n\n# Image with layers as used by all succeeding steps\nFROM ${BASE_OS}:${OS_VERSION} as base\n\n# Use `apt-get` over just `apt`, see https://askubuntu.com/a/990838/978477.\n# Also run `apt-get update` on every `RUN`, see:\n# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run\nRUN apt-get update && \\\n    apt-get install --yes --no-install-recommends \\\n    # wget for `install-tl` script to download TeXLive, and other downloads.\n    wget \\\n    # In a similar vein, `curl` is required by various tools, or is just very\n    # nice to have for various scripting tasks.\n    curl \\\n    # wget/install-tl requires capability to check certificate validity.\n    # Without this, executing `install-tl` fails with:\n    #\n    # install-tl: TLPDB::from_file could not initialize from: https://<mirror>/pub/ctan/systems/texlive/tlnet/tlpkg/texlive.tlpdb\n    # install-tl: Maybe the repository setting should be changed.\n    # install-tl: More info: https://tug.org/texlive/acquire.html\n    #\n    # Using `install-tl -v`, found out that mirrors use HTTPS, for which the\n    # underlying `wget` (as used by `install-tl`) returns:\n    #\n    # ERROR: The certificate of '<mirror>' is not trusted.\n    # ERROR: The certificate of '<mirror>' doesn't have a known issuer.\n    #\n    # This is resolved by installing:\n    ca-certificates \\\n    # Update Perl, otherwise: \"Can't locate Pod/Usage.pm in @INC\" in install-tl\n    # script; Perl is already installed, but do not use `upgrade`, see\n    # https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run\n    perl \\\n    # Install `latexindent` Perl dependencies.\n    # Found these using this method: https://unix.stackexchange.com/a/506964/374985\n    # List of `latexindent` dependencies is here:\n    # https://latexindentpl.readthedocs.io/en/latest/appendices.html#linux,\n    # see also the helper script at\n    # https://github.com/cmhughes/latexindent.pl/blob/master/helper-scripts/latexindent-module-installer.pl\n    #\n    # Installing via Debian system packages because installing the modules via\n    # `cpanm` requires `gcc` and I wanted to avoid installing that (~200MB).\n    #\n    # YAML::Tiny:\n    libyaml-tiny-perl \\\n    # File::HomeDir:\n    libfile-homedir-perl \\\n    # Unicode:GCString:\n    libunicode-linebreak-perl \\\n    # Log::Log4perl:\n    liblog-log4perl-perl \\\n    # Log::Dispatch:\n    liblog-dispatch-perl \\\n    # Usually, `latexmk` is THE tool to use to automate, in a `make`-like style,\n    # LaTeX (PDF) file generation. However, if that is not enough, the following\n    # will fill the gaps and cover all other use cases:\n    make \\\n    # Get `envsubst` to replace environment variables in files with their actual\n    # values.\n    gettext-base \\\n    # Using the LaTeX package `minted` for syntax highlighting of source code\n    # snippets. It's much more powerful than the alternative `listings` (which is\n    # pure TeX: no outside dependencies but limited functionality) but requires\n    # Python's `pygments` package:\n    python3 \\\n    python3-pygments \\\n    # Required to embed git metadata into PDF from within Docker container:\n    git \\\n    # Required to use pdfunite for merging PDF files. Ghostscript is causing\n    # trouble with Mozilla Firefox's PDF Reader.\n    poppler-utils\n\n# The `minted` LaTeX package provides syntax highlighting using the Python `pygmentize`\n# package. That package also installs a callable script, which `minted` uses, see\n# https://tex.stackexchange.com/a/281152/120853.\n# Therefore, `minted` primarily works by invoking `pygmentize` (or whatever it was\n# overridden by using `\\MintedPygmentize`). However, it requires `python` for other\n# jobs, e.g. to remove leading whitespace for the `autogobble` function, see the\n# \"\\minted@autogobble Remove common leading whitespace.\" line in the docs.\n# It is invoked with `python -c`, but Debian only has `python3`. Therefore, alias\n# `python` to invoke `python3`. Use `update-alternatives` because it's cooler than\n# symbolic linking, and made for this purpose.\n# If `python` is not available but `pygmentize` is, stuff like `autogobble` and\n# `\\inputminted`won't work but syntax highlighting will.\n# See also https://stackoverflow.com/a/55351449/11477374\n# Last argument is `priority`, whose value shouldn't matter since there's nothing else.\nRUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1\n\n\nFROM base as downloads\n\n# Cannot share ARGs over multiple stages, see also:\n# https://github.com/moby/moby/issues/37345.\n# Therefore, work in root (no so `WORKDIR`), so in later stages, the location of\n# files copied from this stage does not have to be guessed/WET.\n\n# Using an ARG with 'TEX' in the name, TeXLive will warn:\n#\n#  ----------------------------------------------------------------------\n#  The following environment variables contain the string \"tex\"\n#  (case-independent).  If you're doing anything but adding personal\n#  directories to the system paths, they may well cause trouble somewhere\n#  while running TeX. If you encounter problems, try unsetting them.\n#  Please ignore spurious matches unrelated to TeX.\n\n#     TEXPROFILE_FILE=texlive.profile\n#  ----------------------------------------------------------------------\n#\n# This also happens when the *value* contains 'TEX'.\n# `ARG`s are only set during Docker image build-time, so this warning should be void.\n\n# Renew (https://stackoverflow.com/a/53682110):\nARG TL_VERSION\nARG _BUILD_CONTEXT_PREFIX\n\nARG TL_INSTALL_ARCHIVE=\"install-tl-unx.tar.gz\"\nARG EISVOGEL_ARCHIVE=\"Eisvogel.tar.gz\"\nARG INSTALL_TL_DIR=\"install-tl\"\n\nCOPY ./${_BUILD_CONTEXT_PREFIX}/texlive.sh .\n\nRUN \\\n    # Get appropriate installer for the TeXLive version to be installed:\n    ./texlive.sh get_installer ${TL_VERSION} && \\\n    # Get Eisvogel LaTeX template for pandoc,\n    # see also #175 in that repo.\n    wget https://github.com/Wandmalfarbe/pandoc-latex-template/releases/latest/download/${EISVOGEL_ARCHIVE}\n\nRUN \\\n    mkdir ${INSTALL_TL_DIR} && \\\n    # Save archive to predictable directory, in case its name ever changes; see\n    # https://unix.stackexchange.com/a/11019/374985.\n    # The archive comes with a name in the form of 'install-tl-YYYYMMDD' from the source,\n    # which is of course unpredictable.\n    tar --extract --file=${TL_INSTALL_ARCHIVE} --directory=${INSTALL_TL_DIR} --strip-components 1 && \\\n    \\\n    # Prepare Eisvogel pandoc template (yields `eisvogel.latex` among other things):\n    tar --extract --file=${EISVOGEL_ARCHIVE}\n\n\nFROM base as main\n\n# Renew (https://stackoverflow.com/a/53682110):\nARG TL_VERSION\nARG _BUILD_CONTEXT_PREFIX\n\nARG TL_PROFILE=\"texlive.profile\"\n# Auxiliary, intermediate file:\nARG TMP_TL_PROFILE=\"${TL_PROFILE}.tmp\"\n\n# Layer with graphical and auxiliary tools\n# Put as early as possible in Dockerfile since this should rarely change (cache-friendly)\nRUN apt-get update && \\\n    apt-get install --yes --no-install-recommends \\\n    # cannot use `default-jre-headless` version (25% of normal size), see\n    # https://github.com/alexpovel/latex-cookbook/issues/17\n    default-jre \\\n    # No headless inkscape available currently:\n    inkscape \\\n    # nox (no X Window System): CLI version, 10% of normal size:\n    gnuplot-nox \\\n    # For various conversion tasks, e.g. EPS -> PDF (for legacy support):\n    ghostscript\n\n# Pandoc layer; not required for LaTeX compilation, but useful for document conversions\n# Put as early as possible in Dockerfile since this should rarely change (cache-friendly)\nRUN apt-get update && \\\n    apt-get install --yes --no-install-recommends \\\n    # librsvg2 for 'rsvg-convert' used by pandoc to convert SVGs when embedding\n    # into PDF\n    librsvg2-bin \\\n    pandoc\n\n# User to install and run LaTeX as.\n# This is a security and convenience measure: by default, containers run as root.\n# To work and compile PDFs using this container, you will need to map volumes into it\n# from your host machine. Those bind-mounts will then be accessed as root from this\n# container, and any generated files will also be owned by root. This is inconvenient at\n# best and dangerous at worst.\n# The generated user here will have IDs of 1000:1000. If your local user also has those\n# (the case for single-user Debians etc.), your local user will already have correct\n# ownership of all files generated by the user we create here.\nARG USER=\"tex\"\nRUN useradd --create-home ${USER}\n\n# Label according to http://label-schema.org/rc1/ to have some metadata in the image.\n# This is important e.g. to know *when* an image was built. Depending on that, it can\n# contain different software versions (even if the base image is specified as a fixed\n# version).\nLABEL \\\n    maintainer=\"Alex Povel <alex.povel@tuhh.de>\" \\\n    org.label-schema.description=\"TeXLive with most packages, JavaRE, Inkscape, pandoc and more\" \\\n    org.label-schema.vcs-url=\"https://github.com/alexpovel/latex-cookbook\" \\\n    org.label-schema.schema-version=\"1.0\"\n\nARG INSTALL_DIR=\"/install\"\nWORKDIR ${INSTALL_DIR}\n\n# Copy custom file containing TeXLive installation instructions\nCOPY ${_BUILD_CONTEXT_PREFIX}/config/${TL_PROFILE} ${TMP_TL_PROFILE}\nCOPY --from=downloads /install-tl/ /texlive.sh ./\n\n# Move to where pandoc looks for templates, see https://pandoc.org/MANUAL.html#option--data-dir\nCOPY --from=downloads /eisvogel.latex /home/${USER}/.pandoc/templates/\n\n# Global wget config file, see the comments in that file for more info and the rationale.\n# Location of that file depends on system, e.g.: https://askubuntu.com/a/368050\nCOPY ${_BUILD_CONTEXT_PREFIX}/config/.wgetrc /etc/wgetrc\n\n# \"In-place\" `envsubst` run is a bit more involved, see also:\n# https://stackoverflow.com/q/35078753/11477374.\n# Do not use `mktemp`, will break Docker caching since it's a new file each time.\nRUN cat \"$TMP_TL_PROFILE\" | envsubst | tee \"$TL_PROFILE\" && \\\n    rm \"$TMP_TL_PROFILE\"\n\n# (Large) LaTeX layer\nRUN ./texlive.sh install \"$TL_VERSION\"\n\n# Remove no longer needed installation workdir.\n# Cannot run this earlier because it would be recreated for any succeeding `RUN`\n# instructions.\n# Therefore, change `WORKDIR` first, then delete the old one.\nWORKDIR /${USER}\n\nUSER ${USER}\n\n# Load font cache, has to be done on each compilation otherwise\n# (\"luaotfload | db : Font names database not found, generating new one.\").\n# If not found, e.g. TeXLive 2012 and earlier, simply skip it. Will return exit code\n# 0 and allow the build to continue.\n# Warning: This is USER-specific. If the current `USER` for which we run this is not\n# the container user, the font will be regenerated for that new user.\nRUN luaotfload-tool --update || echo \"luaotfload-tool did not succeed, skipping.\"\n\n# Make our class file available for the entire latex/TeXLive installation, see also\n# https://tex.stackexchange.com/a/1138/120853\nCOPY acp.cls /home/${USER}/texmf/tex/latex/\n\nUSER root\n# Give back control to own user files; might be root-owned from previous copying processes\nRUN chown --recursive ${USER}:${USER} /home/${USER}/\nUSER ${USER}\n\n# The default parameters to the entrypoint; overridden if any arguments are given to\n# `docker run`.\n# `lualatex` usage for `latexmk` implies PDF generation, otherwise DVI is generated.\nCMD [ \"--lualatex\" ]\n\n# Allow container to run as an executable; override with `--entrypoint`.\n# Allows to simply `run` the image without specifying any executable.\n# If `latexmk` is called without a file argument, it will run on all *.tex files found.\nENTRYPOINT [ \"latexmk\" ]\n"
  },
  {
    "path": ".devcontainer/image/README.md",
    "content": "# Docker image with custom, almost-full TeXLive distribution & various tools\n\n[![Docker Pulls](https://img.shields.io/docker/pulls/alexpovel/latex)](https://hub.docker.com/r/alexpovel/latex)\n\nServes a lot of needs surrounding LaTeX file generation and handling.\nFor the rationale behind the installed Debian packages, see [below](#custom-tools).\nTo see how to build the image, also see [below](#building).\n\n## Quick Intro\n\nIf you use [VSCode Remote Containers](https://code.visualstudio.com/docs/remote/containers), the below does not apply.\nThere is no need to run manual `docker` invocations on the host.\n\n---\n\n[Install Docker](https://docs.docker.com/get-docker/), navigate to your project directory, then run the image as follows:\n\n- Bash:\n\n  ```bash\n  docker run --rm --volume $(pwd):/tex alexpovel/latex\n  ```\n\n- PowerShell:\n\n  ```powershell\n  docker run --rm --volume ${PWD}:/tex alexpovel/latex\n  ```\n\nThe parts making up the command are:\n\n- The last line is the location on [DockerHub](https://hub.docker.com/repository/docker/alexpovel/latex).\n  Without specifying a [*tag*](https://hub.docker.com/repository/docker/alexpovel/latex/tags?page=1), the default `latest` is implied.\n  See [below](#historic-builds) for more options.\n- The `--rm` option removes the container after a successful run.\n  This is generally desired since containers are not supposed to be stateful: once their process terminates, the container terminates, and it can be considered junk.\n- Providing a `--volume`, in this case the current working directory aka pwd, is required for the container to find files to work on.\n  It has to be *mounted* to a location *inside* the container.\n  This has to be whatever the last `WORKDIR` instruction in the [Dockerfile](Dockerfile) is, e.g. `/tex`.\n\n  Otherwise, you can always override the `WORKDIR` using the `--workdir` option.\n  This is the directory in which the Docker container's process works in and expects to find files.\n- Note that there is no command given, e.g. there is nothing *after* `alexpovel/latex`.\n  In this form, the container runs as an executable (just as if you ran `lualatex` or similar commands), where the program to be executed is determined by the `ENTRYPOINT` instruction in the [Dockerfile](Dockerfile).\n\n  For example, if the `ENTRYPOINT` is set to `latexmk`, running the above command will execute `latexmk` in the container's context, without you having to specify it.\n\n  (`latexmk` is a recipe-like tool that automates LaTeX document compilation by running `lualatex`, `biber` and whatever else required for compilation as many times as needed for proper PDF output (so references like `??` in the PDF are resolved).\n  It does this by detecting that auxiliary files no longer change (steady-state).\n  The tool is best configured using its config file, `.latexmkrc`.)\n\n  Any options to the `ENTRYPOINT` executable are given at the end of the command, e.g.:\n\n  ```bash\n  docker run --rm --volume $(pwd)/tests:/tex alexpovel/latex -c\n  ```\n\n  to run, if `latexmk` is the `ENTRYPOINT`, the equivalent of `latexmk -c` ([cleaning auxiliary files](https://mg.readthedocs.io/latexmk.html#cleaning-up)).\n\n  To **overwrite** the `ENTRYPOINT`, e.g. because you want to run only `lualatex`, use the `--entrypoint` option, e.g. `--entrypoint=\"lualatex\"`.\n  Similarly, you can work inside of the container directly, e.g. for debugging, using `--entrypoint=\"bash\"`.\n\n### Image\n\nFor the above to work, the `alexpovel/latex` image needs to be available on whatever your default image registry is (usually [DockerHub](https://hub.docker.com/)).\nIf it's not available for pulling (i.e., downloading) from there, you can build this image locally, see [below](#building).\n\n## Approach\n\nThis Dockerfile is based on a custom TeXLive installer using their [`install-tl` tool](https://www.tug.org/texlive/doc/install-tl.html), instead of [Debian's `texlive-full`](https://packages.debian.org/search?searchon=names&keywords=texlive-full).\nOther, smaller `texlive-` collections would be [available](https://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=texlive), but TeXLive cannot install missing packages on-the-fly, [unlike MiKTeX](https://miktex.org/howto/miktex-console/).\nTherefore, images should come with all desirable packages in place; installing them after the fact in running containers using [`tlmgr`](https://www.tug.org/texlive/tlmgr.html) is the wrong approach (containers are only meant to be run; if they are incomplete, modify the *image*, ordinarily by modifying the `Dockerfile`).\n\nThis approach has the following advantages:\n\n- Using [\"vanilla\" TeXLive](https://www.tug.org/texlive/debian.html) affords us the latest packages directly from the source, while the official   Debian package might lag behind a bit.\n  This is often not relevant, but has bitten me several times while working with the latest packages.\n- The installation can be adjusted better.\n  For example, *multiple GBs* of storage/image size are saved by omitting unneeded PDF documentation files.\n- We can install arbitrary TeXLive versions, as long as they are the [current](https://tug.org/texlive/acquire-netinstall.html) or an archived (<ftp://tug.org/historic/systems/texlive/>) version.\n  Otherwise, to obtain [older or even obsolete TeXLive installations](#historic-builds), one would have to also obtain a corresponding Debian version.\n  This way, we can choose a somewhat recent Debian version and simply install an old TeXLive into it.\n\n  Eligible archive versions are those year directories (`2019`, `2020`, ...) present at the above FTP link that have a `tlnet-final` subdirectory.\n  This is (speculating here) a frozen, aka final, version, put online the day the *next* major release goes live.\n  For example, version `2021` released on 2021-04-01 and `2020` received its `tlnet-final` subdirectory that same day.\n\nThe `install-tl` tool is configured via a [*Profile* file](config/texlive.profile), see also the [documentation](https://www.tug.org/texlive/doc/install-tl.html#PROFILES).\nThis enables unattended, pre-configured installs, as required for a Docker installation.\n\n---\n\nThe (official?) [`texlive/texlive` image](https://hub.docker.com/r/texlive/texlive) follows [the same approach](https://hub.docker.com/layers/texlive/texlive/latest/images/sha256-70fdbc1d9596c8eeb4a80c71a8eb3a5aeb63bed784112cbdb87f740e28de7a80?context=explore).\nHowever, there are a bunch of things this Dockerfile does differently that warrant not building `FROM` that image:\n\n- a user-editable, thus more easily configurable [profile](config/texlive.profile).\n  This is mainly concerning the picked package *collections*.\n  Unchecking (putting a `0`) unused ones saves around 500MB at the time of writing.\n- more elaborate support for [historic versions](#historic-builds)\n- an installation procedure incorporating a proper `USER`\n\nThings they do that do not happen here:\n\n- verify download integrity using `gpg`\n\n### Historic Builds\n\nLaTeX is a slow world, and many documents/templates in circulation still rely on outdated practices or packages.\nThis can be a huge hassle.\nMaintaining an old LaTeX distribution next to a current one on the same host is not fun.\nThis is complicated by the fact that (La)TeX seems to do things differently than pretty much everything else.\nFor this, Docker is the perfect tool.\n\nThis image can be built (`docker build`) with different build `ARG`s, and the build process will figure out the proper way to handle installation.\nThere is a [script](texlive.sh) to handle getting and installing TeXLive from the proper location ([current](https://www.tug.org/texlive/acquire-netinstall.html) or [archive](ftp://tug.org/historic/systems/texlive/)).\nRefer to the [Dockerfile](Dockerfile) for the available `ARG`s (all `ARG` have a default).\nThese are handed to the build process via the [`--build-arg` option](https://docs.docker.com/engine/reference/commandline/build/#options).\n\nNote that for a *specific* TeXLive version to be picked, it needs to be present in their [archives](ftp://tug.org/historic/systems/texlive/).\nThe *current* TeXLive is not present there (it's not historic), but is available under the `latest` Docker tag.\nAs such, if for example `2020` is the *current* TeXLive, and the image is to be based on Debian 10, there is *no* `debian-10-texlive-2020` tag.\nYou would obtain this using the `latest` tag.\nAs soon as TeXLive 2020 is superseded and consequently moved to the archives, the former tag can become available.\n\nTo build an array of different versions automatically, DockerHub provides [advanced options](https://docs.docker.com/docker-hub/builds/advanced/) in the form of hooks, e.g. a [build hook](hooks/build).\nThese are bash scripts that override the default DockerHub build process.\nAt build time, DockerHub provides [environment variables](https://docs.docker.com/docker-hub/builds/advanced/#environment-variables-for-building-and-testing) which can be used in the build hook to forward these into the Dockerfile build process.\nAs such, by just specifying the image *tags* on DockerHub, we can build corresponding images automatically (see also [here](https://web.archive.org/web/20201005132636/https://dev.to/samuelea/automate-your-builds-on-docker-hub-by-writing-a-build-hook-script-13fp)).\nFor more info on this, see [below](#on-dockerhub).\n\nThe approximate [matching of Debian to TeXLive versions](https://www.tug.org/texlive/debian.html) is (see also [here](https://www.debian.org/releases/) and [here](https://www.debian.org/distrib/archive).):\n\n| Debian Codename | Debian Version | TeXLive Version |\n| --------------- | :------------: | :-------------: |\n| bullseye        |       11       |      2020       |\n| buster          |       10       |      2018       |\n| stretch         |       9        |      2016       |\n| jessie          |       8        |      2014       |\n| wheezy          |       7        |      2012       |\n| squeeze         |      6.0       |      2009       |\n| lenny           |      5.0       |     unknown     |\n| etch            |      4.0       |     unknown     |\n| sarge           |      3.1       |     unknown     |\n| woody           |      3.0       |     unknown     |\n| potato          |      2.2       |     unknown     |\n| slink           |      2.1       |     unknown     |\n| hamm            |      2.0       |     unknown     |\n\nThis is only how the official Debian package is shipped.\nThese versions can be, to a narrow extend, freely mixed.\nUsing `install-tl`, older versions of TeXLive can be installed on modern Debian versions.\n\n#### Issues\n\nUsing [*obsolete* Debian releases](https://www.debian.org/releases/) comes with a long list of headaches.\nAs such, Debian versions do not reach too far back.\nIt does not seem worth the effort.\nInstead, it seems much easier to install older TeXLive versions onto reasonably recent Debians.\n\nIssues I ran into are:\n\n- `apt-get update` will fail if the original Debian repository is dead (Debian 6/TeXLive 2014):\n\n  ```plaintext\n  W: Failed to fetch http://httpredir.debian.org/debian/dists/squeeze/main/binary-amd64/Packages.gz  404  Not Found\n  W: Failed to fetch http://httpredir.debian.org/debian/dists/squeeze-updates/main/binary-amd64/Packages.gz  404  Not Found\n  W: Failed to fetch http://httpredir.debian.org/debian/dists/squeeze-lts/main/binary-amd64/Packages.gz  404  Not Found\n  E: Some index files failed to download, they have been ignored, or old ones used instead.\n  ```\n\n  As such, there needs to be a [dynamic way to update `/etc/apt/sources.list`](https://github.com/alexpovel/latex-extras-docker/blob/fa9452c236079a65563daff22767b2b637dd80c6/adjust_sources_list.sh) if the Debian version to be used in an archived one, see also [here](https://web.archive.org/web/20201007095943/https://www.prado.lt/using-old-debian-versions-in-your-sources-list).\n- `RUN wget` (or `curl` etc.) via `HTTPS` will fail for older releases, e.g. GitHub rejected the connection due to the outdated TLS version of the old release (Debian 6/TeXLive 2015):\n\n  ```text\n  Connecting to github.com|140.82.121.4|:443... connected.\n  OpenSSL: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version\n  ```\n\n- Downloading older releases requires using the [Debian archives](http://archive.debian.org/debian/).\n  This works fine, however a warning is issued (Debian 6/TeXLive 2014):\n\n  ```plaintext\n  W: GPG error: http://archive.debian.org squeeze Release: The following signatures were invalid: KEYEXPIRED 1520281423 KEYEXPIRED 1501892461\n  ```\n\n  Probably related to this, the installation then fails:\n\n  ```plaintext\n  WARNING: The following packages cannot be authenticated!\n    libgdbm3 libssl0.9.8 wget libdb4.7 perl-modules perl openssl ca-certificates\n  E: There are problems and -y was used without --force-yes\n  ```\n\n  According to `man apt-get`, `--force-yes` is both deprecated and absolutely not recommended.\n  The correct course here is to `--allow-unauthenticated`, however this would also affect the build process for modern versions, where authentication *did not* fail.\n  The official Debian archives are probably trustworthy, but this is still an issue.\n- A more obscure issue is (Debian 7/TeXLive 2011):\n\n  ```plaintext\n  The following packages have unmet dependencies:\n    perl : Depends: perl-base (= 5.14.2-21+deb7u3) but 5.14.2-21+deb7u6 is to be installed\n  E: Unable to correct problems, you have held broken packages.\n  ```\n\n  While the error message itself is crystal-clear, debugging this is probably a nightmare.\n- Tools like `pandoc`, which was released in [2006](https://pandoc.org/releases.html), limit the earliest possible Debian version as long as the tool's installation is part of the Dockerfile.\n  In this example, 2006 should in any case be early enough (if not, update your LaTeX file to work with more recent versions, that is probably decidedly less work).\n\n## Custom Tools\n\nThe auxiliary tools are (for the actual, up-to-date list, see the [Dockerfile](Dockerfile)):\n\n- A *Java Runtime Environment* for [`bib2gls`](https://ctan.org/pkg/bib2gls) from the [`glossaries-extra` package](https://www.ctan.org/pkg/glossaries-extra).\n\n  `bib2gls` takes in `*.bib` files with glossary, symbol, index and other definitions and applies sorting, filtering etc.\n  For this, it requires Java.\n- [`inkscape`](https://inkscape.org/) because the [`svg`](https://ctan.org/pkg/svg) package needs it.\n  We only require the CLI, however there is no \"no-GUI\" version available.\n  Headless Inkscape is [currently in the making](https://web.archive.org/web/20201007100140/https://wiki.inkscape.org/wiki/index.php/Future_Architecture).\n\n  Using that package, required PDFs and PDF_TEXs are only generated at build-time (on the server or locally) and treated as a cache.\n  As such, they can be discarded freely and are regenerated in the next compilation run, using `svg`, which calls `inkscape`.\n  Therefore, the `svg` package gets rid of all the PDF/PDF_TEX intermediate junk and lets us deal with the true source -- `*.svg` files -- directly.\n  These files are really [XML](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), ergo text-based, ergo suitable for VCS like `git` (as opposed to binary PDFs).\n\n  Being an external tool, `svg`/`inkscape` also requires the `--shell-escape` option to `lualatex` etc. for writing outside files.\n- [`gnuplot`](http://www.gnuplot.info/) for `contour gnuplot` commands for `addplot3` in `pgfplots`.\n  So essentially, an external add-on for the magnificent `pgfplots` package.\n  For `gnuplot` to write computed results to a file for `pgfplots` to read, `--shell-escape` is also required.\n- [`pandoc`](https://pandoc.org/) as a very flexible, convenient markup conversion tool.\n  For example, it can convert Markdown (like this very [README](README.md)) to PDF via LaTeX:\n\n  ```bash\n  pandoc README.md --output=README.pdf  # pandoc infers what to do from suffixes\n  ```\n\n  The default output is usable, but not very pretty.\n  This is where *templates* come into play.\n  A very tidy and well-made such template is [*Eisvogel*](https://github.com/Wandmalfarbe/pandoc-latex-template).\n  Its installation is not via a (Debian) package, so it has to be downloaded specifically.\n  For this, additional requirements are:\n\n  - `wget` to download the archive,\n  - `librsvg2-bin` for the `rsvg-convert` tool.\n    This is used by `pandoc` to convert SVGs when embedding them into the new PDF.\n\n  Note that `pandoc` and its *Eisvogel* template can draw [metadata from a YAML header](https://pandoc.org/MANUAL.html#metadata-variables), for example:\n\n  ```yaml\n  ---\n  title: \"Title\"\n  author: [Author]\n  date: \"YYYY-MM-DD\"\n  subject: \"Subject\"\n  keywords: [Keyword1, Keyword2]\n  lang: \"en\"\n  ...\n  ```\n\n  among other metadata variables.\n  *Eisvogel* uses it to fill the document with info, *e.g.* the PDF header and footer.\n\n  `pandoc` is not required for LaTeX work, but is convenient to have at the ready for various conversion jobs.\n\n## Building\n\nThe proper way to access these images is via DockerHub.\n\n### On DockerHub ([Requires Pro Plan](https://docs.docker.com/docker-hub/builds/))\n\nThis repository and its [Dockerfile](Dockerfile) used to be built into the corresponding image continuously and made available on [DockerHub](https://hub.docker.com/repository/docker/alexpovel/latex).\nThis process now requires a Pro plan and was therefore retired.\n\nFor the currently available tags, see [here](https://hub.docker.com/repository/docker/alexpovel/latex/tags?page=1).\n\n### Locally\n\nThe Dockerfile is now built locally and pushed manually.\nRefer to the Dockerfile for all the available configuration environment variables (`ARG`s).\n\nThe build can take a very long time (if you have all collections selected in the [profile](config/texlive.profile)), especially when downloading from the TeXLive/TUG archives.\nFor developing/debugging, it is advisable to download the archive files once.\nE.g. for TexLive 2014, you would want this directory: <ftp://tug.org/historic/systems/texlive/2014/tlnet-final/>.\nDownload in one go using:\n\n```bash\nwget --recursive --no-clobber ftp://tug.org/historic/systems/texlive/2014/tlnet-final\n```\n\nThe `--no-clobber` option allows you to restart the download at will.\nThen, work with the `--repository=/some/local/path` option of `install-tl`, after [copying the archive directory into the image at build time](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#understand-build-context) (see also [here](https://tex.stackexchange.com/a/374651/120853)).\nHaving a local copy circumvents [unstable connections](https://tex.stackexchange.com/q/370686/120853) and minimizes unnecessary load onto TUG servers.\n"
  },
  {
    "path": ".devcontainer/image/config/.wgetrc",
    "content": "# wget config file\n\n# TeXLive uses wget. Make wget as robust as possible here.\n# Make downloading as robust as possible since TeXLive/TUG servers can be unreliable.\n# If we leave downloading to the install script, we cannot influence the parameters\n# and it might fail without retrying and for unfortunate reasons at that (like\n# failing the entire install an hour in because of one package that failed to\n# download). All of this is exacerbated using Docker, since we are building remotely\n# on their infrastructure, which is inaccessible. A failure after 8h of queue and\n# 2h of build time due to unstable downloads is annoying.\n# See also:\n# https://www.gnu.org/software/wget/manual/wget.html#Startup-File\n# https://superuser.com/a/689340/1144470\n# https://www.gnu.org/software/wget/manual/html_node/Sample-Wgetrc.html\n\nretry_connrefused = on\nwait_retry = 120\nread_timeout = 20\ntimeout = 15\ntries = 5\n\n# Setting the following option to `on` can give:\n# install-tl: open tlpdb(ftp://tug.org/historic/systems/texlive/2016/tlnet-final/tlpkg/texlive.tlpdb) failed: Inappropriate ioctl for device at tlpkg/TeXLive/TLPDB.pm line 359.\n# no-clobber = off\n"
  },
  {
    "path": ".devcontainer/image/config/texlive.profile",
    "content": "# -------------------------------------------------------------------------------\n# TeX Live profile to configure the installation procedure, enabling headless/\n# unattended install.\n# For more info, see: https://www.tug.org/texlive/doc/install-tl.html#PROFILES\n# -------------------------------------------------------------------------------\n# File has to have LF line endings to work with `install-tl` Perl script!\n# -------------------------------------------------------------------------------\n\n# We do a manual-ish install, do not use premade scheme:\nselected_scheme scheme-custom\n\n# -------------------------------------------------------------------------------\n# The below directories are the installation destinations.\n# An alternative to using the setting here is to set environment variables like\n# `TEXLIVE_INSTALL_TEXMFHOME` directly (e.g. in the Dockerfile), but as of late,\n# `install-tl` claims to ignore environment variables when installing from a profile\n# file (\"Environment variables are ignored\"):\n# https://web.archive.org/web/20201122233159/https://www.tug.org/texlive/doc/install-tl.html#OPTIONS\n# So with this profile file guaranteed to work and parallel environment variables\n# *maybe* breaking in the future, use this profile file for everything.\n# Replace the below environment variables with appropriate values (this is automated\n# in the Dockerfile using `envsubst`).\n# -------------------------------------------------------------------------------\n\n# See: https://www.tug.org/texlive/doc/install-tl.html#ENVIRONMENT-VARIABLES,\n# https://tex.stackexchange.com/a/470341/120853.\n# IMPORTANT: Put these into the actual designated container's user's home for full\n# write access. Otherwise, we run into all sorts of annoying errors, like\n# https://tex.stackexchange.com/q/571021/120853.\n# The user we run this as is specified in the Dockerfile and inserted into here.\nTEXMFHOME /home/${USER}/texmf\nTEXMFVAR /home/${USER}/.texlive/texmf-var\nTEXMFCONFIG /home/${USER}/.texlive/texmf-config\n\n# Not required, left at default:\n# TEXDIR /usr/local/texlive/<version>\n# TEXMFSYSCONFIG /usr/local/texlive/<version>/texmf-config\n# TEXMFSYSVAR /usr/local/texlive/<version>/texmf-var\n# TEXMFLOCAL /usr/local/texlive/texmf-local\n#\n# -------------------------------------------------------------------------------\n# Collections of packages; for their contents, see\n# http://mirror.ctan.org/systems/texlive/tlnet/tlpkg/texlive.tlpdb\n# and search for 'name collection-<name>', e.g. 'name collection-basic'.\n# At the time of writing, the following encompasses all available collections.\n# Only the core ones with very few supported languages are enabled. For example,\n# just including 'collection-langjapanese' requires 800MB of space.\n# -------------------------------------------------------------------------------\ncollection-basic 1\ncollection-bibtexextra 1\ncollection-binextra 1\ncollection-fontsextra 1\ncollection-fontsrecommended 1\ncollection-fontutils 1\ncollection-formatsextra 1\ncollection-langenglish 1\ncollection-langeuropean 1\ncollection-langgerman 1\ncollection-latex 1\ncollection-latexextra 1\ncollection-latexrecommended 1\ncollection-luatex 1\ncollection-mathscience 1\ncollection-pictures 1\ncollection-plaingeneric 1\ncollection-publishers 1\ncollection-xetex 1\n# -------------------------------------------------------------------------------\n# Enable the following disabled ones as needed. They are included here so\n# everyone can see what is available; as many as possible are disabled, since\n# image size matters. The default is aimed at documents in the sciences domain.\n# Therefore, everything else is disabled. This includes various languages, so\n# activate your missing language here!\n# -------------------------------------------------------------------------------\ncollection-context 0\ncollection-games 0\ncollection-humanities 0\ncollection-langarabic 0\ncollection-langchinese 0\ncollection-langcjk 0\ncollection-langcyrillic 0\ncollection-langczechslovak 0\ncollection-langfrench 0\ncollection-langgreek 0\ncollection-langitalian 0\ncollection-langjapanese 0\ncollection-langkorean 0\ncollection-langother 0\ncollection-langpolish 0\ncollection-langportuguese 0\ncollection-langspanish 0\ncollection-metapost 0\ncollection-music 0\ncollection-pstricks 0\ncollection-texworks 0\ncollection-wintools 0\n# -------------------------------------------------------------------------------\n# Options for TeXLive installation\n# -------------------------------------------------------------------------------\n# Create symlinks in standard PATH directories (TeXLive installs into `TEXDIR`,\n# see its path above). Instead of manipulating PATH, symlinks to `TEXDIR` are\n# created, per default into `/usr/local/bin`.\n# This setting is required to find tools!\n# WARNING: This seems to only have been introduced in TeXLive 2017, see:\n# https://web.archive.org/web/20171213102459/http://www.tug.org/texlive/doc/install-tl.html\n# (archives from 2016 and earlier do not mention `adjustpath` on that page).\n#\n# At the same time, TeXLive 2020 does not seem to respect the set `TEXDIR`, breaking\n# installation. However, adjusting the path here automatically works.\n# Since older installations will simply ignore this setting, enable it for safety.\ninstopt_adjustpath 1\n# Do not adjust remote CTAN repository; keep the one manually specified.\n# Shouldn't matter since the repository is not used after installation/image build.\ninstopt_adjustrepo 0\n# A4 default, not letter format\ninstopt_letter 0\n# No portable installation required\ninstopt_portable 0\n# Required for --shell-escape option, as required by packages, e.g. `svg`\ninstopt_write18_restricted 1\n# -------------------------------------------------------------------------------\n# Some more documentation for the following options at:\n# https://tug.org/texlive/doc/tlmgr.html\n# -------------------------------------------------------------------------------\n# Autobackup just fills cache, skip; see\n# https://tex.stackexchange.com/a/398831/120853\ntlpdbopt_autobackup 0\ntlpdbopt_backupdir tlpkg/backups\n# Create font format files, otherwise they have to be created on the fly each\n# time.\ntlpdbopt_create_formats 1\n# None of the following is required; especially not documentation and source\n# files, which fill multiple GBs\ntlpdbopt_desktop_integration 0\ntlpdbopt_file_assocs 0\ntlpdbopt_generate_updmap 0\ntlpdbopt_install_docfiles 0\ntlpdbopt_install_srcfiles 0\n#\n# Execute postinstallation code for packages:\ntlpdbopt_post_code 1\n# Symlink destinations (binaries, documentation, manuals).\n# Since symlinking is done manually in the Dockerfile, these are not needed.\n# tlpdbopt_sys_bin /usr/local/bin\n# tlpdbopt_sys_info /usr/local/share/info\n# tlpdbopt_sys_man /usr/local/share/man\n"
  },
  {
    "path": ".devcontainer/image/texlive.sh",
    "content": "#!/bin/bash\n\n# Script to fetch `install-tl` script from different sources, depending on argument\n# given.\n\nset -ueo pipefail\n\nusage() {\n    echo \"Usage: $0 get_installer|install latest|version (YYYY)\"\n}\n\n# From: https://stackoverflow.com/a/2990533/11477374\nechoerr() { echo \"$@\" 1>&2; }\n\ncheck_path() {\n    # The following test assumes the most basic program, `tex`, is present, see also\n    # https://www.tug.org/texlive/doc/texlive-en/texlive-en.html#x1-380003.5\n    echo \"Checking PATH and installation...\"\n    if tex --version\n    then\n        echo \"PATH and installation seem OK, exiting with success.\"\n        exit 0\n    else\n        echoerr \"PATH or installation unhealthy, further action required...\"\n    fi\n}\n\nif [[ $# != 2 ]]; then\n    echoerr \"Unsuitable number of arguments given.\"\n    echoerr \"Got arguments: $*\"\n    usage\n    # From /usr/include/sysexits.h\n    exit 64\nfi\n\n# Bind CLI arguments to explicit names:\nACTION=${1}\nVERSION=${2}\n\n# Download the `install-tl` script from the `tlnet-final` subdirectory, NOT\n# from the parent directory. The latter contains an outdated, non-final `install-tl`\n# script, causing this exact problem:\n# https://tug.org/pipermail/tex-live/2017-June/040376.html\nHISTORIC_URL=\"ftp://tug.org/historic/systems/texlive/${VERSION}/tlnet-final\"\nREGULAR_URL=\"http://mirror.ctan.org/systems/texlive/tlnet\"\n\ncase ${ACTION} in\n    \"get_installer\")\n        if [[ ${VERSION} == \"latest\" ]]\n        then\n            # Get from default, current repository\n            GET_URL=\"${REGULAR_URL}/${TL_INSTALL_ARCHIVE}\"\n        else\n            # Get from historic repository\n            GET_URL=\"${HISTORIC_URL}/${TL_INSTALL_ARCHIVE}\"\n        fi\n        wget \"$GET_URL\"\n    ;;\n    \"install\")\n        if [[ ${VERSION} == \"latest\" ]]\n        then\n            # Install using default, current repository.\n            # Install process/script documentation is here:\n            # https://www.tug.org/texlive/doc/texlive-en/texlive-en.html\n            perl install-tl \\\n                --profile=\"$TL_PROFILE\"\n        else\n            # Install using historic repository (`install-tl` script and repository\n            # versions need to match)\n            perl install-tl \\\n                --profile=\"$TL_PROFILE\" \\\n                --repository=\"$HISTORIC_URL\"\n        fi\n\n        # If automatic `install-tl` process has already adjusted PATH, we are happy.\n        check_path\n        echo \"install-tl procedure did not adjust PATH automatically, trying other options...\"\n\n        # `\\d` class doesn't exist for basic `grep`, use `0-9`, which is much more\n        # portable. Finding the initial dir is very fast, but looking through everything\n        # else afterwards might take a while. Therefore, print and quit after first result.\n        # Path example: `/usr/local/texlive/2018/bin/x86_64-linux`\n        TEXLIVE_BIN_DIR=$(find / -type d -regextype grep -regex '.*/texlive/[0-9]\\{4\\}/bin/.*' -print -quit)\n\n        # -z test: string zero length?\n        if [ -z \"$TEXLIVE_BIN_DIR\" ]\n        then\n            echoerr \"Expected TeXLive installation dir not found and TeXLive installation did not modify PATH automatically.\"\n            echoerr \"Exiting.\"\n            exit 1\n        fi\n\n        echo \"Found TeXLive binaries at $TEXLIVE_BIN_DIR\"\n        echo \"Trying native TeXLive symlinking using tlmgr...\"\n\n        # To my amazement, `tlmgr path add` can fail but still link successfully. So\n        # check if PATH is OK despite that command failing.\n        \"$TEXLIVE_BIN_DIR\"/tlmgr path add || \\\n            echoerr \"Command borked, checking if it worked regardless...\"\n        check_path\n        echoerr \"Symlinking using tlmgr did not succeed, trying manual linking...\"\n\n        SYMLINK_DESTINATION=\"/usr/local/bin\"\n\n        # \"String contains\", see: https://stackoverflow.com/a/229606/11477374\n        if [[ ! ${PATH} == *${SYMLINK_DESTINATION}* ]]\n        then\n            # Should never get here, but make sure.\n            echoerr \"Symlink destination ${SYMLINK_DESTINATION} not in PATH (${PATH}), exiting.\"\n            exit 1\n        fi\n\n        echo \"Symlinking TeXLive binaries in ${TEXLIVE_BIN_DIR}\"\n        echo \"to a directory (${SYMLINK_DESTINATION}) found on PATH (${PATH})\"\n\n        # Notice the slash and wildcard.\n        ln \\\n            --symbolic \\\n            --verbose \\\n            --target-directory=\"$SYMLINK_DESTINATION\" \\\n            \"$TEXLIVE_BIN_DIR\"/*\n\n        check_path\n\n        echoerr \"All attempts failed, exiting.\"\n        exit 1\n    ;;\n    *)\n        echoerr \"Input not understood.\"\n        usage\n        # From /usr/include/sysexits.h\n        exit 64\nesac\n"
  },
  {
    "path": ".gitattributes",
    "content": "# bib -> latex does not help much, since it is also not valid latex, but at\n# least highlights comments (%) correctly\n*.bib linguist-language=latex\n\n# Bash is wrong, it is really a plain-text file.\n# However, it gets us comment highlighting (hiding/grey) and is close enough.\n*.profile linguist-language=bash\n\n# Do not include git config files in archives (e.g. when downloading as ZIP):\n.git* export-ignore\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Building and testing\non: [push]\njobs:\n  building:\n    runs-on: ubuntu-latest\n    container:\n      image: alexpovel/latex\n      # Need root, otherwise this exact issue occurs:\n      # https://github.community/t/permission-problems-when-checking-out-code-as-part-of-github-action/202263\n      options: --user root\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n      - name: Run preflight checks\n        run: make preflight\n      - name: Build all LaTeX PDFs\n        run: make tex\n      - name: Build README PDF\n        run: make README.pdf\n      - name: Archive compilation artifacts\n        uses: actions/upload-artifact@v7\n        with:\n          name: pdfs\n          path: ./*.pdf\n          if-no-files-found: error\n  testing:\n    needs: building\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n          cache: \"pip\"\n      - name: Install Python dependencies\n        working-directory: ./tests # Needs to find pyproject.toml file\n        run: >\n          python -m venv .venv\n          && . .venv/bin/activate\n          && pip install .\n      - name: Test the suite itself\n        run: >\n          . ./tests/.venv/bin/activate\n          && make test-self\n      - uses: actions/download-artifact@v8\n        with:\n          name: pdfs # Specify name, else it'll be downloaded to a subdirectory\n      - name: Test generated PDFs\n        run: >\n          . ./tests/.venv/bin/activate\n          && make test-pdfs\n"
  },
  {
    "path": ".gitignore",
    "content": "# This file tells git what files *not* to track in its version control.\n# Specific files, general suffixes, whole directories etc. can be specified.\n\n# ======================================================================================\n# Python (https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore)\n# ======================================================================================\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\nshare/python-wheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.nox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n*.py,cover\n.hypothesis/\n.pytest_cache/\ncover/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\ndb.sqlite3-journal\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\n.pybuilder/\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# IPython\nprofile_default/\nipython_config.py\n\n# pyenv\n#   For a library or package, you might want to ignore these files since the code is\n#   intended to run in multiple environments; otherwise, check them in:\n# .python-version\n\n# pipenv\n#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.\n#   However, in case of collaboration, if having platform-specific dependencies or dependencies\n#   having no cross-platform support, pipenv may install dependencies that don't work, or not\n#   install all needed dependencies.\n#Pipfile.lock\n\n# PEP 582; used by e.g. github.com/David-OConnor/pyflow\n__pypackages__/\n\n# Celery stuff\ncelerybeat-schedule\ncelerybeat.pid\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# Pyre type checker\n.pyre/\n\n# pytype static type analyzer\n.pytype/\n\n# Cython debug symbols\ncython_debug/\n\n# ======================================================================================\n# LaTeX\n# ======================================================================================\n\n# Generated PDF is not suitable for Git. We get our compiled PDF via CI.\n# Only ignore root level PDF, since images/vectors might be in PDF format.\n/*.pdf\n\nEisvogel*/\n\n# Testing environment\ntesting.tex\n\n# Some weird junk file from VSCode LaTeX Workshop?\n__latexindent_temp.tex\n\n# Include settings files, but nothing else, since that is used as part of the cookbook\n.vscode/*\n!.vscode/settings.json\n!.vscode/extensions.json\n\norganisational/\n\n# Used to generate the 'dirty directory tree'\ndirty_directory/\n\n# Temporarily generated files using gnuplot (e.g. 'contour gnuplot') with pgfplots. Filenames are of the form '<main tex file name>_contourtmp_<sequential numbering>.<ext>\n# Extensions <ext> are 'dat', 'table', 'script'\n*contourtmp*\n\n# Automatically generated files by svg package:\n**/svg-inkscape/*\n\n## Core latex/pdflatex auxiliary files:\n*.aux\n*.lof\n*.log\n# List of Reactions (`chemmacros`):\n*.lor\n*.lot\n*.fls\n*.out\n*.toc\n*.fmt\n*.fot\n*.cb\n*.cb2\n.*.lb\n\n## Intermediate documents:\n*.dvi\n*.xdv\n*-converted-to.*\n# these rules might exclude image files for figures etc.\n# *.ps\n# *.eps\n# *.pdf\n\n## Generated if empty string is given at \"Please type another file name for output:\"\n.pdf\n\n## Bibliography auxiliary files (bibtex/biblatex/biber):\n*.bbl\n*.bcf\n*.blg\n*-blx.aux\n*-blx.bib\n*.run.xml\n\n## Build tool auxiliary files:\n*.fdb_latexmk\n*.synctex\n*.synctex(busy)\n*.synctex.gz\n*.synctex.gz(busy)\n*.pdfsync\n\n## Build tool directories for auxiliary files\n# latexrun\nlatex.out/\n\n## Auxiliary and intermediate files from other packages:\n# algorithms\n*.alg\n*.loa\n\n# achemso\nacs-*.bib\n\n# amsthm\n*.thm\n\n# beamer\n*.nav\n*.pre\n*.snm\n*.vrb\n\n# changes\n*.soc\n\n# comment\n*.cut\n\n# cprotect\n*.cpt\n\n# elsarticle (documentclass of Elsevier journals)\n*.spl\n\n# endnotes\n*.ent\n\n# fixme\n*.lox\n\n# feynmf/feynmp\n*.mf\n*.mp\n*.t[1-9]\n*.t[1-9][0-9]\n*.tfm\n\n#(r)(e)ledmac/(r)(e)ledpar\n*.end\n*.?end\n*.[1-9]\n*.[1-9][0-9]\n*.[1-9][0-9][0-9]\n*.[1-9]R\n*.[1-9][0-9]R\n*.[1-9][0-9][0-9]R\n*.eledsec[1-9]\n*.eledsec[1-9]R\n*.eledsec[1-9][0-9]\n*.eledsec[1-9][0-9]R\n*.eledsec[1-9][0-9][0-9]\n*.eledsec[1-9][0-9][0-9]R\n\n# glossaries\n*.acn\n*.acr\n*.glg\n*.glo\n*.gls\n*.glsdefs\n\n# gnuplottex\n*-gnuplottex-*\n\n# gregoriotex\n*.gaux\n*.gtex\n\n# htlatex\n*.4ct\n*.4tc\n*.idv\n*.lg\n*.trc\n*.xref\n\n# hyperref\n*.brf\n\n# knitr\n*-concordance.tex\n# TODO Comment the next line if you want to keep your tikz graphics files\n*.tikz\n*-tikzDictionary\n\n# listings\n*.lol\n\n# makeidx\n*.idx\n*.ilg\n*.ind\n*.ist\n\n# minitoc\n*.maf\n*.mlf\n*.mlt\n*.mtc[0-9]*\n*.slf[0-9]*\n*.slt[0-9]*\n*.stc[0-9]*\n\n# minted\n_minted*\n*.pyg\n\n# morewrites\n*.mw\n\n# nomencl\n*.nlg\n*.nlo\n*.nls\n\n# pax\n*.pax\n\n# pdfpcnotes\n*.pdfpc\n\n# sagetex\n*.sagetex.sage\n*.sagetex.py\n*.sagetex.scmd\n\n# scrwfile\n*.wrt\n\n# sympy\n*.sout\n*.sympy\nsympy-plots-for-*.tex/\n\n# pdfcomment\n*.upa\n*.upb\n\n# pythontex\n*.pytxcode\npythontex-files-*/\n\n# tcolorbox\n*.listing\n\n# thmtools\n*.loe\n\n# TikZ & PGF\n*.dpth\n*.md5\n*.auxlock\n\n# todonotes\n*.tdo\n\n# vhistory\n*.hst\n*.ver\n\n# easy-todo\n*.lod\n\n# xcolor\n*.xcp\n\n# xmpincl\n*.xmpi\n\n# xindy\n*.xdy\n\n# xypic precompiled matrices\n*.xyc\n\n# endfloat\n*.ttt\n*.fff\n\n# Latexian\nTSWLatexianTemp*\n\n## Editors:\n# WinEdt\n*.bak\n*.sav\n\n# Texpad\n.texpadtmp\n\n# LyX\n*.lyx~\n\n# Kile\n*.backup\n\n# KBibTeX\n*~[0-9]*\n\n# auto folder when using emacs and auctex\n./auto/*\n*.el\n\n# expex forward references with \\gathertags\n*-tags.tex\n\n# standalone packages\n*.sta\n\n# tikz externalize with make-list option\n*.makefile\n\n# Glossaries:\n*.slg\n*.slo\n*.sls\n\n# Illustrations Custom Environment and Aux File:\n\n*.illustrations\n\n# from glossaries-extra with bib2gls\n*.glstex\n*.syi\n*.syg\n\n# windows thumbnail cache:\nThumbs.db\n"
  },
  {
    "path": ".latexmkrc",
    "content": "#!/bin/env perl\n\n# This file contains instructions and configurations for the `latexmk` program.\n# That program is somewhat like `make`, but tailored to LaTeX.\n# LaTeX has a distinct characteristic of regularly requiring *multiple runs* of\n# the same program (e.g. `lualatex`) before the build is finished.\n# It's a *multi-pass* system.\n# In the intermediary runs, latex generates auxiliary files responsible for resolving\n# references, links, tables of content etc.\n\n# `latexmk` knows about these dependencies (otherwise we tell it in this very config\n# file, see below), detects these and runs latex (and other, outside programs)\n# accordingly.\n\n# Now, why do we need *both* `latexmk` and `make`?\n# Both automate builds.\n\n# `latexmk` is not powerful enough to cover all use cases.\n# `make` is more general and more suitable to be integrated in CI.\n# For our latex needs, `make` basically only delegates to `latexmk`.\n# We **do not** call e.g. `lualatex` multiple times manually from `make`:\n# this logic is left to `latexmk` and `.latexmkrc`.\n# However, `make` can also do much more, e.g. cover `pandoc`, clean-up operations etc.\n# Therefore, `make` and `latexmkrc` *together* are just super powerful and useful.\n\n\n# The shebang at the top  is only to get syntax highlighting right across GitLab,\n# GitHub and IDEs.\n# This file is not meant to be run, but read by `latexmk`.\n\n# ======================================================================================\n# Perl `latexmk` configuration file\n# ======================================================================================\n\n# ======================================================================================\n# PDF Generation/Building/Compilation\n# ======================================================================================\n\n# PDF-generating modes are:\n# 1: pdflatex, as specified by $pdflatex variable (still largely in use)\n# 2: postscript conversion, as specified by the $ps2pdf variable (useless)\n# 3: dvi conversion, as specified by the $dvipdf variable (useless)\n# 4: lualatex, as specified by the $lualatex variable (best)\n# 5: xelatex, as specified by the $xelatex variable (second best)\n$pdf_mode = 4;\n\n# Treat undefined references and citations as well as multiply defined references as\n# ERRORS instead of WARNINGS.\n# This is only checked in the *last* run, since naturally, there are undefined references\n# in initial runs.\n# This setting is potentially annoying when debugging/editing, but highly desirable\n# in the CI pipeline, where such a warning should result in a failed pipeline, since the\n# final document is incomplete/corrupted.\n#\n# However, I could not eradicate all warnings, so that `latexmk` currently fails with\n# this option enabled.\n# Specifically, `microtype` fails together with `fontawesome`/`fontawesome5`, see:\n# https://tex.stackexchange.com/a/547514/120853\n# The fix in that answer did not help.\n# Setting `verbose=silent` to mute `microtype` warnings did not work.\n# Switching between `fontawesome` and `fontawesome5` did not help.\n$warnings_as_errors = 0;\n\n# Show used CPU time. Looks like: https://tex.stackexchange.com/a/312224/120853\n$show_time = 1;\n\n# Default is 5; we seem to need more owed to the complexity of the document.\n# Actual documents probably don't need this many since they won't use all features,\n# plus won't be compiling from cold each time.\n$max_repeat=7;\n\n# --shell-escape option (execution of code outside of latex) is required for the\n#'svg' package.\n# It converts raw SVG files to the PDF+PDF_TEX combo using InkScape.\n#\n# SyncTeX allows to jump between source (code) and output (PDF) in IDEs with support\n# (many have it). A value of `1` is enabled (gzipped), `-1` is enabled but uncompressed,\n# `0` is off.\n# Testing in VSCode w/ LaTeX Workshop only worked for the compressed version.\n# Adjust this as needed. Of course, only relevant for local use, no effect on a remote\n# CI pipeline (except for slower compilation, probably).\n#\n# %O and %S will forward Options and the Source file, respectively, given to latexmk.\n#\n# `set_tex_cmds` applies to all *latex commands (latex, xelatex, lualatex, ...), so\n# no need to specify these each. This allows to simply change `$pdf_mode` to get a\n# different engine. Check if this works with `latexmk --commands`.\nset_tex_cmds(\"--shell-escape --synctex=1 %O %S\");\n\n# option 2 is same as 1 (run biber when necessary), but also deletes the\n# regeneratable bbl-file in a clenaup (`latexmk -c`). Do not use if original\n# bib file is not available!\n$bibtex_use = 2;  # default: 1\n\n# Change default `biber` call, help catch errors faster/clearer. See\n# https://web.archive.org/web/20200526101657/https://www.semipol.de/2018/06/12/latex-best-practices.html#database-entries\n$biber = \"biber --validate-datamodel %O %S\";\n\n# ======================================================================================\n# Auxiliary Files\n# ======================================================================================\n\n# Let latexmk know about generated files, so they can be used to detect if a\n# rerun is required, or be deleted in a cleanup.\n# loe: List of Examples (KOMAScript)\n# lol: List of Listings (`listings` and `minted` packages)\n# run.xml: biber runs\n# glg: glossaries log\n# glstex: generated from glossaries-extra\npush @generated_exts, 'loe', 'lol', 'lor', 'run.xml', 'glg', 'glstex';\n\n# Also delete the *.glstex files from package glossaries-extra. Problem is,\n# that that package generates files of the form \"basename-digit.glstex\" if\n# multiple glossaries are present. Latexmk looks for \"basename.glstex\" and so\n# does not find those. For that purpose, use wildcard.\n# Also delete files generated by gnuplot/pgfplots contour plots\n# (.dat, .script, .table).\n$clean_ext = \"%R-*.glstex %R_contourtmp*.*\";\n\n# ======================================================================================\n# bib2gls as a custom dependency\n# ======================================================================================\n\n# Grabbed from latexmk CTAN distribution:\n# Implementing glossary with bib2gls and glossaries-extra, with the\n# log file (.glg) analyzed to get dependence on a .bib file.\n# !!! ONLY WORKS WITH VERSION 4.54 or higher of latexmk\n\n# Add custom dependency.\n# latexmk checks whether a file with ending as given in the 2nd\n# argument exists ('toextension'). If yes, check if file with\n# ending as in first argument ('fromextension') exists. If yes,\n# run subroutine as given in fourth argument.\n# Third argument is whether file MUST exist. If 0, no action taken.\nadd_cus_dep('aux', 'glstex', 0, 'run_bib2gls');\n\n# PERL subroutine. $_[0] is the argument (filename in this case).\n# File from author from here: https://tex.stackexchange.com/a/401979/120853\nsub run_bib2gls {\n    if ( $silent ) {\n    #    my $ret = system \"bib2gls --silent --group '$_[0]'\"; # Original version\n        my $ret = system \"bib2gls --silent --group $_[0]\"; # Runs in PowerShell\n    } else {\n    #    my $ret = system \"bib2gls --group '$_[0]'\"; # Original version\n        my $ret = system \"bib2gls --group $_[0]\"; # Runs in PowerShell\n    };\n\n    my ($base, $path) = fileparse( $_[0] );\n    if ($path && -e \"$base.glstex\") {\n        rename \"$base.glstex\", \"$path$base.glstex\";\n    }\n\n    # Analyze log file.\n    local *LOG;\n    $LOG = \"$_[0].glg\";\n    if (!$ret && -e $LOG) {\n        open LOG, \"<$LOG\";\n    while (<LOG>) {\n            if (/^Reading (.*\\.bib)\\s$/) {\n        rdb_ensure_file( $rule, $1 );\n        }\n    }\n    close LOG;\n    }\n    return $ret;\n}\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n\t// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.\n\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp\n\t// List of extensions which should be recommended for users of this workspace.\n\t\"recommendations\": [\n\t\t\"ms-vscode-remote.remote-containers\",\n\t\t\"James-Yu.latex-workshop\"\n\t],\n\t// List of extensions recommended by VS Code that should not be recommended for users of this workspace.\n\t\"unwantedRecommendations\": []\n}"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"latex-workshop.latex.recipes\": [\n        {\n            \"name\": \"latexmk\",\n            \"tools\": [\n                \"latexmk\"\n            ]\n        },\n        {\n            \"name\": \"lualatex\",\n            \"tools\": [\n                \"lualatex\"\n            ]\n        }\n    ],\n    \"latex-workshop.latex.tools\": [\n        {\n            \"name\": \"lualatex\",\n            \"command\": \"lualatex\",\n            \"args\": [\n                \"--shell-escape\",\n                \"--synctex=1\",\n                \"--recorder\",\n                \"%DOC%\"\n            ]\n        },\n        {\n            \"name\": \"latexmk\",\n            \"command\": \"latexmk\",\n            \"args\": [\n                // latexmk doesn't need a file argument, but provide it to avoid running\n                // on *all* found tex files\n                \"%DOC%\"\n            ]\n        }\n    ],\n    \"latex-workshop.latex.recipe.default\": \"first\",\n    \"latex-workshop.linting.chktex.enabled\": true,\n    \"latex-workshop.linting.run\": \"onSave\",\n    \"latex-workshop.latex.autoBuild.run\": \"never\",\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n## [5.0.0] - 2022-05-11\n\n### Added\n\n- GitHub Actions configuration (b847c85)\n\n  This is supposed to replace the GitLab config.\n\n### Changed\n\n- GitLab references to point to GitHub instead (7a33ee3)\n- Updated Python test suite from 3.7 to 3.10 (0733c83)\n- Simplified `polyglossia` language loading (053b87d)\n- Switched VSCode Remote Containers config from building to downloading image (4efd364).\n\n  When new users first use this template, it is extremely frustrating for them to have to *build* the entire Docker image from scratch themselves, which can take very long.\n  Simply download the existing one from DockerHub, which is much faster.\n\n### Removed\n\n- GitLab-specific content (config files, documentation, ...) (7a33ee3)\n- Deprecated `chemmacros` `usechemmodule` macro (0909097)\n- Profanity check in PDF test (0733c83)\n\n## [4.0.0] - 2021-10-18\n\n### Added\n\n- `matlab2tikz` improved alternative showcase using `pgfplots` (0910bca)\n- Important badges of high importance for important information (d19b8d9)\n- Hint on `parskip` usage to remove paragraph indentation in favor of vertical space (a292f6b)\n- Support for *Acronyms* glossary title localization (86c0be1)\n- New package for tables, `tabularray` (6825ff9, 480b400)\n- Docker image source (merged in c584129)\n- Additional math/unit font examples (2e3a582)\n\n### Fixed\n\n- Display of dimensionless quantities (5f8dc71)\n- Tabular vertical excess white space (e5f983e)\n\n### Changed\n\n- usage of `chemmacros` over `chemformula` (e379fa9, c26d613)\n- `siunitx` settings and usage to support [major version 3](https://github.com/josephwright/siunitx/blob/v3.0.0/CHANGELOG.md#v300) (bb931a9, 4fc2caf, 6747a36, 190bc89, e83902a, 82977ce)\n- Docker image source (b50eb6f, f10005e, 548dca9, a8fff45, afa8407, 3a0b4f0, a57a4ec)\n- massive simplification/moving of README content (f8f4d3f, 2925463, 2840312, a99df09, bcb4d69)\n\n### Removed\n\n- LaTeX Workshop automatic compilation on save (6b0d313)\n- Old files (6fbdc2e, 04eb8fe, 096331c, b37316d, cdc285d)\n\n## [3.1.0] - 2021-03-12\n\n### Added\n\n- Toggle for inclusion of glossaries in the Table of Contents (ToC) (5c23bd0)\n- Example for an appendix (d4a42ce)\n- Translations for code listings in references, lists, captions (6148d55)\n- ARCHITECTURE document (840eff8)\n- Example for a `longtabu` (multi-page table) displaying random data generated by custom Lua script (9e89214)\n- Section on alternative ways to compile (f2d550d)\n- Configuration and ideal setup for working with this template inside Visual Studio Code, using its native container development environment (38a0bb2)\n- Example for a new unit specification using `siunitx` (7a2d0d0)\n\n### Changed\n\n- Switched bibliography generation from vanilla Zotero to Zotero with its excellent **Better Bibtex** addon (a05f5f4)\n- Fixed biblatex fields according to `biber --validate-datamodel` validation (eb068bd)\n- Fixed using a system directory for `pandoc`, which required `sudo` privileges (no just user privileges) (d8f4c1c)\n\n### Removed\n\n- TeXGyrePagella font files: use those included in the TeX distribution itself (d74c2d9)\n- Trailing whitespaces (WOW!) (d766fb6)\n\n## [3.0.0] - 2021-02-03\n\n### Added\n\n- Option to suppress printing of pages list in the glossaries (b75d3d1)\n- GitLab description templates (7038798)\n\n### Changed\n\n- Syntax highlighting now uses `minted` instead of `listings`, a backwards-incompatible change (19fbd87)\n- Documentation now stresses Docker usage over manual \"labour\" (6843a2b)\n\n### Removed\n\n- Previous, custom-made `listings` language definitions; these are covered much better by `pygments`, aka `minted` (19fbd87)\n\n## [2.0.0] - 2020-11-11\n\n### Added\n\n- Python-based tests for the produced PDFs (1746e4e).\n  This allows the user to automatically run a test suite against the produced PDFs,\n  for example checking for page count, metadata and much more.\n- Makefiles for the [root](Makefile) and [tests](tests/Makefile) directories, while\n  also swapping all CI routines over to use `make` (b4a9881).\n  This allows for local as well as CI use using the same commands, and reduces coupling\n  with the CI engine.\n- Caching of files in CI, for much faster pipelines (while introducing some issues) (28aea76).\n- Showcase and fixing of `\\abs` macro for absolute values (4d0c6ff, bb11b72).\n\n### Changed\n\n- Git metadata display in the colophon (7c59cbe).\n\n## [1.2.0] - 2020-10-29\n\n### Added\n\n- Showcase for multiple lines with contours in TikZ overlay (ae4ad39)\n- Hint for the `glossaries-extra` *Beginner's Guide* (d8b7fb4)\n- Written permission (license) to use and distribute the [Fontin Sans](https://www.fontsquirrel.com/fonts/fontin-sans)\n  font (cf79ee4)\n- Summary for font licenses (0372475)\n- Contributing guideline (56c4eac)\n- README info on git and Docker (fa228b7)\n- A `matlab2tikz` exported plot example (86dac19, c3e9b09)\n- `YAML`-based configs for pandoc (cb39706)\n- Proper check for the used TeX engine (de2a293)\n\n### Changed\n\n- Fontawesome implementation, away from the `fontawesome` package to the more\n  modern `fontawesome5` (8df784e)\n- Insertion of git metadata into the document (PDF metadata or into the printed text\n  directly): now based on Lua (6d0cd7e)\n- Also adjusted the README according to the new Lua implementation (ed946b8)\n\n## [1.1.1] - 2020-06-09\n\n### Added\n\n- Entry `Mach` in `names.bib` (d0d5683). Was previously removed, but is required.\n\n## [1.1.0] - 2020-06-09\n\n### Added\n\n- Added `bib` file entries for the built-in math macros (f1803d3b):\n  - `\\mean`\n  - `\\logmean`\n  - `\\flow`\n  - `\\difference`\n  - `\\nablaoperator`\n  - `\\vect`\n  - `\\deriv`\n  - `\\fracderiv`\n  - `\\timederiv`\n  - `\\posderiv`\n- New tabular showcasing those built-in math macros (119fce11)\n- New tabular showcasing the built-in glossary commands (0e7ed5a9):\n  - `\\idx`\n  - `\\name`\n  - `\\sym`\n  - `\\sub`\n  - `\\abb`\n  - `\\cons`\n- Added sample entries for the *Terms* index (6ca2670b)\n\n### Removed\n\n- Unused entry `Mach` in `names.bib` (c000d4ec)\n\n## [1.0.0] - 2020-04-22\n\n### Added\n\n- Initial release\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 Alex Povel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# This file contains instructions for the GNU `make` program: https://www.gnu.org/software/make/\n#\n# The program is quite old, very stable, ubiquitous and widely used.\n# It is a staple in the Linux world.\n# There are ways to get it to run on Windows, but I haven't tried any.\n# Use WSL (https://docs.microsoft.com/en-us/windows/wsl/install-win10) instead and\n# save yourself the headaches.\n\n# `make` runs steps according to this very `Makefile` in order to arrive at a target,\n# like a PDF compiled with latex.\n# It checks all the dependencies automatically and only updates the target if changes\n# in the sources are detected.\n\n# The idea is that this project's PDFs can be compiled by simply calling e.g.\n# `make file.pdf` *both locally and in CI*.\n# Without make, we would otherwise have very different build steps in local and CI\n# environments.\n# Additionally, using `make`, the CI instructions (.gitlab-ci.yml, GitHub actions etc.)\n# can be simplified considerably, leading to decoupling.\n# Moving CI systems then becomes much easier.\n\n\n# =====================================================================================\n# =====================================================================================\n# Prerequisites\n# =====================================================================================\n# =====================================================================================\n\n# The following are \"special targets\", see:\n# https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets\n# A phony target: not a file, just some routine.\n.PHONY: all clean mostlyclean clean-aux clean-pdf tex preflight help image\n\n# =====================================================================================\n# Helper tool, adjusted from:\n# https://medium.com/@exustash/three-good-practices-for-better-ci-cd-makefiles-5b93452e4cc3\n# Allows to annotate targets with regular comments and have a summary printed by calling\n# `make help`.\n# =====================================================================================\n\n# Note escaping of comment char #\nFS = \":.*?\\#\"\n\nhelp: # List available targets on this project. First one shown is the default.\n\t@grep --extended-regexp --no-filename \"\\w+$(FS) .*\" $(MAKEFILE_LIST) | \\\n\t\tawk --field-separator=\"$(FS)\" '{printf \"\\033[36m%-30s\\033[0m %s\\n\", $$1, $$2}'\n\n# =====================================================================================\n# Set variables, executables and their flags.\n# =====================================================================================\n\n# Common flags go here:\n\n# Configure latexmk tool using '.latexmkrc' in project root, not in here.\nLATEXMK_FLAGS =\n\n# For pandoc, provide dynamic metadata for the date (see below). Git short SHA works\n# both in CI and locally. All other settings are in the `defaults` file.\nPANDOC_FLAGS = --defaults=pandoc/defaults.yaml\n\n# Flags depending on CI/Local go here:\n\n# GitLab CI defines variables that we can check for. This allows us to detect if we're\n# in a CI scenario.\n# See also:\n# https://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html#Conditional-Syntax\n# https://docs.gitlab.com/ee/ci/variables/predefined_variables.html\n#\n# That same environment variable is defined for GitHub Actions as well:\n# https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables\nifdef CI\n\t# In container, run commands directly:\n\tLATEXMK = latexmk\n\tPANDOC = pandoc\n\t#\n\tGIT_SHORT_SHA = $$CI_COMMIT_SHORT_SHA\n\t# pandoc is quiet by default\n\tPANDOC_FLAGS += --verbose\n\t# After the run, display the relevant rules (for debugging)\n\tLATEXMK_FLAGS += --rules\nelse\n\tDOCKER_RUN = docker run --rm --volume ${PWD}:/tex\n\tDOCKER_IMAGE = alexpovel/latex\n\t#\n\tLATEXMK = $(DOCKER_RUN) --entrypoint=\"latexmk\" $(DOCKER_IMAGE)\n\tPANDOC = $(DOCKER_RUN) --entrypoint=\"pandoc\" $(DOCKER_IMAGE)\n\t# No supporting Docker image available yet:\n\tGIT_SHORT_SHA = $(shell git rev-parse --short HEAD)\n\t# latexmk is verbose by default:\n\tLATEXMK_FLAGS += --quiet\nendif\n\nPANDOC_FLAGS += --metadata=date:\"$(shell date --iso-8601) ($(GIT_SHORT_SHA))\"\n\n# =====================================================================================\n# =====================================================================================\n# Files to build\n# =====================================================================================\n# =====================================================================================\n\n# Produce all found tex files.\ntex_sources = $(wildcard *.tex)\ntex_pdfs := $(tex_sources:.tex=.pdf)\n\n# First rule is what is run by default if just using `make` with no arguments.\n# It is the 'goal': https://www.gnu.org/software/make/manual/html_node/Goals.html.\n# The name `all` is just a convention.\n# Change suffix of multiple different extensions (.tex, .md), to the same suffix (.pdf).\n# See also: https://stackoverflow.com/a/33926814\nall: preflight tex README.pdf test  # Performs preflight checks, then builds and tests all PDFs.\n# A rule for only LaTeX files:\ntex: $(tex_pdfs)  # Builds all *.tex files into PDFs.\n\n# =====================================================================================\n# Rules for file building\n# =====================================================================================\n\n# This Makefile uses implicit rules, see:\n# https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html#Implicit-Rules\n# For those, Automatic Variables are important:\n# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html\n# $*: \"The stem with which an implicit rule matches\"\n# $<: \"The name of the first prerequisite\"\n# $@: \"The file name of the target of the rule\"\n# $^: \"The names of all the prerequisites, with spaces between them\"\n\n# Pattern rule, see:\n# https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html,\n# Just sets up an implicit rule to specify how to get from prerequisite to target,\n# called whever `make` detects it needs to do so. No need to specify things manually.\n%.pdf: %.tex  # Allows to build any PDF from a corresponding *.tex file.\n\t$(info Running $(LATEXMK) to build $@...)\n\t@$(LATEXMK) $(LATEXMK_FLAGS) $<\n\nPANDOC_TEMPLATE = $(strip $(shell grep \"^template:\" pandoc/defaults.yaml | cut --delimiter=\":\" --field=2)).latex\nPANDOC_TEMPLATE_DIR = ~/.pandoc/templates\n\n%.pdf: %.md $(PANDOC_TEMPLATE_DIR)/$(PANDOC_TEMPLATE)  # Allows to build any PDF from a corresponding *.md file.\n\t$(info Running $(PANDOC) to build $@...)\n\t@$(PANDOC) $(PANDOC_FLAGS) --output=$@ $<\n\nEISVOGEL_ARCHIVE = Eisvogel.tar.gz\nEISVOGEL_VERSION = 3.4.0\n\n# The `$(info ...)` function gives out-of-order logging, while `echo` works with the\n# `wget` progress display.\n$(PANDOC_TEMPLATE_DIR)/$(PANDOC_TEMPLATE):\n\t@echo \"Template not found at $@, downloading...\"\n\t@wget --quiet --show-progress --no-clobber \\\n\t\t\"https://github.com/Wandmalfarbe/pandoc-latex-template/releases/download/v${EISVOGEL_VERSION}/${EISVOGEL_ARCHIVE}\"\n\t@echo \"Extracting $(EISVOGEL_ARCHIVE)...\"\n\t@tar --extract --file=${EISVOGEL_ARCHIVE} Eisvogel-${EISVOGEL_VERSION}/eisvogel.latex\n# `$(@D)` is directory part of current target:\n\t@mkdir --parents $(@D)\n\t@mv \"Eisvogel-${EISVOGEL_VERSION}/eisvogel.latex\" $@\n\t@$(RM) $(EISVOGEL_ARCHIVE)\n\n# =====================================================================================\n# Help users install programs required for compilation and help debug.\n# =====================================================================================\npreflight:  # Performs checks to ensure prerequisites for compilation are met.\n\t@echo \"Checking presence of required libraries...\"\n\t@ldconfig --print-cache | grep --silent \"librsvg\" || \\\n\t\t(echo \"librsvg missing: required by pandoc to convert files containing SVGs.\"; exit 69)\n\t@echo \"Libraries OK.\"\n# Output looks like: https://tex.stackexchange.com/a/311753/120853\n\t@$(LATEXMK) --commands\n\n# =====================================================================================\n# Docker\n# =====================================================================================\n\nimage: ./.devcontainer/image/Dockerfile\n\t@docker build --tag alexpovel/latex:local --file $< .\n\n# =====================================================================================\n# Testing.\n# =====================================================================================\n\ninclude tests/Makefile\n\n# =====================================================================================\n# Cleanup jobs.\n# =====================================================================================\nclean-aux:  # Cleans LaTeX's auxiliary files.\n\t@echo \"Removing auxiliary files of all found TeX files...\"\n\t@$(LATEXMK) -c $(LATEXMK_FLAGS)\n\nclean-pdf:  # Cleans all found PDFs.\n\t@echo \"Removing all PDF files:\"\n\t@ls *.pdf 2>/dev/null || echo \"No files to remove.\"\n\t@$(RM) *.pdf\n\n# For target name, see: https://www.gnu.org/prep/standards/html_node/Standard-Targets.html\nmostlyclean: clean-aux clean-pdf  # Runs clean-{aux,pdf}, then cleans more.\n\t@echo \"Removing downloaded pandoc archive, if any...\"\n\t@$(RM) $(EISVOGEL_ARCHIVE)\n\nclean: mostlyclean  # Runs all other clean jobs, then cleans absolutely everything.\n\t@echo \"Removing all files ignored by git (.gitignore)...\"\n\t@echo \"For safety, this is done interactively:\"\n\t@git clean -xd --interactive\n\t@echo \"Removing pandoc template...\"\n\t@$(RM) $(PANDOC_TEMPLATE_DIR)/$(PANDOC_TEMPLATE)\n"
  },
  {
    "path": "README.md",
    "content": "# LaTeX Cookbook\n\n[![Download PDF](https://img.shields.io/badge/Download-PDF-blue.svg)][download]\n\nThis repo contains a [LaTeX document](cookbook.tex), usable as a cookbook (different \"recipes\" to achieve various things in LaTeX) as well as as a template.\nThe resulting PDF covers LaTeX-specific topics and instructions on compiling the LaTeX source.\n\nSee the [releases page](https://github.com/alexpovel/latex-cookbook/releases) for more downloads.\n\n> [!IMPORTANT]\n> This project is not archived, and [issues are still\n> addressed](https://github.com/alexpovel/latex-cookbook/issues/17). However, the\n> document is regarded as \"done\" and no new feature development actively happens. As LaTeX is a glacially slow-moving target, the document\n> should be useful, valid and buildable for many years to come still.\n>\n> There is a [fork\n> maintained](https://collaborating.tuhh.de/m21/public/theses/itt-latex-template) by\n> former coworkers of the author, at the research institute this template originated\n> from as well. Active development is still happening there.\n\n## Getting started\n\nAfter installing [Docker](https://www.docker.com/) (and git), building works out of the\nbox:\n\n- Bash:\n\n  ```console\n  $ git clone git@github.com:alexpovel/latex-cookbook.git\n  $ cd latex-cookbook\n  $ docker run --rm --volume $(pwd):/tex alexpovel/latex\n  $ xdg-open cookbook.pdf\n  ```\n\n- PowerShell:\n\n  ```powershell\n  PS> git clone git@github.com:alexpovel/latex-cookbook.git\n  PS> cd latex-cookbook\n  PS> docker run --rm --volume ${PWD}:/tex alexpovel/latex\n  PS> Invoke-Item cookbook.pdf\n  ```\n\nThe [entrypoint](https://docs.docker.com/engine/reference/builder/#entrypoint) is\n[`latexmk`](https://ctan.org/pkg/latexmk?lang=en), which when given no arguments (as\ndone here) runs on all found `*.tex` files, which in this case is only the root's [main\nfile](./cookbook.tex).\n\n> [!NOTE]\n> Should this fail to compile (this is a bug, please report!), feel free to try other\n> images. When `alexpovel/latex` was built,\n> [`texlive/texlive`](https://hub.docker.com/r/texlive/texlive) did not exist yet.\n> **That image is strongly recommended**, as it is actively maintained by the actual\n> authors of TeXLive. If tools are missing, like `inkscape`, build your own image `FROM\n> texlive/texlive`, then install required software.\n>\n> Alternatively, there is [a\n> fork](https://collaborating.tuhh.de/m21/public/theses/latex_dockerfile) for the image\n> as well, accompanying the [template\n> fork](https://collaborating.tuhh.de/m21/public/theses/itt-latex-template).\n\n## Features\n\nThe [PDF itself][download] has much more to say on this and is meant to speak for itself, visually.\nThe following is simply a brief overview of the features contained in this repo.\n\n### Tooling\n\n- accompanying [Docker image](.devcontainer/image/Dockerfile), usable locally and in CI/CD, guaranteeing compilation success without interfering with your local installation.\n  In fact, using Docker (containerization in general), no LaTeX installation is required at all.\n  - accompanying Visual Studio Code [environment configuration](.devcontainer/devcontainer.json).\n\n    If you open this repository in [Visual Studio Code](https://code.visualstudio.com/), it should automatically put you into the correct Docker container environment for development, and just work™.\n    See [here](.devcontainer/README.md) for more info.\n  - in the image, [`pandoc`](https://pandoc.org/) is available with the [Eisvogel](https://github.com/Wandmalfarbe/pandoc-latex-template) template, allowing beautiful PDFs to be generated from Markdown (like this README: download it from the latest [Actions artifacts](https://github.com/alexpovel/latex-cookbook/actions); it currently looks lackluster because this README is mainly PNGs)\n- [tests](tests/config.yml) for your PDF, using Python to ensure some (basic) properties of your output adhere to expectations\n- a [Makefile](Makefile) to facilitate ease of use and platform independence (commands like `make file.pdf` work locally as well as in CI pipelines)\n\n### LaTeX-specific\n\n- full Unicode support through `lualatex`, the [successor](https://en.wikipedia.org/wiki/LuaTeX) to the obsolete `pdflatex`.\n  This also affords beautiful font typesetting through [`unicode-math`](https://ctan.org/pkg/unicode-math).\n  High-quality fonts like [TeX Gyre Pagella](https://ctan.org/pkg/tex-gyre-pagella) have all desirable font shapes available:\n  ![font-shapes](images/bitmaps/readme/font-shapes.png)\n- automatic compilation using [`latexmk`](.latexmkrc), ensuring the PDF is built fully, running all steps necessary (generation of the bibliography, glossaries, ...) automatically as needed\n- comprehensive support for:\n  - generating [indices](bib/glossaries/index/),\n  - typesetting and displaying [symbols](bib/glossaries/symbols/) in an automatically generated nomenclature,\n  - [acronyms and abbreviations](bib/glossaries/abbreviations.bib), as well as\n  - [mathematical constants](bib/glossaries/constants.bib),\n\n  made possible through [`glossaries-extra`](https://ctan.org/pkg/glossaries-extra).\n- structured and commented source code, explaining rationales and providing context\n- showcasing plotting and data display (floats):\n  - computing more complicated plots (in this example, a contour plot) *directly in LaTeX*, with no explicit outside tools used ([`gnuplot`](http://www.gnuplot.info/) is used by LaTeX in the background):\n\n    ![plot-compute](images/bitmaps/readme/plot-compute.png)\n  - ingesting a CSV directly, and plotting it (so we can skip [`matlab2tikz`](https://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz-matlab2tikz) etc.).\n    The below style is inspired by [Tufte](https://www.edwardtufte.com/tufte/):\n\n    ![plot-csv](images/bitmaps/readme/plot-csv.png)\n  - typesetting more complex tables, with footnotes, decimal alignment and more:\n\n    ![table](images/bitmaps/readme/tables.png)\n  - using tikz:\n    - for annotating bitmap graphics:\n\n      ![tikz-annotation](images/bitmaps/readme/tikz-annotations.png)\n    - for drawing diagrams (this template contains a (basic) `pgf`/`tikz` library for energy systems/thermodynamics/hydraulics/... symbols like pipes, compressors, valves, ...) and 3D sketches.\n      For a much better and comprehensive collection of TikZ examples, see [here](https://texample.net/tikz/examples/).\n\n      ![tikz-diagram](images/bitmaps/readme/tikz-diagram.png)\n      ![tikz-libaries](images/bitmaps/readme/tikz-libraries.png)\n- back-referencing of citations, using the excellent [`biblatex`](https://ctan.org/pkg/biblatex):\n\n  ![backref](images/bitmaps/readme/backref.png)\n- support for elaborate chemical reaction equations, using [`chemmacros`](https://ctan.org/pkg/chemmacros):\n\n  ![chemmacros](images/bitmaps/readme/chem.png)\n- comprehensive code syntax highlighting, thanks to [`minted`](https://ctan.org/pkg/minted) and `pygments`:\n\n  ![pygments](images/bitmaps/readme/code.png)\n- quick and structural switching of language contexts, provided by [`polyglossia`](https://ctan.org/pkg/polyglossia):\n\n  ![language](images/bitmaps/readme/language.png)\n- of course, support for enhanced mathematical typesetting, like highlighted equations or premade macros.\n  The blue color are *hyperlinks*, turning those symbols into links to the glossary (this can be toggled off).\n\n  ![math](images/bitmaps/readme/math.png)\n\n  ![math-macros](images/bitmaps/readme/math-macros.png)\n\n[download]: https://github.com/alexpovel/latex-cookbook/releases/latest/download/cookbook.pdf\n"
  },
  {
    "path": "acp.cls",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% LuaLaTeX based on KOMA-Script\n%\n% Author (2021): Alex Povel - tex(at)alexpovel.de\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Class Options\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Refer to https://www.overleaf.com/learn/latex/Writing_your_own_class\n\\NeedsTeXFormat{LaTeX2e}\n\\ProvidesClass{acp}[2021-10-06 v4.0.0 acp class]\n\n% Fail early and give useful information on the required engine.\n% This helps users who do not read the documentation beforehand, by promoting the\n% requirement from some statement in the docs to actual code that errors out.\n\\RequirePackage{iftex}\n\\RequireLuaTeX{}\n\n\\newcommand*{\\@baseclass}{scrbook}% Name of class this one is based on\n\n% If option 'language' is not given at all, use initialization 'english' as a fallback.\n% If it is called without a value, use default (or throw error of no default given)\n% This method was chosen to have the language available in a macro, so it may be passed\n% to polyglossia.\n% This approach messes with the forwarding of the language and raises a warning\n% 'Unused global options'; we can probably ignore that for now\n% (https://tex.stackexchange.com/a/278172/120853).\n\\RequirePackage{kvoptions}\n    %[default]{language} % If no default entered: option requires a value:\n    \\DeclareStringOption[english]{language}\n    \\DeclareStringOption{titlestyle}\n    \\DeclareBoolOption{censoring}% Initially false by default\n    \\ProcessKeyvalOptions*\n\n\\PassOptionsToClass{%\n    \\acp@language,% Scheme: \\filename@keyoption\n    twoside,% For printing two-sided documents\n    % 'List of (Tables, Figures, ...)' gets pushed down one hierarchical level:\n    % listof=leveldown,\n    listof=totoc,% All registered Lists of XYZ to Table of Contents\n    bibliography=totoc,\n    chapterprefix=true,% Print 'Chapter' etc. label in front of number\n    open=right,% Open new Chapters on recto pages\n    numbers=noenddot,% https://tex.stackexchange.com/a/102305/120853\n}{\\@baseclass}\n\n% Bundle 'a5' to not only have a5paper but also decrease font size.\n% https://tex.stackexchange.com/a/418947/120853\n% https://tex.stackexchange.com/a/27149/120853\n\\DeclareOption{a5}{%\n    % Not forwarded to typearea package if passed as class option: do it manually here:\n    \\PassOptionsToPackage{paper=a5}{typearea}\n    \\PassOptionsToClass{fontsize=10pt}{\\@baseclass}%\n}%\n\n% Forward all other options given to \\documentclass[] to base class:\n\\DeclareOption*{\\PassOptionsToClass{\\CurrentOption}{\\@baseclass}}\n\n\\ProcessOptions\\relax% Execute these options\n\n\\LoadClass{\\@baseclass}% Finally, load the base class\n\n\\RequirePackage[\\acp@language]{tracklang}% Language Tracking\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Typography and Misc.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{scrhack}% Fixes for packages incompatible with KOMA features\n\n\\RequirePackage{import}% Relative path imports\n\n\\RequirePackage[super]{nth}% For ordinal numbers, like \\nth{1} -> 1^{st}\n\n\\RequirePackage{etoolbox}% Programming facilities\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Translations\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Providing localization that are not automatically covered by polyglossia.\n% The commands are provided by KOMAscript.\n% Maintaining the list is not the easiest, but currently likely the best approach.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Colophon\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransCompiledOn}{Compiled on}\n\\providecaptionname{german}{\\TransCompiledOn}{Kompiliert am}\n\n\\providecaptionname{english}{\\TransLatexClass}{Class}\n\\providecaptionname{german}{\\TransLatexClass}{Klasse}\n\n\\providecaptionname{english}{\\TransGenerator}{Generator}\n\\providecaptionname{german}{\\TransGenerator}{Generiert durch}\n\n\\providecaptionname{english}{\\TransCensorNotice}{CENSORED VERSION}\n\\providecaptionname{german}{\\TransCensorNotice}{ZENSIERTE VERSION}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Task\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransPlaceDate}{Place \\& Date}\n\\providecaptionname{german}{\\TransPlaceDate}{Ort \\& Datum}\n\n\\providecaptionname{english}{\\TransTopic}{Topic}\n\\providecaptionname{german}{\\TransTopic}{Thema}\n\n\\providecaptionname{english}{\\TransTask}{Task}\n\\providecaptionname{german}{\\TransTask}{Problemstellung}\n\n\\providecaptionname{english}{\\TransFor}{For}\n\\providecaptionname{german}{\\TransFor}{Für}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Declaration of Authorship\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransAuthorshipDeclTitle}{Declaration of Authorship}\n\\providecaptionname{german}{\\TransAuthorshipDeclTitle}{Erklärung zur Eigenständigkeit}\n\n%\n% No warranty these wordings are valid in your case!\n%\n\\providecaptionname{english}{\\TransAuthorshipDeclText}{%\n    I, \\@author{}, hereby declare to be the sole, independent author of the\n    \\@documenttype{} submitted here.\n    No other than the cited references have been used.\n    Any content directly or indirectly obtained from external sources has been marked up as such.\n    This thesis has neither been submitted to a second examination authority nor been published.%\n}%\n\n\\providecaptionname{german}{\\TransAuthorshipDeclText}{%\n    Hiermit bestätige ich, \\@author{}, der alleinige und selbstständige Autor der hier\n    vorgelegten \\@documenttype{} zu sein.\n    Keine anderen als die angegebenen Quellen wurden benutzt.\n    Jeglicher aus externen Quellen direkt oder indirekt bezogene Inhalt ist als solcher markiert.\n    Diese Arbeit wurde weder einer anderen Prüfungsbehörde vorgelegt noch veröffentlicht.\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Cleveref\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransReaction}{Reaction}\n\\providecaptionname{german}{\\TransReaction}{Reaktion}\n\\providecaptionname{english}{\\TransReactions}{Reactions}\n\\providecaptionname{german}{\\TransReactions}{Reaktionen}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Glossary\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransGreek}{Greek}\n\\providecaptionname{german}{\\TransGreek}{Griech.}\n\n\\providecaptionname{english}{\\TransRoman}{Roman}\n\\providecaptionname{german}{\\TransRoman}{Röm.}\n\n\\providecaptionname{english}{\\TransOther}{Other}\n\\providecaptionname{german}{\\TransOther}{Andere}\n\n\\providecaptionname{english}{\\TransTerms}{Terms}\n\\providecaptionname{german}{\\TransTerms}{Begriffe}\n\n\\providecaptionname{english}{\\TransNames}{Names}\n\\providecaptionname{german}{\\TransNames}{Namen}\n\n\\providecaptionname{english}{\\TransAcronyms}{Acronyms}\n\\providecaptionname{german}{\\TransAcronyms}{Akronyme}\n\n\\providecaptionname{english}{\\TransSubscripts}{Subscripts}\n\\providecaptionname{german}{\\TransSubscripts}{Indizes}\n\n\\providecaptionname{english}{\\TransSuperscripts}{Superscripts}\n\\providecaptionname{german}{\\TransSuperscripts}{Hochgest.}\n\n\\providecaptionname{english}{\\TransSubSuperTitle}{Sub- and Superscripts}\n\\providecaptionname{german}{\\TransSubSuperTitle}{Indizes}\n\n\\providecaptionname{english}{\\TransUnit}{Unit}\n\\providecaptionname{german}{\\TransUnit}{Einheit}\n\n\\providecaptionname{english}{\\TransPhysicalQuantity}{Phys.\\ Qtt.}\n\\providecaptionname{german}{\\TransPhysicalUnit}{Phys.\\ Größe}\n\n\\providecaptionname{english}{\\TransFirstUse}{\\nth{1} Use}\n\\providecaptionname{german}{\\TransFirstUse}{Einführ.}\n\n\\providecaptionname{english}{\\TransShort}{Short}\n\\providecaptionname{german}{\\TransShort}{Kurz}\n\n\\providecaptionname{english}{\\TransContinued}{continued}\n\\providecaptionname{german}{\\TransContinued}{fortgesetzt}\n\n\\providecaptionname{english}{\\TransGlossaryLegend}{\n    Marked (\\specificsymbolmark) symbols possess a mass\\-/specific variant in which\n    the symbol is written in lowercase and the unit is extended by\n    \\unit[per-mode=reciprocal]{\\per\\kilogram}.\n    Alternative symbols are specified following the \\alternativesymbolmark{} mark.\n    International symbols are specified in brackets.%\n}\n\\providecaptionname{german}{\\TransGlossaryLegend}{\n    Markierte (\\specificsymbolmark) Symbole besitzen eine massenspezifische Variante,\n    bei der das Symbol als Kleinbuchstabe gesetzt und die Einheit entsprechend um\n    \\unit[per-mode=reciprocal]{\\per\\kilogram} erweitert wird.\n    Alternative Symbole sind nach \\alternativesymbolmark{} angegeben,\n    internationale Symbole in eckigen Klammern.%\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% SCRLayer\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransBlankPage}{Rest of this page intentionally left blank.}\n\\providecaptionname{german}{\\TransBlankPage}{Rest der Seite absichtlich freigelassen.}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Lists of ...\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransIllustrativeElements}{Illustrative Elements}\n\\providecaptionname{german}{\\TransIllustrativeElements}{Veranschaulichende Elemente}\n\n\\providecaptionname{english}{\\TransListOfIllustrations}{List of Illustrations}\n\\providecaptionname{german}{\\TransListOfIllustrations}{Illustrationsverzeichnis}\n\n\\providecaptionname{english}{\\TransListing}{Code Listing}\n\\providecaptionname{english}{\\TransListings}{Code Listings}% Plural for cleveref\n\n\\providecaptionname{german}{\\TransListing}{Code}\n\\providecaptionname{german}{\\TransListings}{Codes}% Plural for cleveref\n\n\\providecaptionname{english}{\\TransListOfListings}{List of Code}\n\\providecaptionname{german}{\\TransListOfListings}{Codeverzeichnis}\n\n\\providecaptionname{english}{\\TransListOfExamples}{List of Examples}\n\\providecaptionname{german}{\\TransListOfExamples}{Beispielverzeichnis}\n\n\\providecaptionname{english}{\\TransExample}{Example}\n\\providecaptionname{german}{\\TransExample}{Beispiel}\n\\providecaptionname{english}{\\TransExamples}{Examples}\n\\providecaptionname{german}{\\TransExamples}{Beispiele}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Bibliography\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransFurtherReadingTitle}{Further Reading}\n\\providecaptionname{german}{\\TransFurtherReadingTitle}{Weitere Literatur}\n\n\\providecaptionname{english}{\\TransFurtherReadingText}{%\n    The following references were used in this work but not cited in the text body;\n    they are provided here as\\-/is.\n}\n\\providecaptionname{german}{\\TransFurtherReadingText}{%\n    Die folgenden Quellen wurden im Rahmen dieser Arbeit benutzt, jedoch nicht\n    explizit zitiert.\n    Sie sind hier der Vollständigkeit halber aufgeführt.\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Other\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\providecaptionname{english}{\\TransConstant}{const}\n\\providecaptionname{german}{\\TransConstant}{konst}\n\n\\providecaptionname{english}{\\TransAdaptedFrom}{Adapted from}\n\\providecaptionname{german}{\\TransAdaptedFrom}{Adaptiert von}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Tweaks and improvements for amsmath; also loads amsmath.\n% Needs to be loaded before unicode-math!\n\\RequirePackage{mathtools}\n    % We want to be cool, so standard parantheses don't cut it:\n    \\newtagform{brackets}{[}{]}\n    \\usetagform{brackets}\n\n    % Allow multi-line environments to break across pages.\n    % While it makes sense to disallow it, not doing so can produce big spacing issues.\n    % Usually, any such environment will require manual attention.\n    % Number from 1 to 4 as optional argument:\n    % [1]: allow pagebreaks, but avoid as much as possible.\n    % [4]: maximum permissiveness\n    \\allowdisplaybreaks[2]\n\n    % Automatic macro for delimiters (parentheses, brackets, ...)\n    % Using the starred variant of the created command (like \\parens*{<content>})\n    % also scales the delimiters automatically, using \\left and \\right.\n    \\DeclarePairedDelimiter{\\parens}{(}{)}\n    \\DeclarePairedDelimiter{\\brackets}{[}{]}\n    \\DeclarePairedDelimiter{\\braces}{\\{}{\\}}\n\n% For a 'cases' environment that also supports equation numbering,\n% https://tex.stackexchange.com/a/180910/120853\n\\RequirePackage{empheq}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Colour\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Load this before unicode-math font specifications to make colors available there\n\\RequirePackage[x11names]{xcolor}% x11names provides some usable default names\n    % Shades of grey (we don't need 50 though)\n    % This is nice to have consistent color shading.\n    \\colorlet{g1}{black!70}\n    \\colorlet{g2}{black!55}\n    \\colorlet{g3}{black!40}\n    \\colorlet{g4}{black!20}\n    \\colorlet{g5}{black!10}\n    \\colorlet{g6}{black!05}\n\n    % Different fluids/materials.\n    \\definecolor{Glass}{RGB}{170, 238, 255}% Very light blue\n    \\definecolor{Air}{RGB}{213, 246, 255}% Light blue\n    \\definecolor{LightFluid}{RGB}{148, 224, 255}\n    \\definecolor{MediumFluid}{RGB}{135, 178, 232}\n    \\definecolor{DarkFluid}{RGB}{119, 151, 197}\n    \\definecolor{HotFluid}{RGB}{255, 128, 128}% 255/128/128 is same as 'red!50'\n\n    % Dark blue link color:\n    \\definecolor{darklink}{RGB}{48, 62, 116}%\n\n    % From colorbrewer's RdYlBu: from red (1) to blue (6)\n    \\definecolor{rdylbu1}{RGB}{215,  48,  39}%\n    \\definecolor{rdylbu2}{RGB}{252, 141,  89}%\n    \\definecolor{rdylbu3}{RGB}{254, 224, 144}%\n    \\definecolor{rdylbu4}{RGB}{224, 243, 248}%\n    \\definecolor{rdylbu5}{RGB}{145, 191, 219}%\n    \\definecolor{rdylbu6}{RGB}{ 69, 117, 180}%\n\n    % From colorbrewer's Set2 for qualitative data/color discernibility\n    \\definecolor{Set2A}{RGB}{102, 194, 165}%\n    \\definecolor{Set2B}{RGB}{252, 141,  98}%\n    \\definecolor{Set2C}{RGB}{141, 160, 203}%\n    \\definecolor{Set2D}{RGB}{231, 138, 195}%\n    \\definecolor{Set2E}{RGB}{166, 216,  84}%\n    \\definecolor{Set2F}{RGB}{255, 217,  47}%\n    \\definecolor{Set2G}{RGB}{229, 196, 148}%\n    \\definecolor{Set2H}{RGB}{179, 179, 179}%\n\n    % Matlab colours:\n    \\definecolor{mBlue}{HTML}{0072BD}\n    \\definecolor{mOrange}{HTML}{D95319}\n    \\definecolor{mYellow}{HTML}{EDB120}\n    \\definecolor{mPurple}{HTML}{7E2F8E}\n    \\definecolor{mGreen}{HTML}{77AC30}\n    \\definecolor{mSky}{HTML}{4DBEEE}\n    \\definecolor{mRed}{HTML}{A2142F}\n\n    % Code annotations:\n    \\definecolor{cRed}{RGB}{209,0,86}%\n    \\definecolor{cBlue}{RGB}{0, 130, 185}%\n    \\definecolor{cGreen}{RGB}{0, 128, 63}%\n    \\definecolor{cOrange}{RGB}{244, 131, 66}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Typeset code snippets\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% minted is a Python-based syntax highlighter and therefore much, much more powerful\n% than anything LaTeX-built-in\n\\RequirePackage[%\n    % `minted` uses the `float` package to provide the `[H]` float position specifier.\n    % Sadly, the `float` package is incompatible with `floatrow`, which we make heavy\n    % use of. Luckily, we can use `minted` with the `newfloat` package instead, fixing\n    % all those otherwise breaking issues.\n    % See https://tex.stackexchange.com/a/378588/120853\n    newfloat=true,%\n]{minted}\n\n    \\setminted{% Global `minted` aka code syntax highlighting options\n        % If code is indented in the LaTeX source, this is reflected in the print.\n        % This option automatically removes as much whitespace as the first line of a listing\n        % is indented by (note: requires `python` to be available, not only `pygmentize`)\n        autogobble=true,\n        %\n        % Assuming the code to be displayed is written at 80-90 characters per line,\n        % \\footnotesize makes sure it fits onto one line (roughly).\n        fontsize=\\footnotesize,\n        %\n        breaklines=true,\n        breakanywhere=false, % default \"false\"; could be ugly, only use if required\n        breakbytokenanywhere=true, % Breaks tokens on non-spaces too\n        %\n        % Regular LaTeX can occur in these (on UK Keyboard: SHIFT+`).\n        % Otherwise, you'll have to copy-paste this whenever needed.\n        % The problem is that the escapechar has to be quite exotic so it never occurs\n        % in source code.\n        escapeinside=¬¬,\n        %\n        frame=leftline, % leftline pulls it together visually quite nicely\n        framerule=1pt, % default is 0.4pt\n        rulecolor=\\color{g3},\n        %\n        numbers=left,\n        numberfirstline=true, % Always color the first line despite `stepnumber` setting\n        stepnumber=5, % Interval of line numbering\n        numbersep=2pt, % Horizontal distance between line number and line\n        %\n        % Used highlighting style, see https://pygments.org/demo/#try or `python -m pygments -L`\n        % For colorful output, I like:\n        % `paraiso-light` (prob. too light for print), `manni`, `tango`, `lovelace`\n        % For grayscale:\n        % `algol`\n        style=manni,\n    }\n\n    \\setmintedinline{% Overwrite `\\setminted` settings\n        fontsize=auto,% Reset to surrounding font size so its fits into the text flow\n    }\n\n    % Set up the floating environment, e.g. what is says in the caption of floats:\n    \\SetupFloatingEnvironment{listing}{% Requires `newfloat` usage\n        name=\\TransListing{},\n        listname=\\TransListOfListings{},\n    }\n    % Create a new environment for breaking code listings across pages.\n    \\newenvironment{longlisting}{\\captionsetup{type=listing}}{}\n    % Setup for referencing the floats correctly is done in `cleveref` settings!\n\n    % In code environments, to be able to copy from the PDF (despite that not being a good\n    % idea usually), we want the line numbers to not be part of the selection.\n    % This command prints them, but renders the actual copied content empty,\n    % on supported readers like Adobe Acrobat.\n    \\RequirePackage{accsupp}% https://tex.stackexchange.com/a/57160/120853\n\n    \\newcommand*{\\emptyaccsupp}[1]{%\n        \\BeginAccSupp{ActualText={}}#1\\EndAccSupp{}%\n    }%\n\n    \\renewcommand*{\\theFancyVerbLine}{ % Redefine how line numbers are printed\n        \\textcolor{g3}{\\ttfamily\\tiny\\emptyaccsupp{\\arabic{FancyVerbLine}}}\n    }\n\n    % Colors for escaped, normal LaTeX in code environments\n    \\newcommand*{\\phstring}[1]{%\n        \\textcolor{cRed}{#1}%\n    }%\n    \\newcommand*{\\phnum}[1]{%\n        \\textcolor{cBlue}{#1}%\n    }%\n    \\newcommand*{\\phother}[1]{%\n        \\textcolor{cGreen}{#1}%\n    }%\n    \\newcommand*{\\phnote}[1]{%\n        {%\n            \\hypersetup{allcolors=cOrange}% If references occur in here\n            \\textbf{\\textcolor{cOrange}{#1}}%\n        }%\n    }%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% TODO notes in the PDF\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{todonotes}% TODO-notes in the margins\n    \\setuptodonotes{fancyline}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Fonts\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage[\n    warnings-off={\n        % Unicode overwrites colon-commands but uses over/underbracket from mathtools\n        % and warns us; suppress this:\n        mathtools-colon,%\n        mathtools-overbracket,%\n    }\n]{unicode-math}% Builds onto fontspec and loads it automatically\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Fonts shipped with TeXLive from here: https://tug.org/FontCatalogue/\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\setmainfont[%\n    Numbers=Lowercase,% Hanging/OldStyle numbers through Lowercase numbers\n    % Color=Orange2,% Toggle color for debugging (should be xcolor name)\n]{TeX Gyre Pagella}% Load existing fond, see also https://tex.stackexchange.com/a/351100/120853\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Source: https://fonts.google.com/specimen/Inconsolata\n% (Consolas is considered better but is not free (?))\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\setmonofont[%\n    % Inconsolata doesn't have italics font, so fake it. Discouraged but should\n    % only occur in a few places in code and not be noticable there. Inconsolata\n    % is too nice to give up on it for lack of italics. See also\n    % https://tex.stackexchange.com/a/183220/120853\n    AutoFakeSlant,\n    Scale=MatchLowercase,% Prettier when using inline-code alongside our main font\n    % Color=DodgerBlue3,% Toggle color for debugging (should be xcolor name)\n]{inconsolata}%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Source: https://www.exljbris.com/fontinsans.html\n% Viable alternative: https://fonts.google.com/specimen/Fira+Sans\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\setsansfont[%\n    % Color=Red3,% Toggle color for debugging (should be xcolor name)\n]{Merriweather Sans}%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Source: https://ctan.org/texarchive/fonts/tex-gyre-math/opentype\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\setmathfont[%\n    %Set math-font-commands to new versions; use \\symbf{} instead of \\mathbf{} etc:\n    mathrm=sym,%\n    mathit=sym,%\n    mathsf=sym,%\n    mathbf=sym,%\n    mathtt=sym,%\n    % 'tpgl': 'TexGyrePagellaLining'.\n    % This 'NFSS' style is required for \\fontfamily{nfss-code}\\selectfont to work,\n    % e.g. in package chemmacros/chemformula\n    NFSSFamily=tgpl,%\n    % Color=Green4,% Toggle color for debugging (should be xcolor name)\n]{TeX Gyre Pagella Math}% Load existing fond, see also https://tex.stackexchange.com/a/351100/120853\n\n% Provide a new font family for siunitx to work.\n% See: https://tex.stackexchange.com/a/468031/120853.\n% \\newfontfamily is used similarly to \\setmainfont etc,\n% see: https://tex.stackexchange.com/a/12568/120853\n\\newfontfamily{\\unitnumberfont}[\n    % New font family for typesetting units.\n    % Required since otherwise, numbers typeset with \\qty/\\num etc. from siunitx\n    % might be hanging if that feature is turned on in the main font (OldStyle numbers).\n    % To ensure these physical numbers are always upright, set Numbers:\n    Numbers=Uppercase,\n    % Color=LightCyan4,% Toggle color for debugging (should be xcolor name)\n]{TeX Gyre Pagella}% Load existing fond, see also https://tex.stackexchange.com/a/351100/120853\n\n% Looking at CTAN, `fontawesome5' looks much more recent and packs many more symbols\n% in comparison to `fontawesome'.\n% It ships with its own font files, so no need to specify here.\n\\RequirePackage{fontawesome5}% High-quality Unicode vector web symbols\n\n% Wrapper for \"i.e.\", \"e.g.\", \"c.f.\", \"etc.\", etc.\n% Call this command as \"The animals, \\iecfeg{e.g.}\\ an elephant, are...\"\n% to get a small space after the ending period.\n% We do not define dedicated commands here (like \\eg or \\etc) to print that stuff\n% automatically, since there are way too many exceptions and caveats.\n% Such macros are not worth it because the requirements change too much from use to use\n%  (different languages, capitalisation, ending dot if abbreviation is at end of\n% sentence, ...).\n% It is left to the user to do the specifics.\n% This macro just makes sure it is all in italics.\n\\newcommand*{\\iecfeg}[1]{\\textit{#1}}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% System Information Banner\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Provides \\hologo and \\Hologo to typeset various logos, like the LuaLaTeX logo.\n\\RequirePackage{hologo}\n\n% Using fontspec, this document is incompatible with anything but XeLaTeX/LuaLaTeX.\n% LuaLaTeX can grab additional memory as needed, therefore no issues with tikz and no\n% need to tikzexternalize (!).\n% Further, contour-package and XeLaTeX are strictly incompatible (LuaLaTeX works).\n% Therefore, only ever use LuaLaTeX anyway.\n\n\\RequirePackage{xstring}% String manipulation macros\n\n% Print only what occurs after 'This is ' and store in macro given in brackets at end.\n% luatexbanner is provided by luatex engine, but prints 'This is luatex XYX' usually.\n% https://tex.stackexchange.com/a/394043/120853\n\\StrBehind*{\\luatexbanner}{This is }[\\shortbanner]\n\n% Take input and substitute strings; here: make plain LuaTeX string into pretty logo.\n% StrSubstitue has no starred variant, therefore dekotenize.\n% https://tex.stackexchange.com/a/350583/120853\n\\StrSubstitute{\\shortbanner}{\\detokenize{LuaTeX}}{\\hologo{LuaTeX}}[\\prettybanner]\n\n% Generate some control sequences which contain metadata, which can be inserted e.g.\n% into the PDF metadata (e.g. to have the exact git commit SHA of a build).\n% See % https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua\n% for how to inline Lua code in TeX.\n% It's an absolute abomination; the below code first passes through TeX, gets expanded,\n% then gets processed by Lua.\n% Hence, there is a lot of escaping going on.\n\\directlua{%\n    local function get_cmd_stdout(cmd)\n        % -- See: https://stackoverflow.com/a/326715/11477374\n        local fh = assert(io.popen(cmd))\n        local first_line = assert(fh:read())\n        fh:close()\n        return first_line\n    end\n%\n    % -- Environment variables as used e.g. in GitLab CI.\n    % -- Otherwise, e.g. when developing locally, use commands as a fallback.\n    local macro_content_sources = {\n        GitRefName = {\n            env = \"CI_COMMIT_REF_NAME\",\n            cmd = \"git rev-parse --abbrev-ref HEAD\",\n        },\n        GitShortSHA = {\n            env = \"CI_COMMIT_SHORT_SHA\",\n            cmd = \"git rev-parse --short HEAD\",\n        },\n    }\n%\n    for macro_name, content_sources in pairs(macro_content_sources) do\n        % -- Default: check for environment variable:\n        local env = content_sources.env\n        local cmd = content_sources.cmd\n        % -- Default value:\n        local content = \"n.a.\"\n        local env_content = os.getenv(env)\n%\n        % -- Empty string evaluates to true:\n        if env_content and env_content \\noexpand~= \"\" then\n            texio.write_nl(\"Found and will be using environment variable '\"..env..\"'.\")\n            content = env_content\n        else\n            texio.write_nl(\"Environment variable '\"..env..\"' undefined or empty, trying fallback command.\")\n            % -- luatex reference for shell escape:\n            % -- \"0 means disabled, 1 means anything is permitted, and 2 is restricted\"\n            if status.shell_escape == 1 then\n                local cmd_success, cmd_stdout = pcall(get_cmd_stdout, cmd)\n                if cmd_success then\n                    texio.write_nl(\"Fallback command '\"..cmd..\"' succeeded.\")\n                    content = cmd_stdout\n                else\n                    texio.write_nl(\"Fallback command '\"..cmd..\"' unsuccessful.\")\n                end\n            else\n                texio.write_nl(\"shell-escape is disabled, cannot use fallback command.\")\n            end\n        end\n%\n        % -- Shouldn't happen, would be programmer error, therefore assert Python-style\n        assert(content, \"Content not defined (neither success nor fallback present)\")\n%\n        % --[[\n        %     The `content` can contain unprintable characters, like underscores in git branch\n        %     names. Towards this end, use detokenize in the macro itself, which will make all\n        %     characters printable (assigns category code 12). See also:\n        %     https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua\n        % --]]\n        local escaped_content = \"\\unexpanded{\\\\detokenize{\"..content..\"}\"}\n%\n        texio.write_nl(\"Providing new macro '\"..macro_name..\"' with contents: '\"..escaped_content..\"'.\")\n        % --  Set a macro (newcommand) see also: https://tex.stackexchange.com/a/450892/120853\n        token.set_macro(macro_name, escaped_content)\n    end\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Macros to pretty-print keyboard buttons and menu navigation\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage[\n    os=win,% Default is `mac`\n]{menukeys}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% KOMA Layout, Sectioning etc\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% label, e.g. 'Chapter', appearing before the chapter number:\n\\addtokomafont{chapterprefix}{\\raggedleft}\n\n\\renewcommand*{\\chapterformat}{%\n    \\color{g3}% g3 is a shade of grey\n    %\n    % chapappifchapterprefix{addtext} checks if 'chapterprefix=true' is active,\n    % then prints 'Chapter' or 'Appendix' in front of number,\n    % followed by more text 'addtext':\n    \\chapappifchapterprefix{~}% ~ is an unbreakable space character\n    %\n    % Autodot automates the generation of a dot/period, like \\thechapter\\autodot.\n    % Leave out for no dot.\n    \\scalebox{4.5}{\\thechapter}\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Titlepage\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Define new font for the title page, so it is created once (\\newkomafont)\n% and can later be set however often required (\\setkomafont)\n\\newkomafont{documenttype}{\\usekomafont{subtitle}\\footnotesize}\n\n% Emulating a budget 'case' switch statement here\n\n% \\ifstrequal from etoolbox doesn't work, it does not expand macros.\n% Use \\ifdefstring from same package,\n% see also https://tex.stackexchange.com/a/451937/120853\n\n\\ifdefstring{\\acp@titlestyle}{thesis}{\n    % These exist already, overwrite:\n    \\setkomafont{title}{\\sffamily\\bfseries\\Huge}\n    \\setkomafont{subtitle}{\\normalfont\\normalsize\\sffamily}\n    \\setkomafont{author}{\\sffamily\\bfseries}\n    \\setkomafont{publishers}{\\sffamily}\n%\n    % One same line as subtitle, so should look the same; inherit style:\n    \\setkomafont{date}{\\usekomafont{subtitle}}\n%\n    \\setkomafont{documenttype}{\\usekomafont{subtitle}\\footnotesize}\n%\n    \\renewcommand{\\maketitle}{%\n        \\begin{titlepage}\n            \\hfill%\n            %\n            % 2nd optional argument is height, required for \\vfill etc. to work\n            \\begin{minipage}[b][1\\textheight]{0.05\\textwidth}%\n                \\color{black}\\rule{0.15em}{\\textheight}% Vertical line\n                \\hfill%\n            \\end{minipage}% This comment char is important to suppress linebreak\n            %\n            \\begin{minipage}[b][1\\textheight]{0.75\\textwidth}\n                \\vspace{4\\baselineskip}\n                {\\usekomafont{documenttype}\\faGraduationCap{}\\ \\@documenttype{}\\hspace{0.5em}}\n                \\hrulefill\n                \\begin{spacing}{1.1}% In case of multi-line titles, more relaxed spacing\n                    \\usekomafont{title}\\raggedright\\@title\n                \\end{spacing}\n                \\hrule\n                \\vspace{0.8\\baselineskip}\n                {%\n                    \\usekomafont{author}%\n                    % Tabular enables \\and and \\\\ syntax\n                    \\begin{tabular}[t]{@{}l@{}}%\n                        \\@author\n                    \\end{tabular}\n                }%\n                \\hfill\n                {\\usekomafont{date}\\@date}\\par\n                \\vfill\n                {\\usekomafont{subtitle}\\@subtitle}\\par\n                \\vspace{2\\baselineskip}\n                {%\n                    \\usekomafont{publishers}%\n                    \\begin{tabular}[t]{@{}l@{}}%\n                        \\@publishers\n                    \\end{tabular}\n                }\\par\n                \\vspace{0.2ex}% Also required for \\vfill as something to 'fill against'\n            \\end{minipage}\n        \\end{titlepage}\n    }%\n}{%\n    % Else: nothing; faking a 'case' environment\n}\n\n\\ifdefstring{\\acp@titlestyle}{book}{\n    % These exist already, overwrite:\n    \\setkomafont{title}{\\sffamily\\bfseries\\Huge}\n    \\setkomafont{subtitle}{\\itshape}\n    \\setkomafont{author}{\\scshape\\Large}\n    \\setkomafont{date}{\\normalfont\\normalsize\\sffamily}\n    \\setkomafont{publishers}{\\scshape}\n%\n    % One same line as date, so should look the same; inherit style:\n    \\setkomafont{documenttype}{\\usekomafont{date}}\n%\n    \\renewcommand{\\maketitle}{%\n        \\begin{titlepage}\n            \\hfill%\n            %\n            % 2nd optional argument is height, required for \\vfill etc. to work\n            \\begin{minipage}[b][1\\textheight]{0.05\\textwidth}%\n                \\color{black}\\rule{0.15em}{\\textheight}% Vertical line\n                \\hfill%\n            \\end{minipage}% This comment char is important to suppress linebreak\n            %\n            \\begin{minipage}[b][1\\textheight]{0.75\\textwidth}\n                \\vspace{2\\baselineskip}\n                {\\usekomafont{author}\n                    % Tabular enables \\and and \\\\ syntax\n                    \\begin{tabular}[t]{@{}l@{}}%\n                        \\@author\n                    \\end{tabular}\n                }\\par\n                \\vspace{1.5\\baselineskip}\n                \\begin{spacing}{1.1}% In case of multi-line titles, more relaxed spacing\n                    \\usekomafont{title}\\raggedright\\@title\n                \\end{spacing}\n                \\hrule\n                \\vspace{0.8\\baselineskip}\n                {\\usekomafont{documenttype}\\@subtitle}\n                \\hfill\n                {\\usekomafont{date}\\@date}\\par\n                \\vfill\n                {\\usekomafont{publishers}\n                \\begin{tabular}[t]{@{}l@{}}%\n                    \\@publishers\n                    \\end{tabular}\n                }\\par\n                \\vspace{0.2ex}% Also required for \\vfill as something to 'fill against'\n            \\end{minipage}\n        \\end{titlepage}\n    }%\n}{\n    % Else: nothing; faking a 'case' environment\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% tocbasic\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Dynamic width of number column in LoF/LoT etc (numsep + width of longest entry).\n% 'tocline' is the (dynamic) default style.\n\\DeclareTOCStyleEntry[dynnumwidth=true]{tocline}{figure}\n\\DeclareTOCStyleEntry[dynnumwidth=true]{tocline}{table}\n\n% Declare a new list of contents, with the file suffix in brackets.\n% This will give access to \\listof<name>s\n\\DeclareNewTOC[%\n    type=example,% This also creates types=example+s, that is by appending an s\n    % Listname is \"List of <Type>s\" by default, therefore translate:\n    listname={\\TransListOfExamples{}},\n]{loe}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% SCRLayer for page makeup (header/footer etc.)\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage[automark]{scrlayer-scrpage}% Automatically mark\n\n\\clearpairofpagestyles % Reset defaults\n\n% Declare new length (acting as a height) for the vertical bar in the header:\n\\newlength{\\headerrulelength}\n% Increase height of rule here; KOMA Script will complain, no idea how to fix\n\\setlength{\\headerrulelength}{3ex}\n\n% New command for the vertical rule, with height as specified by the new length above:\n\\newcommand*{\\headerrule}{%\n    \\rule[-1ex]{0.1em}{\\headerrulelength}%\n}%\n\n% Define headers:\n\\lehead{% Left, even head\n    \\llap{%\n        \\pagemark\\enskip\\headerrule%\n    }%\n    \\enskip\\headmark%\n}%\n\n\\rohead{% Right, odd head\n    \\headmark\\enskip%\n    \\rlap{%\n        \\headerrule\\enskip\\pagemark%\n    }%\n}%\n\n% https://tex.stackexchange.com/q/299125/120853:\n\\renewcommand*{\\chaptermarkformat}{\\thechapter\\enskip}%\n\n\\addtokomafont{pagehead}{\\sffamily\\itshape\\footnotesize}%\n\\addtokomafont{pagenumber}{\\sffamily\\bfseries\\footnotesize}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Deliberately blank pages with message\n% Occurs if new chapter starts (opens right) but previous chapter ended on\n% a recto (right) page itself.\n% The intermediate left page will be blank; leave a message that this is intentional.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\newcommand*{\\blankpage}{% https://tex.stackexchange.com/a/205536/120853\n    \\par\\vspace*{\\fill}%\n    \\begin{center}\n        \\textcolor{g2}{%\n            \\TransBlankPage{}% See translations file\n        }%\n    \\end{center}\n}%\n\n\\DeclareNewLayer[% Create new layer under some name\n    foreground,%\n    textarea,%\n    contents=\\blankpage,%\n]{blankpage.fg}\n\n\\DeclarePageStyleByLayers{blank}{blankpage.fg}% Make layer available as pagestyle\n\\KOMAoptions{cleardoublepage=blank}% Use pagestyle\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Typesetting\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Using 'shortcuts' package option, do e.g. 'fast\\-/paced' to get a breakable\n% 'fast-pace' word in print.\n% Otherwise, LaTeX does not hyphenate/linebreak words that already come with a hyphen,\n% since that could be ambiguous\n\\RequirePackage[shortcuts]{extdash}\n\n\\RequirePackage{microtype}% Advanced typesetting for kerning etc.\n\n% Dummy text in readable English (Other languages are also detected)\n% Provides a more realistic preview than Lorem Ipsum\n\\RequirePackage{blindtext}\n\n\\RequirePackage{pdflscape}% Pages in landscape format\n\n\\RequirePackage{url}% Escaping special chars as URL\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Language Support\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{polyglossia}% Language rules. Replacement for babel in lualatex\n    % Expand this properly; the version without \\expandsafters does not work fully.\n    % It works this way:\n    % The first \\expandafter is seen, so the following \\setdefaultlanguage is not\n    % expanded and skipped.\n    % Next, the second \\expandafter is looked at. It sees the token { next, saving it\n    % for later.\n    % \\acp@language is then expanded fully, to the current language.\n    % What is left is a properly working string, \\setdefaultlanguage{<language string>}\n    \\expandafter\\setdefaultlanguage\\expandafter{\\acp@language }\n\n    % Whatever main language (setmainlanguage = setdefaultlanguage) was loaded, we want\n    % the \"other\" one (since we expect only English and German) to be available as a\n    % secondary language. This is very convenient if for example a thesis is in English,\n    % but certain parts have to be in German, e.g. for legal reasons. A simple switch\n    % \\begin{german} ... \\end{german} would then achieve that.\n    \\setotherlanguages{german,english}\n\n% Proper quotation support, mainly through \\enquote\n\\RequirePackage[\n    autostyle=true,% true always adapts quotes to current language\n]\n{csquotes}\n    % Add itshape to beginning (beg) of display quote environments:\n    \\renewcommand*{\\mkbegdispquote}[2]{\\itshape}\n\n\\RequirePackage[inline]{enumitem}% Custom list environments\n    \\setlist{noitemsep}% No vertical spacing in lists\n    \\setlist[1]{labelindent=\\parindent}% Indent lists by paragraph indent\n    % Refer to unimath_symbols.pdf for source of \\smblksquare etc.:\n    % https://ctan.org/texarchive/macros/latex/contrib/unicode-math\n    \\setlist[itemize,1]{label=\\smblksquare}%\n    \\setlist[enumerate]{font=\\sffamily\\bfseries}\n\n    % For compact itemize lists within table cells:\n    \\newlist{tabitemize}{itemize}{1}% Second argument is max. depth\n    \\setlist[tabitemize]{%\n        label=\\smblksquare,%\n        nosep,% nosep kills all vertical spacing\n        align=parleft,\n        leftmargin=*,\n        % https://tex.stackexchange.com/a/443573/120853,\n        % but before=\\compress didn't work:\n        after=\\vspace{-\\baselineskip},\n        before=\\vspace{-0.75\\baselineskip},% Hacky manual parameter\n    }\n\n    % For compact enumerations lists within table cells:\n    \\newlist{tabenum}{enumerate}{1}% Second argument is max. depth\n    \\setlist[tabenum]{\n        label={\\arabic*.},\n        font=\\sffamily\\bfseries,\n        leftmargin=*,\n        nosep,% nosep kills all vertical spacing\n        align=parleft,\n        % https://tex.stackexchange.com/a/443573/120853,\n        % but before=\\compress didn't work:\n        after=\\vspace{-\\baselineskip},\n        before=\\vspace{-0.75\\baselineskip},% Hacky manual parameter\n    }\n\n    % An enumerated description list:\n    % https://tex.stackexchange.com/a/30035/120853\n    \\newcounter{descriptcount}\n    \\newlist{enumdescript}{description}{2}% Derive from existing description env.\n    \\setlist[enumdescript, 1]{% Set first level action\n        before={%\n            \\setcounter{descriptcount}{0}%\n            % \\renewcommand*\\thedescriptcount{\\alph{descriptcount}}%\n        },\n        font={\\bfseries\\stepcounter{descriptcount}\\thedescriptcount.~}\n    }\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Floats\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Does \\centering automatically, provides side captions (fcapside) and much more.\n\\RequirePackage{floatrow}\n\n\\floatsetup{footposition=bottom}% For all floats\n\n\\floatsetup[longtable]{LTcapwidth=table}% https://tex.stackexchange.com/a/345772/120853\n\n\\floatsetup[table]{%\n    style=plaintop,% Always above, no matter where \\caption is called\n    footnoterule=none,%\n    footskip=.35\\skip\\footins,%\n}%\n\n\\floatsetup[figure]{%\n    capbesideposition=right,%\n    capbesidesep=quad,%\n}%\n\n\\floatsetup[subfigure]{style=plain}% Plain style, so no rules\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Float Captions\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{caption}\n\n% Will be printed between 'Figure/Table/... XYZ' and the caption text:\n\\DeclareCaptionLabelSeparator{slash}{\\ /\\ }% `\\ ' (backslash+space) is a short space\n\n\\DeclareCaptionFont{ftfont}{%\n    \\scriptsize%\n    \\color{g3}%\n    \\hypersetup{hidelinks}%\n    \\sffamily\\raggedleft%\n}%\n\n\\captionsetup{% All captions\n    format=plain,%\n    textformat=period,% Always print period at end\n    font=small,% All fonts\n    labelfont={sf,bf},%\n    labelsep=slash,%\n    labelformat=simple,% Just Name/Number, no period or similar\n    indention=1em,%\n}%\n\n\\captionsetup[floatfoot]{%\n    footfont=ftfont,% https://tex.stackexchange.com/q/9547/120853\n}%\n\n\\captionsetup[capbesidefigure]{\n    % When using sidecaptions, the linewidth can be rather small and awkward breaks and\n    % many underfull hboxes occur. Therefore, raggedright.\n    justification=raggedright,\n}\n\n\\captionsetup[subfigure]{%\n    labelformat=simple,% 'parens' uses parantheses, 'brace' just the right one\n    labelsep=slash,%\n    labelfont={sf,bf},%\n    list=off,% list=off removes subfigures from LoF\n}%\n\n\\captionsetup[subtable]{%\n    labelformat=simple,% 'parens' uses parantheses, 'brace' just the right one\n    labelsep=slash,%\n    labelfont={sf,bf},%\n    list=off,% list=off removes subfigures from LoF\n}%\n\n% Change counter from Arabic number to letter:\n\\renewcommand*{\\theContinuedFloat}{\\alph{ContinuedFloat}}\n\n% Make this new length and indent, same length as regular caption indent:\n\\newlength{\\floatfootruleindent}\n\\setlength{\\floatfootruleindent}{\\caption@indent}% Set the new length\n\n% A bit hacky; introduce a rule underneath caption if \\floatfoot is called:\n\\renewcommand*{\\floatfootskip}{2pt\\hspace{\\floatfootruleindent}\\hrulefill}%\n\n\\RequirePackage{subcaption}% For subfloats\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Bibliography\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage[% Default back-end: biber\n    % short style is 'alphabetic' (like [AB99]);\n    % longer: 'authoryear' (like (Einstein, 1940)):\n    style=authoryear,\n    autocite=footnote,% Control what \\autocite does\n    %\n    sortcites=true,% Apply what is specified in sorting=\n    % Introduce back references in bibliography:\n    % https://tex.stackexchange.com/a/211631/120853\n    % Do not use hyperref for this\n    backref,\n    url=false,% Still prints URL for @online, but nowhere else\n    doi=false,%\n    isbn=false,%\n]{biblatex}%\n\n% The `\\addbibresource` command moved to the root *.tex file to work for VSCode's\n% LaTeX Workshop extension.\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Special Treatment for anything in \\nocite{*}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Provides a category/sub-bibliography where all entries that occur in the bib-\n% file(s) but were not actually cited occur. Kind of like a \"Further Reading\".\n\n% New heading\n\\defbibheading{notcited}{%\n    \\section*{%\n        \\TransFurtherReadingTitle{}%\n    }%\n}%\n\n\\defbibnote{further}{%\n    \\textit{\\TransFurtherReadingText{}}%\n}%\n\n% https://tex.stackexchange.com/a/280545/120853\n\\DeclareBibliographyCategory{cited}\n\\AtEveryCitekey{\\addtocategory{cited}{\\thefield{entrykey}}}\n\n% A header for when the bibliography is divided per-chapter:\n\\defbibheading{subbibliography}{%\n    \\section*{%\n        \\Cref{refsegment:\\therefsection\\therefsegment}%\n    }%\n}%\n\n% https://tex.stackexchange.com/a/477525/120853\n\\defbibenvironment{bibnonum}{\n        \\list{%\n            %\n        }{%\n            \\setlength{\\leftmargin}{\\bibhang}%\n            \\setlength{\\itemindent}{-\\leftmargin}%\n            \\setlength{\\itemsep}{\\bibitemsep}%\n            \\setlength{\\parsep}{\\bibparsep}\n        }%\n    }%\n    {\\endlist}%\n    {\\item}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Arrays / Tables\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{tabu}% For longtabu in the glossary\n\n\\RequirePackage{array}\n    \\newcolumntype{M}[1]{>{\\centering\\arraybackslash}m{#1}}% Vert.+Hor. centered cells\n\n    % A command to have a cell with vertical text as a multirow:\n    \\newcommand*{\\multirotatecell}[2]{%\n        \\multirow{#1}{*}{%\n            \\begin{tabular}{@{}c@{}}%\n                \\rotatebox[origin=c]{90}{#2}%\n            \\end{tabular}%\n        }%\n    }%\n\n\\RequirePackage{tabularray}% Powerful, up and coming package\n    \\UseTblrLibrary{booktabs}% Get `\\toprule` etc. for tabularrays\n    \\UseTblrLibrary{siunitx}% Get S column type\n\n\\RequirePackage{multirow}% Cells spanning multiple rows (like multicolumn)\n\n\\RequirePackage{booktabs}% Pretty tables; an absolute must\n\n% More vertical stretch for more relaxed visuals in all tables (global setting)\n\\renewcommand*{\\arraystretch}{1.3}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Other\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Replaces datetime; use regional date format from document language\n\\RequirePackage[useregional]{datetime2}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Visuals, Graphics, Drawing etc\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{censor}\n    \\ifacp@censoring\n        % censor package censors by default; do nothing if censoring requested\n        % TeX doesn't have \\ifnot or similar, see also\n        % https://tex.stackexchange.com/q/386093/120853\n    \\else\n        % Turn off if document option given\n        \\StopCensoring\n    \\fi\n\n\\RequirePackage{cancel}% Cancel out math in equations\n\n\\RequirePackage{setspace}% Line spacing, used for title page\n    % To achieve a reasonable 'text color', i.e. 'filled-ness' of the text,\n    % adjust line spacing.\n    % Recommendation for Palatino fonts (TeX Gyre Pagella is a Palatino clone) is a\n    % factor of 1.05.\n    % Discussion: https://tex.stackexchange.com/q/31064/120853\n    % For German, we might even want to go higher to allow space for the many capital\n    % letters.\n    % Also note that inline-math will look terrible at too low leading/linespread\n    \\linespread{1.05}\n    \\KOMAoption{singlespacing}{true}% Do not apply changed linespread to header/footer\n\n% Print a contour around letters, e.g. black text with a white border on some noisy\n% background, so that text remains legible.\n% NOT COMPATIBLE WITH XELATEX! Requires pdflatex or lualatex (our case)\n\\RequirePackage[outline]{contour}\n    \\contourlength{0.12em}\n\n    \\newcommand*{\\ctrw}[1]{% Black text, white contour\n        \\hypersetup{hidelinks}% Hide links, which might be colored\n        \\contour{white}{\\textcolor{black}{#1}}%\n    }%\n\n    \\newcommand*{\\ctrb}[1]{% White text, black contour\n        \\hypersetup{hidelinks}% Hide links, which might be colored\n        \\contour{black}{\\textcolor{white}{#1}}%\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Graphics + Path\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{graphicx}\n    % Set a global standard path, so don't specify ourselves each time;\n    % only do bitmaps here, vectors are handled by the svg package and its path specs\n    \\graphicspath{{images/bitmaps/}}\n\n\\RequirePackage{svg}\n    % See also:\n    % https://tex.stackexchange.com/a/158612/120853.\n    % pdftexcmds package etc. no longer seems necessary.\n    % svg package documentation states that it is a dependency, but done automatically.\n    % https://tex.stackexchange.com/a/74693/120853\n\n    % Build failed on my system due to lack of the 'canberra' module,\n    % see for a fix: https://askubuntu.com/a/872397/978477\n\n    % Running the document to generate the PDF and PDF_TEX file from the original SVG\n    % will require SHELL ESCAPE (--shell-escape), aka elevation.\n    % However, after the auxiliary images have been created, they only need to be input;\n    % shell-escape will no longer be required.\n    \\svgpath{images/vectors/}% Analogous to \\graphicspath{}\n    \\svgsetup{%\n        inkscapepath=svgsubdir,% Put into subdirectory of where original SVG was found\n        % In most cases, we include SVGs that contain no text, then add it in a\n        % tikzpicture overlay. Therefore, don't generate *.pdf_tex file.\n        % Toggle this back to true wherever needed, on a per-file basis\n        inkscapelatex=false,\n    }\n\n    % When placing nodes over included SVGs using Tikz,\n    % we require some help to debug the positions:\n    \\newcommand*{\\debugtikzsvg}{%\n        % This has to be evoked within a TikZ scope of:\n        % `\\begin{scope}[x={(image.south east)},y={(image.north west)}]`\n        % The image we invoke the grid \"on top of\" needs to be labelled \"image\":\n        \\draw[help lines, xstep=0.02,ystep=0.02, opacity=0.5]\n            (image.south west) grid (image.north east);\n        \\draw[gray, thick, xstep=0.1,ystep=0.1, opacity=0.8]\n            (image.south west) grid (image.north east);\n        %\n        \\foreach \\posfraction in {%\n            0, 0.1, ...,1%\n        }{%\n            \\foreach \\startpoint/\\endpoint/\\nodeorientation in {% 2D-grid\n                south west/south east/below,%\n                north west/north east/above,%\n                south east/north east/right,%\n                south west/north west/left%\n            }{\n                \\node[\\nodeorientation, opacity=0.5]\n                    at ($(image.\\startpoint)!\\posfraction!(image.\\endpoint)$)\n                    {%\n                        \\pgfmathparse{int(\\posfraction*10)}% Round result\n                        \\num{\\pgfmathresult}%\n                    };\n            }%\n        }%\n    }%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Custom Symbols\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{scalerel}% Scale stuff relative to e.g. letters\n\n% Wrapper to include vectors icons by filename and scale them\n\\newcommand*{\\mtlbsmlkicon}[1]{%\n    \\scalerel*{%\n        \\includesvg{logos/matlab_simulink/#1}%\n    }{%\n        X% Scale first argument to height for capital X\n    }%\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Tikz + Plots\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{pgfplots}% Also loads Tikz\n\n% For advanced table calcs, e.g. 'y expr' to mathematically process input data:\n\\RequirePackage{pgfplotstable}\n\n\\RequirePackage[edges]{forest}% Comprehensive trees\n\n\\RequirePackage{tikz-3dplot}\n\n% Only use libraries as needed to keep compilation times low\n\\usetikzlibrary{%\n    positioning,% Relative positioning etc.\n    calc,% Calculate distances, coordinates etc.\n    shapes, % For cross out\n    backgrounds,% Draw on background layer\n    fit,% Fit new node around existing coordinates\n    decorations,\n    arrows,\n    arrows.spaced,\n    intersections,\n    trees,\n    circuits.ee.IEC,% Electrical engineering circuits lib\n    patterns,\n    3d,\n    tikzmark,% Marks/coordinates at arbitrary positions\n}%\n\\usepgfplotslibrary{%\n    colorbrewer,%\n    units,%\n    dateplot,\n    fillbetween,\n    groupplots,\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Colour Cycle for plots\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\pgfplotscreateplotcyclelist{mod RdYlBu3}{% Modify existing colorbrewer\n    {rdylbu2},\n    {black!50},\n    {rdylbu5}% No comma or space here!\n}%\n\n\\pgfplotscreateplotcyclelist{mod mark list}{% Modify predefined to start without mark\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill}\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill},mark=*\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill},mark=square*\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill},mark=triangle*\\\\\n    every mark/.append style={solid},mark=star\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill},mark=diamond*\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill!40},mark=otimes*\\\\\n    every mark/.append style={solid},mark=|\\\\\n    every mark/.append style={solid,fill=\\pgfplotsmarklistfill},mark=pentagon*\\\\\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Global plot settings\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\pgfplotstableset{col sep=comma}% If ALL files/tables are comma-separated\n\n\\pgfplotsset{%\n    % Version this document was originally created with;\n    % see also https://tex.stackexchange.com/a/81912/120853\n    % Important for reproducibility\n    compat=1.16,\n    % In case nodes reach out of plot area, dont clip them off.\n    % See: https://tex.stackexchange.com/a/127904/120853 and\n    % https://tex.stackexchange.com/a/311194/120853\n    clip mode=individual,\n    label style={font=\\small},% https://tex.stackexchange.com/a/300673/120853\n    tick label style={%\n        font=\\small,%\n        /pgf/number format/1000 sep={\\,}% Small space instead of comma\n    },\n    cycle multi list={%\n        mod mark list\\nextlist% Just in case; likely never reached\n        linestyles*\\nextlist\n        % Iterate through last one first; if at end,\n        % start anew using next in parent (linestyles *):\n        mod RdYlBu3%\n    },%\n    colormap/viridis,% For 3D/surf plots\n    legend style={%\n        at={(0.5,1.05)},% Center hor. (0.5), slightly out of drawing(>1 vert.)\n        anchor=south,%\n        legend columns=-1,% -1 means only rows, as many columns as required\n        font=\\footnotesize,%\n        draw=none,% Do not draw box\n        fill=none,% No white fill. Important for gray backgrounds\n    },%\n    % These comment lines (visual separation) are super important.\n    % Empty lines will throw errors here!\n    unit code/.code 2 args={\\unit{#1#2}},% Use siunitx for units library\n    unit markings={slash space},% The proper way... apparently?\n    %\n    % Fix micro unit display, see https://tex.stackexchange.com/a/224574/120853:\n    x SI prefix/micro/.style={/pgfplots/axis base prefix={axis x base 6 prefix \\micro}},\n    y SI prefix/micro/.style={/pgfplots/axis base prefix={axis y base 6 prefix \\micro}},\n    z SI prefix/micro/.style={/pgfplots/axis base prefix={axis z base 6 prefix \\micro}},\n    %\n    % Plot styles:\n    regularplot/.style={% A broadly usable, regular plot\n        ultra thick,\n        axis line style=thick,\n        ymajorgrids=true,\n        xmajorgrids=true,\n        grid style=dashed,\n        axis lines=left,\n        % scale only axis,% If off, labels are taken into account for size calculations\n        ytick align=outside,% Puts ticks outside the plot itself\n        xtick align=outside,%\n        % Won't work if enlarge limits are invoked before 'axis lines left':\n        enlargelimits=0.05,\n    },%\n    plainplot/.style={%\n        % A clean, simple plot when numerical values and labels don't matter\n        regularplot,\n        xmajorgrids=false,\n        ymajorgrids=false,\n        ticks=none,% No ticks with numbers\n    },\n    tuftelike/.style={% https://tex.stackexchange.com/a/155210/120853\n        axis line shift=10pt,% Also shifts label automatically\n        try min ticks=3,% https://tex.stackexchange.com/a/95753/120853\n        max space between ticks=50,% High number so ticks are far apart\n        axis lines=left,\n        ultra thick,\n        axis line style = {semithick, -},% '-' suppresses arrow\n        tick style = {semithick, black},%\n        ytick align=inside,% Puts ticks inside the plot itself\n        xtick align=inside,%\n        xtick={%\n            % Always set min, max and middle ticks;\n            % if more desired, use 'extra x ticks={}'\n            \\pgfkeysvalueof{/pgfplots/xmin},\n            \\pgfkeysvalueof{/pgfplots/xmax},\n            (\\pgfkeysvalueof{/pgfplots/xmax}+\\pgfkeysvalueof{/pgfplots/xmin})/2\n        },\n        ytick={% Same as x\n            \\pgfkeysvalueof{/pgfplots/ymin},\n            \\pgfkeysvalueof{/pgfplots/ymax},\n            (\\pgfkeysvalueof{/pgfplots/ymax}+\\pgfkeysvalueof{/pgfplots/ymin})/2\n        },\n        clip = false,% https://tex.stackexchange.com/a/311194/120853\n    },%\n    % Unfortunately, decorations lib is relatively verbose:\n    arrowplot/.style={\n        decoration={\n            markings,\n            mark=at position 0.25 with {\\arrow{#1}},\n            mark=at position 0.5 with {\\arrow{#1}},\n            mark=at position 0.75 with {\\arrow{#1}},\n        },\n        postaction=decorate,\n    },\n    %\n    log x ticks with fixed point/.style={%\n        % Logarithmic plot, but with linear labels instead of scientific notation\n        % (10^2 becomes 100 etc.)\n        % https://tex.stackexchange.com/a/139084/120853\n        xticklabel={\n            \\pgfkeys{/pgf/fpu=true}\n            \\pgfmathparse{exp(\\tick)}%\n            \\pgfmathprintnumber[fixed relative, precision=3]{\\pgfmathresult}\n            \\pgfkeys{/pgf/fpu=false}\n        }\n    },\n    %\n    log y ticks with fixed point/.style={\n        yticklabel={\n            \\pgfkeys{/pgf/fpu=true}\n            \\pgfmathparse{exp(\\tick)}%\n            \\pgfmathprintnumber[fixed relative, precision=3]{\\pgfmathresult}\n            \\pgfkeys{/pgf/fpu=false}\n        }\n    }\n}\n\n% Required in \\tikset body for node placing at x style.\n% Requires intersection lib\n% https://tex.stackexchange.com/a/93968/120853\n\\def\\parsenode[#1]#2\\pgf@nil{%\n    \\tikzset{label node/.style={#1}}\n    \\def\\nodetext{#2}\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Various thermodynamic/mechanical/technical shapes, usable in regular TikZ graphics.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\tikzset{\n    >=stealth',% Global arrow style\n    %\n    % Flow chart styles\n    startstop/.style={%\n        rectangle,\n        rounded corners,\n        minimum width=40mm,\n        minimum height=1cm,\n        text centered,\n        draw=black,\n        fill=red!30,\n    },\n    io/.style={%\n        ellipse,\n        minimum width=35mm,\n        minimum height=10mm,\n        text width=35mm,\n        text centered,\n        inner xsep=-1ex,\n        draw=black,\n        fill=blue!30,\n    },\n    process/.style={%\n        rectangle,\n        minimum width=40mm,\n        minimum height=1cm,\n        text centered,\n        text width=40mm,\n        draw=black,\n        fill=orange!30,\n    },\n    decision/.style={%\n        signal,\n        signal to=east and west,\n        minimum width=40mm,\n        minimum height=1cm,\n        text width=40mm,\n        text centered,\n        inner xsep=-1ex,\n        draw=black,\n        fill=green!30,\n    },\n    arrow/.style={%\n        thick,\n        ->,\n        >=stealth,\n    },\n    %\n    symmetrycross/.style={%\n        % Style for a center-cross to mark symmetry in technical drawings.\n        % Styles have one argument per default. Use it for size,\n        % but also provide a default\n        draw,\n        cross out,% From shapes library\n        thin,\n        dashdotted,\n        rotate=45,\n        minimum size=#1,% This is an argument\n    },\n    symmetrycross/.default={2em},\n    pipecrosssection/.style={\n        circle,\n        minimum size=#1,\n        draw=black!90!red,\n        ultra thick,% Simulate thick pipe around it\n        fill=MediumFluid\n    },\n    pipecrosssection/.default={0.5em},\n    arrowlabel/.style={ % Style for labels along arrows\n        pos=#1,\n        text=black,% Overwrite in case encapsulating draw command is white etc.\n        draw=none,% Do not draw border\n        fill=white,\n        inner sep=1.5pt,\n        rounded corners,\n    },\n    arrowlabel/.default={0.5}, % Default for position: middle\n    wall/.style={ % For all walls, e.g. in crosssections of pipes, ...\n        draw,\n        thick,\n        fill=#1,\n        line join=round,\n        rounded corners=0.5,\n    },\n    wall/.default={g5},\n    fluid/.style={ % For all fluids\n        fill=#1,\n    },\n    fluid/.default={MediumFluid},\n    flowarrow/.style 2 args={% A style for squiggly arrows, for flows:\n        ->,\n        line join=round,\n        thick,\n        dashed,\n        decorate,\n        decoration={\n            snake, % alternatives: snake, zigzag\n            segment length=#1,\n            amplitude=#2,\n            % Stop with decoration at start and end by the given length and just draw\n            % a line:\n            pre=lineto,\n            post=lineto,\n            pre length=1em,\n            post length=1em\n        },\n    },\n    annotationarrow/.style={%\n        % A style intended to point a line with a thick black dot at its end onto\n        % elements to give further explanations.\n        % Since we shorten the line START, any line using this style should originate\n        % from the place where the shortening is supposed to take place.\n        % Further explanation here:\n        % https://tex.stackexchange.com/a/115268/120853\n        % Simply call -* (or any other similar command) after annoationarrow if the\n        % direction should be inverted.\n        *-,\n        shorten <=-(1.8pt + 1.4\\pgflinewidth),%\n    },\n    flowarrow/.default={3em}{2em},% {<INVERSE FREQUENCY>}{<AMPLITUDE>}\n    origindot/.style={ % A simple small dot for coordinate starts/origins\n        circle,\n        fill=#1,\n        inner sep=0pt,\n        minimum width=0.4em\n    },\n    origindot/.default={black},\n    add node at x/.style 2 args={% https://tex.stackexchange.com/a/93968/120853\n        % Add node on a plot by just specifying its x-position.\n        % The corresponding y/value is computed automatically!\n        name path global=plot line,\n        /pgfplots/execute at end plot visualization/.append={\n                \\begingroup\n                \\@ifnextchar[{\\parsenode}{\\parsenode[]}#2\\pgf@nil\n            \\path [name path global=position line #1-1]\n                ({axis cs:#1,0}|-{rel axis cs:0,0}) --\n                ({axis cs:#1,0}|-{rel axis cs:0,1});\n            \\path [xshift=1pt, name path global=position line #1-2]\n                ({axis cs:#1,0}|-{rel axis cs:0,0}) --\n                ({axis cs:#1,0}|-{rel axis cs:0,1});\n            \\path [\n                name intersections={\n                    of={plot line and position line #1-1},\n                    name=left intersection\n                },\n                name intersections={\n                    of={plot line and position line #1-2},\n                    name=right intersection\n                },\n                label node/.append style={pos=1}\n            ] (left intersection-1) -- (right intersection-1)\n            node [label node]{\\nodetext};\n            \\endgroup\n        }\n    },\n    shorten <>/.style={% Allow shortening of both ends simultaneously\n        shorten >=#1,\n        shorten <=#1,\n    },\n    circlednum/.style={% Used for a custom circled number command\n        shape=circle,\n        draw,\n        inner sep=2pt,\n        fill=white\n    }%,\n    % A reusable little 'pic' for a common radiator.\n    % Further down, we also declare a 'shape' for a radiator. A 'shape' is a node shape with anchors etc. and intended to be used to connect nodes together, like in a circuit diagram.\n    % A 'pic' is really just a reusable picture that can be put anywhere, but it (by the package author) not intended to be connected etc.\n    % This pic is prettier than the shape below. The pic should be used for large radiator images where more detail is desired.\n    radiator/.pic={\n        \\tikzset{%\n            every path/.style={\n                    draw,\n                    thick,\n                    line join=round,\n                    line cap=round,% End of lines\n                    fill=g5,\n                    pic actions,% Whatever is used in \\pic[<drawing options>], e.g. dashed, is propagated to this drawing\n                },\n        }\n        % Base measurements. Default unit is centimeter\n        \\pgfmathsetmacro{\\radiatorheight}{2}\n        \\pgfmathsetmacro{\\radiatorwidth}{3}\n        \\pgfmathsetmacro{\\radiatordepth}{0.5}\n\n        % Right surface:\n        \\begin{scope}[canvas is yz plane at x=\\radiatorwidth]\n            \\draw[fill=g4] (0,0) rectangle (\\radiatorheight,\\radiatordepth);\n\n            % Fake the thermostat a bit:\n            \\draw[fill=g3] (0.8*\\radiatorheight,0.5*\\radiatordepth) circle (0.2*\\radiatordepth);\n\n            % Generate some coordinates in analogy to regular tikz naming convetions:\n            \\foreach \\yfrac/\\zfrac/\\coordname in {%\n                    0.5/0.5/center,%\n                    0/0.5/south,%\n                    1/0.5/north,%\n                    0.5/0/east,\n                    0.5/1/west,\n                    0/0/south east,%\n                    0/1/south west,%\n                    1/1/north east,%\n                    1/0/north west,%\n                    0.8/0.5/thermostat%\n                }{\n                    \\coordinate (-right \\coordname) at (\\yfrac*\\radiatorheight,\\zfrac*\\radiatordepth);\n                }\n        \\end{scope}\n\n        % Top surface:\n        \\begin{scope}[canvas is xz plane at y=\\radiatorheight]\n            \\draw (0,0) rectangle (\\radiatorwidth,\\radiatordepth);\n\n            % \"Hollow space\" inside the radiator:\n            \\draw[fill=g2, rounded corners=0.75] (0.05*\\radiatorwidth,0.3*\\radiatordepth) rectangle (0.95*\\radiatorwidth,0.7*\\radiatordepth);\n\n            % Generate some coordinates in analogy to regular tikz naming convetions:\n            \\foreach \\xfrac/\\zfrac/\\coordname in {%\n                    0.5/0.5/center,%\n                    0.5/1/south,%\n                    0.5/0/north,%\n                    1/0.5/east,\n                    0/0.5/west,\n                    1/1/south east,%\n                    0/1/south west,%\n                    1/0/north east,%\n                    0/0/north west%\n                }{\n                    \\coordinate (-top \\coordname) at (\\xfrac*\\radiatorwidth,\\zfrac*\\radiatordepth);\n                }\n        \\end{scope}\n\n        % Front surface:\n        \\begin{scope}[canvas is xy plane at z=\\radiatordepth]\n            \\draw (0,0) rectangle (\\radiatorwidth,\\radiatorheight);\n\n            \\foreach \\posfraction in {0.1, 0.2, ..., 0.9}\n                {%\n                    \\draw[\n                        thick,\n                        preaction={draw, ultra thick, g3},\n                    ] (\\posfraction*\\radiatorwidth, 0.1*\\radiatorheight) -- (\\posfraction*\\radiatorwidth, 0.9*\\radiatorheight);\n                }\n            % Generate some coordinates in analogy to regular tikz naming convetions:\n            \\foreach \\xfrac/\\yfrac/\\coordname in {%\n                    0.5/0.5/center,%\n                    0.5/0/south,%\n                    0.5/1/north,%\n                    1/0.5/east,\n                    0/0.5/west,\n                    1/0/south east,%\n                    0/0/south west,%\n                    1/1/north east,%\n                    0/1/north west%\n                }{\n                    \\coordinate (-front \\coordname) at (\\xfrac*\\radiatorwidth,\\yfrac*\\radiatorheight);\n                }\n            \\node at (-front center) {\\ctrw{\\tikzpictext}};% value of \"pic text\" key is stored in \\tikzpictext macro\n        \\end{scope}\n\n        % Coordinates for convenience:\n        \\coordinate (-thermostat) at (-right thermostat);\n        \\coordinate (-entry) at ($(-front north west)!0.2!(-front south west)$);\n        \\coordinate (-exit) at ($(-right south)!0.2!(-right north)$);\n        \\coordinate (-left center) at (-front west|--right center);% To have an exact opposite of the visible 'center right' position\n\n        % Debugging coordinate system:\n        % \\draw[->] (0,0,0) -- (1,0,0) node[right] {\\(x\\)};\n        % \\draw[->] (0,0,0) -- (0,1,0) node[left] {\\(y\\)};\n        % \\draw[->] (0,0,0) -- (0,0,1) node[above] {\\(z\\)};\n    },\n    TUHHuman/.pic={% A human member of TUHH. Hilarious......\n        \\pgfmathsetmacro{\\roundingradius}{0.4}\n        \\filldraw[pic actions] (0,0) circle (1);% Head\n        %\n        % Use arc over just specifying 'rounded corners', because rounded corners are absolute and aren't affected by 'scale'\n        \\filldraw[pic actions]\n        (0,-1.2)% Below head\n         -- ++ (2.5-\\roundingradius,0) arc (90:0:\\roundingradius)% Right shoulder\n         -- ++ (0,{-(5 - 2*\\roundingradius)}) arc (0:-90:\\roundingradius) -- ++ ({-(0.8 - 2*\\roundingradius)},0) arc (270:180:\\roundingradius) -- ++ (0,{4 - \\roundingradius})% Right arm\n         -- ++ (-0.25,0)% Right arm pit\n         -- ++ (0,{-(8 - \\roundingradius)}) arc (0:-90:\\roundingradius) -- ++ ({-(1 - 2*\\roundingradius)},0) arc (270:180:\\roundingradius) -- ++ (0,{4 - 2*\\roundingradius}) arc (0:90:\\roundingradius)% Right leg\n         -- ++ ({-(1 - 2*\\roundingradius)},0)% Gap between legs\n         arc (90:180:\\roundingradius) -- ++ (0,{-(4 - 2*\\roundingradius)}) arc (0:-90:\\roundingradius) -- ++ ({-(1 - 2*\\roundingradius)},0) arc (270:180:\\roundingradius) -- ++ (0,{8 - \\roundingradius})% Left leg\n         -- ++ (-0.25,0)% Left arm pit\n         -- ++ (0,{-(4 - \\roundingradius)}) arc (0:-90:\\roundingradius) -- ++ ({-(0.8 - 2*\\roundingradius},0) arc (270:180:\\roundingradius) -- ++ (0,{5 - 2*\\roundingradius})% Left arm\n         arc (180:90:\\roundingradius)-- cycle;% Left shoulder; cycle back to below head\n\n        \\node[right, transform shape] at (-1.25,-2.5) {\\ctrw{\\textcolor[RGB]{45,198,214}{\\textbf{\\textsf{TUHH}}}}};% Chest emblem; transform shape allows node to be affected by 'scale' option\n        %\n        % \\draw[help lines] (-3,-11) grid (3,1);% Debugging grid\n    },\n    boilercylinder/.style={\n        cylinder,% Shapes lib\n        draw,\n        thick,\n        shape border rotate=90,\n        aspect=0.3,% Flatten\n        cylinder uses custom fill,\n        % cylinder body fill=g5,% For regular filling, use these and comment out the colors at the bottom here\n        % cylinder end fill=g4,%\n        left color=HotFluid!70,\n        middle color=orange!20,\n        right color=g4,\n        shading angle=180,\n    },\n    % Still use a pic so we can flexible add stuff to all boilers later one, like a burner on the bottom left side:\n    boiler/.pic={\n        \\node[\n            boilercylinder,\n            minimum width=4em,\n            minimum height=6em,\n            pic actions,% Whatever is used in \\pic[<drawing options>], e.g. dashed, is propagated to this drawing\n        ] () {\\ctrw{\\tikzpictext}};% Empty coordinate is important for namespace stuff\n    },\n    equalizing tank/.style={\n        circle split,\n        draw,\n        solid,% In case surrounding context is dashed etc.\n        -,% As opposed to arrows etc.\n        fill=white,\n        double,\n        minimum width=#1,\n    },\n    equalizing tank/.default={1.5em},\n    pipe/.style={% (Water) pipes between devices. For a pipe without arrow line end, call it as e.g. \\draw[pipe, -]\n        line width=#1,\n        double=MediumFluid,\n        double distance={1*#1},\n        -{Triangle Cap []. Fast Triangle[] Fast Triangle[] Fast Triangle[]},% dot represents line end\n        line join=round,\n    },\n    pipe/.default={1.5pt},\n    valve/.style={\n        shape=valve,\n        draw,\n        solid,% In case surrounding context is dashed etc.\n        -,% As opposed to arrows etc.\n        fill=white,\n        rounded corners=0.5,\n        rotate=90,% We probably need the horizontal version more often. Also, this way, \\draw ... node[midway, valve, sloped] {}; works out of the box\n        minimum width=0.6*#1,% Fixed aspect ratio\n        minimum height=#1,\n    },\n    valve/.default={1em},\n    control valve/.style={% Same node style but different shape\n        valve,\n        % blue!10,\n        shape=controlvalve,\n    },\n    threeway valve/.style={\n        valve,\n        shape=threeway valve,\n        minimum width=0.85*#1,% Scale it a bit...\n        minimum height=#1,\n    },\n    threeway valve/.default={1em},\n    fourway valve/.style={\n        valve,\n        rotate=-90,% It's symmetrical, no need to rotate; undo inherited rotation\n        shape=fourway valve,\n        minimum width=#1,% Fixed aspect ratio, square\n        minimum height=#1,\n    },\n    fourway valve/.default={1em},\n    threeway control valve/.style={\n        threeway valve,\n        shape=threewaycontrolvalve,\n    },\n    radiator/.style={\n        shape=radiator,\n        draw,\n        fill=g6,\n        line join=round,\n        minimum width=#1,\n        minimum height=(2/3)*#1,% Fixed aspect ratio\n    },\n    radiator/.default={3em},\n    vented radiator/.style={\n        radiator,% Inherit from style\n        shape=vented radiator,% Different shape\n    },\n    pump/.style={\n        shape=pump,\n        draw,\n        solid,% In case surrounding context is dashed etc.\n        -,% As opposed to arrows etc.\n        fill=white,\n        line join=round,\n        minimum width=#1,\n        rounded corners=0.5,% Alter rounded corners in case surrounding style has them\n    },\n    pump/.default={1.5em},\n    compressor/.style={\n        shape=compressor,\n        draw,\n        solid,\n        -,\n        fill=white,\n        line join=round,\n        minimum size=#1,\n        sloped,% Because why not\n    },\n    compressor/.default={1.5em},\n    heat exchanger/.style={\n        shape=heat exchanger,\n        draw,\n        solid,\n        -,\n        fill=white,\n        line join=round,\n        rounded corners=0.5,\n        minimum width=#1,\n        minimum height=0.5*#1,% Fixed aspect ratio\n        sloped,% Because why not\n    },\n    heat exchanger/.default={1.5em},\n    simple heat exchanger/.style={\n        shape=simple heat exchanger,\n        draw,\n        solid,\n        -,\n        fill=white,\n        line join=round,\n        minimum width=#1,\n        minimum height=2/3*#1,% Fixed aspect ratio\n        sloped,% Because why not\n    },\n    simple heat exchanger/.default={1.5em},\n    sensor/.style={% A vertical stroke with with three horizontal lines of decreasing width underneath\n        shape=sensor,\n        draw,\n        solid,\n        -,\n        line join=round,\n        line cap=round,\n        minimum width=#1,\n        minimum height=2*#1\n    },\n    sensor/.default={0.5em},\n    level indicator/.style={% An upside-down triangle with three horizontal lines of decreasing width underneath\n        shape=levelindicator,\n        draw,\n        fill=white,\n        solid,\n        -,\n        line join=round,\n        line cap=round,\n        minimum width=#1,\n        minimum height=2*#1,\n        inner sep=1.5pt,\n    },\n    level indicator/.default={0.25em}\n}\n\n\\pgfdeclareshape{valve}{%\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough\n    \\inheritanchorborder[from=rectangle]\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\backgroundpath{%\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        % Construct main path, basically 'two triangles touching'\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@ya}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@yb}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya}}\n        \\pgfpathclose\n    }\n}\n\n\\pgfdeclareshape{threeway valve}{\n    % This is asymetrical and stuff, so inheriting from the base valve is a bit hopeless, I don't know how to do it properly\n\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough\n    \\inheritanchorborder[from=rectangle]\n\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    % These have shifted now, since the three-point valve middle is not the node center anymore:\n    \\anchor{center}{\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xa + 0.5*0.75*(\\pgf@xb - \\pgf@xa)}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya + 0.5*(\\pgf@yb - \\pgf@ya)}\n    }\n    \\anchor{north}{\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\southwest \\pgf@xa=\\pgf@x\n        \\pgfmathsetlength\\pgf@x{\\pgf@xa + 0.5*0.75*(\\pgf@xb - \\pgf@xa)}\n        \\pgfmathsetlength\\pgf@y{\\pgf@yb}\n    }\n    \\anchor{south}{\n        \\northeast \\pgf@xb=\\pgf@x\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xa + 0.5*0.75*(\\pgf@xb - \\pgf@xa)}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya}\n    }\n\n    % The triangles meeting at their middle, each with an aspect ratio of 0.75 (base) to 0.5 (height)\n    \\backgroundpath{\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        \\pgfpathmoveto{\\southwest}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.75*(\\pgf@xb - \\pgf@xa)}{\\pgf@yb}}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.75*0.5*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + 0.5*(\\pgf@yb - \\pgf@ya)}}% Valve centerpoint\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya)}}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.75*0.5*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + 0.5*(\\pgf@yb - \\pgf@ya)}}% Valve centerpoint\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.75*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya}}\n        \\pgfpathclose\n    }\n}\n\n\\pgfdeclareshape{fourway valve}{%\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough\n    \\inheritanchorborder[from=rectangle]\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\backgroundpath{%\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        % This yields four triangles meeting in the middle, each with an aspect ratio of 0.6/1.\n        % Construct main path, basically 'two triangles touching'\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + 0.2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.8*(\\pgf@xb - \\pgf@xa)}{\\pgf@yb}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.2*(\\pgf@xb - \\pgf@xa)}{\\pgf@yb}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.8*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya}}\n        \\pgfpathclose\n\n        % Do the same again in the horizontal direction:\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa}{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}}\n        \\pgfpathclose\n    }\n}\n\n\\pgfdeclareshape{controlvalve}{\n    \\inheritsavedanchors[from=valve]\n    \\inheritanchorborder[from=valve]\n    \\inheritanchor[from=valve]{north}\n    \\inheritanchor[from=valve]{north west}\n    \\inheritanchor[from=valve]{north east}\n    \\inheritanchor[from=valve]{center}\n    \\inheritanchor[from=valve]{west}\n    \\inheritanchor[from=valve]{east}\n    \\inheritanchor[from=valve]{mid}\n    \\inheritanchor[from=valve]{mid west}\n    \\inheritanchor[from=valve]{mid east}\n    \\inheritanchor[from=valve]{base}\n    \\inheritanchor[from=valve]{base west}\n    \\inheritanchor[from=valve]{base east}\n    \\inheritanchor[from=valve]{south}\n    \\inheritanchor[from=valve]{south west}\n    \\inheritanchor[from=valve]{south east}\n\n    \\inheritbackgroundpath[from={valve}]\n\n    \\beforebackgroundpath{%\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        % Extension line to control wheel:\n        \\pgfpathmoveto{\\pgfpoint{(\\pgf@xa + \\pgf@xb)/2}{(\\pgf@ya + \\pgf@yb)/2}}\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{(\\pgf@ya + \\pgf@yb)/2}}\n\n        % The factors 0.3, 0.4 and 0.3 need to add up to 1 to give a symmetrical, nice semicircle.\n        % Factor 0.4 is divided by 2 to give the radius\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.3*(\\pgf@yb - \\pgf@ya)}}\n        \\pgfpatharc{-90}{90}{0.4/2*(\\pgf@yb - \\pgf@ya)}\n        \\pgfpathclose\n        \\pgfsetfillcolor{black}\n        \\pgfusepath{fill, stroke}\n    }\n}\n\n\\pgfdeclareshape{pump}{%\n    \\inheritsavedanchors[from=circle]%\n    \\inheritanchorborder[from=circle]\n    \\inheritbackgroundpath[from={circle}]\n    \\inheritanchor[from=circle]{center}\n    \\inheritanchor[from=circle]{north}\n    \\inheritanchor[from=circle]{south}\n    \\inheritanchor[from=circle]{west}\n    \\inheritanchor[from=circle]{east}\n\n    \\beforebackgroundpath{\n        % The simple-most approach:\n        \\pgfpathmoveto{\\pgf@anchor@pump@west}\n            \\pgfpathlineto{\\pgf@anchor@pump@north}\n            \\pgfpathlineto{\\pgf@anchor@pump@east}\n        \\pgfusepath{stroke}\n    }\n}\n\n\\pgfdeclareshape{compressor}{%\n    \\inheritsavedanchors[from=circle]%\n    \\inheritanchorborder[from=circle]%\n    \\inheritbackgroundpath[from={circle}]%\n    \\inheritanchor[from=circle]{center}%\n    \\inheritanchor[from=circle]{north}%\n    \\inheritanchor[from=circle]{south}%\n    \\inheritanchor[from=circle]{west}%\n    \\inheritanchor[from=circle]{east}%\n\n    % Circle has savedanchor of 'centerpoint' and saveddim of 'radius', that's it\n\n    \\beforebackgroundpath{\n        \\centerpoint \\pgf@yc=\\pgf@y\n\n        % Pythagorean theorem is enough here.\n        % Assumption is that default compressor shape 'points to the right'.\n        % This is important to get coorect behaviour out of the 'sloped' node option!\n\n        % Idea (Example for top right point):\n        % 1. Go to center point.\n        % 2. On y-axis, move a fraction of the radius up. This is the y-portion of our top-right coordinate point.\n        % 3. On x-axis, move as far right as Pythagorean theorem dictates (hypotenuse is the radius vector, other known length is the y-length we just specified)\n        % 4. Repeat process to draw and move accordingly; don't forget squares and sqrt() in correct places.\n\n        \\pgfmathsetmacro{\\upperyfraction}{0.3}% y-coordinate of the upper points is \\upperyfraction*\\radius to the sides of the centerpoint\n        \\pgfmathsetmacro{\\loweryfraction}{0.7}% y-coordinate of the lower points is \\loweryfraction*\\radius to the sides of the centerpoint\n\n        \\foreach \\signdirection in {1, -1}{% For left and right side\n            % Upper (always same x-dimension, only y switches sign):\n            \\pgfpathmoveto{\\pgfpoint{sqrt(\\radius^2 - (\\pgf@yc + \\upperyfraction*\\radius)^2)}{\\pgf@yc + \\signdirection*\\upperyfraction*\\radius}}\n            % Bottom (always same x-dimension, only y switches sign):\n            \\pgfpathlineto{\\pgfpoint{-1*sqrt(\\radius^2 - (\\pgf@yc - \\loweryfraction*\\radius)^2)}{\\pgf@yc + \\signdirection*\\loweryfraction*\\radius}}\n        }\n\n        \\pgfusepath{stroke}\n    }\n}\n\n\\pgfdeclareshape{heat exchanger}{\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=rectangle]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\inheritbackgroundpath[from={rectangle}]\n\n    % Anchor to 'in' port of heat exchanger.\n    % This code does not get executed necessarily; we cannot use the \\pgfsetmacros from below.\n    % A solution is probably \\pgfkeys, but this will do for now.\n    % IT NEEDS MANUAL ADJUSTING IF THE SHAPE IS CHANGED.\n    \\anchor{in}{%\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xa + (1 - 0.7)/2*(\\pgf@xb - \\pgf@xa)}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya - 0.3*(\\pgf@yb - \\pgf@ya)}\n    }\n    \\anchor{out}{%\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xb - (1 - 0.7)/2*(\\pgf@xb - \\pgf@xa)}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya - 0.3*(\\pgf@yb - \\pgf@ya)}\n    }\n\n    \\beforebackgroundpath{\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        \\pgfmathsetmacro{\\heatsymbolextension}{0.3}% How far out the 'legs' extend out of the rectangle as a fraction of the overall node's height\n        \\pgfmathsetmacro{\\heatsymbolwidth}{0.7}% The inner drawing's width as a fraction of the node's overall width\n        \\pgfmathsetmacro{\\heatsymbolheight}{0.8}% How high the inner drawing reaches as a fraction of the node's overall height (at 1, it touches the upper rectangle border)\n        \\pgfmathsetmacro{\\heatsymbolindentation}{0.3}% How 'indented' the triangle is, i.e. the vertical distance between the inner drawings highest point and the triangle's down-pointing 'tip'\n\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + (1 - \\heatsymbolwidth)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya - \\heatsymbolextension*(\\pgf@yb - \\pgf@ya)}}% Bottom left corner\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + (1 - \\heatsymbolwidth)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\heatsymbolheight*(\\pgf@yb - \\pgf@ya)}}% Straight line up\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + 0.5*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + (\\heatsymbolheight - \\heatsymbolindentation)*(\\pgf@yb - \\pgf@ya)}}% Line down, to the right; x-coordinate is the middle of the node\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb - (1 - \\heatsymbolwidth)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\heatsymbolheight*(\\pgf@yb - \\pgf@ya)}}% Line up, to the right\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb - (1 - \\heatsymbolwidth)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya - \\heatsymbolextension*(\\pgf@yb - \\pgf@ya)}}% Line straight down\n        \\pgfusepath{stroke}\n    }\n}\n\n\\pgfdeclareshape{simple heat exchanger}{% Just a cross-out rectangle\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=rectangle]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\inheritbackgroundpath[from={rectangle}]\n\n    \\beforebackgroundpath{\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}% Top left corner\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya}}% Bottom right corner\n        \\pgfusepath{stroke}\n    }\n}\n\n\\pgfkeys{/pgf/.cd,\n    radiator offset x/.initial=0.3em,\n    radiator offset y/.initial=0.3em\n}\n\\pgfdeclareshape{radiator}{%\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=rectangle]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{mid}\n    \\inheritanchor[from=rectangle]{mid west}\n    \\inheritanchor[from=rectangle]{mid east}\n    \\inheritanchor[from=rectangle]{base}\n    \\inheritanchor[from=rectangle]{base west}\n    \\inheritanchor[from=rectangle]{base east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\saveddimen{\\xoffset}{% https://tex.stackexchange.com/a/181283/120853\n        \\pgfmathsetlength\\pgf@x{\\pgfkeysvalueof{/pgf/radiator offset x}}\n    }\n    \\saveddimen{\\yoffset}{\n        \\pgfmathsetlength\\pgf@y{\\pgfkeysvalueof{/pgf/radiator offset y}}\n    }\n\n    % In the middle of the right surface:\n    \\anchor{right}{%\n        \\southwest \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xb + \\xoffset/2}\n        \\pgfmathsetlength\\pgf@y{(\\pgf@ya + \\pgf@yb)/2 + \\yoffset/2}\n    }\n    % In the middle of the top surface:\n    \\anchor{top}{%\n        \\southwest \\pgf@xa=\\pgf@x\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{(\\pgf@xa + \\pgf@xb)/2 + \\xoffset/2}\n        \\pgfmathsetlength\\pgf@y{\\pgf@yb + \\yoffset/2}\n    }\n    % Exit at the thermostat:\n    \\anchor{exit}{%\n        \\southwest \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xb + \\xoffset/2}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya) + \\yoffset/2}\n    }\n    % Lower exit on the right side, below the thermostat:\n    \\anchor{lower exit}{%\n        \\southwest \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xb + \\xoffset/2}\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya) + \\yoffset/2}\n    }\n    % Entry in the bottom left somewhere:\n    \\anchor{lower entry}{%\n    \\northeast \\pgf@yb=\\pgf@y\n    \\southwest \\pgf@ya=\\pgf@y% x is now given implicitly\n    \\pgfmathsetlength\\pgf@y{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya)}\n    }\n\n    % Alternative entry in the top left somewhere:\n    \\anchor{upper entry}{%\n        \\northeast \\pgf@yb=\\pgf@y\n        \\southwest \\pgf@ya=\\pgf@y% x is now given implicitly\n        \\pgfmathsetlength\\pgf@y{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}\n    }\n\n    % Front surface is inherited from rectangle:\n    \\inheritbackgroundpath[from={rectangle}]\n\n    % Background is inherited already, so add behind background path:\n    \\behindbackgroundpath{%\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        % Top surface:\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}% Top left\n        \\pgfpathlineto{\\pgfpointadd{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}{\\pgfqpoint{\\xoffset}{\\yoffset}}}% Top left plus offset vector\n        \\pgfpathlineto{\\pgfpointadd{\\northeast}{\\pgfqpoint{\\xoffset}{\\yoffset}}}% Top right (northeast) plus offset vector\n        \\pgfpathlineto{\\northeast}\n        \\pgfpathclose\n\n        % Access current fillcolor as specified by user\n        % Make sides darker than current fill color for some 3D effect\n        \\colorlet{currentfill}{\\tikz@fillcolor}\n        \\pgfsetfillcolor{currentfill!90!black}\n        \\pgfusepath{fill, stroke}\n\n        % Right surface:\n        \\pgfpathmoveto{\\northeast}\n        \\pgfpathlineto{\\pgfpointadd{\\northeast}{\\pgfqpoint{\\xoffset}{\\yoffset}}}% Top right corner plus offset vector\n        \\pgfpathlineto{\\pgfpointadd{\\pgfpoint{\\pgf@xb}{\\pgf@ya}}{\\pgfqpoint{\\xoffset}{\\yoffset}}}% Bottom right corner plus offset vector\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@ya}}% Bottom right corner\n        \\pgfpathclose\n        \\pgfsetfillcolor{currentfill!80!black}% Even darker than top surface\n        \\pgfusepath{fill, stroke}\n\n        % Draw an ellipse to fake a thermostat or pipe exit.\n        % Position it at 0.8 / 80% height\n        % Ellipse axes are confusing and I did not do it properly fully\n        \\pgfpathellipse{\\pgfpointadd{\\pgfpoint{\\pgf@xb}{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}}{\\pgfpointscale{0.5}{\\pgfqpoint{\\xoffset}{\\yoffset}}}}{\\pgfpoint{0.2*\\xoffset}{0.2*\\yoffset}}{\\pgfpoint{0pt}{1pt}}\n        \\pgfsetfillcolor{black}\n        \\pgfusepath{fill}\n    }\n    % Background is already the inherited rectangle. Draw on top of it with beforebackgroundpath\n    \\beforebackgroundpath{\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        % Draw vertical lines on top of front surface:\n        \\foreach \\posfraction in {0.2, 0.4, ..., 0.8}{\n            \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + \\posfraction*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + 0.2*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xa + \\posfraction*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + 0.8*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfusepath{stroke}\n        }\n    }\n}\n\n\\pgfdeclareshape{vented radiator}{\n    \\inheritsavedanchors[from=radiator]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=radiator]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=radiator]{north}\n    \\inheritanchor[from=radiator]{north west}\n    \\inheritanchor[from=radiator]{north east}\n    \\inheritanchor[from=radiator]{center}\n    \\inheritanchor[from=radiator]{west}\n    \\inheritanchor[from=radiator]{east}\n    \\inheritanchor[from=radiator]{mid}\n    \\inheritanchor[from=radiator]{mid west}\n    \\inheritanchor[from=radiator]{mid east}\n    \\inheritanchor[from=radiator]{base}\n    \\inheritanchor[from=radiator]{base west}\n    \\inheritanchor[from=radiator]{base east}\n    \\inheritanchor[from=radiator]{south}\n    \\inheritanchor[from=radiator]{south west}\n    \\inheritanchor[from=radiator]{south east}\n\n    % Inherit our special nodes:\n    \\inheritanchor[from=radiator]{right}\n    \\inheritanchor[from=radiator]{top}\n    \\inheritanchor[from=radiator]{exit}\n    \\inheritanchor[from=radiator]{lower entry}\n    \\inheritanchor[from=radiator]{upper entry}\n\n    % Inherit all stuff from base radiator:\n    \\inheritbackgroundpath[from={radiator}]\n    \\inheritbehindbackgroundpath[from={radiator}]\n    \\inheritbeforebackgroundpath[from={radiator}]\n\n    % Anchor for the ventilation point.\n    % I tried with \\savedanchor, but it didn't work so we have to repeat the calculations for the ventilation device\n    \\anchor{ventilation}{%\n        \\southwest \\pgf@xa=\\pgf@x\n        \\northeast \\pgf@yb=\\pgf@y\n        \\pgfmathsetlength\\pgf@x{\\pgf@xa - 3pt}\n        \\pgfmathsetlength\\pgf@y{\\pgf@yb - 3pt}\n    }\n\n    \\behindforegroundpath{\n        \\southwest \\pgf@xa=\\pgf@x\n        \\northeast \\pgf@yb=\\pgf@y\n\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}% Top left corner\n        \\pgfpatharc{90}{270}{3pt}% Arc from top-top left corner down with specified radius in last argument\n        \\pgfsetfillcolor{black}\n        \\pgfusepath{fill}\n    }\n}\n\n\\pgfdeclareshape{sensor}{\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=rectangle]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    \\backgroundpath{\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + (\\pgf@xb - \\pgf@xa)/2}{\\pgf@yb}}% Upper middle\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + (\\pgf@xb - \\pgf@xa)/2}{\\pgf@ya + 0.3*(\\pgf@yb - \\pgf@ya)}}% Down the middle, to 1/4 of the node height\n\n        % These are percentages of the node height.\n        % At each percentage/fraction of the height, draw a centered line with a width of a certain percentage (fractionlength) of the overall node width\n        \\foreach \\fractionheight/\\fractionlength in {\n            0.3/1,%\n            0.15/0.75,%\n            0/0.5%\n        }{\n            % One horizontal line on this height:\n            \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + (1 - \\fractionlength)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\fractionheight*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb - (1 - \\fractionlength)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\fractionheight*(\\pgf@yb - \\pgf@ya)}}\n        }\n    }\n}\n\n\\pgfdeclareshape{levelindicator}{\n    \\inheritsavedanchors[from=rectangle]% Inherit from rectangle, should be good enough. Rectangle has to 'saved anchors': southwest and northeast\n    \\inheritanchorborder[from=rectangle]\n    % Doesn't hurt to also inherit specific anchors:\n    \\inheritanchor[from=rectangle]{north}\n    \\inheritanchor[from=rectangle]{north west}\n    \\inheritanchor[from=rectangle]{north east}\n    % \\inheritanchor[from=rectangle]{center}\n    \\inheritanchor[from=rectangle]{west}\n    \\inheritanchor[from=rectangle]{east}\n    \\inheritanchor[from=rectangle]{south}\n    \\inheritanchor[from=rectangle]{south west}\n    \\inheritanchor[from=rectangle]{south east}\n\n    % When no other anchor is specified, nodes are placed by their 'center' anchor.\n    % Change it here to be the lower pointy triangle bit, as opposed to the rectangle center.\n    % That way, the triangle always points onto the fluid surface if placed as a node on a drawn line representing this surface\n    \\anchor{center}{%\n        \\southwest \\pgf@xa=\\pgf@x\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n        % Lower pointy bit of triangle, as below:\n        \\pgfpoint{\\pgf@xa + (\\pgf@xb - \\pgf@xa)/2}{\\pgf@yb - sqrt(3)*((\\pgf@xb - \\pgf@xa)/2)}\n    }\n\n    \\backgroundpath{\n        % Store lower left in xa/ya and upper right in xb/yb\n        \\southwest \\pgf@xa=\\pgf@x \\pgf@ya=\\pgf@y\n        \\northeast \\pgf@xb=\\pgf@x \\pgf@yb=\\pgf@y\n\n        \\pgfpathmoveto{\\pgfpoint{\\pgf@xa}{\\pgf@yb}}% Upper left corner\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xb}{\\pgf@yb}}% Upper right corner\n        \\pgfpathlineto{\\pgfpoint{\\pgf@xa + (\\pgf@xb - \\pgf@xa)/2}{\\pgf@yb - sqrt(3)*((\\pgf@xb - \\pgf@xa)/2)}}% Forming an equilateral triangle\n        \\pgfpathclose\n\n        % These are percentages of the node height.\n        % At each percentage/fraction of the height, draw a centered line with a width of a certain percentage (fractionlength) of the overall node width\n        \\foreach \\fractionheight/\\fractionlength in {\n            0.3/1,%\n            0.15/0.75,%\n            0/0.5%\n        }{\n            % One horizontal line on this height:\n            \\pgfpathmoveto{\\pgfpoint{\\pgf@xa + (1 - \\fractionlength)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\fractionheight*(\\pgf@yb - \\pgf@ya)}}\n            \\pgfpathlineto{\\pgfpoint{\\pgf@xb - (1 - \\fractionlength)/2*(\\pgf@xb - \\pgf@xa)}{\\pgf@ya + \\fractionheight*(\\pgf@yb - \\pgf@ya)}}\n        }\n    }\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Scientifics Typesetting\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{chemmacros}% \\ch{}, \\chcpd[]{compound} etc.\n    \\chemsetup{%\n        formula=chemformula,%\n        chemformula/font-family=tgpl,% Use math font family\n    }\n\n    % Some new custom environments. Very simple definitions that behave just like the\n    % widely known AMSMath math environment as specified in the last argument.\n    \\NewChemReaction{reactionsgather}{gather}% Like AMSmath's `gather`\n    \\NewChemReaction{reactionsgather*}{gather*}\n\n    % Sort reaction counter underneath chapter, see\n    % https://tex.stackexchange.com/questions/530210/how-to-cross-reference-reactions-in-chemmacros-chapter#comment1340793_530210\n    \\renewcommand*{\\thereaction}{\\thechapter.\\arabic{reaction}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{siunitx}% Typesetting physical units correctly\n    \\sisetup{%\n        % For siunitx v3, the following block replaces what used to be\n        % `detect-all` (removed in that release, see\n        % https://github.com/josephwright/siunitx/blob/main/CHANGELOG.md#v300 ).\n        % It allows the `siunitx` output to match surrounding text/math (italics/bold/...,\n        % roman/sans/... etc. as much as possible)\n        mode=match,\n        propagate-math-font=true,\n        reset-math-version=false,\n        reset-text-family=false,\n        reset-text-series=false,\n        reset-text-shape=false,% Not part of official fix, but still added (see https://collaborating.tuhh.de/alex/latex-cookbook/-/issues/8)\n        text-family-to-math=true,\n        text-series-to-math=true,\n        %\n        % Requires siunitx v3+, see also https://tex.stackexchange.com/a/468031/120853,\n        % https://github.com/josephwright/siunitx/issues/532 :\n        text-font-command=\\unitnumberfont,\n        %\n        % Alternative range-phrase:\n        % en-dash via '--', but inside \\text{}, so it's not 'two minus signs'\n        % range-phrase={\\,\\text{--}\\,},\n        range-units=single,% single: Print unit only once, at end\n        per-mode=symbol,\n    }%\n    % Second setup step, with locales. See also\n    % https://tex.stackexchange.com/a/46979/120853\n    \\gappto{\\blockextras@german}{%\n        \\sisetup{locale=DE}\n    }\n    \\gappto{\\blockextras@english}{%\n        \\sisetup{locale=US}\n    }\n\n    % Declare units ourselves:\n    % Set as text so it stays a hyphen in math mode, as opposed to minus sign\n    \\DeclareSIUnit{\\volpercent}{Vol.\\text{-}\\%}\n    \\DeclareSIUnit{\\watthour}{Wh}%\n    \\DeclareSIUnit{\\annum}{a}%\n    \\DeclareSIUnit{\\atmosphere}{atm}%\n    \\DeclareSIUnit{\\partspermillion}{ppm}%\n    \\DeclareSIUnit{\\bar}{bar}% https://tex.stackexchange.com/a/598473/120853\n\n    % Unit qualifiers, i.e. subscripts.\n    % We already have a dedicated system (bib file with glossaries-extra) for subscripts\n    % for symbols, so use those (just format, don't index) also for units here.\n    \\DeclareSIQualifier{\\dryair}{% for moist air context\n        \\glsfmtname{sub.dry}\\glsfmtname{sub.air}%\n    }\n    \\DeclareSIQualifier{\\water}{%\n        \\glsfmtname{sub.water}%\n    }\n    \\DeclareSIQualifier{\\thermal}{%\n        \\glsfmtname{sub.thermal}%\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Hyperref and PDFs appearance\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\RequirePackage[pdfusetitle]{hyperref}% Loads url-package internally\n    \\hypersetup{%\n        % Unicode settings are automatically true for luatex engine,\n        % don't specify manually\n        colorlinks=true,% No ugly frames, but still colored\n        allcolors=darklink,%\n        % hidelinks,% Toggle here!\n        plainpages=false,%\n        pdfsubject={%\n            Comprehensive LaTeX template with examples for theses, books\n            and more, employing the 'latest and greatest'.\n        },\n        pdfkeywords={%\n            latex,%\n            template,%\n            modern,%\n            thesis,%\n            phd,%\n            master,%\n            bachelor,%\n            best practices,%\n        },\n        pdfcreator={%\n            LaTeX with hyperref,\n            glossaries-extra/bib2gls\n            and biblatex/biber\n            [\\GitRefName{}@\\GitShortSHA{}]%\n        },\n        bookmarksnumbered=true,%\n        % Default opening of the document in supported PDF viewers:\n        pdfpagelayout=TwoPageRight,\n        pdfdisplaydoctitle,% https://tex.stackexchange.com/a/435434/120853\n    }%\n\n    % In order to translate, polyglossia wraps things into \\text<language>, e.g.\n    % \\textenglish. If this is part of a PDF string, like when we do\n    % \\addchap{\\glossaryname}, LaTeX/hyperref will complain that \\textenglish is not a\n    % PDF string and is dropped.\n    % Therefore, disable commands of the form \\text<language> in this document. Don't\n    % use a static language but the current language from kvoptions.\n    %\n    % Expansion works as follows:\n    % \\expandafter is executed, causing \\let to be saved for later.\n    % \\csname is then executed next. It scans ahead to its matching \\endcsname,\n    % \"performing full expansion as it goes\" (Quote from\n    %  https://tex.stackexchange.com/a/430557/120853).\n    % In that process, \\acp@language is expanded to the value it was given in the\n    % document options through kvoptions.\n    % Now, \\csname finishes and presents a token \\text<language>, e.g. \\textenglish.\n    % LaTeX starts over; \\expandafter is now gone, so it reads \\let\\text<language> ...\n    % In this case, ... is \\relax, removing the macro definition.\n    % It will no longer occur in PDF commands.\n    % See also:\n    % https://www.overleaf.com/learn/latex/Articles/How_does_%5Cexpandafter_work:_A_detailed_study_of_consecutive_%5Cexpandafter_commands\n    % and\n    % TUGboat, Volume 9, 1988, No. 1: Macros: A Tutorial on \\expandafter by\n    % Stephan v. Bechtolsheim.\n    %\n    % Idea from https://tex.stackexchange.com/a/230197/120853\n    \\pdfstringdefDisableCommands{%\n        \\expandafter\\let\\csname text\\acp@language\\endcsname \\relax%\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Appearance of the bookmarks popup in viewers that support it\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\RequirePackage{bookmark}% Control bookmark appearance in PDF\n    \\bookmarksetup{%\n        open,% Open bookmark pane in PDF viewer\n        openlevel=1,% Open first two levels, hide all subsections etc. (0-indexed)\n        addtohook={%\n            \\ifnum\\bookmarkget{level}=0% Only print top-level (0) bookmarks bold\n                \\bookmarksetup{bold}%\n            \\fi%\n        },%\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Glossaries\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage[% Initiate with package options for predefined styles\n    nomain,% Nomain, aka no default glossary\n    record,% Record usages of commands to auxiliary files for bib2gls\n    abbreviations,% Regular abbreviations/acronyms\n    symbols,% Physical symbols\n    index,% A regular book index at the end\n    numbers,% constants like Pi\n    toc=true,% Toggle inclusion in Table of Contents\n]{glossaries-extra}% Also see https://tex.stackexchange.com/q/477658/120853\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% New Glossary 'types'\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    % Using Abbreviations/Symbols etc. package options creates these glossaries already.\n    % Create the rest manually.\n    \\newglossary*{subscripts}{\\TransSubscripts{}}%\n\n    % For example, in the case of symbols, there are three groups: roman, greek and\n    % other.\n    % If the 'other' sub-glossary is used (it provides the built-ins like\n    % \\mean, \\vect, \\deriv, ...) but is NOT supposed to be printed in the PDF glossary,\n    % it is assigned to the following glossary type.\n    % The glossary is printed using \\printunsrtglossary with a `type=<entry type>`\n    % keyword specified, which would also print the 'other' entries, since they are of\n    % type 'symbols' as well. Only by assigning a different type altogether is this\n    % circumvented. This does not impact using the commands and the defined entries using\n    % \\sym{<entry name>}, since that is provided by the 'label-prefix', not the 'type'.\n    % Analogue procedures apply to all glossaries.\n    \\newglossary*{notprinted}{Non-printed entries}% Title never occurs anyway!\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% New Glossary 'fields'\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    % Add custom key for a 'unit' field for symbols:\n    \\glsaddkey{unit}%\n        {\\relax}%\n        {\\glsentryunit}%\n        {\\Glsentryunit}%\n        {\\glsunit}%\n        {\\Glsunit}%\n        {\\GLSunit}\n\n    % For specific quantities (enthalpy etc.)\n    \\glsaddkey{specific}%\n        {\\relax}%\n        {\\glsentryspecific}%\n        {\\Glsentryspecific}%\n        {\\glsspecific}%\n        {\\Glsspecific}%\n        {\\GLSspecific}\n\n    % For First names of people\n    \\glsaddkey{firstname}%\n        {\\relax}%\n        {\\glsentryfirstname}%\n        {\\Glsentryfirstname}%\n        {\\glsfirstname}%\n        {\\Glsfirstname}%\n        {\\GLSfirstname}\n\n    % For values of numbers/constants\n    \\glsaddkey{value}%\n        {\\relax}%\n        {\\glsentryvalue}%\n        {\\Glsentryvalue}%\n        {\\glsvalue}%\n        {\\Glsvalue}%\n        {\\GLSvalue}\n\n    % For international versions of symbols\n    \\glsaddkey{international-symbol}%\n        {\\relax}%\n        {\\glsentryinternationalsymbol}%\n        {\\Glsentryinternationalsymbol}%\n        {\\glsinternationalsymbol}%\n        {\\Glsinternationalsymbol}%\n        {\\GLSinternationalsymbol}\n\n    % For alternative versions of symbols\n    \\glsaddkey{alternative-symbol}%\n        {\\relax}%\n        {\\glsentryalternativesymbol}%\n        {\\Glsentryalternativesymbol}%\n        {\\glsalternativesymbol}%\n        {\\Glsalternativesymbol}%\n        {\\GLSalternativesymbol}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Abstract the prefixes here.\n% For example, if we load 'symbols' from a 'roman' file,\n% we define a prefix and call entries later as \\gls{<prefix>.<entry>}\n% These prefixes are used in various places; define them here once and reference later\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    \\newcommand*{\\symprefix}{sym.}\n    \\newcommand*{\\subprefix}{sub.}\n    \\newcommand*{\\nameprefix}{name.}\n    \\newcommand*{\\constantsprefix}{cons.}\n    \\newcommand*{\\indexprefix}{idx.}\n    \\newcommand*{\\abbreviationprefix}{abb.}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Load the bib files:\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/abbreviations},%\n        sort=doc,% Use document language for sorting\n        label-prefix={\\abbreviationprefix},\n        type=abbreviations,\n        selection={all},%\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/index/terms},%\n        sort=doc, % Use document language for sorting\n        type=index,\n        group=terms,\n        label-prefix={\\indexprefix},\n        selection={all},%\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/index/names},%\n        sort=doc, % Use document language for sorting\n        type=index,\n        category=names,\n        group=names,\n        label-prefix={\\nameprefix},\n        selection={all},%\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/symbols/roman},%\n        sort=doc, % Use document language for sorting\n        symbol-sort-fallback=name,% Sort by name aka symbol if sort field is missing\n        %\n        % If first field is equal, sort by this next (by appending it).\n        % E.g. 'c' for 'Velocity' and also for 'Heat Capacity' is then sorted with\n        % 'Heat Capacity' first etc.:\n        sort-suffix=description,\n        label-prefix={\\symprefix},\n        type=symbols,% Change this to 'notprinted' to omit printing in the glossary\n        category={same as type},\n        selection={all},\n        group={roman},\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/symbols/greek},%\n        sort=doc, % Use document language for sorting\n        symbol-sort-fallback=name,% Sort by name aka symbol if sort field is missing\n        %\n        % If first field is equal, sort by this next (by appending it).\n        % E.g. 'c' for 'Velocity' and also for 'Heat Capacity' is then sorted with\n        % 'Heat Capacity' first etc.:\n        sort-suffix=description,\n        label-prefix={\\symprefix},\n        type=symbols,% Change this to 'notprinted' to omit printing in the glossary\n        category={same as type},\n        selection={all},\n        group={greek},\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/symbols/other},%\n        sort=doc, % Use document language for sorting\n        symbol-sort-fallback=name,% Sort by name aka symbol if sort field is missing\n        %\n        % If first field is equal, sort by this next (by appending it).\n        % E.g. 'c' for 'Velocity' and also for 'Heat Capacity' is then sorted with\n        % 'Heat Capacity' first etc.:\n        sort-suffix=description,\n        label-prefix={\\symprefix},\n        type=symbols,% Change this to 'notprinted' to omit printing in the glossary\n        category={same as type},\n        selection={all},\n        group={other},\n    ]%\n    \\GlsXtrLoadResources[%\n        src={bib/glossaries/symbols/subscripts},%\n        % sort=doc, % Use document language for sorting\n        sort-field=name,% Default is by label, not by name\n        type=subscripts,%\n        category=subscripts,\n        label-prefix={\\subprefix},\n        selection={all},%\n    ]%\n    \\GlsXtrLoadResources[\n        src={bib/glossaries/constants},% constants.bib\n        type={numbers},% set the type for all selected entries\n        category={number},% set the category for all selected entries\n        label-prefix={\\constantsprefix},\n    ]\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Introduce new commands that alias \\gls commands and allow modifiers\n% You then use e.g. \\sym{velocity} to access \\gls{sym.velocity} etc.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    \\glsxtrnewgls{\\symprefix}{\\sym}% \\sym{XYZ} is like \\gls{sym.XYZ}\n    \\glsxtrnewgls{\\subprefix}{\\sub}\n    \\glsxtrnewgls{\\nameprefix}{\\name}\n    \\glsxtrnewgls{\\constantsprefix}{\\cons}\n    \\glsxtrnewgls{\\indexprefix}{\\idx}\n    \\glsxtrnewgls{\\abbreviationprefix}{\\abb}\n\n    % We cannot alias the commands introduced by `\\glsaddkey` the same way:\n    % \\glsxtrnewgls only works on \\gls{<prefix>.<key>} to alias the <prefix> away\n    % into its own command. However, for a command like \\glsspecific{}, it does not work.\n    % We can therefore do \\sym{volume}, but have to do \\glsspecific{sym.volume}, i.e.\n    % specify the prefix manually.\n    % A short-cut command is therefore enabled by the following commands.\n    \\newcommand*{\\symspec}[2][]{\\glsspecific[#1]{\\symprefix#2}}\n    % Register with glossaries-extra so it writes info to aux file:\n    \\glsxtridentifyglslike{\\symprefix}{\\symspec}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Further Options:\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    % indexonlyfirst can also be a package option.\n    % Index only on first use for certain categories, as set manually above.\n    % https://tex.stackexchange.com/a/318886/120853\n    % \\glssetcategoryattribute{symbols}{indexonlyfirst}{true}\n    % \\glssetcategoryattribute{subscripts}{indexonlyfirst}{true}\n    \\glssetcategoryattribute{names}{textformat}{textsc} % As printed in the text\n    \\glssetcategoryattribute{names}{glossnamefont}{textsc} % As printed in the Glossary\n\n    \\newcommand*{\\specificsymbolmark}{*}\n    %\n    \\glsdefpostdesc{symbols}{% If entry has field 'specific', its description is marked\n        \\ifglshasfield{specific}{\\glscurrententrylabel}%\n        {\\specificsymbolmark}%\n        {}%\n    }\n\n    % Append stuff after 'name' field for the 'symbols' category.\n    % Syntax: \\ifglshasfield{<field>}{<label>}{<true part>}{<falsepart>}\n    \\newcommand*{\\alternativesymbolmark}{/}\n    %\n    \\glsdefpostname{symbols}{%\n        % If entry has field 'international-symbol', append it after the regular entry:\n        \\ifglshasfield{international-symbol}{\\glscurrententrylabel}%\n        { [\\glsentryinternationalsymbol{\\glscurrententrylabel}]}%\n        {}% Do nothing in else\n        % If entry has a field 'alternative-symbol', append it after the regular entry:\n        \\ifglshasfield{alternative-symbol}{\\glscurrententrylabel}%\n        {\\ \\alternativesymbolmark{}\\ \\glsentryalternativesymbol{\\glscurrententrylabel}}%\n        {}%\n    }\n\n    % Give proper names for all groups here to override the default,\n    % automatically generated ones\n    \\AtBeginDocument{% Do this after preamble, else errors out\n        \\glsxtrsetgrouptitle{greek}{\\TransGreek{}}\n        \\glsxtrsetgrouptitle{roman}{\\TransRoman{}}\n        \\glsxtrsetgrouptitle{other}{\\TransOther{}}\n        \\glsxtrsetgrouptitle{terms}{\\TransTerms{}}\n        \\glsxtrsetgrouptitle{names}{\\TransNames{}}\n    }\n\n    \\setglossarysection{section} % One down in rprt/book\n\n    % Some styles require manual setting of width for the first column.\n    % Automate this and find widest entry:\n    \\setglossarypreamble[subscripts]{\\glsfindwidesttoplevelname[\\currentglossary]}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% New Styles for glossary printing\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    \\RequirePackage{glossary-bookindex} % The style used for the Index\n\n    \\RequirePackage{glossary-mcols} % Multi-column styles used for Subscripts\n\n    % Long, elaborate base style, providing e.g. 'long3col' for the abbreviations etc.:\n    \\RequirePackage{glossary-longextra}\n\n    \\newcommand*{\\glshdrfont}[1]{\\textbf{#1}} % Font for gls table heads\n\n    \\newglossarystyle{custom-base}{\n        % A simple style subsequent, custom-defined styles will have in common.\n        \\setglossarystyle{long-name-desc-loc}\n        \\renewcommand*{\\glossaryheader}{}% Remove it\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Symbols\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n    % Standard base style, without page list\n    \\newglossarystyle{symbunitlong}{% https://tex.stackexchange.com/a/269571/120853\n        % Base new style on existing one. This is quite important, since it implements\n        % all otherwise missing but maybe required commands,\n        % like \\glsgroupskip if --group option is used for bib2gls\n        \\setglossarystyle{custom-base}\n\n        \\renewcommand*{\\glsgroupskip}{\\addlinespace\\addlinespace}%\n\n        % This command is taken from the source code, I hope I am not abusing it:\n        \\ifglsnonumberlist\n            % User requested NO location list/number list/page list to be printed, so\n            % remove those columns.\n            \\renewenvironment{theglossary}{%\n                % Use Longtabu over longtable, the latter caused inexplicable issues with\n                % 'Column widths have changed, rerun Latex'\n                \\begin{longtabu}{%\n                    r%\n                    p{0.5\\linewidth}%\n                    l%\n                }%\n            }{%\n                \\end{longtabu}%\n            }%\n\n            \\renewcommand*{\\glsgroupheading}[1]{%\n                \\glshdrfont{\\glsgetgrouptitle{##1}} &\n                \\glshdrfont{\\descriptionname} &\n                \\glshdrfont{\\TransUnit{}}\n                \\tabularnewline\n            }%\n\n            \\renewcommand*{\\glossentry}[2]{%\n                \\glsentryitem{##1}\\glstarget{##1}{\\glossentryname{##1}} &\n                \\glossentrydesc{##1}\\glspostdescription &\n                % Use glsentryunit to access entry, NOT glsunit,\n                % https://tex.stackexchange.com/a/281772/120853:\n                \\glsentryunit{##1}\n                \\tabularnewline\n            }\n        \\else\n            \\renewenvironment{theglossary}{% Redefine this, overwriting the base style\n                \\begin{longtabu}{%\n                    r%\n                    p{0.5\\linewidth}%\n                    p{\\glspagelistwidth}%\n                    l%\n                }%\n            }{%\n                \\end{longtabu}%\n            }%\n\n            \\renewcommand*{\\glsgroupheading}[1]{%\n                \\glshdrfont{\\glsgetgrouptitle{##1}} &\n                \\glshdrfont{\\descriptionname} &\n                \\glshdrfont{\\pagelistname} &\n                \\glshdrfont{\\TransUnit{}}\n                \\tabularnewline\n            }%\n\n            \\renewcommand*{\\glossentry}[2]{%\n                \\glsentryitem{##1}\\glstarget{##1}{\\glossentryname{##1}} &\n                \\glossentrydesc{##1}\\glspostdescription &\n                ##2 &\n                % Use glsentryunit to access entry, NOT glsunit,\n                % https://tex.stackexchange.com/a/281772/120853:\n                \\glsentryunit{##1}\n                \\tabularnewline\n            }\n        \\fi\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Numbers.\n% To print constants, as in physical constants with values and unit.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n    \\newglossarystyle{numberlong}{% https://tex.stackexchange.com/a/269571/120853\n        % Base new style on existing one. This is quite important, since it implements\n        % all otherwise missing but maybe required commands, like\n        % \\glsgroupskip if --group option is used for bib2gls\n        \\setglossarystyle{custom-base}\n\n        % This command is taken from the source code, I hope I am not abusing it:\n        \\ifglsnonumberlist\n        % User requested NO location list/number list/page list to be printed, so\n        % remove those columns.\n            \\renewenvironment{theglossary}{\n                % Use Longtabu over longtable, the latter caused inexplicable issues with\n                % 'Column widths have changed, rerun Latex'\n                \\begin{longtabu}{%\n                    r%\n                    p{0.3\\linewidth}%\n                    r%\n                    @{\\;}%\n                    l%\n                }%\n            }{%\n                \\end{longtabu}%\n            }%\n\n            \\renewcommand*{\\glossaryheader}[1]{%\n                \\glshdrfont{\\symbolname} &\n                \\glshdrfont{\\descriptionname} &\n                \\multicolumn{2}{l}{{\\glshdrfont{\\TransPhysicalQuantity{}}}}\n                \\tabularnewline\n            }%\n\n            \\renewcommand*{\\glossentry}[2]{%\n                \\glsentryitem{##1}\\glstarget{##1}{\\glossentryname{##1}} &\n                \\glossentrydesc{##1}\\glspostdescription &\n                \\glsentryvalue{##1} &\n                % Use glsentryunit to access entry, NOT glsunit,\n                % https://tex.stackexchange.com/a/281772/120853:\n                \\glsentryunit{##1}\n                \\tabularnewline\n            }%\n        \\else\n            \\renewenvironment{theglossary}{\n                % Use Longtabu over longtable, the latter caused inexplicable issues with\n                % 'Column widths have changed, rerun Latex'\n                \\begin{longtabu}{%\n                    r%\n                    p{0.3\\linewidth}%\n                    r%\n                    @{\\;}%\n                    l%\n                    p{\\glspagelistwidth}%\n                }%\n            }{%\n                \\end{longtabu}%\n            }%\n\n            \\renewcommand*{\\glossaryheader}[1]{%\n                \\glshdrfont{\\symbolname} &\n                \\glshdrfont{\\descriptionname} &\n                \\multicolumn{2}{l}{{\\glshdrfont{\\TransPhysicalQuantity{}}}} &\n                \\glshdrfont{\\pagelistname}\n                \\tabularnewline\n            }%\n\n            \\renewcommand*{\\glossentry}[2]{%\n                \\glsentryitem{##1}\\glstarget{##1}{\\glossentryname{##1}} &\n                \\glossentrydesc{##1}\\glspostdescription &\n                \\glsentryvalue{##1} &\n                % Use glsentryunit to access entry, NOT glsunit,\n                % https://tex.stackexchange.com/a/281772/120853:\n                \\glsentryunit{##1} &\n                ##2\n                \\tabularnewline\n            }%\n        \\fi\n    }\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% References\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% Should be loaded late, because it does a lot of redefinitions.\n% With Polyglossia, cleveref recognizes what was passed in\n% \\setdefaultlanguage and uses it. It must come before cleveref is loaded.\n\n\\RequirePackage[\n    % Always capitalise; still, use \\Cref and \\cref appropriately in case that changes!\n    capitalise,\n    nameinlink,% Name of reference is part of PDF hyperlink\n    noabbrev,% Full expansion: Figure instead of Fig., etc.\n]{cleveref}%\n    \\creflabelformat{equation}{#2#1#3}% No (1), but 1, aka remove parentheses\n\n    % Syntax: \\crefname{<counter>}{<singular>}{<plural>}\n    % \\Crefname (capitalised) is not required; when it is not present but \\Cref{} is\n    % called, it uses \\MakeUppercase on \\crefname definitions.\n    % However, if LaTeX macros are used in the definition, it is required.\n    % Code listings, see `minted` package.\n    % Introduce a new <type> called `code`, then make the (existing) counter `listing`\n    % use it by aliasing. Modifying `listing` directly with `\\crefname{listing}...`\n    % did not work! See also\n    % https://tex.stackexchange.com/a/310355/120853\n    \\crefname{code}{\\TransListing{}}{\\TransListings{}}\n    \\Crefname{code}{\\TransListing{}}{\\TransListings{}}\n    \\crefalias{listing}{code}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Color Boxes\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{tcolorbox}% Put after tikz\n    \\tcbuselibrary{many}%\n    \\tcbset{%\n        highlight math style={%\n            colframe=white,\n            colback=g6,\n        },%\n    }%\n\n    \\newtcolorbox[%\n        auto counter,%\n        number within=chapter,%\n        % Set cleveref, see https://tex.stackexchange.com/a/126023/120853:\n        crefname={\\TransExample{}}{\\TransExamples{}},\n        % List of Examples. *.loe file ending could clash with package thmtools,\n        % careful if that is used!\n        list inside=loe,\n    ]{example}% Name of environment itself\n        [2]% Number of arguments for the environment\n        []% Default of optional argument, which is the first one. Use it for label\n        {%\n            beforeafter skip=18pt plus 4pt minus 4pt,%\n            width=0.95\\linewidth,%\n            % Center box; see https://tex.stackexchange.com/a/273111/120853:\n            enlarge left by=0.025\\linewidth,\n            title=\\TransExample{}\\ \\thetcbcounter: #2,%\n            fonttitle=\\sffamily,%\n            leftrule=1mm,%\n            arc is angular,%\n            parbox,% Allows regular paragraph breaks\n            breakable,% Breaks across pages\n            enhanced,% Hands drawing to tikz\n            rightrule=0mm,%\n            bottomrule=0mm,%\n            % Setting what ends up in 'list of' so that '<Title>' is not shown:\n            list text=#2,\n            #1,%\n            colback=g6,%\n            colframe=g1,%\n            % float,\n        }%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Custom Commands\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\RequirePackage{suffix}% For variants of custom commands\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Maths\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% To insert math equations into the text flow,\n% we need punctuation marks at the end of display-style equations.\n% Prepend them with a small horizontal space for visual separation.\n\n\\newcommand*{\\eqend}{\\,.}% Command \\eqdot reserved by unicode-math\n\\newcommand*{\\eqcomma}{\\,,}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Gradient operator (so that it will be printed upright)\n\\DeclareMathOperator{\\grad}{grad}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\newcommand*{\\const}{\\text{\\TransConstant{}.}}% For all 'constant' expressions\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Quick Quad like physics package. For text between two equation parts.\n% We do not use physics package because it is currently not in a good condition:\n% https://tex.stackexchange.com/q/471532/120853\n\\newcommand*{\\qq}[1]{\\quad\\text{#1}\\quad}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Unified markup for constructs of the form:\n% '1.2 ppm CO2' etc., with correct, specified spacing.\n\\newcommand*{\\chemamount}[3]{%\n    \\ensuremath{%\n        \\qty{#1}{#2}%\n        \\;% Medium-sized space\n        \\chcpd{#3}%\n    }%\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Circle input and parse as a number\n\\newcommand*{\\circlednum}[1]{%\n    \\tikz[baseline=(char.base)]{%\n            \\node[circlednum] (char) {\\num{#1}};\n    }\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Create a couple of wrappers to integrate with gls\n% These are only necessary because we cannot really create gls entries that also accept\n% arguments, so we treat them separately.\n\n% Use the \\<XYZ>fmt commands only to format arguments, without doing anything else.\n% Then use the \\<XYZ> commands in the text, which includes indexing etc.\n% We use \\glsdisp, which works like \\glsdisp{<indexed label>}{<displayed link text>}\n% and respects the first use flag.\n% If {<displayed link text>} contains another glossary-entry, e.g. a \\sym command,\n% that is still indexed and seems to work. The link leads to <indexed label>.\n\n% If the custom commands do not make use of gls-like commands explicitly,\n% add a \\glsadd to create an entry in the glossary, but no text at the location\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% use dottedsquare (provided by unicode-math package, refer to unimath-symbols.pdf)\n% as a placeholder for symbols\n% HACKY: Raise it a bit, since default symbol hangs low\n\\newcommand*{\\symbolplaceholder}{\\raisebox{0.3ex}{\\dottedsquare}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Mean value: horizontal overbar. The built-in options all look poor\n% https://tex.stackexchange.com/a/22134/120853\n\\newcommand*{\\meanfmt}[1]{%\n    \\ensuremath{%\n        \\mkern 1.5mu%\n        \\overline{%\n            \\mkern-1.5mu#1\\mkern-1.5mu%\n        }%\n        \\mkern 1.5mu%\n    }%\n}\n\\newcommand*{\\mean}[1]{\\glsdisp{sym.mean}{\\meanfmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Logarithmic mean\n\\newcommand*{\\logmeanfmt}[1]{\\ensuremath{\\tilde{#1}}}\n\\newcommand*{\\logmean}[1]{\\glsdisp{sym.logmean}{\\logmeanfmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Absolute value\n\\DeclarePairedDelimiter{\\absfmt}{\\lvert}{\\rvert}% Absolute value\n\\newcommand*{\\abs}[1]{\\glsdisp{sym.abs}{\\ensuremath{\\absfmt*{#1}}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Dotted symbol for flows\n\\newcommand*{\\flowfmt}[1]{\\ensuremath{\\dot{#1}}}\n\\newcommand*{\\flow}[1]{\\glsdisp{sym.flow}{\\flowfmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Delta/Difference\n\\newcommand*{\\differencefmt}[1]{\\ensuremath{\\Delta #1}}\n\\newcommand*{\\difference}[1]{\\glsdisp{sym.difference}{\\differencefmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Wrapper for Nabla Operator\n\\newcommand*{\\nablaoperatorfmt}[1]{\\ensuremath{\\nabla #1}}\n\\newcommand*{\\nablaoperator}[2][]{% Optional argument is degree\n    \\ensuremath{%\n        \\glsdisp{sym.nabla}{\\nablaoperatorfmt{^{#1}#2}}\n    }%\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Wrapper for Heat Exchanger Entry\n\\newcommand*{\\heatexentryfmt}[1]{\\ensuremath{#1'}}\n\\newcommand*{\\heatexentry}[1]{\\glsdisp{sym.heatexentry}{\\heatexentryfmt{#1}}}\n\n% Wrapper for Heat Exchanger Exit\n\\newcommand*{\\heatexexitfmt}[1]{\\ensuremath{#1''}}\n\\newcommand*{\\heatexexit}[1]{\\glsdisp{sym.heatexexit}{\\heatexexitfmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Vectors\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Vector with bold symbol instead of arrow\n\\newcommand*{\\vectfmt}[1]{\\ensuremath{\\symbf{#1}}}\n\\newcommand*{\\vect}[1]{\\glsdisp{sym.vector}{\\vectfmt{#1}}}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Derivatives\n% These functionalities are also provided by the otherwise useful 'physics' package.\n% However, that package has many issues and is best avoided!\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Base Version:\n% Syntax: \\deriv[<degree>]{<symbol>}\n\n% Starred variant gives partial derivative.\n% The star/asterisk and brackets (optional argument in []) may both be left out.\n\n% Usage example 1: \\deriv*[2]{x} -> 2nd degree partial derivative of x\n% Usage example 2: \\deriv{x} -> derivative of x\n% Usage example 3: \\deriv*{x} -> partial derivative of x\n% Usage example 4: \\deriv[5]{x} -> 5th derivative of x\n\n% \\newcommand syntax:\n% \\newcommand{<command>}[<number of arguments>][<defaults>]{<code>}\n\n% I.e., if [<defaults>] is empty, no default values exist.\n% If one optional argument exists, it takes #1, and the mandatory arguments are appended\n% as #2, ...\n\n% Use explicit glssymbol, since the regular field 'name' is oppcupied by what will be\n% printed in the glossary (with the \\symbolplaceholder appended)\n\\newcommand*{\\derivativefmt}[1]{%\n     % Upright d in derivatives\n    \\ensuremath{\\mathup{d}#1}%\n}%\n\n\\newcommand*{\\partialderivativefmt}[1]{%\n    \\ensuremath{\\partial #1}%\n}\n\n\\newcommand*{\\deriv}[2][]{%\n    \\ensuremath{%\n        \\glsdisp{sym.derivative}{%\n            \\derivativefmt{^{#1}#2}%\n        }%\n    }%\n}%\n\n% Make it so that starred version of \\deriv{} command gives partial derivative\n\\WithSuffix\\newcommand\\deriv*[2][]{%\n    \\ensuremath{%\n        \\glsdisp{sym.partial_derivative}{%\n            \\partialderivativefmt{^{#1}#2}%\n        }%\n    }%\n}%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Fraction version:\n\n% Syntax: \\fracderiv[<degree>]{<numerator>}{<denominator>}\n\n% Starred variant gives partial derivative.\n% The star/asterisk and brackets (optional argument in []) may both be left out.\n\n% timederiv simply inserts the time symbol as the denominator automatically.\n% posderiv does the same for the positional coordinate symbol.\n\n% Usage example 1: \\fracderiv*[2]{x}{y}\n% Usage example 2: \\fracderiv{x}{y}\n% Usage example 3: \\timederiv[3]{x} % Note how there is no second mandatory argument\n% Usage example 4 \\posderiv*[2]{y} % Note how there is no second mandatory argument\n\n\\newcommand{\\fracderiv}[3][]{%\n    \\ensuremath{%\n        \\frac{%\n            \\deriv[#1]{#2}%\n        }{%\n            \\deriv{#3}^{#1}%\n        }%\n    }%\n}%\n% starred version gives partial derivative\n\\WithSuffix\\newcommand\\fracderiv*[3][]{%\n    \\ensuremath{%\n        \\frac{%\n            \\deriv*[#1]{#2}%\n        }{%\n            \\deriv*{#3}^{#1}%\n        }%\n    }%\n}\n\n% Time derivative\n\\newcommand*{\\timederiv}[2][]{%\n    \\fracderiv[#1]{#2}{\\gls{sym.time}}%\n}%\n% Partial Time derivative\n\\WithSuffix\\newcommand\\timederiv*[2][]{%\n    \\fracderiv*[#1]{#2}{\\gls{sym.time}}%\n}\n\n% Positional derivative\n\\newcommand*{\\posderiv}[2][]{%\n    \\fracderiv[#1]{#2}{\\gls{sym.first_cart_coord}}%\n}\n% Partial Positional derivative\n\\WithSuffix\\newcommand\\posderiv*[2][]{%\n    \\fracderiv*[#1]{#2}{\\gls{sym.first_cart_coord}}%\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Temperature splits/pairs\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% To print: 45/55 °C\n\\newcommand*{\\temperaturepair}[2]{%\n    \\qtyrange[%\n        range-phrase={/},%\n        range-units=single%\n    ]{#1}{#2}{\\degreeCelsius}%\n}%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Other\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Indicating an image etc. has been adapted from it source\n\\newcommand*{\\adaptedfrom}{%\n    \\TransAdaptedFrom{}%\n}%\n\n% Document metadata commands, like \\author etc.\n% See also https://stackoverflow.com/a/2833982\n\\newcommand*{\\documenttype}[1]{%\n    \\renewcommand*{\\@documenttype}{#1}%\n}\n\n% \\@ehc is generic error text, see also\n% https://tex.stackexchange.com/a/59952/120853.\n% A quick test showed that it prints:\n%\n%      Try typing <return> to proceed.If that doesn’t work, type X <return>\n%      to quit.\n%\n% It's a help message. Help messages are a required third argument for ClassErrors\n% and PackageErrors, but not Warnings.\n\n\\newcommand*{\\@documenttype}{%\n    \\ClassWarning{acp}{No \\noexpand\\documenttype given}%{\\@ehc}%\n}\n\n% Student ID number\n\\newcommand*{\\idnumber}[1]{%\n    \\renewcommand*{\\@idnumber}{#1}%\n}\n\\newcommand*{\\@idnumber}{%\n    \\ClassWarning{acp}{No \\noexpand\\idnumber given}%{\\@ehc}%\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% A signature field with places for the date and time\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\newcommand{\\signaturefield}[1][\\@author]{%\n    % This should only occur on pages with a lot of other pages behind it, to support\n    % writing on it here.\n    % If is occurs at the beginning of the document, put it recto. At the end, verso.\n    % Else, writing and stamping on here won't have much support.\n    \\vspace*{1.5cm}% Leave room for signature\n    \\begin{center}\n        \\begin{tabular}{%\n            % Columns widths control signature line length\n            M{12em}\n            M{4em}% Empty middle\n            M{12em}\n        }\n            \\cmidrule{1-1}\\cmidrule{3-3}\n                \\textit{#1} &\n                & % Empty column\n                \\textit{\\TransPlaceDate{}}\n                \\\\\n        \\end{tabular}\n    \\end{center}\n}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Only for the purpose of demonstration\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\definecolor{DarkLinkGreen}{RGB}{65, 107, 60}\n\n% Wrapper for links to CTAN, or elsewhere\n\\newcommand*{\\ctanpackage}[2][None]{%\n    % Usage:\n    % \\ctanpackage[]{siunitx} -> no link generated, warning issued\n    % \\ctanpackage[www.test.com]{siunitx} -> link to optional argument\n    % \\ctanpackage{siunitx} -> link to siunitx on CTAN (https://ctan.org/pkg/siunitx)\n    \\ifstrequal{#1}{None}{%\n        \\def\\package@link{https://ctan.org/pkg/#2}%\n    }{%\n        \\def\\package@link{#1}%\n    }%\n    \\expandafter\\href\\expandafter{\\package@link}{%\n        \\textcolor{DarkLinkGreen}{\\texttt{\\textbf{#2}}}%\n    }%\n}%\n\n% This sentence contains all 26 letters of the Latin alphabet (pangram)\n\\newcommand*{\\sampletext}{%\n    The quick brown Fox jumps over the lazy Dog 13 times!%\n}\n\n% For demonstrating upright math operators\n\\DeclareMathOperator{\\examplemean}{MEAN}\n"
  },
  {
    "path": "bib/README.md",
    "content": "# **Bib**liographical data\n\nThis directory contains:\n\n1. The [bibliography itself](bibliography.bib).\n    This is auto-generated using [Zotero](https://www.zotero.org/).\n    Using citation management software (any will do) will help you out greatly in managing larger literature collections.\n1. All sorts of [glossaries](glossaries/), which thanks to [`bib2gls`](https://ctan.org/pkg/bib2gls) now also come in `bib` format.\n"
  },
  {
    "path": "bib/bibliography.bib",
    "content": "\n@book{baehrThermodynamikGrundlagenUnd2016,\n  title = {Thermodynamik: Grundlagen und technische Anwendungen},\n  shorttitle = {Thermodynamik},\n  author = {Baehr, Hans Dieter and Kabelac, Stephan},\n  date = {2016},\n  series = {Lehrbuch},\n  edition = {16., aktualisierte Auflage},\n  publisher = {{Springer Vieweg}},\n  location = {{Berlin}},\n  isbn = {978-3-662-49568-1},\n  langid = {german},\n  pagetotal = {671},\n  keywords = {Thermodynamics}\n}\n\n@book{birdNaturalLanguageProcessing2009,\n  title = {Natural Language Processing with {{Python}}},\n  author = {Bird, Steven and Klein, Ewan and Loper, Edward},\n  date = {2009},\n  edition = {1st ed},\n  publisher = {{O'Reilly}},\n  location = {{Beijing ; Cambridge [Mass.]}},\n  abstract = {This is an introduction to natural language processing, which supports a variety of language technologies, from predictive text and email filtering to automatic summarization and translation},\n  isbn = {978-0-596-51649-9},\n  pagetotal = {479},\n  keywords = {Natural language processing (Computer science),Python (Computer program language),Python <Programmiersprache>,Sprachverarbeitung},\n  annotation = {OCLC: ocn301885973}\n}\n\n@book{diracPrinciplesQuantumMechanics1981,\n  title = {The {{Principles}} of {{Quantum Mechanics}}},\n  author = {Dirac, Paul Adrien Maurice},\n  date = {1981},\n  series = {International Series of Monographs on Physics},\n  publisher = {{Clarendon Press}},\n  isbn = {978-0-19-852011-5},\n  keywords = {physics}\n}\n\n@book{dubbelTaschenbuchFurMaschinenbau2007,\n  title = {Taschenbuch Für Den {{Maschinenbau}}},\n  author = {Dubbel, Heinrich and Grote, Karl-Heinrich and Feldhusen, J.},\n  date = {2007},\n  edition = {22},\n  publisher = {{Springer}},\n  location = {{Berlin Heidelberg New York}},\n  isbn = {978-3-540-49714-1},\n  pagetotal = {1},\n  keywords = {Handbooks; manuals; etc,Mechanical engineering}\n}\n\n@article{einsteinZurElektrodynamikBewegter1905,\n  title = {Zur {{Elektrodynamik}} Bewegter {{Körper}}. ({{German}}) [{{On}} the Electrodynamics of Moving Bodies]},\n  author = {Einstein, Albert},\n  date = {1905},\n  journaltitle = {Annalen der Physik},\n  volume = {322},\n  number = {10},\n  pages = {891--921},\n  doi = {http://dx.doi.org/10.1002/andp.19053221004},\n  issue = {10}\n}\n\n@book{goossensLaTeXCompanion1993,\n  title = {The \\textbackslash{{LaTeX}}\\textbackslash{} {{Companion}}},\n  author = {Goossens, Michel and Mittelbach, Frank and Samarin, Alexander},\n  date = {1993},\n  publisher = {{Addison-Wesley}},\n  location = {{Reading, Massachusetts}}\n}\n\n@report{internationalorganizationforstandardizationISO821720172017,\n  type = {Standard},\n  title = {{{ISO}} 8217:2017 - {{Petroleum}} Products - {{Fuels}} (Class {{F}}) - {{Specifications}} of Marine Fuels},\n  author = {{International Organization for Standardization}},\n  date = {2017-03},\n  number = {8217},\n  pages = {23},\n  institution = {{ISO/TC 28/SC 4}},\n  url = {https://www.iso.org/standard/64247.html},\n  urldate = {2018-10-08},\n  langid = {english}\n}\n\n@mvbook{knuthFundamentalAlgorithms1973,\n  title = {Fundamental {{Algorithms}}},\n  author = {Knuth, Donald E.},\n  date = {1973},\n  series = {The {{Art}} of {{Computer Programming}}},\n  edition = {3},\n  volume = {1},\n  publisher = {{Addison-Wesley}},\n  location = {{Reading, Mass.}},\n  isbn = {978-0-201-89683-1},\n  langid = {english},\n  volumes = {4},\n  keywords = {knuth,programming}\n}\n\n@book{knuthTeXbook1986,\n  title = {The {{TeXbook}}},\n  author = {Knuth, Donald Ervin},\n  date = {1986},\n  series = {Computers \\& Typesetting},\n  number = {A},\n  publisher = {{Addison-Wesley}},\n  location = {{Reading, Mass}},\n  isbn = {978-0-201-13447-6},\n  langid = {english},\n  pagetotal = {483},\n  keywords = {Computer programs,Computerized typesetting,Mathematics printing,TeX (Computer file)}\n}\n\n@online{mathworksCreateSimpleClass2020,\n  title = {Create a {{Simple Class}} - {{MATLAB}} \\& {{Simulink}}},\n  author = {{Mathworks}},\n  date = {2020},\n  url = {https://www.mathworks.com/help/matlab/matlab_oop/create-a-simple-class.html},\n  urldate = {2020-04-14}\n}\n\n@book{mckinneyPythonDataAnalysis2018,\n  title = {Python for Data Analysis: Data Wrangling with Pandas, {{NumPy}}, and {{IPython}}},\n  shorttitle = {Python for Data Analysis},\n  author = {McKinney, Wes},\n  date = {2018},\n  edition = {Second edition},\n  publisher = {{O'Reilly Media, Inc}},\n  location = {{Sebastopol, California}},\n  abstract = {\"Get complete instructions for manipulating, processing, cleaning, and crunching datasets in Python. Updated for Python 3.6, the second edition of this hands-on guide is packed with practical case studies that show you how to solve a broad set of data analysis problems effectively. You'll learn the latest versions of pandas, NumPy, IPython, and Jupyter in the process\"--Page 4 of cover},\n  isbn = {978-1-4919-5766-0},\n  pagetotal = {524},\n  keywords = {Data mining,Data Mining,Datenanalyse,Datenmanagement,Programming languages (Electronic computers),Python (Computer program language),Python 3.6},\n  annotation = {OCLC: ocn959595088}\n}\n\n@book{mollenhauerHandbuchDieselmotoren2007,\n  title = {Handbuch Dieselmotoren},\n  author = {Mollenhauer, Klaus and Tschöke, Helmut},\n  date = {2007},\n  series = {VDI-Buch},\n  edition = {3., neubearb. Aufl},\n  publisher = {{Springer}},\n  location = {{Berlin}},\n  isbn = {978-3-540-72164-2},\n  langid = {german},\n  pagetotal = {702},\n  keywords = {Combustion Engines}\n}\n\n@book{ramalhoFluentPython2015,\n  title = {Fluent {{Python}}},\n  author = {Ramalho, Luciano},\n  date = {2015},\n  edition = {First edition},\n  publisher = {{O'Reilly}},\n  location = {{Sebastopol, CA}},\n  abstract = {Learn how to write idiomatic, effective Python code by leveraging its best features. Python's simplicity quickly lets you become productive with it, but this often means you aren't using everything the language has to offer. By taking you through Python's key language features and libraries, this practical book shows you how to make your code shorter, faster, and more readable all at the same time--what experts consider Pythonic},\n  isbn = {978-1-4919-4600-8},\n  pagetotal = {743},\n  keywords = {Object-oriented programming languages,Objektorienterad programmering,Programming Languages,Python,Python (Computer program language)},\n  annotation = {OCLC: ocn884808025}\n}\n\n@inreference{wikipediacontributorsModelica2021,\n  title = {Modelica},\n  booktitle = {Wikipedia},\n  author = {{Wikipedia Contributors}},\n  editor = {{Wikipedia Contributors}},\n  date = {2021-01-05T18:58:26Z},\n  url = {https://en.wikipedia.org/w/index.php?title=Modelica&oldid=998516587},\n  urldate = {2021-02-19},\n  abstract = {Modelica is an object-oriented, declarative, multi-domain modeling language for component-oriented modeling of complex systems, e.g., systems containing mechanical, electrical, electronic, hydraulic, thermal, control, electric power or process-oriented subcomponents. The free Modelica language is developed by the non-profit Modelica Association. The Modelica Association also develops the free Modelica Standard Library that contains about 1400 generic model components and 1200 functions in various domains, as of version 4.0.0.},\n  langid = {english},\n  annotation = {Page Version ID: 998516587}\n}\n\n\n"
  },
  {
    "path": "bib/glossaries/abbreviations.bib",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% IT\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@abbreviation{uniform_resource_locator,\n    short={URL},\n    long={Uniform Resource Locator},\n}\n@abbreviation{single_source_of_truth,\n    short={SSOT},\n    long={Single Source of Truth},\n}\n@abbreviation{what_you_see_is_what_you_mean,\n    short={WYSIWYM},\n    long={What You See Is What You Mean},\n}\n@abbreviation{portable_document_format,\n    short={PDF},\n    long={Portable Document Format},\n}\n@abbreviation{graphical_user_interface,\n    short={GUI},\n    long={Graphical User Interface},\n}\n@abbreviation{integrated_development_environment,\n    short={IDE},\n    long={Integrated Development Environment},\n}\n@abbreviation{scalable_vector_graphics,\n    short={SVG},\n    long={Scalable Vectors Graphics},\n}\n@abbreviation{continuous_integration,\n    short={CI},\n    long={Continuous Integration},\n}\n@abbreviation{continuous_delivery,\n    short={CD},\n    long={Continuous Delivery},\n}\n@abbreviation{js_object_notation,\n    short={JSON},\n    long={JavaScript Object Notation},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Thermodynamics\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@abbreviation{coefficient_of_performance,\n    short={COP},\n    long={Coefficient of Performance},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Organizations\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@abbreviation{international_organization_for_standardization,\n    short={ISO},\n    long={International Organization for Standardization},\n}\n@abbreviation{int_mar_org,\n    short={IMO},\n    long={International Maritime Organization}\n}\n@abbreviation{comprehensive_tex_archive_network,\n    short={CTAN},\n    long={Comprehensive \\TeX{} Archive Network}\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Marine\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@abbreviation{marine_diesel_oil,\n    short={MDO},\n    long={Marine Diesel Oil}\n}\n@abbreviation{heavy_fuel_oil,\n    short={HFO},\n    long={Heavy Fuel Oil}\n}\n"
  },
  {
    "path": "bib/glossaries/constants.bib",
    "content": "@number{pi,\n    name={\\ensuremath{\\pi}},\n    description={Pi},\n    value={\\num{3.14159}\\dots{}},\n    unit={},\n}\n@number{euler,\n    name={\\ensuremath{e}},\n    description={Euler's number},\n    value={\\num{2.71828}\\dots{}},\n    unit={},\n}\n@number{imaginary,\n    name={\\ensuremath{i}},\n    description={Imaginary unit},\n    value={\\(\\sqrt{\\num{-1}}\\)},\n    unit={},\n}\n"
  },
  {
    "path": "bib/glossaries/index/names.bib",
    "content": "% Encoding: UTF-8\n\nIn bib files, there are no comment characters (like %).\nHowever, any entry outside the regular (at)type{...} syntax is ignored.\nThis makes regular text \"comments\".\nFurther, bib2gls supports '%' as a comment character.\n\nFile explanation:\nthe labels cannot contain UTF-8 characters and must stay ASCII.\nIf such a word occurs, we must provide the name field separately and escape UTF-8.\nProvide plural fields just in case they are ever required.\n\n\n% Index entries do not need a 'name' field.\n% if the entry label is printable, it can be used.\n% An explicit name field is required for escaped characters (umlauts etc.)\n\n@index{ernst_mach,\n    name={Mach},\n    firstname={Ernst},\n}\n@index{edward_tufte,\n    name={Tufte},\n    firstname={Edward},\n}\n@index{richard_mollier,\n    name={Mollier},\n    firstname={Richard},\n}\n@index{osborne_reynolds,\n    name={Reynolds},\n    firstname={Osborne},\n}\n"
  },
  {
    "path": "bib/glossaries/index/terms.bib",
    "content": "% Encoding: UTF-8\n\nIn bib files, there are no comment characters (%).\nHowever, any entry outside the regular (at)type{...} syntax is ignored.\nThis makes regular text \"comments\".\nFurther, bib2gls supports '%' as a comment character.\n\nThe labels cannot contain UTF-8 characters and must stay ASCII.\nIf such a word occurs, we must provide the name field separately and escape UTF-8.\nProvide plural fields just in case they are ever required.\n\n@index{latex_package,\n    name={\\LaTeX{} package},\n    plural={\\LaTeX{} packages},\n}\n@index{tikz,\n    name={Ti\\textit{k}Z},\n    parent={latex_package},\n}\n"
  },
  {
    "path": "bib/glossaries/symbols/greek.bib",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Thermodynamics\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{ratio_of_specific_heats,\n    name={\\ensuremath{\\kappa}},\n    description={Ratio of specific heats},\n    unit={\\unit{-}},\n}\n@symbol{celsius_temperature,\n    name={\\ensuremath{\\vartheta}},\n    description={(relative) Temperature},\n    unit={\\unit{\\degreeCelsius}},\n}\n@symbol{relative_humidity,\n    name={\\ensuremath{\\varphi}},\n    description={Relative Humidity},\n    unit={\\unit{\\degreeCelsius}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Fluid Mechanics\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{drag_coefficient,\n    name={\\ensuremath{\\zeta}},\n    description={Drag Coefficient},\n    unit={\\unit{-}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Other\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{mass_fraction,\n    name={\\ensuremath{\\gamma}},\n    description={Mass fraction},\n    unit={\\unit{-}},\n}\n@symbol{angle_one,\n    name={\\ensuremath{\\alpha}},\n    description={Angle},\n    unit={\\unit{\\radian}},\n}\n"
  },
  {
    "path": "bib/glossaries/symbols/other.bib",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Math Operators:\n% REQUIRED for the built-in macros\n% to work (\\deriv, \\vect etc.)!\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@entry{derivative,\n    name={\\derivativefmt{\\symbolplaceholder}},\n    description={infinitesimal change in \\symbolplaceholder},\n    unit={\\symbolplaceholder},\n}\n@entry{partial_derivative,\n    name={\\partialderivativefmt{\\symbolplaceholder}},\n    description={partial, infinitesimal change in \\symbolplaceholder},\n    unit={\\symbolplaceholder},\n}\n@entry{difference,\n    name={\\differencefmt{\\symbolplaceholder}},\n    description={Difference in \\symbolplaceholder},\n    unit={\\symbolplaceholder},\n}\n@entry{flow,\n    name={\\flowfmt{\\symbolplaceholder}},\n    description={\\symbolplaceholder{} as a flow quantity},\n    unit={\\unit{\\symbolplaceholder\\per\\second}},\n}\n@entry{nabla,\n    name={\\nablaoperatorfmt{\\symbolplaceholder}},\n    description={Vector of partial derivatives (Nabla operator) of \\symbolplaceholder},\n    unit={\\unit{-}},\n}\n@entry{mean,\n    name={\\meanfmt{\\symbolplaceholder}},\n    description={Arithmetic mean of \\symbolplaceholder{}},\n    unit={\\symbolplaceholder},\n}\n@entry{logmean,\n    name={\\logmeanfmt{\\symbolplaceholder}},\n    description={Logarithmic mean of \\symbolplaceholder{}},\n    unit={\\symbolplaceholder},\n}\n@entry{vector,\n    name={\\ensuremath{\\vectfmt{x}}},\n    description={Vector},\n    unit={\\unit{-}},\n}\n@entry{abs,\n    name={\\ensuremath{\\absfmt*{\\symbolplaceholder}}},\n    description={Absolute of \\symbolplaceholder},\n    unit={\\symbolplaceholder},\n}\n"
  },
  {
    "path": "bib/glossaries/symbols/roman.bib",
    "content": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Thermodynamic state\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{pressure,\n    name={\\ensuremath{p}},\n    description={Pressure},\n    unit={\\unit{\\pascal}},\n}\n@symbol{abs_temperature,\n    name={\\ensuremath{T}},\n    description={(absolute) Temperature},\n    unit={\\unit{\\kelvin}},\n}\n@symbol{volume,\n    name={\\ensuremath{V}},\n    specific={\\ensuremath{v}},\n    description={Volume},\n    unit={\\unit{\\meter\\cubed}},\n}\n@symbol{gas_constant,\n    name={\\ensuremath{R}},\n    specific={\\ensuremath{R}},\n    description={(specific) Gas Constant},\n    unit={\\unit{\\joule\\per\\kilogram\\per\\kelvin}},\n}\n@symbol{mass,\n    name={\\ensuremath{m}},\n    description={Mass},\n    unit={\\unit{\\kilogram}},\n}\n@symbol{density,\n    name={\\ensuremath{\\rho}},\n    description={Density},\n    unit={\\unit{\\kilogram\\per\\meter\\cubed}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Thermodynamic change of state / energy\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{enthalpy,\n    name={\\ensuremath{H}},\n    specific={\\ensuremath{h}},\n    description={Enthalpy},\n    unit={\\unit{\\joule}},\n}\n@symbol{velocity,\n    name={\\ensuremath{c}},\n    description={Velocity/Speed},\n    unit={\\unit{\\meter\\per\\second}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Air conditioning\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{moisture_content,\n    name={\\ensuremath{x}},\n    description={Moisture Content},\n    unit={%\n        \\unit{\n            \\gram_{\\glsfmtname{sub.water}}\n            \\per\n            \\kilogram_{\\glsfmtname{sub.dry}\\glsfmtname{sub.air}}\n        }\n    },\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Material properties\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{heating_value,\n    name={\\ensuremath{H_{\\glsentryname{sub.inferior}}}},\n    specific={\\ensuremath{H_{\\glsentryname{sub.inferior}}}},\n    description={(specific) Heating Value},\n    unit={\\unit{\\joule\\per\\kilogram}},\n}\n@symbol{heat_capacity,\n    name={\\ensuremath{C}},\n    specific={\\ensuremath{c}},\n    description={Heat capacity},\n    unit={\\unit{\\joule\\per\\kelvin}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Coordinates etc.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% REQUIRED for built-in \\posderiv to work:\n@symbol{first_cart_coord,\n    name={\\ensuremath{x}},\n    description={First Cartesian coordinate (length)},\n    unit={\\unit{\\meter}},\n}\n@symbol{second_cart_coord,\n    name={\\ensuremath{y}},\n    description={Second Cartesian coordinate (width)},\n    unit={\\unit{\\meter}},\n}\n@symbol{third_cart_coord,\n    name={\\ensuremath{z}},\n    description={Third Cartesian coordinate (height)},\n    unit={\\unit{\\meter}},\n}\n@symbol{radius,\n    name={\\ensuremath{r}},\n    description={Radius},\n    unit={\\unit{\\meter}},\n}\n@symbol{area,\n    name={\\ensuremath{A}},\n    description={Area},\n    unit={\\unit{\\meter\\squared}},\n}\n% REQUIRED for built-in \\timederiv to work:\n@symbol{time,\n    name={\\ensuremath{t}},\n    description={Time},\n    unit={\\unit{\\second}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Electrical\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{voltage,\n    name={\\ensuremath{U_{\\glsentryname{sub.electric}}}},\n    description={Voltage},\n    unit={\\unit{\\volt}},\n}\n@symbol{electric_current,\n    name={\\ensuremath{J_{\\glsentryname{sub.electric}}}},\n    description={Electric current},\n    unit={\\unit{\\ampere}},\n}\n@symbol{electrical_resistance,\n    name={\\ensuremath{R_{\\glsentryname{sub.electric}}}},\n    description={Electrical resistance},\n    unit={\\unit{\\ohm}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Dimensionless Quantities\n% Use \\operatorname (for which \\DeclareMathOperator is a wrapper)\n% for correct spacing etc.\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{mach_number,\n    name={\\ensuremath{\\operatorname{M}}},\n    description={\\glsfmtname{name.ernst_mach} number},\n    unit={\\unit{-}},\n}\n@symbol{reynolds_number,\n    name={\\ensuremath{\\operatorname{Re}}},\n    description={\\glsfmtname{name.osborne_reynolds} number},\n    unit={\\unit{-}},\n}\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Other\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n@symbol{component,\n    name={\\ensuremath{n}},\n    description={Component},\n    unit={\\unit{-}},\n}\n@symbol{count,\n    name={\\ensuremath{k}},\n    description={Count/Quantity},\n    unit={\\unit{-}},\n}\n"
  },
  {
    "path": "bib/glossaries/symbols/subscripts.bib",
    "content": "@symbol{inferior,\n    name={\\text{i}},\n    description={inferior},\n}\n@symbol{water,\n    name={\\text{w}},\n    description={Water},\n}\n@symbol{dry,\n    name={\\text{d}},\n    description={dry},\n}\n@symbol{air,\n    name={\\text{a.}},\n    description={air},\n}\n@symbol{electric,\n    name={\\text{el.}},\n    description={electric},\n}\n@symbol{thermal,\n    name={\\text{th}},\n    description={thermal},\n}\n"
  },
  {
    "path": "chapters/README.md",
    "content": "# Content files\n\nThis directory contains all the source `tex` files with the document content.\nSplitting up files, putting them here and then running `\\import` or `\\subimport` on them is a good way of modularisation.\nIt allows to compile only what is needed by commenting out unneeded `\\(sub)import` statements, greatly speeding up compilation times.\n"
  },
  {
    "path": "chapters/backmatter.tex",
    "content": "% For the order of things here (appendix, indices, bibliographies, ...) and their\n% numbering, see also https://tex.stackexchange.com/a/20547/120853.\n% Feel free to deviate since this is a subjective topic.\n\n\\appendix\n\n\\chapter{An appendix chapter}\n\nSome appendix content can go here, for example detailed computations.\n\n\\section{More appendix}\n\nThe usual sectioning commands keep working, as does page numbering, showcased by the\nfollowing blind text.\n\n\\Blindtext\n\n\\section{Unprocessed data}\n\\label{ch:appendix_table}\n\nThis is also a good place to put unprocessed data, like \\cref{tab:random_long}.\n\n% The following is an experimental table based on the new and promising-looking\n% tabularray package. If it matures and proves useful, we might want to employ it\n% everywhere.\n\\begin{longtblr}[%\n        caption={%\n            A \\texttt{longtblr} from the new \\ctanpackage{tabularray} package.\n            It introduces many new features and concepts and is based on a new interface.\n            For example, this table breaks across pages and has an automatically sized column%\n        },\n        entry={A \\texttt{longtblr} from the new \\ctanpackage{tabularray} package.},\n        label={tab:random_long},\n        note{1}={Some footnote.},\n        remark{Note}={Some general hint regarding the table, which might span multiple lines.},\n    ]{\n        colspec={\n            S% An siunitx number column; takes numbers as input and formats them; like \\num\n            c% `s` column has been removed from siunitx version 3 and above\n            X% Variable-width column; will be as wide as needed to fill width\n            c\n        },\n        column{2}={% Second column contains siunitx units\n            cmd={\\unit}% \\unit replaces \\si in siunitx version 3 and above\n        },\n        column{4}={% Fourth column contains math content, so prepend and append math mode\n            preto=\\(,\n            appto=\\),\n        },\n        rowhead=1,% 'number of the first rows of the table appear in every page'\n        row{odd}={gray!20},\n        row{1}={white},\n        row{2-Z}={font=\\footnotesize},% X, Y and Z dynamically refer to the last three lines\n    }%\n    \\toprule\n        {{{Magnitude}}} & Unit & Variable-width text & \\text{Math column} \\\\\n    \\midrule\n        10.0 & \\meter & Some rather long text that will get broken up. & x = y\\\\\n        % From here on: randomly generated rows, using a Lua script previously part of\n        % this repo (check git log).\n        37.13 & \\giga\\degreeCelsius & Foo & H^i=f\\\\\n        496.111 & \\kilo\\bar & Yeet & a-P=d\\\\\n        0.23 & \\milli\\meter & Baz & C^u=o\\\\\n        3.30 & \\nano\\watt & Baz & I+Y=C\\\\\n        0.6 & \\kilo\\ohm & C & p+n=t\\\\\n        5.845 & \\bar & B & Y^H=x\\\\\n        7.343 & \\nano\\newton & Yeet & Z/z=c\\\\\n        403.0 & \\giga\\newton & Foo & a^Z=v\\\\\n        312.81 & \\nano\\candela & Bar & I-l=g\\\\\n        0.457 & \\pascal & B & f+Q=i\\\\\n        545.773 & \\kilo\\degreeCelsius & Bar & i+j=W\\\\\n        76.5 & \\newton & Hello World & o/q=A\\\\\n        67.20 & \\ampere & Hello World & T^e=M\\\\\n        2.571 & \\giga\\gram & Foo & O+o=j\\\\\n        285.542 & \\nano\\pascal & A & o+T=Z\\\\\n        12.458 & \\volt & A & k/K=b\\\\\n        668.0 & \\volt & B & p+E=o\\\\\n        799.923 & \\kilo\\meter & Hello World & p^j=X\\\\\n        413.0 & \\nano\\degreeCelsius & Foo & j^s=l\\\\\n        86.64 & \\milli\\gram & Yeet & F^k=C\\\\\n        50.931 & \\nano\\candela & A & T^j=M\\\\\n        0.75 & \\kelvin & Yeet & X/g=z\\\\\n        0.184 & \\milli\\kelvin & This is a longer text that will probably span multiple lines in the table because it is overly wide. & i+k=K\\\\\n        24.0 & \\giga\\kelvin & Baz & R+H=a\\\\\n        583.56 & \\nano\\ampere & B & R+C=r\\\\\n        4.92 & \\giga\\pascal & This is a longer text that will probably span multiple lines in the table because it is overly wide. & P/O=z\\\\\n        196.104 & \\giga\\watt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & u^R=g\\\\\n        11.2 & \\giga\\volt & C & q+P=R\\\\\n        60.14 & \\nano\\bar & Bar & E^B=B\\\\\n        347.91 & \\milli\\ampere & Baz & u^t=M\\\\\n        563.70 & \\ohm & Baz & S/y=D\\\\\n        0.43 & \\milli\\kelvin & Yeet & w/z=u\\\\\n        3.851 & \\milli\\kelvin & A & m/Z=c\\\\\n        0.74 & \\gram & Foo & b^d=F\\\\\n        0.98 & \\nano\\ohm & Yeet & m/w=G\\\\\n        942.0 & \\giga\\candela & Hello World & T^I=S\\\\\n        426.661 & \\nano\\ampere & Hello World & b/n=H\\\\\n        663.729 & \\giga\\newton & Yeet & j+D=Z\\\\\n        0.65 & \\nano\\candela & C & J-s=E\\\\\n        0.29 & \\bar & B & f+J=M\\\\\n        433.72 & \\watt & Foo & s^k=r\\\\\n        0.96 & \\nano\\gram & C & H/P=m\\\\\n        51.79 & \\nano\\volt & Baz & b/G=b\\\\\n        0.744 & \\kilo\\watt & B & G^C=X\\\\\n        0.9 & \\candela & B & H+i=U\\\\\n        416.71 & \\giga\\kelvin & Foo & H^j=I\\\\\n        447.0 & \\degreeCelsius & Bar & N+o=K\\\\\n        0.65 & \\degreeCelsius & Yeet & K-h=F\\\\\n        0.954 & \\nano\\pascal & Hello World & z+Y=J\\\\\n        874.234 & \\nano\\watt & Baz & M+i=w\\\\\n        0.14 & \\volt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Q+i=v\\\\\n        4.427 & \\milli\\newton & Baz & B/B=p\\\\\n        5.4 & \\kilo\\gram & This is a longer text that will probably span multiple lines in the table because it is overly wide. & t/A=w\\\\\n        0.60 & \\candela & B & n^P=K\\\\\n        163.0 & \\kilo\\ampere & Yeet & M+w=b\\\\\n        53.911 & \\ohm & Yeet & E-y=a\\\\\n        61.0 & \\giga\\candela & Yeet & T-M=E\\\\\n        0.686 & \\kilo\\candela & Foo & d^a=f\\\\\n        6.354 & \\bar & A & F/L=G\\\\\n        2.88 & \\kilo\\degreeCelsius & Bar & M^r=T\\\\\n        283.457 & \\milli\\gram & Hello World & D-E=u\\\\\n        490.455 & \\meter & Hello World & S/u=E\\\\\n        960.1 & \\ampere & Yeet & r/M=q\\\\\n        884.0 & \\bar & B & w^R=v\\\\\n        824.9 & \\kilo\\watt & Baz & Z-t=T\\\\\n        91.6 & \\volt & Yeet & E/o=s\\\\\n        45.0 & \\newton & Baz & Z-m=P\\\\\n        75.0 & \\nano\\watt & C & Y-U=R\\\\\n        778.0 & \\milli\\kelvin & Foo & x^j=L\\\\\n        0.885 & \\milli\\watt & C & u^S=G\\\\\n        70.49 & \\milli\\candela & Yeet & z^R=r\\\\\n        185.0 & \\kilo\\gram & Bar & O+T=A\\\\\n        4.880 & \\giga\\ohm & A & F/U=q\\\\\n        0.78 & \\giga\\kelvin & Bar & m+C=E\\\\\n        712.36 & \\nano\\bar & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Z+D=p\\\\\n        37.13 & \\giga\\degreeCelsius & Foo & H^i=f\\\\\n        496.111 & \\kilo\\bar & Yeet & a-P=d\\\\\n        0.23 & \\milli\\meter & Baz & C^u=o\\\\\n        3.30 & \\nano\\watt & Baz & I+Y=C\\\\\n        0.6 & \\kilo\\ohm & C & p+n=t\\\\\n        5.845 & \\bar & B & Y^H=x\\\\\n        7.343 & \\nano\\newton & Yeet & Z/z=c\\\\\n        403.0 & \\giga\\newton & Foo & a^Z=v\\\\\n        312.81 & \\nano\\candela & Bar & I-l=g\\\\\n        0.457 & \\pascal & B & f+Q=i\\\\\n        545.773 & \\kilo\\degreeCelsius & Bar & i+j=W\\\\\n        76.5 & \\newton & Hello World & o/q=A\\\\\n        67.20 & \\ampere & Hello World & T^e=M\\\\\n        2.571 & \\giga\\gram & Foo & O+o=j\\\\\n        285.542 & \\nano\\pascal & A & o+T=Z\\\\\n        12.458 & \\volt & A & k/K=b\\\\\n        668.0 & \\volt & B & p+E=o\\\\\n        799.923 & \\kilo\\meter & Hello World & p^j=X\\\\\n        413.0 & \\nano\\degreeCelsius & Foo & j^s=l\\\\\n        86.64 & \\milli\\gram & Yeet & F^k=C\\\\\n        50.931 & \\nano\\candela & A & T^j=M\\\\\n        0.75 & \\kelvin & Yeet & X/g=z\\\\\n        0.184 & \\milli\\kelvin & This is a longer text that will probably span multiple lines in the table because it is overly wide. & i+k=K\\\\\n        24.0 & \\giga\\kelvin & Baz & R+H=a\\\\\n        583.56 & \\nano\\ampere & B & R+C=r\\\\\n        4.92 & \\giga\\pascal & This is a longer text that will probably span multiple lines in the table because it is overly wide. & P/O=z\\\\\n        196.104 & \\giga\\watt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & u^R=g\\\\\n        11.2 & \\giga\\volt & C & q+P=R\\\\\n        60.14 & \\nano\\bar & Bar & E^B=B\\\\\n        347.91 & \\milli\\ampere & Baz & u^t=M\\\\\n        563.70 & \\ohm & Baz & S/y=D\\\\\n        0.43 & \\milli\\kelvin & Yeet & w/z=u\\\\\n        3.851 & \\milli\\kelvin & A & m/Z=c\\\\\n        0.74 & \\gram & Foo & b^d=F\\\\\n        0.98 & \\nano\\ohm & Yeet & m/w=G\\\\\n        942.0 & \\giga\\candela & Hello World & T^I=S\\\\\n        426.661 & \\nano\\ampere & Hello World & b/n=H\\\\\n        663.729 & \\giga\\newton & Yeet & j+D=Z\\\\\n        0.65 & \\nano\\candela & C & J-s=E\\\\\n        0.29 & \\bar & B & f+J=M\\\\\n        433.72 & \\watt & Foo & s^k=r\\\\\n        0.96 & \\nano\\gram & C & H/P=m\\\\\n        51.79 & \\nano\\volt & Baz & b/G=b\\\\\n        0.744 & \\kilo\\watt & B & G^C=X\\\\\n        0.9 & \\candela & B & H+i=U\\\\\n        416.71 & \\giga\\kelvin & Foo & H^j=I\\\\\n        447.0 & \\degreeCelsius & Bar & N+o=K\\\\\n        0.65 & \\degreeCelsius & Yeet & K-h=F\\\\\n        0.954 & \\nano\\pascal & Hello World & z+Y=J\\\\\n        874.234 & \\nano\\watt & Baz & M+i=w\\\\\n        0.14 & \\volt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Q+i=v\\\\\n        4.427 & \\milli\\newton & Baz & B/B=p\\\\\n        5.4 & \\kilo\\gram & This is a longer text that will probably span multiple lines in the table because it is overly wide. & t/A=w\\\\\n        0.60 & \\candela & B & n^P=K\\\\\n        163.0 & \\kilo\\ampere & Yeet & M+w=b\\\\\n        53.911 & \\ohm & Yeet & E-y=a\\\\\n        61.0 & \\giga\\candela & Yeet & T-M=E\\\\\n        0.686 & \\kilo\\candela & Foo & d^a=f\\\\\n        6.354 & \\bar & A & F/L=G\\\\\n        2.88 & \\kilo\\degreeCelsius & Bar & M^r=T\\\\\n        283.457 & \\milli\\gram & Hello World & D-E=u\\\\\n        490.455 & \\meter & Hello World & S/u=E\\\\\n        960.1 & \\ampere & Yeet & r/M=q\\\\\n        884.0 & \\bar & B & w^R=v\\\\\n        824.9 & \\kilo\\watt & Baz & Z-t=T\\\\\n        91.6 & \\volt & Yeet & E/o=s\\\\\n        45.0 & \\newton & Baz & Z-m=P\\\\\n        75.0 & \\nano\\watt & C & Y-U=R\\\\\n        778.0 & \\milli\\kelvin & Foo & x^j=L\\\\\n        0.885 & \\milli\\watt & C & u^S=G\\\\\n        70.49 & \\milli\\candela & Yeet & z^R=r\\\\\n        185.0 & \\kilo\\gram & Bar & O+T=A\\\\\n        4.880 & \\giga\\ohm & A & F/U=q\\\\\n        0.78 & \\giga\\kelvin & Bar & m+C=E\\\\\n        712.36 & \\nano\\bar & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Z+D=p\\\\\n        37.13 & \\giga\\degreeCelsius & Foo & H^i=f\\\\\n        496.111 & \\kilo\\bar & Yeet & a-P=d\\\\\n        0.23 & \\milli\\meter & Baz & C^u=o\\\\\n        3.30 & \\nano\\watt & Baz & I+Y=C\\\\\n        0.6 & \\kilo\\ohm & C & p+n=t\\\\\n        5.845 & \\bar & B & Y^H=x\\\\\n        7.343 & \\nano\\newton & Yeet & Z/z=c\\\\\n        403.0 & \\giga\\newton & Foo & a^Z=v\\\\\n        312.81 & \\nano\\candela & Bar & I-l=g\\\\\n        0.457 & \\pascal & B & f+Q=i\\\\\n        545.773 & \\kilo\\degreeCelsius & Bar & i+j=W\\\\\n        76.5 & \\newton & Hello World & o/q=A\\\\\n        67.20 & \\ampere & Hello World & T^e=M\\\\\n        2.571 & \\giga\\gram & Foo & O+o=j\\\\\n        285.542 & \\nano\\pascal & A & o+T=Z\\\\\n        12.458 & \\volt & A & k/K=b\\\\\n        668.0 & \\volt & B & p+E=o\\\\\n        799.923 & \\kilo\\meter & Hello World & p^j=X\\\\\n        413.0 & \\nano\\degreeCelsius & Foo & j^s=l\\\\\n        86.64 & \\milli\\gram & Yeet & F^k=C\\\\\n        50.931 & \\nano\\candela & A & T^j=M\\\\\n        0.75 & \\kelvin & Yeet & X/g=z\\\\\n        0.184 & \\milli\\kelvin & This is a longer text that will probably span multiple lines in the table because it is overly wide. & i+k=K\\\\\n        24.0 & \\giga\\kelvin & Baz & R+H=a\\\\\n        583.56 & \\nano\\ampere & B & R+C=r\\\\\n        4.92 & \\giga\\pascal & This is a longer text that will probably span multiple lines in the table because it is overly wide. & P/O=z\\\\\n        196.104 & \\giga\\watt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & u^R=g\\\\\n        11.2 & \\giga\\volt & C & q+P=R\\\\\n        60.14 & \\nano\\bar & Bar & E^B=B\\\\\n        347.91 & \\milli\\ampere & Baz & u^t=M\\\\\n        563.70 & \\ohm & Baz & S/y=D\\\\\n        0.43 & \\milli\\kelvin & Yeet & w/z=u\\\\\n        3.851 & \\milli\\kelvin & A & m/Z=c\\\\\n        0.74 & \\gram & Foo & b^d=F\\\\\n        0.98 & \\nano\\ohm & Yeet & m/w=G\\\\\n        942.0 & \\giga\\candela & Hello World & T^I=S\\\\\n        426.661 & \\nano\\ampere & Hello World & b/n=H\\\\\n        663.729 & \\giga\\newton & Yeet & j+D=Z\\\\\n        0.65 & \\nano\\candela & C & J-s=E\\\\\n        0.29 & \\bar & B & f+J=M\\\\\n        433.72 & \\watt & Foo & s^k=r\\\\\n        0.96 & \\nano\\gram & C & H/P=m\\\\\n        51.79 & \\nano\\volt & Baz & b/G=b\\\\\n        0.744 & \\kilo\\watt & B & G^C=X\\\\\n        0.9 & \\candela & B & H+i=U\\\\\n        416.71 & \\giga\\kelvin & Foo & H^j=I\\\\\n        447.0 & \\degreeCelsius & Bar & N+o=K\\\\\n        0.65 & \\degreeCelsius & Yeet & K-h=F\\\\\n        0.954 & \\nano\\pascal & Hello World & z+Y=J\\\\\n        874.234 & \\nano\\watt & Baz & M+i=w\\\\\n        0.14 & \\volt & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Q+i=v\\\\\n        4.427 & \\milli\\newton & Baz & B/B=p\\\\\n        5.4 & \\kilo\\gram & This is a longer text that will probably span multiple lines in the table because it is overly wide. & t/A=w\\\\\n        0.60 & \\candela & B & n^P=K\\\\\n        163.0 & \\kilo\\ampere & Yeet & M+w=b\\\\\n        53.911 & \\ohm & Yeet & E-y=a\\\\\n        61.0 & \\giga\\candela & Yeet & T-M=E\\\\\n        0.686 & \\kilo\\candela & Foo & d^a=f\\\\\n        6.354 & \\bar & A & F/L=G\\\\\n        2.88 & \\kilo\\degreeCelsius & Bar & M^r=T\\\\\n        283.457 & \\milli\\gram & Hello World & D-E=u\\\\\n        490.455 & \\meter & Hello World & S/u=E\\\\\n        960.1 & \\ampere & Yeet & r/M=q\\\\\n        884.0 & \\bar & B & w^R=v\\\\\n        824.9 & \\kilo\\watt & Baz & Z-t=T\\\\\n        91.6 & \\volt & Yeet & E/o=s\\\\\n        45.0 & \\newton & Baz & Z-m=P\\\\\n        75.0 & \\nano\\watt & C & Y-U=R\\\\\n        778.0 & \\milli\\kelvin & Foo & x^j=L\\\\\n        0.885 & \\milli\\watt & C & u^S=G\\\\\n        70.49 & \\milli\\candela & Yeet & z^R=r\\\\\n        185.0 & \\kilo\\gram & Bar & O+T=A\\\\\n        4.880 & \\giga\\ohm & A & F/U=q\\\\\n        0.78 & \\giga\\kelvin & Bar & m+C=E\\\\\n        712.36 & \\nano\\bar & This is a longer text that will probably span multiple lines in the table because it is overly wide. & Z+D=p\\\\\n    \\bottomrule\n\\end{longtblr}\n\n\\chapter{Another appendix chapter}\n\nMore stuff can go into the next appendix chapter, for example algorithms and code.\n\n\\backmatter\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Bibliography\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\nocite{*}% Add everything that has not yet been cited\n\n\\label{ch:bibliography}\n\\printbibliography[% Print the 'real' bibliography of actually cited references\n    category=cited,%\n]\n\n\\printbibliography[%\n    notcategory=cited,%\n    heading=notcited,%\n    env=bibnonum,%\n    prenote=further,%\n]%\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Index\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\setglossarysection{chapter}\n\\printunsrtindex[%\n    style=bookindex,%\n]\n"
  },
  {
    "path": "chapters/frontmatter/abstract.tex",
    "content": "% Use built-in macro for internationalization\n\\chapter*{\\abstractname}\n\n\\Blindtext\n\n\\begin{itemize}\n    \\item We found this out,\n    \\item and also that!\n\\end{itemize}\n"
  },
  {
    "path": "chapters/frontmatter/authorship_declaration.tex",
    "content": "% Put page onto its own _recto_ page. It is a page intended to be signed and stamped.\n% Therefore, it cannot be verso, since then there is no paper behind this page to\n% support writing on it.\n\\cleardoubleoddpage\n\n\\vspace*{\\fill}\n\n\\subsection*{\\TransAuthorshipDeclTitle{}}\n\n\\TransAuthorshipDeclText{}\n\n\\signaturefield{}\n"
  },
  {
    "path": "chapters/frontmatter/colophon.tex",
    "content": "% No \\cleardoubleoddpage shenanigans: the colophon page is supposed to be on the verso\n% behind the title.\n\n\\thispagestyle{empty}\n\\vspace*{\\fill}\n\n\\begingroup% Keep changes local to this group\n    \\hypersetup{hidelinks}\n    \\color{g2}\n    \\footnotesize\n\n    \\begin{tabular}{\n        r\n        l\n    }\n        % \\TransXYZ commands are from translations file\n            Name &\n                \\texttt{\\textbf{%\n                    \\jobname{}% Always print the job name\n                }}\n                    \\makeatletter\n                        % Only print if censoring is on; command defined by kvoptions\n                        \\ifacp@censoring%\n                            % This duplicate \\textt\\textbf is necessary.\n                            % This if construct cannot be inside the one font commands\n                            % for \\jobname{}\n                            \\texttt{\\textbf{(\\TransCensorNotice{})}}\n                        \\fi\n                    \\makeatother\n                \\\\\n            \\TransCompiledOn{} & \\textbf{\\DTMnow{}}\\\\\n        \\addlinespace\n            \\faIcon{git-alt} & \\texttt{\\textbf{\\GitShortSHA{}} (\\GitRefName{})} \\\\\n        \\addlinespace\n            Engine & \\prettybanner{}\\\\\n            \\LaTeX{} Version & \\hologo{\\fmtname} (\\fmtversion)\\\\\n            \\glossaryname{} & \\texttt{glossaries-extra} + \\texttt{bib2gls}\\\\\n            \\bibname{} & biblatex + \\hologo{biber}\\\\\n            \\TransGenerator{} & \\texttt{latexmk}\\\\\n            \\TransLatexClass{} & \\KOMAScriptVersion{}\n    \\end{tabular}%\n\\endgroup%\n"
  },
  {
    "path": "chapters/frontmatter/preface.tex",
    "content": "\\addchap{Preface}\n\nThis document is not a beginner guide.\nThere is a wide choice of those out there already, both free and paid for.\nHowever, what is lacking is a collection of modern, or even at least current,\nbest practices.\nIf you scouted through package documentations and\n\\href{https://tex.stackexchange.com/}{StackExchange}\nlong enough, you would eventually get an idea of what is current, idiomatic \\LaTeX{}\nand what is not.\nThis is how I learned \\LaTeX{} too, so I cannot recommend any useful beginner books.\nYou might want to check out \\href{https://www.overleaf.com/}{Overleaf} though,\nan online \\LaTeX{} editor%\n\\footnote{%\n    I do not recommend using online editors.\n    You are putting your hard work onto some remote, foreign server, relying on\n    their ongoing availability and forfeiting the chance of understanding \\LaTeX{},\n    in case you have to continue locally.\n    Theses containing confidential material should also not be hosted externally.\n}\nwith a large knowledge database.\n\nThis document is an attempt at collecting best practices\n--- or at least, useful approaches ---\nand pointing out the old ones they could, often should, and sometimes absolutely have to replace.\nSee also \\href{https://web.archive.org/web/20210317090850/https://user.math.uni-bremen.de/~grimpen/LaTeX.html}{here} for a second opinion on the topic.\nMore than most other languages, the \\LaTeX{} code in circulation world\\-/wide is\nquite aged.\nWhile that code does not necessarily get \\emph{worse}, it also does not exactly\nage like cheese and wine would.\nTo that end, notice how the packages integral to this document are actively\nmaintained and kept modern.\n\n\\paragraph{Usage as a Cookbook}\nThis document is supposed to be used in a \\emph{cookbook} style.\nThat is, it is not meant to be read cover to cover\n(declaring it a cookbook is also a useful excuse for the mess I made).\n\nThe document contains various \\enquote{recipes}, most of which exist in parallel and\nare independent of one another.\nThe goal is to answer questions of the form \\emph{How can this and that be done?}\nA quick search in the (printed) output or the source code is supposed to deliver\nanswers.\n\n\\paragraph{Usage as a Template}\nConsiderable effort went into the class file, aka the template.\nIt pulls all settings together, producing an output that is very different from\nvanilla \\LaTeX{}.\nTherefore, feel free to rip out all the cookbook content, keeping just the settings\nfiles to be used as a template.\n\n\\paragraph{Source Code}\nThis document is meant to be read side\\-/by\\-/side with its source code.\nThat is why there is almost no source code in the printed output itself.\nIf you are curious how a certain output is achieved, navigate to the source code\nitself.\nThis approach was chosen since, plainly, code does not lie, while annotations and\ncomments might.\nSo while the printed output will always remain true to its actual source code,\nduplicating that source code so it can be read in the printed output directly\nis just another vector for errors to creep in.\n\n\\paragraph{Source Repository}\nThe source repository for this document is at\n\\begin{center}\n    \\url{https://github.com/alexpovel/latex-cookbook} .\n\\end{center}\nAny references to the \\enquote{source} or \\enquote{repository} refer to that project.\n"
  },
  {
    "path": "chapters/frontmatter/task.tex",
    "content": "\\chapter*{\\TransTask{}}\n\n\\makeatletter\n    \\begin{tabular}{\n        l\n        p{0.7\\linewidth}\n    }\n        \\TransFor{}: & \\textbf{\\@author{}} [\\@idnumber{}]\\\\\n        \\TransTopic{}: & \\textbf{\\@title} (\\@documenttype{})\n    \\end{tabular}\\\\[\\baselineskip]\n\\makeatother\n\n\\blindtext\n\n\\begin{itemize}\n    \\item First you are doing this,\n    \\item then another thing,\n    \\item lastly that.\n\\end{itemize}\n\nYou will be working on this a lot.\n\n\\signaturefield{}\n"
  },
  {
    "path": "chapters/frontmatter.tex",
    "content": "% Helper file that pulls subchapters together.\n\n% Set initial pages to alpha, so that they do not collide with later Arabic numbering\n% in the generated PDF. This won't show in print because page numbers aren't displayed\n% until later. But you will be able to print the title page by printing page 'a', which\n% would otherwise overlap with page '1', aka the first actual text page.\n\\pagenumbering{alph}\n\\maketitle% Print main title page\n\\subimport{frontmatter/}{colophon}\n\n\\frontmatter% In KOMAScript, resets pagenumber, uses Roman numerals etc.\n\n% Note that \\subincludefrom{}{} cannot be nested, therefore us \\subimport\n\\subimport{frontmatter/}{task}\n\\subimport{frontmatter/}{authorship_declaration}\n\\subimport{frontmatter/}{abstract}\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Lists of Content\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\tableofcontents\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% addchap is KOMA equivalent for \\chapter*, but also creates ToC entry, see also\n% https://tex.stackexchange.com/a/116085/120853\n% Use built-in macro \\glossaryname for proper internationalization. With polyglossia, it\n% will contain \\text<language>{<glossary translation>}, which has been taken care of\n% using \\pdfstringdefDisableCommands{} in the class file\n\\addchap{\\glossaryname}%\n\\label{ch:glossary}\n\n\\emph{%\n    \\TransGlossaryLegend{}%\n}%\n\n% Print \"unsorted\" glossaries; these are in fact sorted, but externally using bib2gls.\n% These will throw 'Token not allowed in PDF, removing \\text<language>' warning.\n% Specify title= manually if that gets too annoying.\n\\printunsrtglossary[\n    type=symbols,\n    style=symbunitlong,\n]\n\\printunsrtglossary[\n    type=numbers,\n    style=numberlong,\n]\n\\printunsrtglossary[\n    type=subscripts,\n    style=mcolalttree,\n    nonumberlist,\n]\n\\printunsrtglossary[\n    type=abbreviations,\n    style=long3colheader,\n    title=\\TransAcronyms{},\n]\n\n\\addchap{\\glossaryname{} without page lists}%\n\n\\emph{\n    The following styles do not contain page lists of the entries' occurrences,\n    leading to a cleaner, more concise look.\n    Refer to the source code on how to achieve this (which options and styles to use).\n}\n\n% For all sorts of styles, see also\n% https://www.dickimaw-books.com/gallery/glossaries-styles/\n\n% Simply pass the `nonumberlist` parameter where desired/required:\n\\printunsrtglossary[\n    type=symbols,\n    style=symbunitlong,\n    nonumberlist,\n]\n\\printunsrtglossary[\n    type=numbers,\n    style=numberlong,\n    nonumberlist,\n]\n\\printunsrtglossary[\n    type=subscripts,\n    style=mcolalttree,\n    nonumberlist,\n]\n\\printunsrtglossary[\n    type=abbreviations,\n    % If `nonumberlist` is passed, the `long3colheader` style simply leaves the\n    % corresponding table cells *empty* (leading to an entirely empty column), but does\n    % not actually remove the column. So use a different, but equivalent style\n    % altogether:\n    style=longheader,\n    % The `longheader` style prints the page list behind the description, just not in a\n    % separate column. So also explicitly suppress the generation of that:\n    nonumberlist,\n    title=\\TransAcronyms{},\n]\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\\listoffigures%\n\n\\listoftables%\n\n\\listofexamples%\n\n\\listoflistings%\n\n\\listofreactions%\n\n\\subimport{frontmatter/}{preface}\n"
  },
  {
    "path": "chapters/mainmatter/base-features.tex",
    "content": "\\chapter{Base Features}\n\\label{ch:base-features}\n\nLet us first go through some of the base features offered by \\LaTeX{} and used in\nthis template.\nBefore anything happens, the \\TeX{} engine is chosen.\nThis is the binary responsible for compiling the \\LaTeX{} source code.\nIf you have used \\LaTeX{} before but never heard those terms before, you are most\nlikely using \\hologo{pdfLaTeX} as your engine.\nThis is the go\\-/to default for generating \\abb{portable_document_format} output.\nIts most popular modern alternatives are \\hologo{XeLaTeX} and \\hologo{LuaLaTeX}.\nThese two offer various new, shiny features, chief among which is Unicode\nsupport through the \\ctanpackage{unicode-math} package, which builds onto\n\\ctanpackage{fontspec} and extends it with math fonts capabilities.\nNote that these packages \\emph{require} \\hologo{XeLaTeX} or \\hologo{LuaLaTeX} use:\n\\hologo{pdfLaTeX} is \\emph{old} and will no longer work.\nMore on that in \\cref{ch:fonts_text}.\n\n\\hologo{LuaLaTeX} is preferred over \\hologo{XeLaTeX} for the following reasons:\n\\begin{enumerate}\n    \\item \\ctanpackage{contour}, a package that can do things like\n        \\contour{black}{\\textcolor{white}{this}}, works.\n        For an application of that, see \\cref{fig:bitmap_tikz} on\n        \\cpageref{fig:bitmap_tikz}.\n        Getting \\ctanpackage{contour} to work on \\hologo{XeLaTeX} is somewhat impossible,\n        see also\n        \\href{https://tex.stackexchange.com/questions/421970/contour-text-in-xelatex}{here},\n        \\href{https://tex.stackexchange.com/questions/354410/how-should-the-effects-of-manipulating-specials-be-switched-off}{here},\n        \\href{https://tex.stackexchange.com/questions/225637/how-to-add-outline-to-a-character-under-xelatex}{here} and\n        \\href{https://tex.stackexchange.com/questions/25221/outlined-characters}{here}.\n    \\item \\hologo{LuaLaTeX} allocates as much memory as it happens to need.\n        The ancient limitations of \\TeX{} are easily reached by packages like\n        \\ctanpackage{tikz} and \\ctanpackage{pgfplots}.\n        Circumventing that either feels hacky, or actually is hacky.\n        \\texttt{tikzexternalize} is a great module, but has some caveats, like\n        breakage of clickable references.\n        It solves a problem that should no longer exist in the first place.\n    \\item The fantastic \\ctanpackage{microtype} package has a number of unavailable\n        functionalities when using \\hologo{XeLaTeX}.\n\\end{enumerate}\nUsing \\hologo{LuaLaTeX}, you do not have to worry about any of that:\nhit compile, wait, done%\n\\footnote{\n    The \\emph{waiting} part might be a bit longer than what you might be used to\n    from \\hologo{pdfLaTeX}.\n    So far, this is the only disadvantage I could find.\n}.\n\n\\section{Fonts and Text}\n\\label{ch:fonts_text}\n\nUsing high-quality fonts is one goal.\nThis includes the fantastic\n\\href{https://ctan.org/texarchive/fonts/tex-gyre/opentype}{\\TeX Gyre fonts},\nof which the \\emph{\\href{https://en.wikipedia.org/wiki/Palatino}{Palatino}}\n(by Hermann Zapf) clone \\emph{\\href{https://ctan.org/pkg/tex-gyre-pagella}{Pagella}}\nwas chosen for this document.\nIt comes with an accompanying\n\\href{https://ctan.org/texarchive/fonts/tex-gyre-math/opentype}{math font}\nof the same name%\n\\footnote{\n    Both fonts are vector fonts;\n    if \\LaTeX{} yields any warnings about \\emph{font size substitutions},\n    that is bogus and can be ignored.\n}%\n.\nThere are not very many high\\-/quality free fonts with a math companion available,\nsee also \\href{https://tex.stackexchange.com/a/425099/120853}{this compilation}.\nA similar compilation of \\enquote{nice} fonts is\n\\href{https://tex.stackexchange.com/a/59706/120853}{found here},\nhowever that is specifically for \\hologo{pdfLaTeX}, not \\hologo{LuaLaTeX}.\nThe font choice can be changed with relative ease in the options for the\n\\ctanpackage{unicode-math} package.\nIf a new font does not provide at least the same array of features,\nparts of the document might break!\nFor reference, there is a list of\n\\href{http://mirrors.ctan.org/macros/unicodetex/latex/unicode-math/unimath-symbols.pdf}{symbols defined by \\ctanpackage{unicode-math}}.\n\nUsing both normal and maths fonts in conjunction is made possible through the\n\\ctanpackage{unicode-math} package.\nAs such, an exact match of the text and math fonts is achieved.\nThis is important but often overlooked.\nHowever, such a match is often plain unavailable in the typesetting tool at hand.\n\\LaTeX{} is no exception here if there simply exist no matching fonts.\nWe took care to ensure a complete match here.\n\nNot only do the fonts look great on their own and paired up, they (just as importantly)\nalso feature very broad support for all sorts of symbols and characters, as well as font\nshapes and weights and combinations thereof.\nThe latter is demonstrated in \\cref{tab:main_font_examples}.\n%\n\\begin{table}\\ContinuedFloat*\n    \\ttabbox{%\n        % Brackets hold entry that will go into List of Tables (short form)\n        \\caption[Main/Roman Font Examples]{%\n            Examples for font features offered by the main roman font.\n            Notice the small vertical white space after the fourth row,\n            nicely separating content that is slightly dissimilar%\n        }%\n        % Use a string like 'tab:' to help with organization and auto-complete\n        % when reffing\n        \\label{tab:main_font_examples}\n    }{%\n        \\small\n        \\begin{tabular}{\n            % @{<value>} specifies the column separator;\n            % Use @{} to remove white space from sides (empty value)\n            @{}\n            l% If no other significant reason, left-align\n            l\n            @{}\n        }\n            \\toprule\n                Feature & Sample Text\\\\\n            \\midrule\n                Regular & \\sampletext\\\\\n                \\textbf{Bold} & \\textbf{\\sampletext}\\\\\n                \\textit{Italics} & \\textit{\\sampletext}\\\\\n                \\textbf{\\textit{Bold Italics}} & \\textbf{\\textit{\\sampletext}}\\\\\n            % Some inconspicuous vertical separation,\n            % more visually pleasing than a full rule\n            \\addlinespace\n                \\textsc{Small Capitals} & \\textsc{\\sampletext}\\\\\n                \\textbf{\\textsc{Bold SC}} & \\textbf{\\textsc{\\sampletext}}\\\\\n                \\textit{\\textsc{Italics SC}} & \\textit{\\textsc{\\sampletext}}\\\\\n            \\bottomrule\n        \\end{tabular}\n    }%\n\\end{table}\n\nCombine all that with \\ctanpackage{microtype} (a package taking care of typesetting\ndetails), and we get very beautiful typesetting.\nFor example:\n\n\\begin{displayquote}\n    \\blindtext\n\\end{displayquote}\n\nNotice the balanced line endings and low number of hyphenation;\neasy on the eyes and very readable.\n\n\\paragraph{Old approach}\nThe overwhelming majority of \\LaTeX{} documents relies on the two lines\n\\begin{minted}[linenos=false]{latex}\n    \\usepackage[T1]{fontenc}\n    \\usepackage[utf8]{inputenc}\n\\end{minted}\nThis approach is \\textbf{outdated} and only required when using \\hologo{pdfLaTeX}.\nSince this is what most people still do, the two packages are still required.\nHowever, these two packages should at least not be used for \\emph{new} work anymore!\nUsing \\hologo{LuaLaTeX}, they are not required anymore:\n\\begin{itemize}\n    \\item input encoding is automatically UTF-8 (as it should be in \\verb|$CURRENTYEAR|),\n    \\item font encoding is also not required, since fully capable fonts are used,\n        which come with all the glyphs required.\n\\end{itemize}\nThe same is true for \\hologo{XeLaTeX}.\n\n\\subsection{Math}\n\nWhat often does not occur at first glance is that many documents use text and math fonts\nthat are very different from one another.\nAs far as I know, Microsoft's \\emph{Word} has usable math typesetting and sensible default\nfonts for that.\nYet, it cannot do what dedicated, fully\\-/fleshed text and math fonts\n--- different, but matched ---\ncan achieve.\nThey provide a seamless transition, especially when using actual text in the math\nenvironment or vice versa, like when we go for \\(x \\to \\infty\\) and then also do\n\\(\\int_{1}^{2} y^2 \\deriv{y}\\) or maybe \\(a^2 + b^2 = c^2\\).\nAll these inline math elements look perfectly natural.\nIf instead the fonts did not match, inline math would stick out like a sore thumb.\nToggle the colors in the class file (\\texttt{*.cls}) to highlight each different\nfont family to see all the differences (see the \\verb|Color| option for\n\\ctanpackage{unicode-math}).\nSome display-style math examples follow.\n\\begin{gather}\n        \\sym{pressure}\\symspec{volume}\n        =\n        \\symspec{gas_constant}\\sym{abs_temperature}\n        \\label{eq:glossaries_extra_example}\n    \\\\\n        \\cons{euler}^{\\cons{imaginary}\\cons{pi}} + \\num{1} = \\num{0}\n    \\\\\n        \\tcbhighmath{\n            \\lim\\limits_{\\sym{first_cart_coord} \\to \\infty}\n            % Writing \\frac this verbosely is good for readability and diffing/VCS.\n            % This way, the fraction parts are stacked on top of each other, just like\n            % they are in the print output.\n            % Since math contexts gobble all whitespace anyway, we can freely use it\n            % without accidentally producing extraneous spaces in the output.\n            \\frac{\n                \\cons{pi}\\parens*{\\sym{first_cart_coord}}\n            }{\n                \\sym{first_cart_coord} / \\ln\\parens*{\\sym{first_cart_coord}}\n            }\n            =\n            \\num{1}\n        }\n        \\label{eq:highlighted}\n    \\\\\n        \\mathbf{% This is how you do bold math\n            \\sum_{\\sym{count} = \\num{0}}^{\\sym{component}}\n                \\begin{pmatrix}\n                    \\sym{count} \\\\ \\sym{component}\n                \\end{pmatrix}\n            =\n            \\num{2}^{\\sym{count}}\n        }\n    \\\\\n        % This equation does not make sense.\n        \\brackets*{\n            \\sym{abs_temperature}\n            \\cancelto{\\num{0}}{\n                \\fracderiv*{%\n                    %\n                }{%\n                    \\sym{abs_temperature}\n                }\n            }\n            +\n                \\sym{ratio_of_specific_heats}\\parens*{\\sym{pressure}}\n                \\fracderiv*{}{\\sym{density}}\n            +\n                \\sym{angle_one}\n        }\n        \\sym{celsius_temperature}^{\\sym{count}}\n        \\parens*{\n            \\sym{first_cart_coord}_{\\num{1}},\n            \\sym{first_cart_coord}_{\\num{2}},\n            \\dots, \\sym{first_cart_coord}_{\\sym{count}}\n        } = \\num{0}\n    \\\\\n        \\difference{\\symspec{enthalpy}_{\\text{change}}}\n        =\n        \\nicefrac{\\num{1}}{\\num{2}}\n        \\parens*{\n            \\sym{velocity}^{\\num{2}}_{\\text{exit}}\n            -\n            \\sym{velocity}^{\\num{2}}_{\\text{entry}}\n        }\n\\end{gather}\nIf these symbols are colored, it is because they are links and link coloring is on.\nThis can be turned off (globally or for certain elements) in the options to\n\\ctanpackage{hyperref}.\nIf color is turned off, they are still hyperlinks.\nIf even that is undesired, that can also be turned off in that package.\n\n\\subsubsection{Predefined Macros}\n\nThe \\ctanpackage{physics} package has some\n\\href{https://tex.stackexchange.com/q/471532/120853}{issues},\nand as such, this document relies on a couple custom macros in place of it, see\n\\cref{tab:predefined_math_macros}.\n\n\\begin{table}\n    \\ttabbox{%\n        \\caption[Predefined math macros]{%\n            Predefined math macros.\n            Refer to the source code for help on the syntax.\n            For derivatives, the starred macros yield partial derivatives%\n        }%\n        \\label{tab:predefined_math_macros}\n    }{%\n        \\renewcommand*{\\arraystretch}{1.8}% For the fracs, increase spacing (local effect)\n        \\small\n        \\begin{tabular}{%\n            @{}\n            l\n            l\n            @{}\n        }\n            % floatrow cannot be used with \\verb, or even \\texttt and escaped special\n            % characters, see \"Limitations\" in floatrow docs.\n            % As a consequence, use normal names and refer the reader to the source\n            % code.\n            \\toprule\n                Name & Examples \\\\\n            \\midrule\n                Mean & \\(\\mean{\\sym{density}}\\), \\(\\mean{\\sym{area}}\\) \\\\\n                Logarithmic Mean & \\(\\logmean{\\sym{density}}\\), \\(\\logmean{\\sym{area}}\\) \\\\\n                % The starred variant scales automatically:\n                Absolute\\mpfootnotemark[1] & \\(\\abs{\\sym{density}}\\), \\(\\abs{\\sym{area}}\\), \\(\\abs{\\frac{\\sym{area}^{2}}{\\sym{area}^{3}}}\\) \\\\\n                Flow & \\(\\flow{\\sym{mass}}\\), \\(\\flow{\\sym{enthalpy}}\\) \\\\\n                Delta & \\(\\difference{\\sym{volume}}\\), \\(\\difference{\\symspec{enthalpy}}\\) \\\\\n                Nabla Operator &\n                    \\(\n                        \\nablaoperator{\\sym{first_cart_coord}},\n                        \\nablaoperator[3]{\\sym{first_cart_coord}}\n                    \\) \\\\\n                Vectors & \\(\\vect{\\sym{first_cart_coord}}\\), \\(\\vect{A}\\) \\\\\n            \\addlinespace\n                Derivatives &\n                    \\(\n                        \\deriv{\\sym{mass}},\n                        \\deriv[2]{\\sym{first_cart_coord}},\n                        \\deriv*{\\sym{mass}},\n                        \\deriv*[2]{\\sym{first_cart_coord}}\n                    \\) \\\\\n                Fractional Deriv. &\n                    \\(\n                        \\fracderiv{\\sym{voltage}}{\\sym{time}},\n                        \\fracderiv[2]{\\sym{second_cart_coord}}{\\sym{first_cart_coord}},\n                        \\fracderiv*{\\sym{voltage}}{\\sym{time}},\n                        \\fracderiv*[2]{\\sym{second_cart_coord}}{\\sym{first_cart_coord}},\n                        \\fracderiv{\\symspec{enthalpy}}{\\sym{abs_temperature}},\n                        \\fracderiv[2]{\\symspec{enthalpy}}{\\sym{abs_temperature}},\n                        \\fracderiv*{\\symspec{enthalpy}}{\\sym{abs_temperature}},\n                        \\fracderiv*[2]{\\symspec{enthalpy}}{\\sym{abs_temperature}}\n                    \\) \\\\\n                Time Deriv.\\mpfootnotemark[2] &\n                    \\(\n                        \\timederiv{\\sym{voltage}},\n                        \\timederiv[2]{\\sym{second_cart_coord}},\n                        \\timederiv*{\\sym{voltage}},\n                        \\timederiv*[2]{\\sym{first_cart_coord}}\n                    \\) \\\\\n                Positional Deriv.\\mpfootnotemark[2] &\n                    \\(\n                        \\posderiv{\\sym{volume}},\n                        \\posderiv[2]{\\sym{velocity}},\n                        \\posderiv*{\\sym{volume}},\n                        \\posderiv*[2]{\\sym{velocity}}\n                    \\) \\\\\n            \\addlinespace\n                % The starred variant scales automatically. The non-starred version\n                % does not scale.\n                % Supply the optional argument for manual control of the size, e.g.\n                % `\\abs[\\Bigg]{\\frac{a}{b}}`, should this ever be needed.\n                Parentheses\\mpfootnotemark[1] &\n                    \\(\n                        \\parens*{x},\n                        \\parens*{x_{2}},\n                        \\parens*{x^{2}},\n                        \\parens*{\\frac{x}{y}},\n                        \\parens*{\\frac{x^{2}}{y^{3}}}\n                    \\) \\\\\n                Brackets\\mpfootnotemark[1] &\n                    \\(\n                        \\brackets*{x},\n                        \\brackets*{x_{2}},\n                        \\brackets*{x^{2}},\n                        \\brackets*{\\frac{x}{y}},\n                        \\brackets*{\\frac{x^{2}}{y^{3}}}\n                    \\) \\\\\n                Braces\\mpfootnotemark[1] &\n                    \\(\n                        \\braces*{x},\n                        \\braces*{x_{2}},\n                        \\braces*{x^{2}},\n                        \\braces*{\\frac{x}{y}},\n                        \\braces*{\\frac{x^{2}}{y^{3}}}\n                    \\) \\\\\n            \\bottomrule\n        \\end{tabular}\n        \\footnotetext[1]{%\n            These scale automatically according to their content, using \\ctanpackage{mathtools}.%\n        }%\n        \\footnotetext[2]{%\n            As a shortcut version of fractional derivatives.%\n        }%\n    }\n\\end{table}\n\n\\subsubsection{Symbols}\n\nNote how the symbols in equations are hyperlinks\n(leading to their definition in the glossary), courtesy of\npackages \\ctanpackage{hyperref} and the powerful \\ctanpackage{glossaries-extra}.\nHaving not specified anything else, they take on whatever hyperlink color was specified\nin the preamble.\nIn the final document, all links should be hidden, aka black.\nThis is a given for print output, but probably also sensible for digital output.\nThe visual noise introduced by colored links is quite immense.\nTheir only point is to let users know there is something clickable ---\nthere is a good chance that is figured out anyway.\nIf at all, use a dark green or blue tone.\n\n\\subsubsection{Math Highlighting}\n\nIn a very unobtrusive yet also unambiguous way, we can highlight important results,\nas shown in \\cref{eq:highlighted}.\nThis feature is a natural part of \\ctanpackage{tcolorbox},\na very powerful package for anything color and boxes.\nNote that for print, the gray tones should probably be darkened.\n\n\\subsubsection{Indices and Operators}\n\nIndices are typeset upright!\nThey are text.\nMath output like \\(x_{upper}\\) is one of the most common mistakes.\nIf text occurs in math mode, that is also actual text.\nConsider\n\\begin{equation}\\label{eq:stupid}\n    MEAN_{sample} \\neq \\num{2}\\eqcomma{}\n\\end{equation}\nwhich looks stupid.\nWhat \\cref{eq:stupid} really says is \\enquote{\\(M \\cdot E \\cdot A \\cdot N\\)}:\nslanted characters are variables, and not specifying any operator implies\nmultiplication.\nThis example is pedantic, but it is very easy to imagine such an issue evolving\ninto real ambiguity, which would then be a serious error.\nSince multiplication is implied by doing nothing, leaving out \\verb|*| aka\n\\verb|\\cdot| altogether often looks best.\n\nIn the preamble, use \\verb|\\DeclareMathOperator{\\examplemean}{MEAN}|, then use\n\\verb|\\text| for the subscript:\n\\begin{equation}\\label{eq:eqend}\n    \\examplemean_{\\text{sample}} \\neq \\num{2} \\eqend{}\n\\end{equation}\n\n\\subsubsection{Text-Flow}\n\n\\Cref{eq:eqend} is part of the surrounding sentence.\nMath is just another written \\enquote{language} (the only one understood around\nthe globe!) which can and will be read as a natural part of the surrounding text.\nAs such, it should contain punctuation marks.\nSo that now, having considered that we have the amazing result of\n\\begin{equation}\n    \\num{1} \\neq \\num{2} \\eqcomma{}\n\\end{equation}\nwe have achieved better overall reading flow, with commas where there would\nnaturally be separations when reading the sentence out loud as a whole.\nNotice the small spaces \\verb|\\,| before the commas and dots in equations.\nThey are convenient to avoid ambiguities.\nImplementing these as \\verb|\\eqcomma| and \\verb|\\eqend| ensures consistency.\nAdditionally, these punctuations can then also be switched off globally if your\nrequirements demand so.\n\nA second example often occurs when symbols are defined.\nNotice the difference between these:\n\\begin{enumerate}\n    \\item The density \\sym{density} is defined in \\cref{eq:density_definition_1}.\n        \\begin{equation}\\label{eq:density_definition_1}\n            \\sym{density} \\coloneq \\sym{mass} / \\sym{volume}\n        \\end{equation}\n    \\item \\label{item:equation_nice} We can therefore define the density as\n        \\begin{equation}\n            \\sym{density} \\coloneq \\sym{mass} / \\sym{volume} \\eqend{}\n        \\end{equation}\n\\end{enumerate}\nThe example in \\cref{item:equation_nice}%\n\\footnote{%\n    Items in lists can be labeled and referenced using \\ctanpackage{enumitem} and\n    \\ctanpackage{cleveref}.%\n}\nreads more naturally, is less clunky, there is less duplication of code and\ninformation and the reader does not have to jump around references.\nNevertheless, embedding equations into the surrounding text is unfortunately\nsomewhat subjective.\n\n\\subsubsection{Physical Units}\n\nIn the name of all that is holy, \\emph{never} manually type out units, numbers\nor quantities yourself: use \\ctanpackage{siunitx}.\nThe package is an absolute must\\-/have if there are any units to be typeset.\nIt is also worth using if there are no units, but numerals.\nThe latter can be typeset using the \\verb|\\num| command.\nIt is capable of parsing number constructs:\n\n\\begin{tabular}{%\n    l\n    @{ \\textrightarrow{} }\n    l\n    l\n}\n    \\verb|\\num{1.0}| & \\num{1.0} & \\multirow{3}{*}{(Localisation)}\\\\\n    \\verb|\\num{1,0}| & \\num{1,0} & \\\\\n    \\verb|\\num{1.0}| & \\begin{german}\\num{1.0}\\end{german} (German) & \\\\\n    \\verb|\\num{1.2e3}| & \\num{1.2e3} & \\\\\n    \\verb|\\num{1.2e-7}| & \\num{1.2e-7} & \\\\\n    \\verb|\\num{-e7}| & \\num{-e7} & \\\\\n    \\verb|\\num{3.2(9)}| & \\num{3.2(9)} & (Uncertainty)\\\\\n    \\verb|\\num{300000000}| & \\num{300000000} & (Group separation)\\\\\n\\end{tabular}\n\nIf the roman text font uses hanging numerals (like:\n% Safe-guard so example does not fail if OldStyle numbers are deactivated\n\\IfFontFeatureActiveTF{Numbers=OldStyle}{%\n    % True branch: nothing required\n}{%\n    % False branch: turn on\n    % This is currently broken, see also https://tex.stackexchange.com/a/525603/120853.\n    % \\addfontfeature{Numbers=OldStyle}%\n}%\n1234567890%\n\\IfFontFeatureActiveTF{Numbers=OldStyle}{%\n    % True branch: nothing required\n}{%\n    % False branch: turn back off\n    % \\addfontfeature{Numbers=Lining}%\n}%\n), but a stand\\-/alone\nnumber needs to be typeset, \\verb|\\num| is also required.\nIn this document, it will use the math font: \\num{1234567890}.\n\nPhysical units are output using \\verb|\\unit|.\nIt also has parsing capabilities:\n\\begin{minted}[linenos=false]{latex}\n    \\unit{\\meter\\cubed\\kelvin\\per\\kilogram\\squared\\per\\giga\\watt\\per\\degreeCelsius}\n\\end{minted}\nwill print\n\\unit{\\meter\\cubed\\kelvin\\per\\kilogram\\squared\\per\\giga\\watt\\per\\degreeCelsius}.\nThe mode in which units with negative exponents are displayed can be changed,\n\\iecfeg{e.g.}\\ fractions can be used:\n\\unit[per-mode=fraction]{\\meter\\cubed\\kelvin\\per\\kilogram\\squared\\per\\giga\\watt\\per\\degreeCelsius}.\nYou can also use \\verb|\\DeclareSIQualifier| to create textual subscripts for units,\nfurther specifying them, or create entirely custom units using \\verb|\\DeclareSIUnit|.\nAn example for both combined is: \\unit[per-mode=fraction]{\\mega\\watthour\\thermal\\per\\meter\\cubed}.\n\nThe \\verb|\\qty{<quantity>}{<unit>}| command essentially combines \\verb|\\num| and\n\\verb|\\unit|, inserting a small space in between, for correct typesetting.\nNo or full spaces are wrong and painful to read.\n\nThere are also commands to print ranges: \\qtyrange{20}{50}{\\meter}.\nRefer to the package documentation for more.\n\n\\subsubsection{Chemistry}\n\nClosely related to purely mathematical equations are chemical ones,\nas shown in \\cref{reac:carbon-oxidation}.\n% As with the `equations` environment, the starred environment variant omits\n% numbering.\n\\begin{reaction}[%\n    Carbon~Oxidation% This is a description/caption going into the list of reactions\n]\n    % Quotes around `label` are important for escaping, see\n    % https://tex.stackexchange.com/q/596722/120853\n    C + O2 -> CO2 \"\\label{reac:carbon-oxidation}\"\n\\end{reaction}\nAligned arrays of multiple chemical reaction equations are also possible, as\ndemonstrated in \\cref{reac:nitrogen-oxidation-one,reac:nitrogen-oxidation-two}.\n\\begin{reactions}\n    % For usage of `\\sb`, see https://tex.stackexchange.com/a/48818/120853 and\n    % https://tex.stackexchange.com/a/271498/120853 .\n    % In an array of multiple reactions, we need \\AddRxnDesc, see the docs.\n    N2 + O &<->[\\(k\\sb{1}\\)] NO + N\n        \\AddRxnDesc{First~Zeldovich~mechanism} \"\\label{reac:nitrogen-oxidation-one}\" \\\\\n    N + O2 &<->[\\(k\\sb{2}\\)] NO + O\n        \\AddRxnDesc{Second~Zeldovich~mechanism} \"\\label{reac:nitrogen-oxidation-two}\"\n\\end{reactions}\nSingle chemical compounds are invoked using \\verb|\\chcpd|, as demonstrated in\n\\cref{eq:boie}.\n\\begin{equation}\\label{eq:boie}\n    \\tcbhighmath{\n        \\frac{\n            \\sym{heating_value}\n        }{\n            \\num{1e6}\n        }\n        =\n        \\num{35}\\sym{mass_fraction}_{\\chcpd{C}}\n            +\n            \\num{94.3}\\sym{mass_fraction}_{\\chcpd{H}}\n            +\n            \\num{10.4}\\sym{mass_fraction}_{\\chcpd{S}}\n            +\n            \\num{6.3}\\sym{mass_fraction}_{\\chcpd{N}}\n            -\n            \\num{10.8}\\sym{mass_fraction}_{\\chcpd{O}}\n            -\n            \\num{2.44}\\sym{mass_fraction}_{\\text{w}}\n    }\n\\end{equation}\n\nThese commands are provided by \\ctanpackage{chemmacros} and its \\ctanpackage{chemformula}\nmodule.\nThose packages are very capable, so more complex chemistry can also be typeset:\n\\begin{reactionsgather*}\n    ^{227}_{90}Th+\\\\\n    [Cu(NH3)4]^2+\\\\\n    RNO2^{-.}\\\\\n    CH+CH\\\\\n    \\{[CH2=CH-CH2]- <-> {}[CH2-CH=CH2]- \\}\\\\\n    H2C-C+C-CH=CH+ + CrO4^2- <=>[x][y] 2.5 Cl^{-.} + 3_1/2 Na*OH_{(aq)} + !(name)( A^n )\n\\end{reactionsgather*}\nAll these examples are courtesy of the documentations of these two packages.\n\n\\subsection{Sans-Serif}\n\nHaving taken care of the main, aka roman, font, the sans\\-/serif font is the\nlogical next step.\n\\href{https://www.exljbris.com/fontinsans.html}{Fontin Sans} is a decent such font.\nImportantly, and in contrast to most other free sans\\-/serif fonts, it comes with all\nthe bells and whistles required for stunts, see \\cref{tab:sans_font_examples}.\nThis even includes small\\-/capitals support.\n\n\\begin{table}\\ContinuedFloat\n    \\ttabbox{%\n        \\caption[Sans-Serif Examples]{%\n            Examples for font features offered by the sans-serif font%\n        }%\n        \\label{tab:sans_font_examples}\n    }{%\n        \\sffamily\n        \\begin{tabular}{\n            @{}\n            l\n            l\n            @{}\n        }%\n            \\toprule\n                Feature & Sample Text\\\\\n            \\midrule\n                Regular & \\sampletext\\\\\n                \\textbf{Bold} & \\textbf{\\sampletext}\\\\\n                \\textit{Italics} & \\textit{\\sampletext}\\\\\n                \\textbf{\\textit{Bold Italics}} & \\textbf{\\textit{\\sampletext}}\\\\\n                \\textsc{SC} & \\textsc{\\sampletext}\\\\\n            \\bottomrule\n        \\end{tabular}\n    }%\n\\end{table}\n\n\\subsection{Mono-Spaced}\n\\label{ch:mono-spaced}\n\nWanting to display any sort of code, or maybe a \\abb{uniform_resource_locator},\nin the document will have you looking for a mono\\-/spaced aka typewriter font.\n\\href{https://fonts.google.com/specimen/Inconsolata}{Inconsolata}, published by Google,\nis the pick here.\nSee \\cref{ch:code-listings} for a more in-depth demonstration.\nAt the time of writing (\\DTMdate{2020-04-15})%\n\\footnote{%\n    % \\verb is not possible in footnote and \\lstinline is not escaping LaTeX\n    % commands inside of it properly, there do it the budget way.\n    % See also https://tex.stackexchange.com/q/203/120853\n    Date typeset as \\texttt{\\textbackslash{}DTMdate\\{YYYY-MM-DD\\}} using\n    \\ctanpackage{datetime2}.\n    This gets us \\textbf{language-independent}\n    \\abb{international_organization_for_standardization} formatting.\n},\nInconsolata has native regular and bold faces, but no italics.\nHowever, such a feature can be faked using \\ctanpackage{unicode-math}/%\n\\ctanpackage{fontspec}, where the regular font is \\emph{slanted} to give an\nitalics\\-/like result.\nItalics are a nice but uncritical feature for code listings, so this should be okay.\nSee for yourself in \\cref{tab:mono_font_examples}.\n\n\\begin{table}\\ContinuedFloat\n    \\ttabbox{%\n        \\caption[Monospaced Examples]{%\n            Examples for font features offered by the monospaced font.\n            The italics are indeed faked and not real glyphs, just slanted\n            regular shapes%\n        }%\n        \\label{tab:mono_font_examples}\n    }{%\n        \\ttfamily\n        \\begin{tabular}{\n            @{}\n            l\n            l\n            @{}\n        }%\n            \\toprule\n                Feature & Sample Text\\\\\n            \\midrule\n                Regular & \\sampletext\\\\\n                \\textbf{Bold} & \\textbf{\\sampletext}\\\\\n                \\textit{Italics} & \\textit{\\sampletext}\\\\\n            \\bottomrule\n        \\end{tabular}\n    }%\n\\end{table}\n\n\\subsection{Symbols}\n\n\\ctanpackage{fontawesome5} is a package providing hundreds of freely usable vector\nsymbols.\nThey scale just like normal vector graphics and can be used alongside text, like\nthis little friend here: \\faIcon{firefox}.\nThey can also be colored (\\textcolor{mRed}{\\faIcon{chrome}}) or scaled:\n\\begin{center}\n    \\scalebox{20}{\\faIcon{linux}}\n\\end{center}\nAll of these should also be select- and then copyable, yielding \\iecfeg{e.g.}\\\n\\emph{LINUX}.\nRefer to the package documentation for a list of all the available symbols.\n\n\\section{Language}\n\nClosely related to the previous \\lcnamecref{ch:fonts_text} are the language features.\nCurrently, there are two supported languages: English and German.\nSee for yourself in the file responsible for the translations, \\verb|translations.tex|.\nIt leverages the \\verb|\\providecaptionname{}| command from KOMA\\-/Script.\nGiven the name of that command, it is probably a misuse and not its purpose, but\nit worked better than its alternatives.\n\nThe \\ctanpackage{polyglossia} package does all the heavy lifting for this document.\nIt is an alternative to the widespread \\ctanpackage{babel} package.\nNote that \\ctanpackage{polyglossia} requires the language to be passed to its\n\\verb|\\setdefaultlanguage{}| command.\nIt will normally not work by just specifying a global document language.\nHowever, you can pass a global language to the \\verb|language=| keyword in the\noptions to \\verb|\\documentclass{acp}|, and it will be picked up correctly.\n\nThe chosen language option will also be forwarded to various other packages, like\n\\ctanpackage{enquote} for quotations and \\ctanpackage{siunitx} for localization of\nnumerals typesetting.\n\\ctanpackage{polyglossia} will take care of all the hyphenation rules, so there\nshould be no or very minimal need for manual \\verb|\\hyphenation{}| or \\verb|\\-|\ncommands.\n\nThe language can be switched dynamically, and all content will be adjusted, see\n\\cref{tab:languages}.\nMore languages can be added easily in the translations file.\nNote that the \\verb|listing| type of \\ctanpackage{cleveref} will only work with\nthe main document language and is currently not able to be switched dynamically.\n\\begin{table}\n    \\ttabbox{%\n        \\caption{%\n            Available languages and dynamic switching.\n            Note how the commands are language\\-/dependent; no manual adjustments\n            necessary%\n        }%\n        \\label{tab:languages}%\n    }{%\n        \\footnotesize\n        \\begin{tabular}{\n            @{}\n            *3{l}\n            p{0.15\\linewidth}\n            p{0.25\\linewidth}\n            @{}\n        }\n            \\toprule\n                Language & Quotes & Numerals & Headers \\iecfeg{etc.} & Hyphenation \\\\\n            \\midrule\n                English &\n                    % An alternative command is \\textenglish, \\textgerman etc.\n                    % However, that command can break due to macro expansion stuff,\n                    % if it contains macros and not just plain text.\n                    \\begin{english}\\enquote{Quote!}\\end{english} &\n                    \\begin{english}\\qty{100.2}{\\meter}\\end{english} &\n                    % polyglossia \\begin{<language>} environment seems to introduce\n                    % empty lines in paragraph columns; remove them manually.\n                    \\vspace{-\\baselineskip}% This is guesswork; haven't figured this out yet\n                    \\begin{english}%\n                        \\glossaryname{},%\n                        \\cref{fig:censorbox},\n                        \\cref{tab:main_font_examples},\n                        \\cref{ch:base-features}\n                    \\end{english} &\n                    \\vspace{-\\baselineskip}% This is guesswork; haven't figured this out yet\n                    \\begin{english}\n                        This is a random text intended to show of hyphenation and line\n                        endings in the respective language.\n                        It is therefore a bit longer, so hopefully some words will break\n                        at the word boundaries.\n                        This cannot be guaranteed however.\n                        So there is to hoping that this test shows off the hyphenation\n                        rules and capabilities put into place by\n                        \\ctanpackage{polyglossia}.\n                    \\end{english}\n                \\\\\n                German &\n                    \\begin{german}\\enquote{Zitat!}\\end{german} &\n                    \\begin{german}\\qty{100.2}{\\meter}\\end{german} &\n                    \\vspace{-\\baselineskip}% This is guesswork; haven't figured this out yet\n                    \\begin{german}\n                        \\glossaryname{},\n                        \\cref{fig:censorbox},\n                        \\cref{tab:main_font_examples},\n                        \\cref{ch:base-features}\n                    \\end{german} &\n                    \\vspace{-\\baselineskip}% This is guesswork; haven't figured this out yet\n                    \\begin{german}\n                        Dies ist ein zufälliger Text, der die Worttrennungsregeln und\n                        Satzenden der jeweiligen Sprache demonstrieren soll.\n                        Er ist daher etwas länger, sodass manche Wörter hoffentlich\n                        an den Seitenrändern gebrochen werden.\n                        Dies kann allerdings nicht garantiert werden.\n                        Wir können also nur hoffen, dass dieser Test die\n                        Silbentrennungsregeln und -fähigkeiten des\n                        \\ctanpackage{polyglossia} Pakets.\n                    \\end{german}%\n                \\\\\n            \\bottomrule\n        \\end{tabular}\n    }%\n\\end{table}\n\n\\section{Sectioning}\n\\label{ch:sectioning}\n\n% There should be content here\n\n\\subsection{Explanation}\n\\label{ch:sectioning_explanation}\n\nBetween any two sectional commands (from \\verb|\\part| down), there always should be\nbe at least \\emph{some} content.\nAnything else looks off, \\iecfeg{cf.}\\ the direct transition between\n\\cref{ch:sectioning,ch:sectioning_explanation}.\nAt least, tell the reader what the following hierarchical level contains for them.\n\nFurther, three numbered levels of hierarchy are enough.\nThe numbering and even availability of sectioning commands depends on the used\n\\verb|documentclass|.\nIn \\ctanpackage{koma-script} articles (\\verb|scrartcl|), these are sections,\nsubsections and subsubsections.\n\\ctanpackage{koma-script} reports (\\verb|scrreprt|) and books (\\verb|scrreprt|)\nextend this by parts and chapters, both of which numbered.\nSubsubsections will no longer be numbered.\nTrying to create a \\verb|\\part| or \\verb|\\chapter| in article classes will result\nin errors.\n\n\\subsubsection{Deeper!}\n\nDeeper sectioning is fine, but it should not be numbered or occur in the table of\ncontents.\nNotice how, without specifying anything, \\ctanpackage{koma-script} abides by that\nautomatically.\nThis is despite using \\verb|\\subsubsection{Deeper!}| as opposed to \\verb|\\subsubsection*|,\nits explicitly unnumbered counterpart.\n\nAlso notice how between \\verb|\\section{Sectioning}|, which produced \\cref{ch:sectioning},\nand \\verb|\\subsubsection{Deeper!}|, there was no subsection.\nUsually, you would want a clean cascade with no jump in the hierarchy levels.\nIf you catch yourself jumping, it is also a sign there might be something off with your\nactual content structure or thought process.\nThat being said, it is absolutely okay to do; just be aware.\n\n\\LaTeX{} has many ways where it does not let you do something easily, or where\ncommands look off.\n\\emph{Never fight \\LaTeX{}} in that; you will lose, it will win.\nWhen something is awkward to do or requires a lot of manual labor, you are probably\ndoing it wrong and there will be an easier way.\nMost often, that comes in the form of packages.\nBeing a fully\\-/fleshed programming language under the hood, \\emph{any} repetition\nin \\LaTeX{} should make you stop for a second and wonder about another way.\nThat may lead to you discovering suboptimal approaches and code.\nJust as often, it will not lead anywhere and trying to force minimum code and\nmaximum optimization will not be economical.\nAfter all, \\LaTeX{} is a markup language.\n\n\\paragraph{Paragraphs}\nThey are a nice touch, introducing a new, distinct paragraph, idea or thought\nwithout being too loud about it.\n\nThat being said, leave a blank line in the source code for regular paragraphs.\nUse either vertical spacing between paragraphs or indentation (like here).\nDo not use both!\n\n\\noindent\nEach new train of thought should go into its own paragraph.\nThis paragraph is not indented, as was intended by manually calling \\verb|\\noindent|.\nIn regular text and documents, there are very few reasons that should ever occur.\nAgain, let \\LaTeX{} do its thing; if you find yourself typing \\verb|\\noindent|\nall the time, there will be something wrong.\nFor example, paragraph styles (vertical spacing between them, indentation \\iecfeg{etc.})\nis configured globally.\n\n\\section{References}\n\\label{ch:references}\n\nThis \\textcolor{mRed}{\\lcnamecref{ch:references}} is about referencing.\nNotice {\\color{mRed}{\\verb|\\lcnamecref|}} in the previous sentence:\nit references (in \\textbf{l}ower-\\textbf{c}ase) the name of the passed label.\nIf this \\lcnamecref{ch:references} ever changes to something else (chapter, \\dots),\nit is updated automatically.\n\nNote that using package \\ctanpackage{cleveref}, we only ever issue\n\\verb|\\cref{<label>}| commands.\nThat command also has many useful cousins, like \\verb|\\crefname{<label>}|.\nThe package does the heavy lifting and inserts the reference \\emph{type},\nalso with correct plural forms if required:\n\\cref{tab:main_font_examples,fig:censorbox,fig:bitmap_tikz}\n\\textleftarrow{} all of that was done automagically.\nDoing it any other way is just way too laborious and error\\-/prone.\n\nFor added convenience, insert the \\emph{type} directly into the label,\n\\iecfeg{e.g.}\\ \\verb|\\label{fig:hello}|.\nThis aids auto\\-/completion and readability.\n\n\\subsection{Bibliography}\n\\label{ch:bibliography_rationale}\n\nThe second place where references occur are bibliographical contexts.\nExamples are spread throughout this document.\nAt their basis, they rely on \\ctanpackage{biblatex} and its back\\-/end\n\\ctanpackage{biber}.\nForget about the outdated \\ctanpackage{bibtex}: that package urges users to use\n\\ctanpackage{biblatex} instead, especially for UTF-8 support, which is crucial\nfor citing authors with arbitrary, international names.\n\nUsing \\verb|\\autocite{bibid}|, sources can be cited reliably, while having a whole range\nof features delivered for free.\nWe do not have to worry about the specific citation styles\n(in parentheses, as a superscript, \\dots) ---\n\\verb|\\autocite{bibid}| takes care of that, we can then manage its behavior globally.\n\nAs such, we can have citations looking like:\n\\cites[8]{einsteinZurElektrodynamikBewegter1905}[29\\psqq]{goossensLaTeXCompanion1993}[2-9]{knuthTeXbook1986}%\n[89\\psq]{knuthFundamentalAlgorithms1973}{diracPrinciplesQuantumMechanics1981}\n.\nA note may be added to each citation; if this note is an integer number, it is\nautomatically taken to be the page number.\nNo need to write \\enquote{\\emph{p.}}\\ and similar manually.\nIf a following page is to be included in the citation, append \\verb|\\psq|.\nOtherwise, \\verb|\\psqq| for \\enquote{this page and the following ones}.\nUsing \\verb|\\autocites{}| \\iecfeg{etc.}, we can then chain together as many as we want.\n\n\\textcite[3]{diracPrinciplesQuantumMechanics1981} does not claim anything, this is just an example\nfor a \\verb|\\textcite|, used to implement a citation to be a readable part of the\nsentence.\nThere is also a plural form available.\nExplore the documentation for a taste of the vast selection of automatic citation\ncommands.\n\n\\paragraph{Language support}\nAll of this is incredibly convenient, for there is minimal manual work and a lot\nof abstraction into high\\-/level commands.\nImportantly, this is language\\-/agnostic, and \\ctanpackage{biblatex} will make use\nof \\ctanpackage{polyglossia} (the \\hologo{LuaLaTeX} replacement for \\ctanpackage{babel})\nand \\ctanpackage{csquotes}.\nTherefore, through changing the desired document language for just these packages,\nall others including \\ctanpackage{biblatex} will quickly adjust automatically.\n\n\\paragraph{backref-feature}\nTaking a look at the bibliography (\\cpageref{ch:bibliography}) in the backmatter\nof this document reveals the \\texttt{backref} feature:\nthe pages where a reference was cited occur after its entry.\nThis is helpful in print, but amazing in digital format, for these page numbers\nare also links.\nThis allows readers to very swiftly navigate and jump within the document.\n\nTry it out by following this reference: \\cite{diracPrinciplesQuantumMechanics1981},\nleading you to the bibliography.\n\\label{backref_example}\nIt will have this page's number (\\cpageref{backref_example}) at the end of its entry.\nClicking it will land you back here exactly.\n\n\\paragraph{Citation Manager}\nTo generate the \\texttt{*.bib} file from which \\LaTeX{} pulls the info in the\nfirst place, a citation manager is a must\\-/have.\nZotero\n(especially with its excellent \\href{https://retorque.re/zotero-better-bibtex/}{\\emph{Better Bibtex}} addon)\nis recommendable, but it ultimately does not matter much.\nJust use \\emph{some} manager to keep your actual documents\n(consisting of bibliographical info and the attachments themselves, like e-books)\nand the automatically derived \\texttt{*.bib} files in one place,\nnamed and structured consistently.\n\n\\section{Lists}\n\nIn technical publications, using lists (either bullet points or enumerations)\nis highly encouraged.\nThey should almost always be preferred over doing the same thing in a block of text.\nJust consider this example list:\n\\begin{itemize}\n    \\item The demonstrated approach is more complex than the previous one:\n    \\begin{enumerate}\n        \\item more time was spent doing computations,\n        \\item less was spent fooling around,\n        \\item features were added.\n    \\end{enumerate}\n    \\item At the same time, the following simplifications were made:\n    \\begin{enumerate}\n        \\item went from continuous- to discrete-time simulations,\n        \\item threw out some superfluous stuff.\n    \\end{enumerate}\n\\end{itemize}\nThe very same information in form of a text block is suddenly much more inaccessible\nto readers.\nIn technical writing, precision and conciseness matter --- prose, synonyms and\nfiller words do not.\n\nNote the block\\-/like \\texttt{itemize} symbol (\\smblksquare{})%\n\\footnote{%\n    This is also a regular Unicode character.\n    When copy-pasting old or outdated \\LaTeX{} documents, ever noticed all the\n    funny business going on?\n    A good example is copying German \\emph{umlauts} like Ä, Ö, Ü.\n    They might turn into \\emph{\\(\\ddot{\\phantom{A}}\\text{A}\\)}, since \\LaTeX{}\n    only ever put two random dots over the regular ASCII letter A.\n    With \\ctanpackage{unicode-math} (building onto \\ctanpackage{fontspec}) and\n    \\hologo{LuaLaTeX}, this document is fully Unicode-compatible.\n    Copy-paste anything correctly: \\(\\delta \\sigma \\int_{1}^{2} y\\).\n    Googling the \\smblksquare{} block will reveal that it is \\texttt{U+25AA}.\n}\nand the fact that enumerate numbers are part of the {\\sffamily sans-serif family}\nand \\textbf{bold}.\nThat is totally revolutionary and stuff, because it's\\dots{} different?\nIf it is not to your liking, lists may be changed, configured and created using the\n\\ctanpackage{enumitem} package.\nFor example, using that package, this document has a list for numbered descriptions,\nin essence a combination of the \\verb|enumerate| and \\verb|description| environments:\n\\begin{enumdescript}\n    \\item[This item] has this description.\n    \\item[This other item] has a different description.\n\\end{enumdescript}\n\n\\section{Censoring}\n\nThere is a censoring feature, provided by \\ctanpackage{censor}.\nIt allows you to publish documents containing sensitive information, \\iecfeg{e.g.}\\ for\nproofreading.\nSo, this is now a huge\n\\todo{I am a TODO note.}\nsecret:\n\\censor{today is \\DTMtoday{}}.\n\nFloat contents can also be censored, as illustrated in \\cref{fig:censorbox}.\n\\begin{figure}\n    \\ffigbox[\\FBwidth]{%\n        \\caption{Example for a censoring box}%\n        \\label{fig:censorbox}%\n    }{%\n        \\censorbox{%\n            % Having issued \\graphicspath globally, we do not have to specify the full\n            % path here. Not even a file extension is necessary.\n            \\includegraphics[width=0.5\\textwidth]{field}\n        }%\n    }\n\\end{figure}\n\n\\section{Glossaries}\n\\label{ch:glossaries}\n\n\\ctanpackage{glossaries-extra} is an absolute unit of a package.\nFor this document, it is used with its back\\-/end \\ctanpackage{bib2gls}.\nThis Java tool comes with installations of TeXLive and MiKTeX.\nYou should already have it.\nThis \\lcnamecref{ch:glossaries} is only a brief, opinionated overview.\nFor a more appropriate introduction, there is a suitable\n\\href{http://tug.ctan.org/macros/latex/contrib/glossaries/glossariesbegin.pdf}{Beginner's Guide},\nwritten by the package author.\nBefore you jump further into the relevant, proper documentations (these are three: the\n\\ctanpackage{glossaries} base package, the comprehensive extension\n\\ctanpackage{glossaries-extra} and the helper tool \\ctanpackage{bib2gls}), you might\nwant to give the beginner's guide a shot.\n\nIn a format similar to normal bibliographies, all glossary entries are now managed\nusing \\texttt{*.bib} files.\nEach entry is processed by \\ctanpackage{bib2gls} and put into an auxiliary file.\nFrom it, \\ctanpackage{glossaries-extra} reads and inserts all contents when \\verb|\\gls|\nand its many sibling commands are used.\nThe framework for all of that, also printing of the glossary and nomenclature,\nis already taken care of for this document.\nIn addition to printing the glossaries, they are also added to the table of contents.\nThis behavior can be toggled using the \\texttt{toc} package option flag,\nsee the source code for more info.\n\nTraditionally, glossary packages are used for abbreviations.\nHowever, using \\ctanpackage{glossaries-extra} this can be kicked into top gear.\nIt is used for:\n\\begin{itemize}\n    \\item abbreviations,\n    \\item (physical) constants,\n    \\item symbols (greek, roman and all other),\n    \\item subscripts,\n    \\item the book index, consisting of names and the normal index.\n\\end{itemize}\n\nIn the case of symbols, this means the source now relies on \\verb|\\sym{<label>}|\ncommands, see also \\cref{tab:available_bib_files}.\nFor example, equations no longer read \\verb|E = mc^{2}|, but instead\n\\begin{verbatim}\n    \\sym{energy} = \\sym{mass}\\sym{velocity}^{2}\n\\end{verbatim}\nThis initially unintuitive approach has several critical advantages:\n\\begin{enumerate}\n    \\item absolute \\textbf{consistency} following the \\abb{single_source_of_truth}\n        principle:\n        there is exactly \\emph{one} place where the symbol itself is defined.\n        All other usages are just \\emph{references} to this central definition.\n        If suddenly, the symbol for velocity has to change from \\(c\\) to \\(v\\)\n        throughout the entire document, it can be done with ease.\n        Replacing single letters like that using tools like \\texttt{sed} would be a\n        nightmare, if not impossible.\n\n        There is also absolutely no danger that \\emph{both} symbols occur (unless\n        it is explicitly set up like that), with both referring to velocity,\n        as can happen when returning to a document after abandoning it for many months\n        or if multiple authors work on one document.\n    \\item following the \\textbf{\\abb{what_you_see_is_what_you_mean}} principle:\n        this is \\LaTeX{}'s big strength.\n        In the source code, it no longer states what you \\emph{want to see}, but\n        instead \\emph{what you mean}.\n        When you write \\verb|E = mc^2|, you are writing what you want to see:\n        the letter \\texttt{E} is somehow equal to the product of letter \\texttt{m}\n        times \\texttt{c} squared.\n        But the \\emph{meaning} is that \\emph{energy} equals \\emph{mass} times\n        \\emph{velocity} squared.\n        This can now be expressed directly in the source code.\n\n        The \\abb{what_you_see_is_what_you_mean} principle is at the core of \\LaTeX{}\n        and is what sets it apart.\n        It is the reason you also do not say\n        \\begin{verbatim}\n            {\\Huge\\textsf{\\textbf{<Section Title>}}}\n        \\end{verbatim}\n        but instead simply\n        \\begin{verbatim}\n            \\section{<Section Title>}\n        \\end{verbatim}\n        In the first, it was stated what the author wants to \\emph{see}, but only\n        in the second one does it say what was \\emph{meant}.\n        It is painfully obvious why the latter approach is the correct one.\n        Another example is emphasized text.\n        Do \\emph{emphasized} (produced from \\verb|\\emph|) and \\textit{emphasized}\n        (\\verb|\\textit|) text look the same?\n        They certainly do\\dots{} usually.\n\n        Yet, what is \\emph{meant} is \\emph{emphasis}; italic text is just what it\n        happens to look like now, but it is not the \\emph{meaning}.\n        For example, we could later decide to redefine emphasized text to bold,\n        or colored.\n        If you previously did not differentiate strictly enough between\n        \\verb|\\emph| and \\verb|\\textit|, you are in for a bad time.\n        This is a trap beginners unfortunately often fall into.\n        Using \\ctanpackage{glossaries-extra}, abstracted markup\\-/commands can be\n        taken to a whole next level, leveraging this core \\LaTeX{} strength.\n    \\item \\textbf{abolishing ambiguity}:\n        especially when the source code is read by other people, or even worked on,\n        \\enquote{naked} symbols can become ambiguous.\n        What American authors refer to with a capital \\emph{P}, European authors\n        interpret as \\emph{power}, when really \\emph{pressure} was meant.\n        This is a non\\-/issue if in the source it says \\verb|\\sym{pressure}|.\n        For internationalization, authors would then only adjust their\n        \\emph{style-sheets} (in this case the \\texttt{*.bib} files) and be done.\n    \\item arguably improving \\textbf{readability}.\n        The source code can almost be read like a normal sentence consisting of full\n        words, albeit with braces and backslashes in the way.\n    \\item printing the \\textbf{nomenclature} becomes trivial.\n        A single command simply prints the \\texttt{*.bib} file contents.\n        Being an external Java tool, the customization, sorting and filtering\n        capabilities of \\ctanpackage{bib2gls} for printing those lists are likely\n        more than will ever be needed.\n    \\item lastly, some more gimmicky features are enabled, like printing all\n        page numbers of occurrences of a symbol.\n        Alternatively, only the first occurrence can be printed.\n\\end{enumerate}\n\n\\paragraph{Available Commands}\n\\ctanpackage{glossaries-extra} is already heavily leveraged for this document.\nTake a look around the source code for all the details.\nFor starters, there are a couple of predefined \\texttt{*.bib} files, showcased in\n\\cref{tab:available_bib_files}.\nNote that using entries with commands like \\verb|\\sym{<entry name>}| is independent\nof the entry type used in the \\texttt{*.bib} file.\nFor example, subscripts are invoked using \\verb|\\sub{<entry name>}| despite being\ndefined as \\verb|@symbol{<entry name> ...| in \\texttt{subscripts.bib}.\n\n\\begin{table}\n    \\ttabbox{%\n        % Brackets hold entry that will go into List of Tables (short form)\n        \\caption[Predefined glossaries]{%\n            Predefined glossaries with their respective \\texttt{*.bib} files,\n            invoking commands and list occurrence in the document%\n        }%\n        % Use a string like 'tab:' to help with organization and auto-complete\n        % when reffing\n        \\label{tab:available_bib_files}\n    }{%\n        \\small\n        \\begin{tabular}{\n            % @{<value>} specifies the column separator;\n            % Use @{} to remove white space from sides (empty value)\n            @{}\n            *3{l}% If no other significant reason, left-align\n            @{}\n        }\n            \\toprule\n                Name (\\texttt{.bib}) & Command & Listed in / Description \\\\\n            \\midrule\n                % \\nameref is courtesy of the nameref package, which is part of\n                % hyperref. It references the target by name, e.g. Chapter name.\n                % However, that does not work very well for generated chapter names.\n                \\texttt{terms} & \\texttt{\\textbackslash idx} & Index \\textrightarrow{} Terms \\\\\n                \\texttt{names} & \\texttt{\\textbackslash name} & Index \\textrightarrow{} Names \\\\\n            \\addlinespace\n                \\texttt{roman} &\n                    \\texttt{\\textbackslash sym} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Symbols \\textrightarrow{} Roman \\\\\n                \\texttt{greek} &\n                    \\texttt{\\textbackslash sym} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Symbols \\textrightarrow{} Greek \\\\\n                \\texttt{other} &\n                    \\texttt{\\textbackslash sym} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Symbols \\textrightarrow{} Other \\\\\n            \\addlinespace\n                \\texttt{subscripts} &\n                    \\texttt{\\textbackslash sub} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Subscripts \\\\\n            \\addlinespace\n                \\texttt{constants}\\mpfootnotemark[1] &\n                    \\texttt{\\textbackslash cons} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Numbers \\\\\n            \\addlinespace\n                \\texttt{abbreviations} &\n                    \\texttt{\\textbackslash abb} &\n                    \\nameref{ch:glossary} \\textrightarrow{} Acronyms \\\\\n            \\bottomrule\n        \\end{tabular}\n        \\footnotetext[1]{%\n            Constants like \\cons{pi} are toy examples for this document.\n            However, this glossary section is very convenient to share assumptions\n            and used constants in a clear and concise way in one central place,\n            aiding reproducibility and overall document integrity.%\n        }\n    }%\n\\end{table}\n\n\\paragraph{Modifying Print Output}\nTo use glossary entries but not print them in a glossary, comment out the entire\nrelevant \\verb|\\printunsrtglossary| macro where appropriate.\nFor the index, the relevant command is \\verb|\\printunsrtindex|.\nSome glossary categories, like \\emph{Symbols}, have sub\\-/categories, like \\emph{Roman},\n\\emph{Greek} and \\emph{Other}.\nTo omit printing a single sub\\-/category in the glossaries (but still allow their use\nin the document%\n\\footnote{\n    The \\emph{Other} symbol entries are required for the provided built\\-/in math\n    macros, see \\cref{tab:predefined_math_macros}, to work!%\n}%\n), refer to the \\texttt{notprinted} type and the instructions found in the \\texttt{*.cls}\nfile.\n\n\\subsection{bib2gls}\n\\label{ch:bib2gls}\n\n\\ctanpackage{bib2gls} is an external tool (of the same name as the package) that\n\\ctanpackage{glossaries-extra} employs to convert external \\texttt{*.bib} files with\ndefinitions for, for example, acronyms, into a \\TeX{}\\-/compatible format.\nDuring conversion, it also processes all the entries, like sorting them in whatever\nway you request.\nThe sorting and filtering capabilities are very strong, and of course also Unicode\ncompatible.\nA minimal \\texttt{bib} file for acronyms can be as simple as:\n\\begin{minted}[linenos=false]{bib}\n    @abbreviation{cont_int,\n        short={CI},\n        long={Continuous Integration},\n    }\n\\end{minted}\nFor concrete examples, see the files for this document at \\texttt{bib/glossaries/}.\nThere can be as many keys as required, with custom ones being easily created.\nEffectively, this is analogous to how bibliography entries are created.\nThus, users of \\LaTeX{} who are already familiar with that concept and format\nshould have an easy time getting started with \\ctanpackage{glossaries-extra}.\nUsing it for mathematical symbols can look like:\n\\begin{minted}[linenos=false]{bib}\n    @symbol{abs_temperature,\n        name={\\ensuremath{T}},\n        description={absolute temperature},\n        group={roman},\n        unit={\\unit{\\kelvin}},\n    }\n\\end{minted}\n\n\\begin{landscape}\n    \\section{Landscape}\n\n    Pages in landscape format are rather straightforward to implement.\n    Note that not only are these in landscape orientation; they are also recognized\n    as such by supporting document viewers, rotating the page for you and keeping\n    it legible.\n\\end{landscape}\n"
  },
  {
    "path": "chapters/mainmatter/code-listings.tex",
    "content": "\\chapter{Code Syntax Highlighting}\n\\label{ch:code-listings}\n\nTo properly typeset code in \\LaTeX{}, we use the \\ctanpackage{minted} package.\nIt relies on Python, and calls in outside help for syntax highlighting using Python's\n\\texttt{pygments} package.\nAs such, it requires \\texttt{--shell-escape} to compile, and of course Python.\nThe latter can be a pain in the buttocks to set up; Docker usage is especially useful here.\nSince \\texttt{pygments} has nothing to do with \\LaTeX{} (whose ecosystem is a sad mess),\nbut is instead a regular old Python package, chances are the language of your choice is\nnot only available but also well\\-/supported!%\n\\footnote{%\n    For example, \\ctanpackage{listings}, the inferior alternative to \\ctanpackage{minted},\n    still had no Python 3 support (only basic 2) in 2020, at the time of originally writing this.\n    At that point, Python 3 was over 10 years old already and Python 2 was end-of-life.\n}\n\n\\paragraph{Color Scheme}\nNote how the color scheme is the same throughout languages.\nThe idea is that keywords of similar importance, status or semantics are highlighted uniformly.\nFor example, keywords for class and function definitions, like \\mintinline{python}{class}\nfor Python or \\mintinline{matlab}{classdef} for MATLAB.%\n\\footnote{%\n    Notice how these keywords were created using an \\emph{inline} listing, like:\n    \\mintinline{python}{y = [file_patterns[x] for x in [\"send\", \"help\"]]}.\n}\nAnother example are error\\-/handling and -throwing keywords, which many languages\noffer.\nAll these different types should be identified and treated equally.\n\\ctanpackage{minted} is a widely used package and knows about a lot of languages.\nYou can check it out at\n\\begin{center}\n    \\url{https://pygments.org/demo/}.\n\\end{center}\n\nIf the current colors are not to your liking they can be changed easily using\n\\ctanpackage{minted}'s \\texttt{style} option.\nRefer to the comments in the source code on how to see available styles.\n\n\\paragraph{References}\nIndividual code lines can also be referenced.\nFor example, we find a \\mintinline{python}{return} statement on\n% NOTE: referencing single \"minted\" lines *CANNOT* be done with cleveref, unfortunately.\n% See: https://tex.stackexchange.com/q/132420/120853 . A plain old `ref` does the trick.\nline \\ref{line:python_return} in \\cref{lst:float_example}.\nThat line is also highlighted, using \\ctanpackage{minted}'s \\texttt{highlightlines} option.\n\n\\section{Python}\nThe following examples are not always complete or functioning, they are only supposed\nto showcase the available syntax highlighting.\nThe base style looks like:\n\\begin{minted}{python}\n    def get_nonempty_line(\n        lines: Iterable[str],\n        last: bool = True\n    ) -> str:\n        if last:\n            lines = reversed(lines)\n        return next(line for line in lines if line.rstrip())\n\\end{minted}\nIt is intended for (small) samples of code that flow into the surrounding text.\nA second feature are code listings as regular floats, as demonstrated in\n\\cref{lst:float_example}.\nAs floats, they behave like any other figure, table \\iecfeg{etc}.\n\n\\begin{listing}\n    \\begin{minted}[highlightlines={24}]{python}\n        import json\n        import logging.config\n        from pathlib import Path\n\n        from resources.helpers import path_relative_to_caller_file\n\n        ¬\\phstring{\\LaTeX{} can go in here: \\(\\sum_{i = 1}^{n} a + \\frac{\\pi}{2} \\)}¬\n\n        def set_up_logging(logger_name: str) -> logging.Logger:\n            \"\"\"Set up a logging configuration.\"\"\"\n            config_filepath = path_relative_to_caller_file(\"logger.json\")  # same directory\n\n            try:\n                with open(config_filepath) as config_file:\n                    config: dict = json.load(config_file)\n                logging.config.dictConfig(config)\n            except FileNotFoundError:\n                logging.basicConfig(\n                    level=logging.INFO, format=\"[%(asctime)s: %(levelname)s] %(message)s\"\n                )\n                logging.warning(f\"Using fallback: no logging config found at {config_filepath}\")\n                logger_name = __name__\n\n            return logging.getLogger(logger_name) ¬\\label{line:python_return}¬\n    \\end{minted}\n    \\caption{%\n        This is a caption.\n        Listings cannot be overly long since floats do not page-break% No period here!\n    }\n    \\label{lst:float_example}\n\\end{listing}\n\nThe third example showcases breaking across pages, probably best suited for an appendix:\n\\begin{minted}{python}\n    def ansi_escaped_string( ¬\\phnote{A random reference: \\cref{fig:censorbox}}¬\n        string: str,\n        *,\n        effects: Union[List[str], None] = None,\n        foreground_color: Union[str, None] = None,\n        background_color: Union[str, None] = None,\n        bright_fg: bool = False,\n        bright_bg: bool = False,\n    ) -> str:\n        \"\"\"Provides a human-readable interface to escape strings for terminal output.\n\n        Using ANSI escape characters, the appearance of terminal output can be changed. The\n        escape chracters are numerical and impossible to remember. Also, they require\n        special starting and ending sequences. This function makes accessing that easier.\n\n        Args:\n            string: The input string to be escaped and altered.\n            effects: The different effects to apply, e.g. underlined.\n            foreground_color: The foreground, that is text color.\n            background_color: The background color (appears as a colored block).\n            bright_fg: Toggle whatever color was given for the foreground to be bright.\n            bright_bg: Toggle whatever color was given for the background to be bright.\n\n        Returns:\n            A string with requested ANSI escape characters inserted around the input string.\n        \"\"\"\n\n        def pad_sgr_sequence(sgr_sequence: str = \"\") -> str:\n            \"\"\"Pads an SGR sequence with starting and end parts.\n\n            To 'Select Graphic Rendition' (SGR) to set the appearance of the following\n            terminal output, the CSI is called as:\n            CSI n m\n            So, 'm' is the character ending the sequence. 'n' is a string of parameters, see\n            dict below.\n\n            Args:\n                sgr_sequence: Sequence of SGR codes to be padded.\n            Returns:\n                Padded SGR sequence.\n            \"\"\"\n            control_sequence_introducer = \"\\x1B[\"  # hexadecimal '1B'\n            select_graphic_rendition_end = \"m\"  # Ending character for SGR\n            return control_sequence_introducer + sgr_sequence + select_graphic_rendition_end\n\n        # Implement more as required, see\n        # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters.\n        sgr_parameters = {\n            \"underlined\": 4,\n        }\n\n        sgr_foregrounds = {  # Base hardcoded mapping, all others can be derived\n            \"black\": 30,\n            \"red\": 31,\n            \"green\": 32,\n            \"yellow\": 33,\n            \"blue\": 34, ¬\\phnum{\\(30 + 4\\)}¬\n            \"magenta\": 35,\n            \"cyan\": 36,\n            \"white\": 37,\n        }\n\n        # These offsets convert foreground colors to background or bright color codes, see\n        # https://en.wikipedia.org/wiki/ANSI_escape_code#Colors\n        bright_offset = 60\n        background_offset = 10\n\n        if bright_fg:\n            sgr_foregrounds = {\n                color: value + bright_offset for color, value in sgr_foregrounds.items()\n            }\n\n        if bright_bg:\n            background_offset += bright_offset\n\n        sgr_backgrounds = {\n            color: value + background_offset for color, value in sgr_foregrounds.items()\n        }\n\n        # Chain various parameters, e.g. 'ESC[30;47m' to get white on black, if 30 and 47\n        # were requested. Note, no ending semicolon. Collect codes in a list first.\n        sgr_sequence_elements: List[int] = []\n\n        if effects is not None:\n            for sgr_effect in effects:\n                try:\n                    sgr_sequence_elements.append(sgr_parameters[sgr_effect])\n                except KeyError:\n                    raise NotImplementedError(\n                        f\"Requested effect '{sgr_effect}' not available.\"\n                    )\n        if foreground_color is not None:\n            try:\n                sgr_sequence_elements.append(sgr_foregrounds[foreground_color])\n            except KeyError:\n                raise NotImplementedError(\n                    f\"Requested foreground color '{foreground_color}' not available.\"\n                )\n        if background_color is not None:\n            try:\n                sgr_sequence_elements.append(sgr_backgrounds[background_color])\n            except KeyError:\n                raise NotImplementedError(\n                    f\"Requested background color '{background_color}' not available.\"\n                )\n\n        # To .join() list, all elements need to be strings\n        sgr_sequence: str = \";\".join(str(sgr_code) for sgr_code in sgr_sequence_elements)\n\n        reset_all_sgr = pad_sgr_sequence()  # Without parameters: reset all attributes\n        sgr_start = pad_sgr_sequence(sgr_sequence)\n        return sgr_start + string + reset_all_sgr\n\\end{minted}\n\n\\section{MATLAB}\n\nThis section contains example code for MATLAB, for example:\n\\begin{minted}{matlab}\n    %{\n        Universal Gas Constant for SIMULINK.\n    %}\n    R_m = Simulink.Parameter;\n        R_m.Value = 8.3144598;\n        R_m.Description = 'universal gas constant';\n        R_m.DocUnits = 'J/(mol*K)';\n\\end{minted}\nOf course, floats (see \\cref{lst:matlab_class_definition}) are available as well.\nSo are longer sections, like the following.\n\n\\begin{listing}\n    \\begin{minted}{matlab}\n        classdef BasicClass\n            properties\n                Value {mustBeNumeric}\n            end\n            methods\n                function r = roundOff(obj)\n                    r = round([obj.Value],2);\n                end\n                function r = multiplyBy(obj,n)\n                    r = [obj.Value] * n;\n                end\n            end\n        end\n    \\end{minted}\n    \\caption[A class definition in MATLAB]{%\n        A class definition in MATLAB, from \\cite{mathworksCreateSimpleClass2020}%\n    }\n    \\label{lst:matlab_class_definition}\n\\end{listing}\n\n\\begin{minted}{matlab}\n    fullfilepath = mfilename('fullpath');\n    [filepath, filename, ~] = fileparts(fullfilepath);\n\n    %% Begin Dialogue\n    %{\n    Extract Data from user-specified input. Can be either a File that is run\n    (an *.m-file), variables in the Base Workspace or existing data from a\n    previous run (a *.MAT-file). All variables are expected to be in Table\n    format, which is the data type best suited for this work. Therefore, we\n    force it. No funny business with dynamically named variables or naked\n    matrices allowed.\n    %}\n    pass_data = questdlg({'Would you like to pass existing machine data?', ...\n        'Its data would be used to compute your request.', ...\n        ['Regardless, note that data is expected to be in ',...\n        'Tables named ''', dflt.comp, ''' and ''', dflt.turb, '''.'], '',...\n        'If you choose no, existing values are used.'}, ...\n        'Machine Data Prompt', btnFF, btnWS, btnNo, btnFF);\n\n    switch pass_data\n        case btnFF\n            prompt = {'File name containing the Tables:', ...\n                'Compressor Table name in that file:',...\n                'Turbine Table name in that file:'};\n            title = 'Machine Data Input';\n            dims = [1 50];\n            definput = {dflt.filename.data, dflt.comp, dflt.turb};\n            machine_data_file = inputdlg(prompt, title, dims, definput);\n            if isempty(machine_data_file)\n                fprintf('[%s] You left the dialogue and function.\\n',...\n                    datestr(now));\n                return\n            end\n            run(machine_data_file{1});%spills file contents into funcWS\n        case btnWS\n            prompt = {'Base Workspace Compressor Table name:',...\n                    'Base Workspace Turbine Table name:'};\n            title = 'Machine Data Input';\n            dims = [1 50];\n            definput = {dflt.comp, dflt.turb};\n            machine_data_ws = inputdlg(prompt, title, dims, definput);\n            if isempty(machine_data_ws)\n                fprintf('[%s] You left the dialogue and function.\\n',...\n                    datestr(now));\n                return\n            end\n        case btnNo\n            boxNo = msgbox(['Looking for stats in ''', dflt.filename.stats, ...\n                '''.'], 'Using Existing Data', 'help');\n            waitfor(boxNo);\n            try\n                stats = load(dflt.filename.stats);\n                stats = stats.stats;\n            catch ME\n                switch ME.identifier\n                    case 'MATLAB:load:couldNotReadFile'\n                        warning(['File ''', dflt.filename.stats, ''' not ',...\n                            'found in search path. Make sure it has been ',...\n                            'generated in a previous run or created ',...\n                            'manually. Resorting to hard-coded data ',...\n                            'for now.']);\n                            a_b = 200.89;\n                            x_c = 0.0012;\n                            f_g = 10.0;\n                    otherwise\n                        rethrow(ME);\n                end\n            end\n        case ''\n            fprintf('[%s] You left the dialogue and function.\\n',datestr(now));\n            return\n        otherwise%Only gets here if buttons are misconfigured\n            error('This option is not coded, should not get here.');\n    end\n\\end{minted}\n\n\\subsection{MATLAB/Simulink icons}\n\nFor an older project, MATLAB/Simulink vector icons were created.\nThey are included here at the off\\-/chance that someone else might find a use for these.\n\\begin{itemize}\n    \\item \\mtlbsmlkicon{matlab_object_box}\n    \\item \\mtlbsmlkicon{matlab_struct}\n    \\item \\mtlbsmlkicon{matlab_table}\n    \\item \\mtlbsmlkicon{simulink_algebraic_constraint}\n    \\item \\mtlbsmlkicon{simulink_base_workspace}\n    \\item \\mtlbsmlkicon{simulink_configuration}\n    \\item \\mtlbsmlkicon{simulink_data_dictionary}\n    \\item \\mtlbsmlkicon{simulink_library_model}\n    \\item \\mtlbsmlkicon{simulink_library}\n    \\item \\mtlbsmlkicon{simulink_log_data}\n    \\item \\mtlbsmlkicon{simulink_lut}\n    \\item \\mtlbsmlkicon{simulink_model_workspace}\n    \\item \\mtlbsmlkicon{simulink_model}\n    \\item \\mtlbsmlkicon{simulink_referenced_model}\n    \\item \\mtlbsmlkicon{simulink_step_block}\n\\end{itemize}\n\n\\section{Modelica}\n\nNaturally, floating and all other environments and styles are also available for\nModelica.\nThe syntax highlighting for a few basic code samples \\autocite{wikipediacontributorsModelica2021} looks like:\n\n\\begin{minted}{modelica}\n    x := 2 + y;\n    x + y = 3 * z;\n\n    model FirstOrder\n        parameter Real c=1 \"Time constant\";\n        Real x (start=10) \"An unknown\";\n    equation\n        der(x) = -c*x \"A first order differential equation\";\n    end FirstOrder;\n\n    type Voltage = Real(quantity=\"ElectricalPotential\", unit=\"V\");\n    type Current = Real(quantity=\"ElectricalCurrent\", unit=\"A\");\n\n    connector Pin \"Electrical pin\"\n        Voltage      v \"Potential at the pin\";\n        flow Current i \"Current flowing into the component\";\n    end Pin;\n\n    model Capacitor\n        parameter Capacitance C;\n        Voltage u \"Voltage drop between pin_p and pin_n\";\n        Pin pin_p, pin_n;\n    equation\n        0 = pin_p.i + pin_n.i;\n        u = pin_p.v - pin_n.v;\n        C * der(u) = pin_p.i;\n    end Capacitor;\n\n    model SignalVoltage\n        \"Generic voltage source using the input signal as source voltage\"\n        Interfaces.PositivePin p;\n        Interfaces.NegativePin n;\n        Modelica.Blocks.Interfaces.RealInput v(unit=\"V\")\n            \"Voltage between pin p and n (= p.v - n.v) as input signal\";\n        SI.Current i \"Current flowing from pin p to pin n\";\n    equation\n        v = p.v - n.v;\n        0 = p.i + n.i;\n        i = p.i;\n    end SignalVoltage;\n\n    model Circuit\n        Capacitor C1(C=1e-4) \"A Capacitor instance from the model above\";\n        Capacitor C2(C=1e-5) \"A Capacitor instance from the model above\";\n            ...\n    equation\n        connect(C1.pin_p, C2.pin_n);\n            ...\n    end Circuit;\n\\end{minted}\n\n\\section{Lua}\n\nFiles can also be read into \\LaTeX{} directly.\nFor example, the following is some current Lua code \\emph{used for this very document}:\n\\inputminted{lua}{./lib/example.lua}\n"
  },
  {
    "path": "chapters/mainmatter/floats.tex",
    "content": "\\chapter{Float Features}\n\nExamples for floats were already shown in \\cref{fig:censorbox,tab:main_font_examples}.\nThese are mainly handled by the packages:\n\\begin{description}\n    \\item[\\ctanpackage{caption}]\n        The base package providing customizations for the caption text, for example\n        automatic ending periods, which can be toggled globally.\n    \\item[\\ctanpackage{svg}]\n        Including \\abb{scalable_vector_graphics} files using \\LaTeX{}, or in this\n        case \\hologo{LuaLaTeX}, is not very straightforward.\n        In fact, it is anything but: \\abb{scalable_vector_graphics} files cannot\n        be included directly at all and intermediate steps are needed.\n\n        Using the \\ctanpackage{svg} package, the workflow is somewhat automated.\n        Only the original \\abb{scalable_vector_graphics} files are kept as the\n        \\abb{single_source_of_truth}, and the generation of the\n        \\abb{portable_document_format} and accompanying \\verb|.pdf_tex| files\n        are left to the package.\n        It calls InkScape for converting the \\abb{scalable_vector_graphics} to\n        \\abb{portable_document_format} (or another format of choice), and if the\n        \\abb{scalable_vector_graphics} contains text to be included as \\LaTeX{},\n        a sidecar \\verb|.pdf_tex| file is generated (the default behavior).\n        To call InkScape, two requirements have to be met:\n        \\begin{enumerate}\n            \\item elevation aka \\texttt{--shell-escape} is required to write\n                external files, and\n            \\item InkScape has to be on the \\verb|$PATH|, that means installed and\n                subsequently registered.\n                This is automatically done for Linux.\n                If it is not done automatically on Windows, navigate to\n                \\emph{Edit the system environment variables} and add the directory\n                containing \\texttt{inkscape.exe} to the variable.\n        \\end{enumerate}\n        Once the files are generated, they can be treated as temporary junk and are\n        always easily regenerated from the source \\abb{scalable_vector_graphics}.\n\n        After years of experimentation, this seems like the best workflow.\n        The only laborious manual task left is placement of annotations onto the\n        generated \\abb{portable_document_format} files.\n        This seems like the best deal: no text is left in the\n        \\abb{scalable_vector_graphics} files themselves.\n        Placing and debugging text in \\abb{scalable_vector_graphics} files using\n        the InkScape \\textrightarrow{} \\verb|PDF+PDF_TEX| route is \\emph{very, very}\n        annoying.\n        This is because while InkScape offers text alignment operations\n        (left, center, right) that translate into the embedded \\verb|PDF_TEX|,\n        the font cannot be known a priori while working on the\n        \\abb{scalable_vector_graphics}.\n        Neither font size (most importantly its height), nor any other font\n        property can be assumed.\n        This also makes functions like \\emph{Resize page to drawing or selection}\n        futile if text is part of the outer elements of a drawing.\n\n        Wanting to change any text later on results in having to start InkScape\n        instead of just doing it conveniently in the \\LaTeX{} source.\n        The alternative is to place macros (\\verb|\\newcommand*{}|) everywhere\n        inside the original \\abb{scalable_vector_graphics}, where content should\n        later be placed.\n        These macros serve as labels, but are ugly, annoying, and remove the\n        usability of the plain, original \\abb{scalable_vector_graphics} file\n        (since we would first need to know what each macro stands for).\n\n        Using the \\ctanpackage{svg} package to generate plain, text\\-/less\n        \\abb{portable_document_format} and only later adding any\n        text or annotation in the \\LaTeX{} source itself seems the best of both\n        worlds.\n        \\textbf{It certainly allows both tools to do what they're good at, and no more}:\n        draw free\\-/flowing vectors graphics with InkScape, then add text in\n        \\LaTeX{} (which can be done in \\verb|\\foreach| loops as well).\n        An example for annotations (with loops) is shown in \\cref{fig:bitmap_tikz}.\n        All other graphics that are neither bitmaps nor \\idx{tikz} graphics are\n        handled using the \\ctanpackage{svg} approach.\n\n        All of this is very convenient indeed, since we can now do everything in\n        \\LaTeX{} and \\ctanpackage{tikz} and basically never have to revisit the base\n        \\abb{scalable_vector_graphics} file, unless the graphic itself changes.\n        All the labels stay in the \\LaTeX{} source and are therefore also manageable\n        through \\texttt{git}.\n    \\item[\\ctanpackage{floatrow}]\n        A notable feature is the capability for captions the same width as the\n        float they are attached to.\n        This tends to look much tighter and tidier, see\n        \\cref{fig:wide_caption,fig:tighter_caption} for a comparison.\n\n        Other features are automatic centering of floats, automatic positioning\n        of captions (tables on top, figures below, independent of where the\n        \\verb|\\caption| command occurs in the source), multiple floats and\n        captions on the side.\n        Depending on the aspect ratio of the image, positioning the caption besides\n        the figure can look (subjectively) pretty, see \\cref{fig:sidecap}.\n\\end{description}\n\n\\begin{figure}\\ContinuedFloat*% Floats can be \"continued\" across pages like this\n    % Conventional figure-syntax\n    \\includesvg[width=0.4\\textwidth]{compressor_impeller_isometric}%\n    \\caption{%\n        Example for a regular caption,\n        spanning the whole width since it is so long.\n        This can quickly look strange, especially if the figure itself is narrow%\n    }%\n    \\label{fig:wide_caption}%\n\\end{figure}\n\n\\begin{figure}\\ContinuedFloat\n    % Optional argument \\FBwidth causes graphic to be its actual size and caption\n    % to take up the remaining space. Otherwise, horizontal space is split 50/50,\n    % which doesn't make much sense.\n    \\ffigbox[\\FBwidth]{%\n        \\caption{\n            Example for a new caption, spanning just the width of the float\n            it is attached to, despite the caption being much longer than the\n            float is wide%\n        }%\n        \\label{fig:tighter_caption}%\n    }{%\n        \\includesvg[width=0.4\\textwidth]{compressor_impeller_isometric}%\n    }%\n\\end{figure}\n\n\\subsubsection{Multiple floats}\n\nOther possibilities are rather arbitrary arrangements of sub\\-/figures and -captions.\nFor this, see \\cref{fig:multiple_floats}, which contains the two sub\\-/figures\n\\cref{fig:multiple_floats_one,fig:multiple_floats_two}.\nMultiple sub\\-/tables are also possible, see \\cref{tab:multiple_tables} with its four\nsub\\-/tables\n\\cref{tab:multiple_tables_one,tab:multiple_tables_two,tab:multiple_tables_three,tab:multiple_tables_four}.\n\n\\begin{figure}\n    \\ffigbox[\\FBwidth]{%\n        \\begin{subfloatrow}[2]% Default is 2\n            \\ffigbox[\\FBwidth]{%\n                \\includesvg[width=0.4\\textwidth]{rotor_tip_clearance}\n            }{%\n                \\caption{An example}%\n                \\label{fig:multiple_floats_one}%\n            }%\n            \\ffigbox[\\FBwidth]{%\n                \\includesvg[width=0.4\\textwidth]{gas_volume}\n            }{%\n                \\caption{Another example}%\n                \\label{fig:multiple_floats_two}%\n            }%\n        \\end{subfloatrow}\n    }{%\n        \\caption{%\n            An example for sub\\-/figures%\n        }%\n        \\label{fig:multiple_floats}%\n        \\floatfoot{%\n            This field can be used for a reference to a source:\n            \\adaptedfrom{} wherever%\n        }%\n    }%\n\\end{figure}\n\n\\begin{table}\n    \\small\n    \\floatbox{table}{\n        %https://tex.stackexchange.com/q/295567/120853\n        \\begin{subfloatrow}\n            \\ttabbox[\\FBwidth]{%\n                \\begin{tabular}{\n                    @{}\n                    m{0.25\\textwidth}\n                    m{0.15\\textwidth}\n                    @{}\n                }\n                    \\toprule\n                        Column One & Column Two\\\\\n                    \\midrule\n                        Just & a \\\\\n                        normal & table\\\\\n                        Nothing & special.\\\\\n                    \\bottomrule\n                \\end{tabular}\n            }{%\n                \\caption{Table One}%\n                \\label{tab:multiple_tables_one}%\n            }%\n            %\n            \\ttabbox[\\FBwidth]{%\n                \\begin{tabular}{\n                    @{}\n                    m{0.25\\textwidth}\n                    m{0.15\\textwidth}\n                    @{}\n                }\n                    \\toprule\n                        Column One & Column Two\\\\\n                    \\midrule\n                        Just & a \\\\\n                        normal & table\\\\\n                        Nothing & special.\\\\\n                    \\bottomrule\n                \\end{tabular}\n            }{%\n                \\caption{Table Two}%\n                \\label{tab:multiple_tables_two}%\n            }%\n            %\n        \\end{subfloatrow}\n        \\vspace{1.5\\baselineskip}%\n\n        \\begin{subfloatrow}\n            \\ttabbox[\\FBwidth]{%\n                \\begin{tabular}{\n                    @{}\n                    m{0.25\\textwidth}\n                    m{0.15\\textwidth}\n                    @{}\n                }\n                    \\toprule\n                        Column One & Column Two\\\\\n                    \\midrule\n                        Just & a \\\\\n                        normal & table\\\\\n                        Nothing & special.\\\\\n                    \\bottomrule\n                \\end{tabular}\n            }{%\n                \\caption{Table Three}%\n                \\label{tab:multiple_tables_three}%\n            }%\n            %\n            \\ttabbox[\\FBwidth]{%\n                \\begin{tabular}{\n                    @{}\n                    m{0.25\\textwidth}\n                    m{0.15\\textwidth}\n                    @{}\n                }\n                    \\toprule\n                        Column One & Column Two\\\\\n                    \\midrule\n                        Just & a \\\\\n                        normal & table\\\\\n                        Nothing & special.\\\\\n                    \\bottomrule\n                \\end{tabular}\n            }{%\n                \\caption{Table Four}%\n                \\label{tab:multiple_tables_four}%\n            }%\n            %\n        \\end{subfloatrow}\n    }{%\n        \\caption{%\n            Example for multiple tables in one float%\n        }%\n        \\label{tab:multiple_tables}%\n    }%\n\\end{table}\n\n\\subsubsection{Side-Captions}\n\nOccasionally, figures and their captions can look disproportionate in combination.\nIn these cases, placing a side\\-/caption might relieve the situation,\nas shown in \\cref{fig:sidecap}.\n\\begin{figure}\n    \\fcapside[\\FBwidth]{%\n        \\caption{%\n            A side caption, which may also span multiple lines like demonstrated\n            in this rather long caption right here%\n        }\n        \\label{fig:sidecap}%\n    }{%\n        \\includesvg[width=0.6\\textwidth]{compressor_rotating_stall}%\n    }%\n\\end{figure}\n\n\\subsubsection{Large Floats}\n\nAn example for a larger table is shown in \\cref{tab:fuel_composition}.\nOne key aspect there: the \\verb|S| column\\-/type, provided by \\ctanpackage{siunitx}.\nIt automatically applies \\verb|\\num| to each cell, which in turn allows easy\nprinting of things like: \\num{-3.23e-5}.\nFurther, decimal places are accounted for and aligned by automatically.\nUse \\verb|*x{y}| to print column-type \\verb|y| (\\iecfeg{i.e.}\\ \\verb|c|) \\verb|x|\ntimes.\nNo need for tedious repetition.\n\n\\begin{landscape}\n    \\begin{table}\n        \\crefname{equation}{eq.}{eqs.}% Keep this change scoped to the environment\n        \\Crefname{equation}{Eq.}{Eqs.}%\n        \\footnotesize%\n        \\ttabbox{%\n            \\caption{%\n                Compositions and properties of fuels, as used in \\Cref{eq:tikz_in_text}%\n            }%\n            \\label{tab:fuel_composition}%\n        }{%\n            \\begin{tabular}{\n                @{}\n                p{5em}\n                *7{S[table-format=1.4]}\n                S[table-format=4.0]\n                S[table-format=2.1]\n                @{}\n            }\n                \\toprule\n                    Name &\n                        \\multicolumn{7}{c}{{Mass fraction \\(\\sym{mass_fraction}\\)}} &\n                        {\\(\\sym{density}\\)} &\n                        {\\(\\sym{heating_value}\\)}\n                    \\\\\n                    &\n                        \\multicolumn{7}{c}{{[--]}} &\n                        \\(\\brackets*{\\unit{\\kilogram\\per\\meter\\cubed}}\\) &\n                        \\(\\brackets*{\\unit{\\mega\\joule\\per\\kilogram}}\\)\n                    \\\\\n                \\cmidrule(lr){2-8}% truncate left and right\n                    &\n                        \\chcpd{C} &\n                        \\chcpd{H} &\n                        \\chcpd{S} &\n                        \\chcpd{O} &\n                        \\chcpd{N} &\n                        \\chcpd{H2O} &\n                        {Ash} & % Escape text from S-column using braces\n                        &\n                    \\\\\n                \\midrule\n                    Diesel\\mpfootnotemark[1] &\n                        0.8600 &\n                        0.1320 &\n                        0.0060 &\n                        \\multicolumn{2}{c}{\\num{0.0020}\\mpfootnotemark[2]} &\n                        {n.a.} &\n                        {n.a.} &\n                        840 &\n                        42.7\n                    \\\\\n                    Oil EL\\mpfootnotemark[1] &\n                        0.8570 &\n                        0.1310 &\n                        0.0100 &\n                        \\multicolumn{2}{c}{\\num{0.0020}\\mpfootnotemark[2]} &\n                        {n.a.} &\n                        {n.a.} &\n                        840 &\n                        42.7\n                    \\\\\n                    Oil H\\mpfootnotemark[1] &\n                        0.8490 &\n                        0.1060 &\n                        0.0350 &\n                        \\multicolumn{2}{c}{\\num{0.0100}\\mpfootnotemark[2]} &\n                        {n.a.} &\n                        {n.a.} &\n                        980 &\n                        40.0\n                    \\\\\n                    \\abb{marine_diesel_oil}\\mpfootnotemark[3] &\n                        {n.a.} &\n                        {n.a.} &\n                        0.0150 &\n                        {n.a.} &\n                        {n.a.} &\n                        {\\num{0.0030}\\mpfootnotemark[4]} &\n                        0.0001 &\n                        900 &\n                        {n.a.}\n                    \\\\\n                    \\abb{heavy_fuel_oil}\\mpfootnotemark[5] &\n                        {n.a.} &\n                        {n.a.} &\n                        {\\num{0.0350}\\mpfootnotemark[6]} &\n                        {n.a.} &\n                        {n.a.} &\n                        {\\num{0.0050}\\mpfootnotemark[4]} &\n                        0.0015 &\n                        1010 &\n                        {n.a.}\n                    \\\\\n                \\addlinespace\n                    Light\\mpfootnotemark[7] &\n                        0.8600 &\n                        0.1320 &\n                        0.0060 &\n                        0.0010 &\n                        0.0010 &\n                        0 &\n                        0 &\n                        840 &\n                        {\\Cref{eq:boie}}\n                    \\\\\n                    Medium\\mpfootnotemark[7] &\n                        0.8530 &\n                        0.1269 &\n                        0.0150 &\n                        0.0010 &\n                        0.0010 &\n                        0.0030 &\n                        0.0001 &\n                        900 &\n                        {\\Cref{eq:boie}}\n                    \\\\\n                    Heavy\\mpfootnotemark[7] &\n                        0.8460 &\n                        0.1025 &\n                        0.0350 &\n                        0.0050 &\n                        0.0050 &\n                        0.0050 &\n                        0.0015 &\n                        1010 &\n                        {\\Cref{eq:boie}}\n                    \\\\\n                \\bottomrule\n            \\end{tabular}%\n            % Unfortunately, these have to be numbered manually.\n            % Float/table footnotes are a touchy topic, and this was chosen as the\n            % least worst approach out of the alternatives.\n            \\footnotetext[1]{%\n                \\cite[634]{baehrThermodynamikGrundlagenUnd2016}; see also\n                \\cite[L70]{dubbelTaschenbuchFurMaschinenbau2007} and\n                \\cite[97]{mollenhauerHandbuchDieselmotoren2007}.%\n            }%\n            \\footnotetext[2]{%\n                Given as a sum\n                \\(\\sym{mass_fraction}_{\\chcpd{O}} + \\sym{mass_fraction}_{\\chcpd{N}}\\).%\n            }%\n            \\footnotetext[3]{%\n                Max.\\ values of specification \\emph{DMB},\n                \\cite{internationalorganizationforstandardizationISO821720172017}.%\n            }%\n            \\footnotetext[4]{%\n                Given as a volume fraction, assumed equal to mass fraction.%\n            }%\n            \\footnotetext[5]{%\n                Max.\\ values of specification \\emph{RMK},\n                \\cite{internationalorganizationforstandardizationISO821720172017}.%\n            }%\n            \\footnotetext[6]{%\n                \\abb{int_mar_org} level prior to \\num{2020}.%\n            }%\n            \\footnotetext[7]{%\n                Derived, \\emph{virtual} fuels.%\n            }%\n        }%\n    \\end{table}%\n\\end{landscape}\n\n\\paragraph{Very long tables}\n\nSee \\cref{tab:random_long} in \\cref{ch:appendix_table} for an example of a very large table (which does not float).\n\n\\subsubsection{Table Style}\n\nIn general, use the least ink possible to get your point across.\nAny more is only noise.\nThis is especially true for tables.\nFor this, compare \\cref{tab:main_font_examples} to its not\\-/so\\-/blessed\ntwin, \\cref{tab:main_font_examples_ugly}:\n\\begin{itemize}\n    \\item do not use vertical lines in tables,\n    \\item avoid double lines,\n    \\item if in doubt, left-align.\n        If there is no actual reason to center or right\\-/align, refrain from it.\n        Of course, if your language flows right\\-/to\\-/left, like Arabic or Hebrew,\n        this advice is reversed.\n\\end{itemize}\nFor more info, see the package \\ctanpackage{booktabs}.\n\n\\begin{table}\n    \\ttabbox{%\n        \\caption{%\n            Dreadful version of \\cref{tab:main_font_examples}%\n        }%\n        \\label{tab:main_font_examples_ugly}%\n    }{%\n        \\begin{tabular}{\n            |\n            c\n            ||\n            c\n            |\n        }\n        \\hline\n            \\textit{Feature} & \\textit{Sample Text}\\\\\n        \\hline\n        \\hline\n            Regular & \\sampletext\\\\\n        \\hline\n            \\textbf{Bold} & \\textbf{\\sampletext}\\\\\n        \\hline\n            \\textit{Italics} & \\textit{\\sampletext}\\\\\n        \\hline\n            \\textbf{\\textit{Bold Italics}} & \\textbf{\\textit{\\sampletext}}\\\\\n        \\hline\n            \\textsc{Small Capitals} & \\textsc{\\sampletext}\\\\\n        \\hline\n            \\textbf{\\textsc{Bold SC}} & \\textbf{\\textsc{\\sampletext}}\\\\\n        \\hline\n            \\textit{\\textsc{Italics SC}} & \\textit{\\textsc{\\sampletext}}\\\\\n        \\hline\n        \\end{tabular}\n    }%\n\\end{table}\n\n\\subsubsection{Caption Positioning}\n\nNote that table captions (see for example \\cref{tab:multiple_tables}) occur\n\\emph{above} the table no matter the \\verb|\\caption| command's position in\nthe source code.\nPer convention, figure captions should appear below, table captions above their bodies.\nThis is handled automatically by \\ctanpackage{floatrow}.\nAlso note that there is neither a period nor \\emph{any} character\n(no space, no empty line) behind the last caption line in the source code,\nsince those periods are managed globally by the \\ctanpackage{caption} package.\nThey can therefore be toggled easily.\n\n\\paragraph{Float Footer}\nThere is also a \\verb|\\floatfoot| command for all floats.\nThis is used to place additional info underneath the caption, for example for\nreferences, \\iecfeg{cf.}\\ \\cref{fig:multiple_floats}.\n\n\\section{TikZ and pgfplots}\nPackages \\ctanpackage{tikz} and \\ctanpackage{pgfplots} offer a vast array of features.\nA select few are presented here.\n\n\\subsection{Drawing over Bitmaps}\n\nWhen having to rely on bitmaps, one might still want to add additional info.\nThis can be done directly in \\LaTeX{}, profiting from all the usual features.\nIn the example here, this is of course the retaining of the text font, but also\nemploying the useful \\ctanpackage{contour} package to draw legible black\\-/on\\-/white\n(or vice\\-/versa) text.\nAn example is shown in \\cref{fig:bitmap_tikz}.\nThere is a debugging grid functionality to allow for easier positioning of the labels\non the graphic.\n\\cref{fig:bitmap_tikz} also showcases a vertical alignment of sub\\-/figures.\n\n\\begin{figure}\n    \\ffigbox[\\FBwidth]{%\n        \\begin{subfloatrow}\n        \\hsize1\\textwidth\n        \\vbox{\n            \\ffigbox[\\FBwidth]{\n                \\begin{tikzpicture}[%\n                    every node/.style={\n                        font=\\footnotesize\n                    }\n                ]\n                    \\node[anchor=south west,inner sep=0] (image) at (0,0) {\n                        \\includegraphics[width=0.7\\textwidth]{field}\n                    };\n                    \\begin{scope}[x={(image.south east)},y={(image.north west)}]\n\n                        % All floating descriptions:\n                        \\foreach \\x/\\y/\\nodetext in {\n                            0.50/0.20/{A field!},\n                            0.50/0.70/{The sky!}%\n                        }{\n                            \\node at (\\x,\\y) {\\ctrw{\\nodetext}};\n                        }\n\n                        % \\ctrw{} cannot deal with linebreaks contained inside of it,\n                        % so it has to be applied manually each time.\n                        \\node[align=left, right] at (0.02, 0.50) {%\n                            \\ctrw{Multiple lines}\\\\%\n                            \\ctrw{with manual}\\\\%\n                            \\ctrw{linebreaks!}%\n                        };%\n\n                        \\draw[annotationarrow] (0.75,0.45) -- (1.05,0.50)\n                            node[align=left, right, text width=5em] {An annotation!};\n\n                        % DEBUGGING COMMAND\n                        \\debugtikzsvg\n                    \\end{scope}\n                \\end{tikzpicture}\n            }{\n                \\caption{Debugging/positioning grid}\n                \\label{fig:bitmap_tikz_debug}\n            }%\n            \\vss\n            \\vspace{3ex}\n\n            \\ffigbox[\\FBwidth]{\n                \\begin{tikzpicture}[%\n                    every node/.style={\n                        font=\\footnotesize\n                    }\n                ]\n                    \\node[anchor=south west,inner sep=0] (image) at (0,0) {\n                        \\includegraphics[width=0.7\\textwidth]{field}\n                    };\n                    \\begin{scope}[x={(image.south east)},y={(image.north west)}]\n\n                        % All floating descriptions:\n                        \\foreach \\x/\\y/\\nodetext in {\n                            0.50/0.20/{A field!},\n                            0.50/0.70/{The sky!}%\n                        }{\n                            \\node at (\\x,\\y) {\\ctrw{\\nodetext}};\n                        }\n\n                        % \\ctrw{} cannot deal with linebreaks contained inside of it,\n                        % so it has to be applied manually each time.\n                        \\node[align=left, right] at (0.02, 0.50) {%\n                            \\ctrw{Multiple lines}\\\\%\n                            \\ctrw{with manual}\\\\%\n                            \\ctrw{linebreaks!}%\n                        };%\n\n                        \\draw[annotationarrow] (0.75,0.45) -- (1.05,0.50)\n                            node[align=left, right, text width=5em] {An annotation!};\n\n                        % DEBUGGING COMMAND\n                        % \\debugtikzsvg\n                    \\end{scope}\n                \\end{tikzpicture}\n            }{\n                \\caption{Result}\n                \\label{fig:bitmap_tikz_result}\n            }\n        }\n        \\end{subfloatrow}\n    }{%\n        \\caption{%\n            Drawing over a bitmap graphic using \\idx{tikz} in a vertical sub\\-/figure\n            environment%\n        }\n        \\label{fig:bitmap_tikz}\n    }\n\\end{figure}\n\n\\subsection{Trees}\n\nDrawing trees is possible with \\ctanpackage{forest}, see \\cref{fig:tree}.\nIt is a very easy package to get started with.\nTake a look at the source code.\nIt is deceivingly simple, but also highly customizable.\nNote that the package is stand\\-/alone, but uses \\idx{tikz} under the hood\n(like a lot of packages do).\n\\begin{figure}\n    \\ffigbox[\\textwidth]{% forest does not work with \\FBwidth (?)\n        \\caption{Example for a tree}\n        \\label{fig:tree}\n    }{\n        \\footnotesize\n        \\begin{forest}\n            forked edges,% Instead of direct connections, draw edges\n            for tree={%\n                    grow'=east,\n                    anchor=west,\n                    where level=0{}{calign=first},% works like {if}{else}\n                    %\n                    % Put all nodes of same level onto same tier also, aligning\n                    % them vertically:\n                    tier/.pgfmath=level(),\n                    %\n                    where level=1{font={\\bfseries}}{},%\n                },%\n            % Decrease distance to only affect root-first level with s sep, see\n            % https://tex.stackexchange.com/a/188461/120853\n            [Overall Category, anchor=south, rotate=90, for children={s sep-=1em}\n                [Number One\n                    [At vero eos]\n                    [et accusamus]\n                    [et iusto]\n                ]\n                [Number Two\n                    [{odio dignissimos, ducimus}]% Escape commas\n                    [qui blanditiis]\n                    [praesentium]\n                    [voluptatum]\n                    [deleniti atque]\n                    [corrupti quos]\n                    [dolores et]\n                    [quas molestias]\n                ]\n                [Number Three\n                    [excepturi sint]\n                    [occaecati]\n                    [non provident]\n                    [similique]\n                    [sunt in culpa qui officia]\n                ]\n                [Number Four\n                    [deserunt]\n                    [mollitia\n                            [{animi, id est}]\n                            [laborum et]\n                    ]\n                ]\n                [Number Four\n                    [dolorum\n                        [fuga]\n                        [Et harum]\n                    ]\n                    [quidem\n                        [rerum facilis]\n                        [est et expedita]\n                    ]\n                ]\n                [distinctio\n                    [Nam libero]\n                    [tempore]\n                    [soluta nobis]\n                    [est eligendi]\n                ]\n            ]\n        \\end{forest}\n    }\n\\end{figure}\n\n\\subsection{Flow charts}\n\nDrawing flow charts is possible with \\idx{tikz} as well.\nAn example can be found in \\cref{fig:flowchart_example}.\nThe style definitions for the nodes can be found in the class file.\n\n\\begin{figure}\n    \\ffigbox[\\FBwidth]{\n        \\caption{Example for a Flowchart}\n        \\label{fig:flowchart_example}\n    }{%\n        \\footnotesize\n        \\begin{tikzpicture}[node distance=1cm]\n\n            \\node (start) [startstop] {Start};\n            \\node (in1) [io, below=of start] {Input};\n            \\node (pro1) [process, below=of in1] {Process 1};\n            \\node (dec1) [decision, below=of pro1] {Decision 1};\n            \\node (pro2a) [process, below=of dec1] {Process 2a text text text text text text text text text text};\n            \\node (pro2b) [process, right=of dec1] {Process 2b};\n            \\node (out1) [io, below=of pro2a] {Output};\n            \\node (stop) [startstop, below=of out1] {Stop};\n\n            \\draw [arrow] (start) -- (in1);\n            \\draw [arrow] (in1) -- (pro1);\n            \\draw [arrow] (pro1) -- (dec1);\n            \\draw [arrow] (pro1.west) -| ++(-0.5,0) node[anchor=east] {Maybe} |- (pro2a.west);\n            \\draw [arrow] (dec1) -- node[anchor=east] {yes} (pro2a);\n            \\draw [arrow] (dec1) -- node[anchor=south] {no} (pro2b);\n            \\draw [arrow] (pro2b) |- (pro1);\n            \\draw [arrow] (pro2a) -- (out1);\n            \\draw [arrow] (out1) -- (stop);\n\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\subsection{Plotting}\n\nIf you rely on tools like \\texttt{matlab2tikz}, this is for you.\nInstead of these outside tools, one can plot \\emph{directly} in \\LaTeX{}, either\nthrough importing external \\texttt{*.csv} data (for example from experiments)\nor through computing the plots using \\ctanpackage{pgfplots} directly from within\n\\LaTeX{}.\n\n\\subsubsection{Directly in \\LaTeX{}}\nPlotting and computing the return values directly in \\LaTeX{} is achieved through\nthe \\texttt{declare function} command.\nWhile the functionality is limited (owed to the limitations of \\TeX{}, which is\nof course not meant for this sort of thing),\nit may still save a lot of time and headaches.\nFinding and specifying the correct settings for \\ctanpackage{pgfplots} can take\na lot of time.\nThis is already taken care of for this document.\nAs such, a plot from existing \\texttt{*.csv} data can be set up in a handful of\nlines using one of the built-in styles, like \\texttt{regularplot}.\nPlotting from a \\idx{tikz} function is demonstrated in\n\\cref{fig:plotting_in_latex,fig:plotting_in_latex_tufte}.\n\n\\tikzset{\n    declare function={% https://tex.stackexchange.com/a/279234/120853\n        % SHOMATE equation for air w/ N2/O2/Ar/CO2.\n        % This is needlessly complex and verbose, but showcases some interesting\n        % features, like conditionals for piecewise functions.\n        cpm(\\x)=%\n            (\\x<=500) *% Below 500 degC\n                (\n                    0.781 *% N2\n                    (\n                        28.98641+1.853978*((\\x+273.15)/1000)\n                        -\n                        9.647459*((\\x+273.15)/1000)^2\n                        +\n                        16.63537*((\\x+273.15)/1000)^3\n                        +\n                        0.000117/(((\\x+273.15)/1000)^2)\n                    )\n                    +\n                    0.2093 *% O2\n                    (\n                        31.32234-20.23531*((\\x+273.15)/1000)\n                        +\n                        57.86644*((\\x+273.15)/1000)^2\n                        -\n                        36.50624*((\\x+273.15)/1000)^3\n                        -\n                        0.007374/((\\x+273.15)/1000)^2\n                    )\n                    +\n                    0.0093 *% Ar\n                    (\n                        20.78600+2.825911e-7*((\\x+273.15)/1000)\n                        -\n                        1.464191e-7*((\\x+273.15)/1000)^2\n                        +\n                        1.092131e-8*((\\x+273.15)/1000)^3\n                        -\n                        3.661371e-8/((\\x+273.15)/1000)^2\n                    )\n                    +\n                    0.0004 *% CO2\n                    (\n                        24.99735+55.18696*((\\x+273.15)/1000)\n                        -\n                        33.69137*((\\x+273.15)/1000)^2\n                        +\n                        7.948387*((\\x+273.15)/1000)^3\n                        -\n                        0.136638/((\\x+273.15)/1000)^2\n                    )\n                )\n            +\n            (\\x>500) *% Above 500 degC\n                (\n                    0.781 *% N2\n                    (\n                        19.50583+19.88705*((\\x+273.15)/1000)\n                        -\n                        8.598535*((\\x+273.15)/1000)^2\n                        +\n                        1.369784*((\\x+273.15)/1000)^3\n                        +\n                        0.527691/(((\\x+273.15)/1000)^2)\n                    )\n                    +\n                    0.2093 *% O2\n                    (\n                        31.32234-20.23531*((\\x+273.15)/1000)\n                        +\n                        57.86644*((\\x+273.15)/1000)^2\n                        -\n                        36.50624*((\\x+273.15)/1000)^3\n                        -\n                        0.007374/((\\x+273.15)/1000)^2\n                    )\n                    +\n                    0.0093 *% Ar\n                    (\n                        20.78600+2.825911e-7*((\\x+273.15)/1000)\n                        -\n                        1.464191e-7*((\\x+273.15)/1000)^2\n                        +\n                        1.092131e-8*((\\x+273.15)/1000)^3\n                        -\n                        3.661371e-8/((\\x+273.15)/1000)^2\n                    )\n                    +\n                    0.0004 *% CO2\n                    (\n                        24.99735+55.18696*((\\x+273.15)/1000)\n                        -\n                        33.69137*((\\x+273.15)/1000)^2\n                        +\n                        7.948387*((\\x+273.15)/1000)^3\n                        -\n                        0.136638/((\\x+273.15)/1000)^2\n                    )\n                );\n    }%\n}\n\n\\begin{figure}\\ContinuedFloat*\n    \\ffigbox[\\FBwidth]{%\n        \\caption[Caloric parameters of air]{%\n            Caloric parameters of air.\n            \\textbf{Avoid legends} and put info where it belongs,\n            improving legibility (less back-and-forth for the eye).\n            This plot is using the custom \\texttt{regularplot} style%\n        }%\n        \\label{fig:plotting_in_latex}%\n    }{%\n        \\begin{tikzpicture}\n            \\begin{axis}[%\n                regularplot,%\n                axis y line*=right,%\n                axis x line=none,%\n                grid=none,% Grid can only be on one side\n                % Using \\ensuremath{} for each symbol, no need to use math mode here\n                ylabel={\\sym{ratio_of_specific_heats}},\n                y unit={-},\n            ]\n                \\addplot+[domain=20:400]{cpm(x)/(cpm(x)-8.3145)}\n                    node [arrowlabel=0.3, sloped]\n                        {\\sym{ratio_of_specific_heats}};\n            \\end{axis}\n            \\begin{axis}[% https://tex.stackexchange.com/a/31504/120853\n                regularplot,%\n                xlabel={\\sym{celsius_temperature}},%\n                x unit={\\degreeCelsius},% This is a siunitx-accepted command\n                ylabel={\\(\\symspec{heat_capacity}_{\\sym{pressure}}\\)},\n                y unit={\\joule\\per\\kilogram\\per\\kelvin},\n                cycle list shift=1,\n            ]\n                \\addplot+[domain=20:400]{cpm(x)/0.0289524}\n                    node [arrowlabel=0.3, sloped]\n                        {\\(\\symspec{heat_capacity}_{\\sym{pressure}}\\)};%\n            \\end{axis}\n        \\end{tikzpicture}\n    }%\n\\end{figure}\n\n\\begin{figure}\\ContinuedFloat\n    \\ffigbox[\\FBwidth]{%\n        \\caption[Tufte-like plot]{%\n            Same content as \\cref{fig:plotting_in_latex} in\n            \\enquote{\\emph{\\glsentryname{name.edward_tufte}}-like}\n            for a modern, minimalist look where precision counts less than\n            the overall message.\n            For more info, refer to its namesake, \\name{edward_tufte}%\n        }%\n        \\label{fig:plotting_in_latex_tufte}\n    }{%\n        \\begin{tikzpicture}\n            \\begin{axis}[%\n                tuftelike,%\n                ylabel={\\(\\symspec{heat_capacity}_{\\sym{pressure}}\\)},\n                y unit = {\\joule\\per\\kilogram\\per\\kelvin},\n                xlabel={\\sym{celsius_temperature}},%\n                x unit = {\\degreeCelsius},\n                domain=50:400,\n                ymin=1000,\n                ymax=1100,\n                ytick={1000, 1050, 1100},% Specify manually due to weird rounding\n            ]\n                \\addplot+{cpm(x)/0.0289524}\n                    node [arrowlabel=0.3, sloped]\n                        {\\(\\symspec{heat_capacity}_{\\sym{pressure}}\\)};%\n            \\end{axis}%\n            \\begin{axis}[% https://tex.stackexchange.com/a/31504/120853\n                tuftelike,%\n                axis y line*=right,%\n                axis x line=none,%\n                ylabel={\\sym{ratio_of_specific_heats}},%\n                y unit={-},\n                cycle list shift=1,\n                domain= 50:400,\n                ymin=1.35,\n                ymax=1.4,\n            ]\n                \\addplot+{cpm(x)/(cpm(x)-8.3145)}\n                    node [arrowlabel=0.3, sloped]\n                        {\\sym{ratio_of_specific_heats}};\n            \\end{axis}\n        \\end{tikzpicture}\n    }%\n\\end{figure}\n\n\\paragraph{Contour Plots}\nContour plots are too much to handle for \\ctanpackage{pgfplots} itself.\nThis is owed to the limitations of the underlying \\TeX{} engine.\nWhat the math and computation engine of \\ctanpackage{pgfplots} does is amazing,\nbut in the end, \\TeX{} is a typesetting system, not a general\\-/purpose programming\nlanguage.\nHowever, \\ctanpackage{pgfplots} has an option to delegate computations to the\nexternal \\texttt{gnuplot} tool.\nIn analogy to \\ctanpackage{svg}, using it requires \\texttt{gnuplot} itself to be\ninstalled and on the \\verb|$PATH|.\n\\Cref{fig:mollier_diagram} shows an example for a plot entirely specified in the\n\\LaTeX{} source.\nAll the functions required are defined using \\ctanpackage{pgfplots} functionalities!\n\\enquote{Only} the computation itself is outsourced to \\texttt{gnuplot}.\nThe resulting plot is two\\-/dimensional, but the underlying logic is\nthree\\-/dimensional, where one dimension was reduced, forming contours.\nThis is where the complexity resides.\nThe entire plot is just 200 lines of code, with really only half that being\nlines that effectively do something useful.\n\n\\begin{figure}\n    \\ffigbox[\\textwidth]{\n        \\caption[%\n            \\glsfmtname{name.richard_mollier} diagram for humid air as an example\n            for \\texttt{gnuplot}%\n        ]{%\n            \\name{richard_mollier} diagram for humid air as an example\n            for \\texttt{gnuplot}.\n            The entire source code required (functions \\iecfeg{etc.}) is in the\n            \\LaTeX{} source%\n        }\n        \\label{fig:mollier_diagram}\n    }{\n        \\begin{tikzpicture}\n            % Moving the grid lines behind our annotation nodes.\n            % Else, the grid is drawn over the annotation text, which looks terrible.\n            % The layer set has to be called with 'set layers' later on.\n            % Code 'borrowed' from https://tex.stackexchange.com/a/456905/120853\n            \\pgfplotsset{\n                /pgfplots/layers/Bowpark/.define layer set={\n                    axis background,axis grid,main,axis ticks,axis lines,axis tick labels,\n                    axis descriptions,axis foreground\n                }{/pgfplots/layers/standard},\n            }\n            \\begin{axis}[\n                regularplot,\n                %\n                width=0.95\\textwidth,\n                height=0.4\\textheight,\n                %\n                set layers=Bowpark,\n                %\n                every axis title/.append style={%\n                    at={(0.5,1.1)},% Move above legend\n                    anchor=south,%\n                    font=\\footnotesize%\n                },\n                %\n                xlabel={\\glsdesc{sym.moisture_content}},\n                x unit={\\glsunit{sym.moisture_content}},\n                ylabel={Temperature},\n                y unit={\\degreeCelsius},\n                %\n                % Not displayed when viewing contour plot (view={0}{90}),\n                % but maybe useful for debugging when viewing the 3d surface plot\n                % at an angle\n                zlabel={\\glsdesc{sym.relative_humidity}},\n                z unit={--},\n                %\n                title={% Print title depending on what ambient pressure was specified down below\n                    \\pgfkeys{/pgf/fpu=true}% https://tex.stackexchange.com/a/36189/120853\n                    \\pgfkeys{/pgf/fpu/output format=fixed}\n                    \\pgfmathparse{AmbientPressure/1e5}\n                    %\n                    For \\qty[round-mode=figures, round-precision=1]{\\pgfmathresult}{\\bar}\n                    air pressure.%\n                    %\n                    \\pgfkeys{/pgf/fpu=false}\n                },\n                %\n                variable=MoistureContent,% New name for default 'x' variable for unambiguity\n                variable y=Temperature,% New name for default 'y' variable for unambiguity\n                domain=0:20,% Moisture content range in g per kg\n                domain y=-5:30,% Temperature range in degC\n                %\n                % Name space using 'contour/' to apply to all contour plots:\n                contour/contour label style={\n                    every node/.append style={text=black}\n                },\n                %\n                % Default is 70pt. High value pushes them off to one side (HACKY;\n                % see https://tex.stackexchange.com/q/443508/120853 and\n                % https://tex.stackexchange.com/q/88031/120853)\n                contour/label distance=10*70pt,\n                %\n                % point meta settings are not required for contour plotting.\n                % point meta min=0,% Starting z value for color map scale\n                % point meta max=1,% Ending z value for color map scale\n                %\n                view={0}{90},% View contour plot 'from above'\n                % view={90}{0},% Debugging\n                % view={0}{0},% Debugging\n                %\n                declare function={%\n                    % No empty lines allowed in here.\n                    % All equations for constant material constants like c_p.\n                    %\n                    AmbientPressure = 1e5;% Ambient, overall air pressure in Pascal\n                    %\n                    Buck(\\Temperature) =\n                        % Units: T in degC, Water Vapour Pressure result according\n                        % to Buck in Pascal\n                        611.21 * exp(\n                            (18.678 - (\\Temperature / 234.5) )\n                            *\n                            (\\Temperature / (\\Temperature + 257.14) )\n                        );\n                    %\n                    Relative_Humidity(\\MoistureContent,\\Temperature) =\n                        % Relative humidity phi as a fraction 0..1, with\n                        % T (temperature) in degC and x (moisture content) in g/kg\n                        AmbientPressure\n                        *\n                        \\MoistureContent\n                        /\n                        (\n                            1000 * (\n                                Buck(\\Temperature)\n                                *\n                                (\\MoistureContent/1000 + 0.622)\n                            )\n                    );\n                    %\n                    Saturation_Moisture_Content(\\Temperature) =\n                        % Moisture content at saturation (phi = 1), with T in degC\n                        0.622\n                        *\n                        Buck(\\Temperature)\n                        /\n                        (\n                            AmbientPressure - Buck(\\Temperature)\n                    );\n                    %\n                    Dry_Air_Enthalpy(\\MoistureContent,\\Temperature) =\n                        % Enthalpy of dry air with conditional expressions, so that\n                        % this is valid for both the unsaturated as well as 'foggy'\n                        % (moisture content above saturation, but temperatures above\n                        % freezing, so just vapour and liquid present) area\n                        1.0045 * \\Temperature\n                        +\n                        min(\n                            (\\MoistureContent/1000),\n                            Saturation_Moisture_Content(\\Temperature)\n                        )\n                        *\n                        (\n                            1.86 * \\Temperature + 2500\n                        )\n                        +\n                        max(\n                            0,\n                            (\n                                \\MoistureContent/1000\n                                -\n                                Saturation_Moisture_Content(\\Temperature)\n                            )\n                        )\n                        *\n                        4.19 * \\Temperature;\n                },\n            ]\n                % Add the contour plots:\n                \\addplot3+ [\n                    % surf,\n                    ultra thick,\n                    forget plot,% Required for legend to work\n                    contour gnuplot={\n                        levels={0.1, 0.5, 1},\n                        draw color=rdylbu5,\n                    },\n                ] {Relative_Humidity(MoistureContent, Temperature)};\n                \\addlegendimage{color=rdylbu5, ultra thick}\n                \\addlegendentry{Relative Humidity}\n                %\n                \\addplot3+ [\n                    % surf,\n                    ultra thick,\n                    dashdotted,\n                    forget plot,\n                    contour gnuplot={\n                        levels={20, 40, 60},\n                        draw color=rdylbu2,\n                    },\n                ] {Dry_Air_Enthalpy(MoistureContent, Temperature)};\n                %\n                \\addlegendimage{color=rdylbu2, ultra thick, dashdotted}\n                \\addlegendentry{%\n                    Specific Enthalpy in \\unit{\\kilo\\joule\\per\\kilogram\\dryair}%\n                }\n\n                % Add nodes and connect them. Connect the one we are currently\n                % drawing to the previous one.\n                % x and y coordinates are moisture content and temperature respectively\n                \\foreach [count=\\i, remember=\\i as \\previousi]\n                    \\MoistureContent/\\Temperature/\\nodetext/\\nodeorientation in {\n                        1.8/3/{Ambient}/right,\n                        1.8/27/{Preheated}/{above, text width=6em},\n                        8.0/11/{Moisturized}/right,\n                        8.0/26/{Inlet}/above,\n                        9.0/21/{Room = Outlet}/{below right}%\n                }{%\n                    % Use edef to control node expansion within axis environment.\n                    % Expand all stuff that is only present in the loop\n                    \\edef\\temp{\\noexpand\\coordinate (LABELDOT_\\i) at\n                        (\\MoistureContent, \\Temperature);}\n                    \\temp\n\n                    \\edef\\temp{\\noexpand\\node[\n                        \\nodeorientation,\n                        align=center,\n                        fill=white,\n                        inner sep=1pt,\n                        rounded corners,\n                        outer sep=0.5em,\n                        font=\\noexpand\\small\n                    ] at (LABELDOT_\\i) {\\nodetext};}\n                    \\temp\n\n                    % After the first one, start connecting backwards.\n                    \\ifnum \\i > 1\n                        \\edef\\temp{\n                            \\noexpand\\draw[\n                                *<-*,\n                                ultra thick,\n                                shorten <>={-(1.8pt + 1.4\\pgflinewidth)}\n                            ] (LABELDOT_\\i) -- (LABELDOT_\\previousi);\n                        }\n                        \\temp\n                    \\fi\n                }\n            \\end{axis}\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\n\\paragraph{Time-series}\nTime-series plots are straightforward to implement.\n\\ctanpackage{pgfplots}, using its \\texttt{dateplot} library, can automatically parse\nand plot dates.\nFor this to work best and most reliably, dates and times should be in\n\\abb{international_organization_for_standardization} 8601 format:\n\\begin{center}\n    \\texttt{YYYY-MM-DDThh:mm:ss\\phantom{Z}}:% \\phantom for budget alignment\n\n    \\texttt{2020-05-19T12:15:31Z},\n\\end{center}\nwhere \\texttt{Z} is time\\-/zone information and \\texttt{T} is an arbitrary, but\nfixed separator.\nIt can also be a simple space.\nUse just the date \\emph{or} time part when appropriate.\n\nThis format is unambiguous and understood worldwide as well as, most importantly here,\nby computers.\nNo extra string and date parsing is required, it will just work in a lot of cases,\nnot only for \\ctanpackage{pgfplots} like here.\nFurther, it is often the standard output format (or close to it) of measurement\nequipment anyway, so there is not even a need to modify it.\n\nAn example is shown in \\cref{fig:example_timeseries_plot}.\nNote how the actually displayed date/time format can be modified and made human\\-/readable\nfreely.\nOnly the underlying data format is best followed strictly in\n\\abb{international_organization_for_standardization} 8601 format.\n\n\\begin{figure}\n    % Data is small enough to not require a separate CSV file, put it here.\n    % Specify date as YYYY-MM-DD for pgfplots to recognize it as date data automatically.\n    % Currently, the xlabel alignment is off using dateplots, so revert to plain\n    % old methods for now.\n    \\pgfplotstableread[row sep=\\\\]{%\n        Date, Apples, Bananas, Peaches, Kiwis, Skunks, Grapes, Lemons\\\\%\n        2020-02-01, 50, 1, 17, 10, 15, 2, 5\\\\%\n        2020-03-04, 40, 2, 32, 10, 10, 2, 4\\\\%\n        2020-05-02, 30, 3, 37, 10, 15, 2, 3\\\\%\n        2020-05-28, 20, 4, 52, 10, 10, 2, 2\\\\%\n        2020-06-14, 10, 5, 57, 10, 15, 2, 1\\\\%\n    }{\\examplepfgtable}%\n    %\n    \\ffigbox[\\FBwidth]{\n        \\caption[Example automatic timeseries plot]{\n            Example automatic timeseries plot.\n            Note the automatic spacing\\-/out according to the actual time deltas,\n            and the automatic conversion of timestamps to human\\-/friendly versions,\n            to whatever specification the author chooses.\n            Also note the colors: here, \\emph{distinction} is important and a\n            \\emph{qualitative} palette is chosen.\n            A \\emph{sequential} or a \\emph{diverging} palette would have been\n            less suited (some would say plain wrong)%\n        }%\n        \\label{fig:example_timeseries_plot}%\n    }{%\n        \\begin{tikzpicture}\n            \\begin{axis}[%\n                    regularplot,\n                    width=0.9\\textwidth,\n                    height=0.3\\textheight,\n                    ybar stacked,\n                    xtick=data,% xticks at data points, not uniformly\n                    % Use next line for manual labels from table; get from {<table>}{<column>}\n                    % xticklabels from table={\\examplepfgtable}{year},\n                    %\n                    % If using date data in the table (of the form YYYY-MM-DD):\n                    date coordinates in=x,\n                    %\n                    % Customize display here; macros automatically defined/grabbed\n                    % by pgfplots:\n                    xticklabel={\\day.\\month.\\year},\n                    %\n                    xticklabel style={rotate=45,anchor=north east},\n                    ymin=0,% Cuts off data otherwise\n                    ylabel={Share},\n                    y unit={\\percent},\n                    xlabel={Date of purchase},\n                    legend style={font=\\scriptsize},%\n                    % nodes near coords,% uncomment for numeric labels\n                    cycle list/Set2-7,\n                    every axis plot/.append style={fill},% https://tex.stackexchange.com/a/317684/120853\n                ]\n                \\foreach \\columnname in {Apples, Bananas, Peaches, Kiwis, Skunks, Grapes, Lemons}{%\n                    \\addplot+ table [y=\\columnname] {\\examplepfgtable};\n                }\n                % Legend manually; \\addlegenentry per \\foreach loop is very error-prone\n                \\legend{Apples, Bananas, Peaches, Kiwis, Skunks, Grapes, Lemons}\n            \\end{axis}\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\n\\subsubsection{Importing CSV}\n\nOften, one wants to plot data from files.\nThe better behaved the file is (meaningful headers, no junk rows), the easier that is.\nIn \\cref{fig:diffuser}, \\verb|y=<column header>| is all that has to be specified for the\ncolumn corresponding to that name to be automatically chosen, with no confusion\nabout indices or column numbers.\n\\begin{figure}\n\\ffigbox[\\FBwidth]{\n        \\caption{Plotting from CSV data for a diffuser}\n        \\label{fig:diffuser}\n    }{%\n        \\pgfplotstableread{data/diffuser.csv}{\\diffusertable}%\n        \\begin{tikzpicture}\n            \\begin{axis}[%\n                tuftelike,%\n                axis y line*=left,%\n                xlabel={\\(\\sym{radius}/\\sym{radius}_{\\num{2}}\\)},%\n                x unit={-},\n                ylabel={\n                    \\sym{mach_number},\n                    \\(\\sym{pressure}/\\sym{pressure}_{\\num{2}}\\),\n                    \\(\\sym{abs_temperature}/\\sym{abs_temperature}_{\\num{2}}\\),\n                    \\(\\sym{density}/\\sym{density}_{\\num{2}}\\)\n                },%\n                y unit={-},\n                table/x={R_pres},%\n                ymin=0.4,\n                ymax=1.3,\n                ytick={0.4, 0.7, 1, 1.3},\n                xmin=1,\n                xmax=1.6\n            ]%\n                % Do this manually, node macro expansion in foreach/invokeforeach\n                % is error-prone\n                \\addplot+ table [y=M] {\\diffusertable}\n                    node [arrowlabel=0.2]\n                    {\\sym{mach_number}};\n                \\addplot+ table [y=Pi] {\\diffusertable}\n                    node [arrowlabel=0.9]\n                    {\\(\\sym{pressure}/\\sym{pressure}_{\\num{2}}\\)};\n                \\addplot+ table [y=Theta] {\\diffusertable}\n                    node [arrowlabel=0.7]\n                    {\\(\\sym{abs_temperature}/\\sym{abs_temperature}_{\\num{2}}\\)};\n                \\addplot+ table [y=Rho] {\\diffusertable}\n                    node [arrowlabel=0.8]\n                    {\\(\\sym{density}/\\sym{density}_{\\num{2}}\\)};\n            \\end{axis}%\n            %\n            \\begin{axis}[%\n                tuftelike,%\n                axis y line*=right,%\n                axis x line=none,%\n                ylabel={abs.\\ flow angle \\sym{angle_one}},%\n                y unit={\\degree},\n                cycle list shift=4,%\n                ymin=13,\n                ymax=15,\n                xmin=1,\n                xmax=1.6,\n            ]%\n                \\addplot+ table [x=R_pres, y=alpha] {\\diffusertable}\n                    node [arrowlabel] {\\sym{angle_one}};%\n            \\end{axis}%\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\subsubsection{Using MATLAB2Ti\\textit{k}Z}\n\n\\href{https://github.com/matlab2tikz/matlab2tikz}{MATLAB2Ti\\textit{k}Z} is a tool to\nconvert MATLAB figures to \\LaTeX{}, see \\cref{fig:matlab2tikz_vanilla}.\nNotice that by default, it exports using whitespace (tabs) as column separators,\nwhich might differ from what is set as a global option in \\verb|\\pgfplotstableset|.\n\n\\begin{figure}\\ContinuedFloat*\n    \\ffigbox[\\FBwidth]{%\n        \\caption[%\n            A vanilla \\href{https://github.com/matlab2tikz/matlab2tikz}{MATLAB2Ti\\textit{k}Z}\n            example%\n        ]{%\n            A vanilla \\href{https://github.com/matlab2tikz/matlab2tikz}{MATLAB2Ti\\textit{k}Z}\n            example, imported here without changes except those to allow successful compilation\n            (see commit \\texttt{56556a0}: set \\texttt{table/col sep=space}).\n            While it works, the style created in MATLAB conflicts with the local one,\n            and you miss out on many useful features, like \\ctanpackage{siunitx} or\n            \\ctanpackage{glossaries-extra}.\n            A more frictionless approach is to export plain-text (CSV) data from MATLAB,\n            and import it into \\LaTeX{}, see \\cref{fig:diffuser,fig:matlab2tikz_pgfplots}%\n        }%\n        \\label{fig:matlab2tikz_vanilla}%\n    }{%\n        % Can't use `subimport', since import is not from any child directory.\n        % Note that changing plot scaling/size for matlab2tikz is apparently very\n        % awkward: https://tex.stackexchange.com/a/173490/120853\n        \\import{data/}{matlab2tikz_table_example}\n    }\n\\end{figure}\n\n\\Cref{fig:matlab2tikz_pgfplots} is the same plot, but generated directly in \\LaTeX{}, without\nrelying on MATLAB2Ti\\textit{k}Z---using the latter, a plethora of things break since it\nhard\\-/codes a bunch of stuff.\n\\Cref{fig:matlab2tikz_pgfplots} is only around 30 lines of code (arrived at after only a couple of hours\\dots{})!\n\n\\begin{figure}\\ContinuedFloat\n    \\ffigbox[\\FBwidth]{\n        \\caption[%\n            Same data as \\cref{fig:matlab2tikz_vanilla} but plotted in \\LaTeX{} directly, using only the provided raw data%\n        ]{%\n            Same data as \\cref{fig:matlab2tikz_vanilla} but plotted in \\LaTeX{} directly, using only the provided raw data.\n            Note how this allows for a consistent style and unlocks all other, usual features found in this template.\n            Also take a look at the source data to see what \\emph{tidy data} looks like, a data format most suitable for data processing%\n        }\n        \\label{fig:matlab2tikz_pgfplots}\n    }{%\n        \\pgfplotstableread{data/matlab2tikz_table_example_data.csv}{\\matlabtikztable}%\n        \\begin{tikzpicture}\n            \\begin{axis}[%\n                regularplot,%\n                width=0.9\\linewidth,\n                %\n                localstyle/.style={% Common, local plot style options\n                    only marks,% Scatter plot, do not connect marks\n                    error bars/y dir=both,% Y errors in both directions, positive and negative\n                    error bars/y explicit,% Absolute, not relative, values\n                },\n                % Modify x labels, drop scientific notation, see also\n                % https://tex.stackexchange.com/a/119888/120853\n                xticklabel style={\n                    /pgf/number format/fixed,\n                    /pgf/number format/precision=5\n                },\n                scaled x ticks=false,\n                %\n                xlabel={\\glsdesc{sym.reynolds_number} \\sym{reynolds_number}},%\n                x unit={\\glsunit{sym.reynolds_number}},\n                ylabel={\\glsdesc{sym.drag_coefficient} \\sym{drag_coefficient}},%\n                y unit={\\glsunit{sym.drag_coefficient}},\n                % Table namespace, options for all tables:\n                table/y=Drag_Coefficient,\n                % Data sources for the requested error bars:\n                table/y error plus=Drag_Coefficient_Error_Pos,\n                table/y error minus=Drag_Coefficient_Error_Neg,\n                % We're going to filter using NaN a lot, don't spam logs:\n                filter discard warning=false,\n            ]%\n                % We essentially have this same issue:\n                % https://tex.stackexchange.com/questions/264330/grouping-data-in-pgfplots\n                %\n                % Trying to group well-structured data by some other columns.\n                % It's not currently possible, but the below is a decent enough\n                % surrogate:\n                % Generate plots in a loop; pretty neat and automated with one\n                % core downside: we can't just say `groupby(pressure, temperature)`\n                % as we could in e.g. pandas, Excel PowerPivot and many others.\n                % That's inconvenient but it's understandable pgfplots/tex (whose\n                % job is to *plot*, not to mangle and process data) can't\n                % deliver this.\n                % Note how grouping data this way is AMAZING and dearly recommended\n                % for any serious data work:\n                % https://vita.had.co.nz/papers/tidy-data.pdf\n                \\foreach\\pressure/\\temperature in {\n                        9/30,%\n                        13.2/45,%\n                        16.6/55%\n                }{\n                    \\addplot+ [\n                        localstyle,\n                        table/x expr={\n                            % Ternary filter: https://tex.stackexchange.com/a/412235/120853\n                            \\thisrow{Pressure}==\\pressure?\\thisrow{Reynolds}:nan\n                        },\n                    ] table {\\matlabtikztable};\n                    % Expansion in `foreach` is problematic with legend printing;\n                    % use this special command version, see also\n                    % https://tex.stackexchange.com/a/317015/120853\n                    \\addlegendentryexpanded{\n                        \\qty{\\pressure}{\\bar}/\\qty{\\temperature}{\\degreeCelsius}\n                    }\n                }\n            \\end{axis}%\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\subsection{TikZ and Text}\n\n\\idx{tikz} content can also be intertwined with text using \\verb|\\tikzmark|.\nThis is illustrated in \\cref{eq:tikz_in_text}.\nNote that this procedure needs two compilation runs, since the label positions\nneed to be written to an auxiliary file first.\n\n\\begin{minipage}{1\\linewidth}\n    % https://tex.stackexchange.com/q/83746/120853 and\n    % https://tex.stackexchange.com/a/188221/120853\n    \\newcommand*{\\setmuskip}[2]{#1=#2\\relax}\n    \\setmuskip{\\medmuskip}{15mu plus 2mu minus 4mu}\n    \\setmuskip{\\thickmuskip}{18mu plus 2mu minus 4mu}\n\n    \\begin{equation}\\label{eq:tikz_in_text}\n        \\tikzmark{c}\\sym{mass_fraction}_{\\chcpd{C}}\n        +\n        \\tikzmark{h}\\sym{mass_fraction}_{\\chcpd{H}}\n        +\n        \\tikzmark{s}\\sym{mass_fraction}_{\\chcpd{S}}\n        +\n        \\tikzmark{o}\\sym{mass_fraction}_{\\chcpd{O}}\n        +\n        \\tikzmark{n}\\sym{mass_fraction}_{\\chcpd{N}}\n        +\n        \\tikzmark{w}\\sym{mass_fraction}_{\\chcpd{H2O}}\n        +\n        \\tikzmark{a}\\sym{mass_fraction}_{\\mathrm{ash}}\n        \\coloneq% prints as :=\n        \\num{1}\n        \\eqend{}\n    \\end{equation}\n\n    \\begin{tikzpicture}[%\n        remember picture,%\n        overlay,%\n    ]\n        \\pgfmathsetmacro{\\vshiftone}{4}\n        \\pgfmathsetmacro{\\vshifttwo}{6.5}\n        \\pgfmathsetmacro{\\vshiftthree}{9}\n        \\pgfmathsetmacro{\\hshiftone}{1}\n        \\pgfmathsetmacro{\\hshifttwo}{2}\n        \\pgfmathsetmacro{\\hshiftthree}{3}\n\n        \\foreach \\x/\\y/\\a/\\b in {%\n            c/Carbon/\\vshiftone/-\\hshiftthree,%\n            h/Hydrogen/\\vshifttwo/-\\hshifttwo,%\n            s/Sulphur/\\vshiftthree/-\\hshiftone,%\n            o/Oxygen/\\vshifttwo/0,%\n            n/Nitrogen/\\vshiftthree/\\hshiftone,%\n            w/Water/\\vshifttwo/\\hshifttwo,%\n            a/Ash/\\vshiftone/\\hshiftthree%\n        }{%\n            \\node (\\x1) [below right=0.1em and 0.4em of pic cs:\\x]\n                {};\n            \\node (\\x2) [on grid, below right=\\a ex and \\b ex of \\x1, anchor=north]\n                % 'on grid' option makes positioning snappy (uses actual middle\n                % of nodes); without, even 'right=0pt' would not be centered\n                {\\y};\n            \\draw[-stealth] [out=90](\\x2) to [in=270](\\x1);\n        }%\n    \\end{tikzpicture}\n\n    % We need to use 'overlay', but this also means we lose the bounding box.\n    % Eye-ball it here, sadly.\n    \\vspace{4\\baselineskip}\n\\end{minipage}\n\n\\subsection{Regular TikZ pictures}\n\n\\idx{tikz} really is not meant for arbitrary graphics.\nThe more free\\-/form images shown in this document were created using InkScape.\nStill, \\enquote{drawing} in \\idx{tikz} is much preferred and easier when the\nimages are somewhat programmatic, aka there are straight corners, edges and turns,\nequal distances, and everything is a bit \\enquote{block-like}, repetitive.\nFor example, a small file structure diagram:\n\\begin{center}\n    \\begin{tikzpicture}[\n        %http://www.texample.net/tikz/examples/filesystem-tree/\n            grow via three points={one child at (0.5,-0.7) and\n                two children at (0.5,-0.7) and (0.5,-1.4)},\n            edge from parent path={(\\tikzparentnode.south) |- (\\tikzchildnode.west)},\n            every node/.style={draw=black,thick,anchor=west,fill=g5},\n            font=\\ttfamily,%\n        ]%\n            % `[regular]` optional arg gives outlined symbol, as opposed to `solid`\n            \\node {\\faIcon[regular]{file-code} parent.py}\n            child { node {\\faIcon[regular]{file-code} constants.py}}\n            child { node {\\faIcon[regular]{file-code} parameters.py}}\n            child { node {\\faIcon[regular]{file-code} handling.py}}\n            child { node {\\faIcon[regular]{file-code} performance\\_maps.py}};\n    \\end{tikzpicture}\n\\end{center}\nNote how \\verb|tikzpicture| environments do not have to be contained in floats.\n\nMore \\idx{tikz} examples are shown in\n\\cref{fig:tikz_control_diagram,fig:tikz_circuit_example,fig:tikz_threedimensional_example}.\n\n\\begin{figure}\\ContinuedFloat*\n    \\ffigbox[0.95\\linewidth]{%\n        \\begin{tikzpicture}[%\n            every path/.style={thick},%https://tex.stackexchange.com/a/302931/120853\n            simblock/.style={%\n                draw,%\n                line width=1.5pt,%\n                minimum size=1.5em,%\n                rounded corners,%\n                fill=white,%\n            },%\n            triangle/.style={%\n                regular polygon,%\n                regular polygon sides=3,%\n                inner sep=0.2ex,% Fit tightly\n                outer sep=0pt,\n            },\n        ]%\n        % Row of Model Blocks\n            \\node[simblock, minimum height=5ex] (outlet)\n                {Outlet};\n            \\node[simblock, minimum height=5ex, right=of outlet] (turbine)\n                {Turbine};\n            \\node[simblock, minimum height=5ex, right=of turbine] (compressor)\n                {Compressor};\n            \\node[simblock, minimum height=5ex, right=of compressor] (inlet)\n                {Inlet};\n            \\draw[->] (outlet) -- (turbine)\n                node [midway, above, font=\\footnotesize] {feeds};\n            \\draw[->] (turbine) -- (compressor)\n                node [midway, above, font=\\footnotesize, align=center] (shaft) {via\\\\shaft};\n            \\draw[->] (compressor) -- (inlet)\n                node [midway, above, font=\\footnotesize] {feeds};\n\n            % Division Block underneath Engine\n            \\node[below=12ex of inlet.south, draw=none] (div) {};\n            \\node[below=4ex of div, draw=none] (mult) {};\n            \\node[simblock, fit=(mult) (div), minimum height=8ex] (multdiv) {};\n            \\node at (div) {\\(\\div\\)};\n            \\node at (mult) {\\(\\ast\\)};\n\n            % Connect Inlet and Division part\n            \\draw[->] (inlet.east) -- ++ (+1, 0)\n                node [pos=1, above] {\\(p_{\\text{in}}(\\tau)\\)}\n                |-\n                ($(multdiv.east)!0.5!(multdiv.north east)$);\n\n            % p min block next to multiplication\n            \\draw[<-] ($(multdiv.east)!0.5!(multdiv.south east)$) -- ++ (1, 0)\n                node[simblock] {\\(p\\)};\n\n            \\node [circle, fill, inner sep=0.3ex, left=0.7em of multdiv] (split1) {};\n            \\draw (multdiv) -- (split1);\n\n            % Bias and inverted Bias blocks\n            \\node[simblock, left = of div] (biasinv) {\\(1 - u\\)};\n            \\node[simblock, left = of mult] (bias) {\\(u - 1\\)};\n            \\draw[->] (split1) |- (bias);\n            \\draw[->] (split1) |- (biasinv);\n\n            % Split again\n            \\node [circle, fill, inner sep=0.3ex, left=1em of biasinv] (split2) {};\n            \\draw (biasinv) -- (split2);\n\n            \\node[simblock, left=1em of split2, triangle, shape border rotate=90] (gainint)\n                {\\small\\(I\\)};\n            \\draw[->] (split2) -- (gainint);\n\n            \\node[simblock, above=of gainint, triangle, shape border rotate=90] (gainp)\n                {\\small\\(P\\)};\n            \\draw[->] (split2) |- (gainp);\n\n            % Intersection between Integer Gain and Multi/Div block as helper\n            \\coordinate (help1) at (gainint|-multdiv);\n\n            % Integer Text, but don't draw\n            \\node[draw=none, left=4em of help1, minimum height=8ex] (int)\n                {\\(\\frac{KTs}{z - 1}\\)};\n\n            % Falling Edge Sign with Arrow\n            \\draw ($(int.east)!0.5!(int.south east)$)\n                -- ++ (0.5em, 0)\n                -- ++ (0, -0.7em)\n                -- ++ (0.5em, 0) coordinate (intsign_end);\n            \\draw[thin, ->] ($(int.east)!0.5!(int.south east)$)\n                -- ++ (0.5em, 0) -- ++ (0, -0.5em);\n\n            % Move fitting to background so it does not overwrite the nodes it fits to\n            \\begin{pgfonlayer}{background}\n                \\node[simblock, fit=(int.north west)(intsign_end)] (int_block) {};\n            \\end{pgfonlayer}\n\n            \\draw[->] (bias) -- (int_block.east|-mult)\n                node [midway, below, align=center, font=\\footnotesize]\n                    {falling edge\\\\reset};\n            \\draw[->] (gainint) -- (int_block.east|-div);\n\n            \\node [simblock, circle, left=of int_block] (sum) {};\n            \\draw[->] (gainp) -| (sum) node [pos = 0.9, right] {\\(+\\)};\n            \\draw[->] (int_block) -- (sum) node [pos = 0.8, below] {\\(+\\)};\n\n            \\node[simblock, left = of sum] (biasinvout) {\\(1- u\\)};\n            \\draw[->] (sum) -- (biasinvout);\n\n            \\node[simblock, left = of outlet] (times) {\\(\\times\\)};\n            \\draw[->] (times) -- (outlet) node [midway, above, font=\\footnotesize]\n                {\\(\\dot{\\sym{mass}}_{\\text{T}}\\)};\n\n            \\node[simblock, below=of times] (sat) {\\(\\num{0.1} \\leq u \\leq \\num{1}\\)};\n            \\draw[->] (biasinvout) -| (sat);\n            \\draw[->] (sat) -- (times) node [midway, left]\n                {\\(\\symbf{\\zeta(\\tau)}\\)};\n\n            \\node[simblock, above=of outlet, minimum height=5ex] (eng) {Engine};\n\n            \\draw[->] (inlet) |- (eng) node [pos=0.8, above, font=\\footnotesize]\n                {feeds};\n            \\draw[->] (eng) -| (times) node [pos=0.7, left, font=\\footnotesize]\n                {\\(\\dot{\\sym{mass}}_{\\text{E}}\\)};\n        \\end{tikzpicture}\n    }{%\n        \\caption[Wastegate implementation in a feedback\\-/loop]{%\n            % See here: https://tex.stackexchange.com/a/471263/120853\n            % for a good macro to print \"MATLAB/Simulink\" (not used here since it\n            % it wouldn't be used much at all)\n            Wastegate implementation in a feedback\\-/loop in MATLAB/Simulink\n            as an example for a \\idx{tikz} diagram%\n        }%\n        \\label{fig:tikz_control_diagram}%\n    }%\n\\end{figure}\n\n\\begin{figure}\\ContinuedFloat\n    \\fcapside[\\FBwidth]{\n        \\caption{Example for the \\texttt{circuits.ee.IEC} \\idx{tikz} library}\n        \\label{fig:tikz_circuit_example}\n    }{\n        \\begin{tikzpicture}[\n                circuit ee IEC,% As loaded by the lib of the same name\n                % every circuit symbol/.style={thick},\n            ]\n            \\pgfmathsetmacro{\\circuitwidth}{4}\n            \\pgfmathsetmacro{\\circuitheight}{2}\n            % Try to close manually, we cannot 'cycle'\n            % https://tex.stackexchange.com/q/33294/120853\n            \\draw (0,0) -- node[contact] (CONTACT_LEFT) {} (0,\\circuitheight)\n                to [resistor={name={RESISTOR}, info={\\sym{electrical_resistance}}}]\n                    node[%\n                        current direction,\n                        pos=0.9,\n                        label={[name=ELECTRIC_CURRENT_LABEL]above:{\\(\\sym{electric_current}\\)}}\n                    ] {}\n                (\\circuitwidth,\\circuitheight) -- node[contact] (CONTACT_RIGHT) {}\n                (\\circuitwidth,0) to [battery] (0,0);\n\n            \\draw[<->, shorten <>=0.7em] (CONTACT_LEFT) -- (CONTACT_RIGHT)\n                node[arrowlabel] {\\(\\sym{voltage}\\)};\n\n            \\node[\n                fit={(RESISTOR)(ELECTRIC_CURRENT_LABEL)(CONTACT_LEFT)(CONTACT_RIGHT)},\n                inner sep=1em,\n                draw,\n                dashed\n            ] (BOUNDARY) {};\n\n            % The following draws a label directly onto the node border.\n            % Cannot really be done with supplying a 'label' directly to the node\n            % BOUNDARY (?)\n            \\node[fill=white, font={\\small}] at (BOUNDARY.north) {Boundary};\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\begin{figure}\\ContinuedFloat\n    \\fcapside[\\FBwidth]{\n        \\caption{%\n            Example for a three\\-/dimensional \\idx{tikz} drawing using the\n            \\texttt{3d} library%\n        }\n        \\label{fig:tikz_threedimensional_example}\n    }{\n        \\tdplotsetmaincoords{110}{-12}% View angle\n        \\begin{tikzpicture}[tdplot_main_coords]\n            % Debugging coordinate system:\n            % \\draw (0,0,0) -- (1,0,0) node[right] {\\(x\\)};\n            % \\draw (0,0,0) -- (0,1,0) node[left] {\\(y\\)};\n            % \\draw (0,0,0) -- (0,0,1) node[above] {\\(z\\)};\n\n            % Base measurements. Default unit is centimeter\n            \\pgfmathsetmacro{\\plateheight}{0.2}\n            \\pgfmathsetmacro{\\platewidth}{4}\n            \\pgfmathsetmacro{\\platedepth}{3}\n            % Stretch how arrows are distanced from the plate:\n            \\pgfmathsetmacro{\\arrowdistance}{2.5}\n\n            % Bottom arrow:\n            \\begin{scope}[canvas is xy plane at z=-\\plateheight/\\arrowdistance]\n                \\draw[flowarrow={4em}{0.2em}, solid] (-\\platewidth*0.25,\\platedepth*0.5)\n                    node[left] {\\(\\flow{\\sym{mass}}_{2}''\\)}\n                    --\n                    (\\platewidth*1.25,\\platedepth*0.5)\n                    node[right] {\\(\\flow{\\sym{mass}}_{2}'\\)};\n            \\end{scope}\n\n            % Top surface:\n            \\begin{scope}[canvas is xy plane at z=\\plateheight]\n                \\draw[wall] (0,0) rectangle (\\platewidth,\\platedepth)\n                    node[midway] {\\ctrw{\\(\\sym{area}\\)}};\n            \\end{scope}\n            % Right surface:\n            \\begin{scope}[canvas is yz plane at x=\\platewidth]\n                \\draw[wall] (0,0) rectangle (\\platedepth,\\plateheight);\n            \\end{scope}\n            % Front surface:\n            \\begin{scope}[canvas is xz plane at y=\\platedepth]\n                \\draw[wall] (0,0) rectangle (\\platewidth,\\plateheight);\n\n                \\foreach [count=\\i] \\posfraction in {0.2, 0.4, ..., 0.8}{%\n                    \\draw[->, dashed, thick] (\\posfraction*\\platewidth, \\plateheight*2)\n                    --\n                    (\\posfraction*\\platewidth, -2*\\plateheight) coordinate[below] (ARROW_\\i);\n                }\n            \\end{scope}\n\n            % Top arrow:\n            \\begin{scope}[canvas is xy plane at z=\\plateheight*\\arrowdistance]\n                \\draw[flowarrow={4em}{0.2em}, solid] (\\platewidth*1.25,\\platedepth*0.5)\n                    node[right] {\\(\\flow{\\sym{mass}}_{1}''\\)}\n                    --\n                    (-\\platewidth*0.25,\\platedepth*0.5)\n                    node[left] {\\(\\flow{\\sym{mass}}_{1}'\\)};\n            \\end{scope}\n\n            % Manually set arrow label here:\n            \\node at ($(ARROW_1)!0.5!(ARROW_4)$) {\\(\\flow{\\sym{volume}}\\)};\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\paragraph{Included shapes}\nThis repository includes custom\\-/made shapes for thermodynamic applications.\nThese can be used like many other \\idx{tikz} elements, for example by\npositioning them somewhere on the canvas, connecting them to other elements,\nrotating them \\iecfeg{etc}.\nIn that sense, they work like usual \\idx{tikz} elements (just buggier\\dots{}).\nThere are a couple of advantages:\n\\begin{enumerate}\n    \\item unified looks: no more drawing these in InkScape, where they come out\n        slightly dissimilar every time,\n    \\item tight integration with \\idx{tikz}, allowing to use all its other\n        features,\n    \\item very fast generation of drawings once some familiarity is gained;\n        with InkScape or other outside tools, one can also become fast, but it is\n        hard to beat a \\LaTeX{}\\-/internal approach.\n\\end{enumerate}\nExamples are shown in\n\\cref{fig:tikz_thermodynamic_drawing,fig:tikz_thermodynamics_radiators}.\nRefer to their source code to see how more or less easily they are created.\n\n\\begin{figure}\\ContinuedFloat*\n    \\ffigbox[\\FBwidth]{\n        \\caption{%\n            Example for a thermodynamic device drawing using \\idx{tikz}.\n            It relies heavily on the custom\\-/made library of shapes%\n        }\n        \\label{fig:tikz_thermodynamic_drawing}\n    }{\n        \\begin{tikzpicture}[\n            thisshaft/.style={\n                line width=3pt\n            },\n            every label/.style={\n                font=\\footnotesize\n            },\n            every node/.style={\n                font=\\footnotesize\n            }\n        ]\n            % The main circle itself:\n            % Note that when rotating shapes, the label positions also rotate and get mixed up.\n            \\draw (0,0) --\n                node[midway, valve, sloped, label=left:Throttle] (VALVE) {} (0,2.5) --\n                node[midway, heat exchanger, rotate=180, label=above:Condenser] (CONDENSER) {} (5,2.5) --\n                (5,0)\n                node[midway, compressor, label=above:Compressor, rotate=180] (COMPRESSOR) {} --\n                node[midway, heat exchanger, label=above:Evaporator] (EVAPORATOR) {}\n                cycle;\n\n            % Engine on right of compressor:\n            \\draw[thisshaft] (COMPRESSOR) -- ++ (2,0)\n                node [right, rectangle, draw, thin] (ENGINE) {Engine}\n                    coordinate[midway] (SHAFT_MIDDLE);\n\n            % Shift down by 7pt (shaft line width is 3pt) and also specify that as a radius\n            \\draw[->] ([yshift=-7pt]SHAFT_MIDDLE) arc (290:60:7pt);\n\n            \\foreach [count=\\i] \\xcomponent/\\ycomponent/\\orientation in {\n                COMPRESSOR/EVAPORATOR/right,\n                COMPRESSOR/CONDENSER/right,\n                VALVE/CONDENSER/left,\n                VALVE/EVAPORATOR/left%\n            }{\n                \\node[\n                    origindot,\n                    label={[name={NUMBER_\\i}]\\orientation:{\\num{\\i}}}\n                ] at (\\xcomponent|-\\ycomponent) {};\n            }\n\n            \\draw[<-] (EVAPORATOR) -- ++ (0,-0.8)\n                node[at end, below, align=center]\n                    {supplied heat} coordinate[near start] (LOWER_BOUNDARY);\n\n            \\draw[->] (CONDENSER) -- ++ (0,1.2) coordinate[pos=0.6] (UPPER_BOUNDARY)\n                node[at end, above, align=center]\n                    {heat discharge} coordinate[near start] (A);\n\n            % Drawings around engine\n            \\draw[->, dashdotted] (ENGINE) |-\n                node[very near end, right, fill=white] {excess engine heat} (A);\n            \\draw[<-] (ENGINE) -- ++ (1.3,0) node[right, align=left]\n                {Electricity,\\\\gas} coordinate[midway] (RIGHT_BOUNDARY);\n\n            % Fit a rectangle around the relevant parts:\n            \\node[\n                fit={(UPPER_BOUNDARY)(LOWER_BOUNDARY)(RIGHT_BOUNDARY)(VALVE)(NUMBER_3)(NUMBER_4)},\n                draw,\n                dashed\n            ] (COP_BOUNDARY) {};\n\n            % COP area labels.\n            \\node[fill=white, left] at ([xshift=-2em]COP_BOUNDARY.north east)\n                {\\glsxtrshort{abb.coefficient_of_performance}-Boundary};\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\begin{figure}\\ContinuedFloat\n    \\tikzset{\n        thispipe/.style={rounded corners=0.5},\n        node distance=1em,\n        every node/.style={font=\\small}\n    }\n    \\ffigbox[\\FBwidth]{%\n        \\caption{Example \\idx{tikz} shapes}\n        \\label{fig:tikz_thermodynamics_radiators}\n    }{%\n        \\begin{tikzpicture}\n            \\pgfmathsetmacro{\\gridspread}{2.2}\n            \\pgfmathsetmacro{\\numberofrows}{3}\n            \\pgfmathsetmacro{\\numberofcolumns}{3}\n            % Extension by which the pipes expand to the left, out of the radiators:\n            \\pgfmathsetmacro{\\pipeextension}{1}\n\n            \\foreach [remember=\\x as \\prevx] \\x in {1, 2, ..., \\numberofcolumns}{\n                    \\foreach [remember=\\y as \\prevy] \\y in {1, 2, ..., \\numberofrows}{\n                            \\node[radiator] at (\\x*\\gridspread, 0.7*\\y*\\gridspread) (RADIATOR_\\x_\\y) {};\n\n                            % Draw the radiators with pipes sticking out:\n                            % \\ifnum doesn't have elseif, so nest if\n                            \\ifnum \\x = 1\n                                \\draw[thispipe] (RADIATOR_\\x_\\y.upper entry) -- ++\n                                    (-\\pipeextension, 0) node[midway, control valve] {}\n                                    node[at end, origindot] (UPPER_PIPE_END_\\x_\\y) {};\n                                \\draw[thispipe] (RADIATOR_\\x_\\y.lower entry) --\n                                    (RADIATOR_\\x_\\y.lower entry-|UPPER_PIPE_END_\\x_\\y)\n                                    node[at end, origindot] (LOWER_PIPE_END_\\x_\\y) {};\n                                % Connect the two pipe ends:\n                                \\draw[thispipe] (UPPER_PIPE_END_\\x_\\y) -- (LOWER_PIPE_END_\\x_\\y);\n                            \\else\n                                \\ifnum \\x = 2\n                                    \\draw[thispipe] (RADIATOR_\\x_\\y.upper entry) -- ++\n                                        (-0.4*\\pipeextension, 0)\n                                        node[at end, threeway valve, rotate=-90] (THREEWAY_VALVE_\\x_\\y) {};\n                                    \\draw[thispipe] (RADIATOR_\\x_\\y.lower entry) --\n                                        (RADIATOR_\\x_\\y.lower entry-|THREEWAY_VALVE_\\x_\\y.south)\n                                        node[at end, origindot] (LOWER_PIPE_END_\\x_\\y) {};\n                                    % Connect valve to lower pipe end:\n                                    \\draw[thispipe] (THREEWAY_VALVE_\\x_\\y.south) --\n                                        (LOWER_PIPE_END_\\x_\\y);\n                                    % Create an alias for this row, since pipe end is now at threeway valve north input.\n                                    % This way, we can use it like the other ones at the bottom.\n                                    \\coordinate (UPPER_PIPE_END_\\x_\\y) at (THREEWAY_VALVE_\\x_\\y.north);\n                                \\else% In all other cases, so the rows after the second to the right\n                                    % Upper radiator entry to the left:\n                                    \\draw[thispipe] (RADIATOR_\\x_\\y.upper entry) -- ++\n                                        (-0.2*\\pipeextension, 0) coordinate[at end] (UPPER_PIPE_END_\\x_\\y);\n                                    % Lower radiator entry to the left:\n                                    \\draw[thispipe] (RADIATOR_\\x_\\y.lower entry) --\n                                        (RADIATOR_\\x_\\y.lower entry-|UPPER_PIPE_END_\\x_\\y)\n                                            coordinate[at end] (LOWER_PIPE_END_\\x_\\y);\n                                \\fi\n                            \\fi\n                            % After the first row, connect radiator pipes to the previous ones:\n                            \\ifnum \\y > 1\n                                \\draw (UPPER_PIPE_END_\\x_\\prevy) -- (LOWER_PIPE_END_\\x_\\y);\n                            \\fi\n                        }\n                }\n\n            \\pic[below left=0em and 3em of LOWER_PIPE_END_1_1, scale=0.3, pic text={Boiler}]\n                (BOILER) {boiler};\n\n            % Helper coordinates because perpendicularity operator (-| or |-) seems to have trouble in conjunction with calculated nodes ($ $)\n            \\coordinate (BOILERTOP) at ($(BOILER.before top)!0.5!(BOILER.after top)$);\n            % Pipe from boiler straight up, until criteration is met:\n            \\draw[thispipe] (BOILERTOP) --\n                ([yshift=1.5em]BOILERTOP|-UPPER_PIPE_END_1_\\numberofrows)\n                coordinate[at end] (BOILER_OUT_PIPE_END)\n                node[pos=0.2, pump] {};\n\n            \\foreach \\x in {1, 2, ..., \\numberofcolumns}{\n                    % Connect end of boiler vertical pipe to each radiator column:\n                    \\draw[thispipe] (BOILER_OUT_PIPE_END) -|\n                        (UPPER_PIPE_END_\\x_\\numberofrows);\n                    % Connect bottom row lower pipes to boiler:\n                    \\draw[thispipe, ->] (LOWER_PIPE_END_\\x_1) |- (BOILER.east);\n                }\n\n            % Helper coords to make calc etc work reliably\n            \\coordinate (B) at (BOILER.east-|LOWER_PIPE_END_1_1);\n            \\coordinate (EQUALIZING_TANK_PIPE_POSITION) at ($(B)!0.5!(BOILER.east)$);\n\n            % Set it above horizontal middle of boiler and start of first row.\n            \\draw (EQUALIZING_TANK_PIPE_POSITION) -- ++ (0, 2em) node[equalizing tank] {};\n\n            % 'Air discharged (Lufttopf)' at top\n            \\draw[thispipe] (BOILER_OUT_PIPE_END) -- ++ (0, 0.5em)\n                node[\n                    at end,\n                    rectangle,\n                    draw,\n                    minimum width=1em,\n                    minimum height=1.5em,\n                    anchor=south,\n                    label=right:{Air Discharge}\n                ] (AIR_DISCHARGE) {};\n            \\draw[thispipe, ->] (AIR_DISCHARGE.north) -- ++ (0, 0.75em) -|\n                ([shift={(0.5em, 0.75em)}]AIR_DISCHARGE.east);\n        \\end{tikzpicture}\n    }\n\\end{figure}\n\n\\subsection{InkScape}\n\nHaving seen what \\idx{tikz} is good at,\n\\cref{fig:tighter_caption,fig:multiple_floats,fig:sidecap}\nare good examples for when InkScape might be the better choice:\nthree\\-/dimensional, curvy drawings.\n\n\\Cref{fig:tighter_caption} is a vectorized bitmap.\nInkScape can detect edges and contrasts in bitmaps and replicate those lines in\nvector format (\\texttt{Path > Trace Bitmap}).\n\n\\section{Example Boxes}\n\nAs a special gimmick, there is an environment for examples (can also be renamed).\nIt may be useless now, but you can alter it to suit your needs; the skeleton is\nthere for you.\nIt even has its own list, like the list of figures.\nFor an example box, see \\cref{ex:example}.\n\n\\begin{example}[%\n    label={ex:example},%\n]{%\n    I am a useless box%\n}\n    There can be pretty much any content in here.\n    Math works --- as we can see,\n    \\begin{equation}\n        1 = 1\n    \\end{equation}\n    still holds true after all these years!\n\n    If the \\verb|float| setting is set, this box also floats.\n    Inserting other floats in here will then cause \\LaTeX{} to have a massive fit\n    (floats inside floats do not make sense).\n    This is circumvented setting the \\verb|[H]| flag,\n    saying \\enquote{this float is not really a float, pin it down \\emph{right} here}.\n\n    \\textbf{In any other context, setting any such flag is code smell/poor style.}\n    These are often used wrong and just as often set prematurely and then reset\n    countless times, all the while \\LaTeX{} complains (rightfully so) about the poor\n    spacing introduced by forcing float positions, instead of letting \\LaTeX{} take\n    care of it.\n    For the love of God, let \\LaTeX{} do its job in placing the floats.\n    Truth be told, they will on occasion not be placed where you need or want them.\n    Keep working.\n    At the very end, when all is done, go ahead and change the few \\emph{truly}\n    misplaced floats manually, by shoving them about in the source code\n    (still not using \\verb|htb!| flags).\n    This ensures minimal pain and maximum usage of \\LaTeX{}'s spacing and placing\n    capabilities.\n\n    Anyway --- here is such a float within an example box:\n    \\begin{figure}[H]\n        \\fcapside[\\FBwidth]{%\n            \\caption{%\n                Side-captions are still possible.\n                So are labels%\n            }\n            \\label{fig:inside_float}\n        }{%\n            \\includesvg[width=0.6\\linewidth]{compressor_impeller_isometric}\n        }\n    \\end{figure}\n    Note how using \\verb|\\linewidth| as a length, not the global constant\n    \\verb|\\textwidth|, figures can be scaled according to the current context.\n\n    This box even breaks across pages if so required.\n    Should this turn out ugly, some manual action is certainly required.\n\\end{example}\n"
  },
  {
    "path": "chapters/mainmatter/usage.tex",
    "content": "\\chapter{Usage}\n\nThis document \\enquote{requires}%\n\\footnote{\n    It does not \\emph{technically} require Docker, but I hope to convince you that\n    the non\\-/Docker, manual way is the way of the dodo and a big no\\-/no.\n}\n\\href{https://www.docker.com/}{Docker}.\nOn a high level, Docker allows to prepare specific software bundles, tailor\\-/made for\nwhatever application the bundle author desires.\nOther users can then use these software bundles for their own projects.\nThe bundles are well\\-/defined and can be distributed and run very easily.\nThe more complex and demanding the required software, the higher the benefit of using such bundles.\nThe driving design principle and primary use case for these bundles is \\emph{isolation}.\nWhatever you do with the bundles, it happens in isolation from your host system.\nThis allows a user to have, for example, arbitrary Python versions at their disposal,\nwhereas a local system installation can only ever offer a single version.\n\nFor a \\LaTeX{} document, the one at hand here is pretty complex.\nThis is owed to the many used packages and outside tooling.\nOutside tooling (programs other than \\LaTeX{} called from within \\LaTeX{}) is quite\nprevalent in \\LaTeX{}, since it itself is so limited.%\n\\footnote{\n    For example, when writing Python, you would not call Perl or JavaScript from within it,\n    because whatever they can do, Python can.\n    The same analogy does \\emph{not} hold for \\LaTeX{}: base \\LaTeX{} can do surprisingly\n    little, even though \\TeX{} is technically Turing\\-/complete.\n}\nLet us look at the outside tooling used for this document.\n\n\\section{Outside tools and special packages}\n\nThis section highlights the pain points of \\emph{not} using Docker.\nIf you are already familiar and need no convincing, skip to \\cref{ch:using-docker}.\nFor this document, outside tools are required for:\n\\begin{enumerate}\n    \\item \\ctanpackage{glossaries-extra}: requires the outside tool\n        \\ctanpackage{bib2gls}, see \\cref{ch:bib2gls}, which in turn requires\n        a Java Runtime Environment.\n    \\item \\ctanpackage{biblatex}: requires the outside tool \\ctanpackage{biber},\n        see \\cref{ch:bibliography_rationale}.\n    \\item \\ctanpackage{svg}: requires the outside program\n        \\href{https://inkscape.org/}{InkScape}.\n        Examples for that package's main command, \\verb|\\includesvg|, are\n        \\cref{fig:wide_caption,fig:tighter_caption,fig:multiple_floats,fig:sidecap,fig:inside_float}.\n    \\item Using \\texttt{contour gnuplot} commands with \\ctanpackage{pgfplots}, see\n        \\cref{fig:mollier_diagram}, requires\n        \\href{http://www.gnuplot.info/download.html}{gnuplot}.\n    \\item Syntax highlighting for source code, see \\cref{ch:code-listings},\n        is done through \\ctanpackage{minted}.\n        It requires \\href{https://www.python.org/}{Python} (built into virtually all Linux\n        distributions but needs to be installed on Windows) with its\n        \\href{https://pypi.org/project/Pygments/}{pygments} package installed.\n        That package does the heavy lifting and \\ctanpackage{minted} inserts the result\n        into your \\LaTeX{} document.\n\\end{enumerate}\n\nIf you have a proper \\LaTeX{} distribution, \\texttt{bib2gls} and \\texttt{biber}\nwill already be available as commands and ready to be invoked.\nThe latter means that they are on your \\texttt{\\$PATH}, \\iecfeg{i.e.}\\ the paths to\nthe respective binaries are part of the \\texttt{PATH} environment variable.\n\\emph{All other stuff, you have to install manually}.\n\nYou will have to install and keep everything else updated by hand.\nWhat if one of the dependencies of this document conflicts with something you have already\ninstalled on your system?\nWhat if that conflict is not resolvable?\nYou would be unable to use this document.\nThis is where Docker comes into play.\nYou outsource all this setting\\-/up to someone who already bundled all that stuff together.\nDocker calls these \\enquote{bundles} \\emph{images}.\nThere is a Docker image \\emph{tailor\\-/made} for this document:\n\\begin{center}\n    \\href{https://hub.docker.com/r/alexpovel/latex}{alexpovel/latex}.\n\\end{center}\nIt is guaranteed to function correctly for this document, since the author maintains both\nin parallel.\nThere will never be a mismatch.\nIf maintenance ceases, it will cease for both components at the same time, hence it will\nstill continue to work, just not get updated anymore.\n\n\\section{Using Docker}\n\\label{ch:using-docker}\n\nInstead of all of the above, \\textbf{only one installation is required}: Docker.\nYou can get it from\n\\begin{center}\n    \\url{https://docs.docker.com/get-docker/} .\n\\end{center}\n\\emph{You don't even need a \\LaTeX{} distribution}.\nAll you need is an editor to edit the files in, see \\cref{ch:editor}.\nOnce you want to compile, open a terminal, navigate to your directory and run\n\\begin{minted}[linenos=false]{powershell}\n    docker run --rm --volume ${PWD}:/tex alexpovel/latex\n\\end{minted}\nfor PowerShell or\n\\begin{minted}[linenos=false]{shell}\n    docker run --rm --volume $(pwd):/tex alexpovel/latex\n\\end{minted}\nfor bash.\nThat's it!\n\nThe command consists of:\n\\begin{itemize}\n    \\item The \\texttt{--rm} option, which removes the run container after you are done\n        (containers are \\enquote{instances} of images).\n        This is generally desired, since containers are ephemeral and should be treated as such.\n        Do not keep containers around, simply create new ones!\n        If you need adjustments, adjust the image, not the container, then create new containers\n        from that adjusted image.\n    \\item The \\texttt{--volume} option makes the current directory (\\texttt{pwd})\n        available \\emph{inside} the running container, at the \\texttt{/tex} destination path.\n        The \\LaTeX{} process needs your files to work with.\n        Without this option, the container would be \\enquote{naked}, with no way of\n        accessing your files.\n    \\item The final argument to \\texttt{docker run} is the image to be run, in this case\n        \\texttt{alexpovel/latex}, which will look for that name on\n        \\href{https://hub.docker.com/}{DockerHub}.\n\\end{itemize}\n\nIdeally, the command can be registered as the \\enquote{compilation} command of your\neditor.\nThat way, you just hit the compile button and will be using Docker in the background,\nwith no changes to your workflow.\n\n\\subsection{Compilation steps}\n\\label{ch:compilation_steps}\n\nYou are probably used to running \\texttt{pdflatex} or similar on your source files,\nas many times as needed.\nSo where does that step happen in the above \\texttt{docker} command?\n\nThe Docker approach uses the \\textbf{\\texttt{latexmk}} tool to ease all the painful labour\nof running chains of \\texttt{pdflatex}, \\texttt{biber} \\iecfeg{etc}.\\ manually.\n\\texttt{latexmk} automates \\LaTeX{} compilation by detecting all the required\nsteps and then running them as often as required.\nIt requires \\textbf{Perl}.\nLinux users will already have it available, Windows users may grab\n\\href{http://strawberryperl.com/}{Strawberry Perl}.\nAs such, this document's processing pipeline \\emph{as a whole} requires Perl,\nalthough it is technically not required for document compilation only.\n\nOnce Perl is installed (of course, the Docker image already contains it),\nthe entire document can be compiled by \\textbf{simply calling \\texttt{latexmk}}.\nYou do not even have to provide a \\texttt{*.tex} file argument.\nBy default, \\texttt{latexmk} will simply compile all found \\texttt{*.tex} files.\n\\textbf{The core ingredient to this magic process is the \\texttt{.latexmkrc} configuration file}.\nYou can find it in the repository root directory.\nIt is tailored to this document and does not need to be touched if the compilation\nprocess itself has not changed.\nIt also contains some more insights to the entire process.\n\n\\texttt{latexmk} is great because it figures out most things by itself and enjoys\nwide\\-/spread acceptance and adoption.\nIf it does not figure out everything from the get\\-/go, it is easily customized,\nlike for this document.\n\nHaving walked through all this manually, hopefully using the prepared Docker image\ninstead makes more sense now.\nIt is guaranteed to work for everyone, because the Docker container (that is, the\nvirtual build environment) will be identical for all users.\nIt is independent of local \\LaTeX{} installations and all their quirks.\nAs such, it simply and forever does away with the entire, huge class of\n\\begin{displayquote}[Everyone, at some point]\n    But it works on my machine!\n\\end{displayquote}\nGood riddance to that.\n\nIf all of this is embedded into a pipeline on GitLab, GitHub Actions, or similar,\nyour documents are built whenever you \\texttt{git push} to the remote server\n(or whenever you configure it to).\nIt does not get simpler; the downside is of course the lengthier setup.\nAlso, the repository itself is a live demonstration where everything is set up already!\n\n\\subsubsection{Slow compilation}\n\nThe most prevalent downside to \\texttt{latexmk} are longer compilation times.\nThe tool examines changes in auxiliary and source files.\nThis is made possible by the way \\LaTeX{} works with its kind of unique way of writing out auxiliary files (a system of multiple passes).\nConsider a simplified, manual example chain:\n\\begin{enumerate}\n    \\item You have a \\texttt{test.tex} file (and nothing else!), with \\texttt{cref} or equivalent cross\\-/referencing commands in it.\n    \\item You compile the file \\emph{once}, \\iecfeg{e.g.}\\ using \\texttt{lualatex}.\n    \\item A \\texttt{test.aux} file (and probably others, \\iecfeg{e.g.}\\ \\texttt{.toc}) will have been generated, as well as the \\abb{portable_document_format} file itself.\n\n        The \\abb{portable_document_format} has literal \\textbf{??} markers where there should be references.\n        This is because to resolve those references, and print \\iecfeg{e.g.}\\ the correct page number, \\LaTeX{} needs to look into the \\texttt{.aux} file.\n        But that file was just generated and was not available yet for the first compilation run.\n    \\item Hence, you compile again.\n\n        The \\textbf{??} markers are now replaced by their properly spelled\\-/out reference.\n        However, what if, hypothetically, one of these \\textbf{??} substitutions now reads \\emph{very super long reference to page 37 in the document}.\n        It is so long that subsequent content has shifted again.\n        That content is now on different pages.\n        This triggered another change in the auxiliary files.\n    \\item \\label{item:last_compilation} You compile \\emph{again}, the third time.\n        Things have settled, no changes happened this time anymore.\n        You are done.\n\\end{enumerate}\n\n\\texttt{latexmk} works by detecting this convergence towards a steady\\-/state (which may, through bugs, never be reached).\nHowever, it would compile \\emph{an additional} time after \\cref{item:last_compilation}, to make sure or because it cannot really be certain (just talking from experience here, not knowledge).\nSo while you gain deterministic, automated builds, they will take much longer.\n\nWhat if you do not care if there are \\textbf{??} markers left, undefined entries, shifted pages and so forth, maybe because you are only drafting things up?\nYou can simply compile yourself once, manually, \\iecfeg{e.g.}\\ using \\texttt{lualatex}.\nThis will speed things up by a long shot, but is considered advanced usage.\nIt does, as opposed to \\texttt{latexmk}, not \\enquote{just work} anymore, and beginners might wonder what those \\textbf{??} are.\nNow that you know, you may handle them.\n\n\\paragraph{Faster compilation}\nThe base \\texttt{docker} commands were shown at the beginning of \\cref{ch:using-docker}.\nAn alternative is to run\n\\begin{minted}[linenos=false]{shell}\n    docker run --rm --volume $(pwd):/tex alexpovel/latex -e '$max_repeat=1'\n\\end{minted}\nThis limits \\texttt{latexmk} to only run commands once (\\texttt{-e} is for additional Perl code), with the following effects:\n\\begin{itemize}\n    \\item \\texttt{latexmk} might complain that it did not succeed for lack of repeats (including a non\\-/zero exit code, meaning failure when it was only partial failure).\n    \\item Results are compiled quickly.\n    \\item \\texttt{latexmk} and its tailor\\-/made config is still used under the hood, so you do not have to adjust anything.\n    \\item Other commands like \\texttt{biber} for bibliography generation might still be run.\n\\end{itemize}\nThis is probably your best bet to get faster drafting cycles while retaining high likelihood of it working.\n\n\\paragraph{Fastest compilation}\nThe following method is the most advanced (but not hard at all!).\nTo overwrite the Docker image's default, so\\-/called \\mintinline{dockerfile}{ENTRYPOINT}, which is \\texttt{latexmk}, run the command as:\n\\begin{minted}[linenos=false]{shell}\n    docker run --rm --volume $(pwd):/tex --entrypoint=\"lualatex\" alexpovel/latex --shell-escape $FILENAME\n\\end{minted}\nNotice that you now have to give a filename, like \\texttt{cookbook.tex}, since \\texttt{lualatex} expects that.\nThe above command is exactly like running \\emph{only} \\texttt{lualatex}, just in the context of that image (with your files made available at \\texttt{/tex}).\nThe effects of this command are:\n\\begin{itemize}\n    \\item No \\texttt{latexmk} involved at all:\n    \\begin{itemize}\n        \\item it is therefore the fastest approach,\n        \\item but you have to pass all required options yourself (like \\texttt{--shell-escape}).\n    \\end{itemize}\n    \\item No commands like \\texttt{biber} run; you have to do that yourself (or use \\texttt{latexmk}).\n\\end{itemize}\nThis is the approach I personally use, while outsourcing the full \\texttt{latexmk}\\-/based compilations to a server using \\abb{continuous_integration}/\\abb{continuous_delivery}.\nIt affords us the fastest iteration speeds while having a full version available \\enquote{in the background}: the best of both worlds and arguably the fastest workflow.\n\n\\paragraph{Fastest still slow}\nWe cannot compile faster than a naked \\texttt{lualatex} run (\\texttt{docker} overhead is negligible).\nFor the current document you see here, even such a single run takes about one minute.\nRemember that you need upwards of three runs from a \\enquote{cold} (no auxiliary files, empty caches, \\dots{}) start.\nSingle, article\\-/size, \\texttt{pdflatex}\\-/based documents compile in only a few seconds.\nThe reasons for the slowness are, among others:\n\\begin{itemize}\n    \\item \\texttt{lualatex} is simply considerably slower than \\texttt{pdflatex}\n        (the additional capabilities make up for that many times over).\n        One reason is the time spent dealing with (system) fonts.\n    \\item This document loads a metric crapton of packages, some of which are very expensive to load, like \\ctanpackage{tikz}.\n        This is in the spirit of providing a useful document with numerous examples of various functionalities and packages.\n        You should definitely \\textbf{\\textcolor{mRed}{comment out the packages you do not need}}.\n    \\item Compiling the entire document takes long, so \\textbf{\\textcolor{mRed}{make use of the \\texttt{include} and \\texttt{subinclude}} commands and comment out unneeded parts}.\n        The more fine\\-/grained you do this, the more control you get.\n        If you cut it down to short (only a handful of \\abb{portable_document_format} pages) files, you can work on and compile only those.\n        This method has the highest time saving potential.\n    \\item If you perform \\ctanpackage{pgfplots} calculations within \\LaTeX{}, \\iecfeg{c.f.}\\ \\cref{fig:plotting_in_latex,fig:plotting_in_latex_tufte,fig:mollier_diagram}, expect significant slowness.\n        For simple plots, this is still much better than having to use an external program, export data, import to \\LaTeX{}, repeat on data change (instead of adjusting the equation in \\LaTeX{} directly) \\iecfeg{etc.}\n    \\item \\LaTeX{} is not compiled in parallel.\n\\end{itemize}\nThis document is like an aircraft carrier: modern, feature\\-/rich and high\\-/impact, but very sluggish.\n\n\\subsection{More on Docker}\n\nYou do not need to know of the entire chain of how Docker images are created and run.\nOnly consuming the final image has all the benefits with little effort.\nHowever, the process is not complex:\n\\begin{enumerate}\n    \\item A \\textbf{\\texttt{Dockerfile} text document} is created, containing instructions on how the image should look like (like what stuff to install, what to copy where, ...).\n\n        As a baseline, these instructions often rely on a Debian distribution.\n        As such, all the usual Debian/Linux tools can be accessed, like \\texttt{bash}.\n\n        An (unrelated)\n        \\href{https://github.com/alexpovel/random_python/blob/master/music-converter/Dockerfile}{example Dockerfile}\n        can look like:\n\n        \\begin{minted}{dockerfile}\n            # Get the latest Debian Slim with Python installed\n            FROM python:slim\n\n            # Update the Debian package repositories and install a Debian package.\n            # Agree to installation automatically (`-y`)!\n            # This is required because Dockerfiles need to run without user interaction.\n            RUN apt-get update && apt-get install -y ffmpeg\n\n            # Copy a file from the building host into the image\n            COPY requirements.txt .\n\n            # Run some shell command, as you would in a normal sh/bash environment.\n            # This is a Python-specific command to install Python packages according to some\n            # requirements.\n            RUN pip install -r requirements.txt\n\n            # Copy more stuff!\n            COPY music-converter/ music-converter/\n\n            # This will be the command the image executes if run.\n            # It runs this command as a process and terminates as soon as the process ends\n            # (successfully or otherwise).\n            # Docker is not like a virtual machine: it is intended to run *one* process, then\n            # die. If you need to run it again, just create a new container (instance of a\n            # Docker image). Treat containers as *cattle*, not as a *pet*. The\n            # container-recreation process is light-weight, fast and the way to go.\n            #\n            # Of course, this does not stop anyone from running one *long-running* process\n            # (as in infinity, `while True`-style). This is still a good use-case for Docker\n            # (as are most things!). An example for this is a webserver.\n            ENTRYPOINT [ \"python\", \"-m\", \"music-converter\", \"/in\", \"--destination\", \"/out\" ]\n        \\end{minted}\n\n        The Dockerfile this project uses for LaTeX stuff is here:\n        \\begin{center}\n            \\url{https://github.com/alexpovel/latex-extras-docker/blob/master/Dockerfile}\n        \\end{center}\n        It is not as simple, so not as suited for an example.\n        Its length gives you an idea of the setup required to compile this \\LaTeX{} document.\n        All of that complexity is of no concern to you when using Docker!\n        Of course, such an image also works for much simpler documents.\n\n        If you require custom additions, you can always inherit from existing base images:\n        \\begin{minted}{dockerfile}\n            FROM alexpovel/latex\n\n            # ... Your stuff goes here ...\n        \\end{minted}\n    \\item The \\textbf{image} is then built according to the \\texttt{Dockerfile} instructions,\n        resulting in a large\\-/ish file that contains an executable environment.\n        For example, if we install a comprehensive TeXLive distribution, the image can be\n        more than \\qty{2}{\\giga\\byte} in size.\n        Note that you will never interact with that \\enquote{file} directly.\n        Docker manages it for you, and all interaction occurs through the \\texttt{docker} command.\n\n        The Docker image can be distributed.\n        If you just instruct to run an image called \\iecfeg{e.g.} \\texttt{alexpovel/latex}, without\n        specifying a full URL to somewhere, Docker will look on its Hub for an image of that\n        name (and find it \\href{https://hub.docker.com/r/alexpovel/latex}{here}).\n        Anyone can pull (public) images from there, and everyone will\n        be on the same page (alternatively, you can build the image from the Dockerfile).\n\n        For example, as stated, the \\LaTeX{} environment for this project requires a whole bunch of setting\\-/up.\n        This can take more than an afternoon to read up upon, understand, implement and getting to run.\n        In some cases, it will be impossible if some required part of a project conflicts\n        with a pre\\-/existing condition on your machine.\n        For example, suppose project \\emph{A} requires Perl in version \\texttt{6.9.0},\n        but project \\emph{B} requires version \\texttt{4.2.0}.\n        This is what Docker is all about: isolation.\n        Whatever is present on your system does not matter, only the Docker image/container\n        contents are relevant.\n\n        Further, if you for example specify \\mintinline{dockerfile}{FROM python:3.8.6}\n        as your base image, aka provided a so\\-/called tag of \\texttt{3.8.6}, it will be that tag in ten years' time still.\n        As such, you nailed the version your process takes place in and requires.\n        Once set up, this will run on virtually any computer running Docker, be it your\n        laptop now or whatever your machine is in ten years.\n        This is especially important for the reproducibility of research.\n    \\item Once the image is created, it can be run, \\textbf{creating a container}.\n        We can then enter the container and use it like a pretty normal (usually Linux)\n        machine, for example to compile our \\LaTeX{} files.\n        Other, single commands can also be executed.\n\n        The proper way is to run one container \\emph{per process}.\n        If that process (\\iecfeg{e.g.}\\ \\texttt{latexmk}) finishes, the container exits.\n        A new process then requires a new container.\n\\end{enumerate}\n\n\\subsection{Editor}\n\\label{ch:editor}\n\nYou are free to do whatever you want.\nHowever, a garbage editor can substantially hamstring your work.\nFor example, please do not use Notepad++.\nIt is a fantastic little program but unsuitable for any serious, longer work.\n\nThe author uses and dearly recommends \\href{https://code.visualstudio.com/}{Visual Studio Code},\nusing its\n\\href{https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop}{\\LaTeX{} Workshop} extension, which provides syntax highlighting, shortcuts and many other useful things.\nVisual Studio Code is among the most state\\-/of\\-/the\\-/art editors currently available.\nBeing usable for \\LaTeX{} is just a nice side\\-/effect we can take advantage of.\nIt is open\\-/source and therefore also has a privacy\\-/respecting alternative fork, \\emph{VSCodium}.\n\nFor a more conventional, complete \\abb{integrated_development_environment},\ntry \\href{https://www.texstudio.org/}{TeXStudio}.\nLike VSCode, it is also\n\\href{https://github.com/texstudio-org/texstudio}{open source}.\nTeXStudio will cater to \\qty{90}{\\percent} of your \\LaTeX{} needs, but nothing else (Markdown, \\dots{}).\n\n\\subsubsection{Visual Studio Code}\n\nThe repository of this document comes with a \\href{https://github.com/microsoft/vscode-dev-containers}{\\texttt{.devcontainer}} directory.\nIn it is all the configuration necessary to run your development environment \\emph{inside} the Docker container entirely.\nTo make the magic work, install the \\href{https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers}{\\emph{Remote -- Containers}} extension.\nVisual Studio Code automatically prompts you to install it when you first open this repository, as configured in \\texttt{.vscode/extensions.json}.\nFollow the instructions there on how to download all prerequisites, like of course Docker.\nVisual Studio Code will detect the remote container configuration of this repository automatically.\nIf not, run the steps manually:\n\\begin{enumerate}\n    \\item Open the command palette (\\keys{\\ctrl{} + \\shift{} + P} --- the command palette is one of the defining, core features of Visual Studio Code, it's great!).\n    \\item Run \\menu{Remote-Containers: Reopen in container}.\n\\end{enumerate}\nYour development environment is now \\emph{inside} the container.\nHence, if you ran for example \\texttt{latexmk} in the console, it executes the container version.\nThis is exactly what we want and previously did using the \\texttt{docker run} command.\n\n\\paragraph{Extensions}\nThere is a small problem.\nOn its own, Visual Studio Code has no concept of \\LaTeX{}, since out of the box, it is much closer to being an editor than an \\abb{integrated_development_environment}.\nYou increase the program's capabilities by choosing and installing extensions.\nUsing the \\href{https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop}{\\emph{LaTeX Workshop}} extension for Visual Studio Code is recommended.\nFor the container environment, it is installed automatically from the settings found in \\texttt{devcontainer.json}.\nThe \\emph{LaTeX Workshop} extension turns Visual Studio Code into a \\LaTeX{} \\abb{integrated_development_environment}.\nIt works using \\emph{recipes}, which in turn use \\emph{tools}.\nThe extension comes with a pre\\-/defined \\texttt{latexmk} tool:\n\\begin{enumerate}\n    \\item Open the command palette.\n    \\item Run \\menu{LaTeX Workshop: Build with recipe > latexmk}.\n\\end{enumerate}\nThis just runs \\texttt{latexmk} within the container.\nAs usual using Docker, your host machine does not need a \\LaTeX{} installation for this to work.\nIf you want, you can stop here --- running \\texttt{latexmk} is all that is ever needed.\nHit \\keys{\\ctrl{} + \\Alt{} + B} to build the project again, using the last used recipe.\n\n\\paragraph{Settings}\nYou can configure \\emph{everything} in Visual Studio Code, including its extensions, in the settings.\nOpen them by either:\n\\begin{itemize}\n    \\item The command palette at \\menu{Preferences: Open Settings (JSON)}, or\n    \\item navigating to \\menu{File > Preferences > Settings}, then opening as \\abb{js_object_notation}.\n\\end{itemize}\nFor example, as discussed at the end of \\cref{ch:compilation_steps}, you might want to have a recipe that only runs \\texttt{lualatex}, once.\nThis is \\textbf{already taken care of} for this repository:\n\\inputminted{json}{./.vscode/settings.json}\nThese are \\emph{Workspace Settings}, which \\href{https://code.visualstudio.com/docs/getstarted/settings}{take precedence over (global) user settings}.\nAs such, they also override all the recipes \\emph{LaTeX Workshop} usually comes with.\nYou will have to define more recipes yourself.\n\nWith the new recipes, you can now run\n\\begin{center}\n    \\menu{LaTeX Workshop: Build with recipe > lualatex}\n\\end{center}\nfrom the command palette.\nNotice the freedom and flexibility you have for defining many more recipes.\nIn fact, alongside \\texttt{latexmk} and classic \\texttt{make}, you now have more potential flexibility and automation than one could possibly need.\n\nUsing the above \\emph{Remote -- Containers} approach, the entire development chain happens inside the container, with your working directory mounted into it.\nThis enables:\n\\begin{itemize}\n    \\item the \\emph{LaTeX Workshop} extension to work fully:\n        \\begin{itemize}\n            \\item SyncTeX works:\n                \\begin{itemize}\n                    \\item \\keys{\\ctrl{} + Click} into the \\abb{portable_document_format} preview goes to the source code\n                    \\item \\menu{LaTex Workshop: SyncTeX from cursor} (command palette) goes the other way.\n                \\end{itemize}\n            \\item Highlighting infos, warnings and errors (\\emph{Problems} pane) works\n            \\item \\href{https://github.com/James-Yu/LaTeX-Workshop/wiki/Intellisense}{IntelliSense} works, providing autocompletion for:\n                \\begin{itemize}\n                    \\item citations (\\texttt{autocite} \\iecfeg{etc.}) --- check out the \\emph{Citation Browser} in the command palette!\n                    \\item references (\\texttt{cref} \\iecfeg{etc.})\n                    \\item and more, like commands\n                \\end{itemize}\n            \\item Auto\\-/Formatting (\\keys{\\shift{} + \\Alt{} + F}) works (\\emph{LaTeX Workshop} uses \\ctanpackage{latexindent})\n        \\end{itemize}\n    \\item Your files are persisted normally, despite the container being ephemeral.\n    \\item Tools like \\texttt{make} work from within the Visual Studio Code terminal.\n        For example, run \\texttt{make clean} to clear everything not tracked by git.\n        This is very convenient for a cold start, because \\LaTeX{} sometimes gets stuck if auxiliary files are corrupted.\n\\end{itemize}\n\n\\paragraph{More Settings}\nFor more control, you might want to keep the extension from compiling on every document save:\n\\begin{minted}{json}\n    \"latex-workshop.latex.autoBuild.run\": \"never\"\n\\end{minted}\nSee \\href{https://github.com/James-Yu/LaTeX-Workshop/wiki/Compile#latex-recipes}{the official documentation} for more.\n\n\\subsubsection{Other Editors}\n\nYou will have to incorporate the \\texttt{docker} commands shown in \\cref{ch:using-docker} manually.\nMost editors do not support container\\-/native developing, so you will go the old\\-/school route.\n"
  },
  {
    "path": "chapters/mainmatter.tex",
    "content": "\\mainmatter\n\n% Uncomment the following if you'd like vertical space (with no indentation) between\n% paragraphs, instead of the default of *no* vertical space *with* indentation.\n% This lives inside the main matter since for example the `mcolalttree` style for\n% `glossaries-extra` (glossaries live in the front matter) is based around `\\par`, which\n% breaks if we request the `parskip` option.\n\n% \\KOMAoptions{parskip}\n\n\\subimport{mainmatter/}{usage}\n\\subimport{mainmatter/}{base-features}\n\\subimport{mainmatter/}{floats}\n\\subimport{mainmatter/}{code-listings}\n"
  },
  {
    "path": "cookbook.tex",
    "content": "% Magic Comment: this template requires LuaLaTeX. The following 'magic comment' is\n% recognized by editors and will ensure lualatex engine use:\n\n%!TEX TS-program = lualatex\n\n% Note that package `svg` also requires elevation, aka the `--shell-escape` option to\n% read/write SVG/PDF files.\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\documentclass[%\n    % Global language, passed down to packages and base class.\n    language=english,\n    titlestyle=thesis,% Style of titlepage: thesis, book or uncomment for vanilla\n    BCOR=5mm,% Binding Correction. Cannot be known a priori, only guesstimated\n    a4,% Options: a4/a5 for a4 paper with 11pt or a5 paper with 10pt, respectively\n    % Toggle all \\censor{} etc. commands, e.g. to generate a public version:\n    censoring=true,\n]{acp}% Load custom class file (*.cls)\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% This is still the preamble. You can insert '\\newcommand's and all other stuff here. If\n% it is a more long-term change, write it to the class (*.cls) file. You also find all\n% settings to existing packages there.\n\n%\\usepackage{showframe}% Uncomment for debugging (show frames)\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n% The following occurs here so VSCode's 'LaTeX Workshop' extension can find all bib\n% resources (it doesn't seem to look into class files):\n\\addbibresource{bib/bibliography.bib}% *.bib file goes here\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% Titlepage and document metadata content:\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\author{Alex Povel}%\n\n\\date{\\DTMtoday{}}% Print today's date w/ syntax of newer package datetime2\n\n\\title{A modern \\LaTeX{} cookbook}\n\n\\subtitle{% Examiners or other, rather arbitrary content\n    \\begin{tabular}[t]{% [t] sets tabular anchor to the top\n        @{}% Remove horizontal space left of tabular\n        l% If no really good reason to do otherwise, always left-align cell\n        @{\\ }% '\\ ' (backslash-space) is a small space, here a column separator\n        l\n        l\n        @{}% Remove horizontal space right of tabular\n    }\n        \\nth{1} & Examiner & Prof.\\ Jane Doe\\\\\n        \\nth{2} & Examiner & Prof.\\ Foo Bar\\\\\n        \\multicolumn{2}{@{}l}{Supervisor} & John Doe, M.Sc.%\n    \\end{tabular}\n}%\n\n\\documenttype{Example Document}% Document type, like Master Thesis, PhD Thesis, ...\n\n\\idnumber{666}% Enrolment/student ID number if applicable\n\n\\publishers{%\n    University of Greatness\\\\%\n    Institute of Big Bang%\n}% Institutions, university, etc. Can also use graphics here\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\\begin{document}\n    \\import{chapters/}{frontmatter}\n    \\import{chapters/}{mainmatter}\n    \\import{chapters/}{backmatter}\n\\end{document}\n"
  },
  {
    "path": "data/README.md",
    "content": "# (Raw) data\n\nThis directory contains data used inside the main document, e.g. CSV data for `pgfplots`.\nYou can put all sorts of things here.\n"
  },
  {
    "path": "data/diffuser.csv",
    "content": "R,M,Pi,Theta,Rho,alpha,R_pres\n1,0.8,1,1,1,15,1\n1.016666667,0.783683071,1.015164946,1.004602799,1.010513754,14.86740098,1.016666667\n1.033333333,0.768036211,1.029662489,1.008966272,1.020512299,14.74464478,1.033333333\n1.05,0.753014821,1.043529062,1.013107287,1.030028187,14.63084233,1.05\n1.066666667,0.738578426,1.056798955,1.017041194,1.039091593,14.52520715,1.066666667\n1.083333333,0.724690667,1.069503564,1.020781859,1.047729791,14.42704236,1.083333333\n1.1,0.711318399,1.081672288,1.024341949,1.055967969,14.33572754,1.1\n1.116666667,0.698431125,1.093333083,1.027733116,1.063829768,14.25070752,1.116666667\n1.133333333,0.686000827,1.104512334,1.030966065,1.071337236,14.17148429,1.133333333\n1.15,0.674001977,1.115234408,1.034050577,1.078510503,14.09761064,1.15\n1.166666667,0.662411065,1.125522178,1.036995663,1.08536826,14.02868356,1.166666667\n1.183333333,0.651206258,1.135397416,1.039809668,1.09192812,13.96433827,1.183333333\n1.2,0.64036732,1.144880709,1.042500316,1.098206582,13.90424402,1.2\n1.216666667,0.62987562,1.153991176,1.045074722,1.104218819,13.84810071,1.216666667\n1.233333333,0.619713857,1.162746803,1.047539484,1.109978975,13.79563529,1.233333333\n1.25,0.609865858,1.171164727,1.049900747,1.115500423,13.74659837,1.25\n1.266666667,0.600316526,1.179261177,1.052164226,1.120795735,13.70076187,1.266666667\n1.283333333,0.591051844,1.187051288,1.054335225,1.125876533,13.65791712,1.283333333\n1.3,0.58205872,1.194549326,1.056418685,1.13075369,13.61787279,1.3\n1.316666667,0.573324841,1.201768898,1.058419229,1.135437514,13.58045281,1.316666667\n1.333333333,0.56483865,1.208722909,1.060341177,1.139937725,13.54549501,1.333333333\n1.35,0.55658935,1.215423436,1.062188559,1.144263347,13.51285004,1.35\n1.366666667,0.5485668,1.221881881,1.063965144,1.148422848,13.48238004,1.366666667\n1.383333333,0.540761419,1.228109134,1.065674473,1.152424276,13.45395735,1.383333333\n1.4,0.533164175,1.234115536,1.067319869,1.156275239,13.42746374,1.4\n1.416666667,0.525766583,1.239910796,1.068904442,1.159982826,13.40278965,1.416666667\n1.433333333,0.518560637,1.245504093,1.070431116,1.163553708,13.37983341,1.433333333\n1.45,0.511538748,1.250904206,1.071902642,1.166994238,13.35850038,1.45\n1.466666667,0.50469373,1.256119485,1.073321614,1.170310436,13.33870246,1.466666667\n1.483333333,0.498018804,1.261157785,1.074690467,1.17350793,13.32035762,1.483333333\n1.5,0.49150755,1.266026551,1.076011499,1.176592027,13.30338937,1.5\n1.516666667,0.485153862,1.270732905,1.077286878,1.179567794,13.28772618,1.516666667\n1.533333333,0.478951937,1.275283637,1.078518652,1.182440039,13.27330119,1.533333333\n1.55,0.472896282,1.279685147,1.079708753,1.185213275,13.26005186,1.55\n1.566666667,0.466981677,1.283943509,1.080859007,1.18789176,13.24791965,1.566666667\n1.583333333,0.461203143,1.288064544,1.081971143,1.190479573,13.2368496,1.583333333\n1.6,0.455555936,1.292053806,1.083046797,1.192980589,13.22679012,1.6\n1.616666667,0.450035549,1.295916543,1.084087518,1.195398454,13.21769282,\n1.633333333,0.444637686,1.299657743,1.085094773,1.197736618,13.20951217,\n1.65,0.439358241,1.303282192,1.086069953,1.199998387,13.20220536,\n1.666666667,0.434193291,1.306794463,1.087014381,1.202186913,13.195732,\n"
  },
  {
    "path": "data/matlab2tikz_table_example.tex",
    "content": "% This file was created by matlab2tikz.\n%\n%The latest updates can be retrieved from\n%  http://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz-matlab2tikz\n%where you can also make suggestions and rate matlab2tikz.\n%\n\\begin{tikzpicture}\n\n\\begin{axis}[%\n% width=6.053in,\n% height=5.538in,\n% at={(1.338in,1.274in)},\nscale only axis,\nxmin=0,\nxmax=150000,\nxlabel style={font=\\color{white!15!black}},\nxlabel={Reynold's Number [-]},\nymin=-20,\nymax=60,\nylabel style={font=\\color{white!15!black}},\nylabel={Drag coefficient $\\zeta$ [-]},\naxis background/.style={fill=white},\naxis x line*=bottom,\naxis y line*=left,\nxmajorgrids,\nymajorgrids,\nlegend style={legend cell align=left, align=left, draw=white!15!black},\ntable/col sep=space,\n]\n\\addplot [color=black, only marks, mark=o, mark options={solid, black}]\n plot [error bars/.cd, y dir=both, y explicit, error bar style={line width=0.5pt}, error mark options={line width=0.5pt, mark size=6.0pt, rotate=90}]\n table[row sep=crcr, y error plus index=2, y error minus index=3]{%\n91450.4005348642\t18.8206494302446\t0.22784420833039\t0.22784420833039\\\\\n9600.2287009917\t17.0940855567971\t18.8769483727188\t18.8769483727188\\\\\n98040.7874556726\t18.6728583096816\t0.202036909770865\t0.202036909770865\\\\\n65157.2349669312\t19.3095953696594\t0.418204806276939\t0.418204806276939\\\\\n49337.9741089259\t19.8795961310237\t0.722764642682136\t0.722764642682136\\\\\n16355.6858822063\t21.6588058718839\t6.48504129977849\t6.48504129977849\\\\\n68662.1156767816\t19.2826158073702\t0.379906394244728\t0.379906394244728\\\\\n88193.8884388812\t18.8512612583498\t0.241587510229639\t0.241587510229639\\\\\n52897.2052503459\t19.7556610691345\t0.63682805169426\t0.63682805169426\\\\\n45361.2310463829\t19.9283864286216\t0.857322986465614\t0.857322986465614\\\\\n35629.1264772871\t20.5353610928944\t1.37414627818398\t1.37414627818398\\\\\n95043.2938482082\t18.7591297797428\t0.213416328531058\t0.213416328531058\\\\\n61640.0699375336\t19.465583058119\t0.466703246588861\t0.466703246588861\\\\\n58751.4523099524\t19.4914842217088\t0.508777380354382\t0.508777380354382\\\\\n41886.8624922781\t20.2213805881069\t0.988945957346638\t0.988945957346638\\\\\n71787.1923690876\t19.183171510498\t0.349958881481435\t0.349958881481435\\\\\n55566.6189222481\t19.6884300185046\t0.57492765151384\t0.57492765151384\\\\\n22414.4905749956\t21.4563894028588\t3.46477796770842\t3.46477796770842\\\\\n29891.5116045859\t20.8072061681644\t1.95317002720734\t1.95317002720734\\\\\n81648.5561586976\t18.9338775855205\t0.276308105964505\t0.276308105964505\\\\\n84915.3205825358\t18.9018965006065\t0.25775055811768\t0.25775055811768\\\\\n12748.6992906755\t20.956252098279\t10.6964468685791\t10.6964468685791\\\\\n19702.7655801537\t21.3720690437585\t4.47489311485873\t4.47489311485873\\\\\n78363.5688516276\t19.0751370068433\t0.297546198952902\t0.297546198952902\\\\\n32704.8269868436\t20.8291059476584\t1.63441062956786\t1.63441062956786\\\\\n39454.0447791576\t20.3956969160794\t1.11850790152941\t1.11850790152941\\\\\n25852.5857440217\t21.5131319639883\t2.60715319679087\t2.60715319679087\\\\\n75047.302268985\t19.1129078534408\t0.322186799342343\t0.322186799342343\\\\\n};\n\\addlegendentry{9 bar, 30 $^\\circ$C}\n\n\\addplot [color=blue, only marks, mark=o, mark options={solid, blue}]\n plot [error bars/.cd, y dir=both, y explicit, error bar style={line width=0.5pt}, error mark options={line width=0.5pt, mark size=6.0pt, rotate=90}]\n table[row sep=crcr, y error plus index=2, y error minus index=3]{%\n90364.8194858743\t18.851972315629\t0.305217342375055\t0.305217342375055\\\\\n8076.2640578434\t24.0111558434839\t35.8029501848227\t35.8029501848227\\\\\n50772.0591562781\t19.7992917932574\t0.928394801097195\t0.928394801097195\\\\\n66195.4322434412\t19.2914810641625\t0.550235869227531\t0.550235869227531\\\\\n47363.6661097263\t20.0685366715685\t1.0630574120011\t1.0630574120011\\\\\n19902.7764508919\t21.2759580135189\t5.98521694141482\t5.98521694141482\\\\\n39900.5151261104\t20.5397185970455\t1.48849529409474\t1.48849529409474\\\\\n74866.732832787\t19.0900594677447\t0.434436734327329\t0.434436734327329\\\\\n82545.9819399738\t18.9439559950128\t0.361002096005894\t0.361002096005894\\\\\n106171.719883028\t18.6283535384433\t0.229496342278619\t0.229496342278619\\\\\n94122.014260214\t18.7599655960001\t0.282619972807026\t0.282619972807026\\\\\n55431.0307804117\t19.61223734667\t0.783444980800781\t0.783444980800781\\\\\n59322.7541290298\t19.6319108649163\t0.684931628377185\t0.684931628377185\\\\\n114221.038645558\t18.4694576373584\t0.203347977101083\t0.203347977101083\\\\\n78925.5166005358\t19.0282740070502\t0.393135093952\t0.393135093952\\\\\n63096.2993854333\t19.3936301169532\t0.605948000756784\t0.605948000756784\\\\\n86358.0944477848\t18.8993234493532\t0.331341638288088\t0.331341638288088\\\\\n110454.377590452\t18.567036984956\t0.214660611248231\t0.214660611248231\\\\\n35864.0452240558\t20.7795087552391\t1.84052287954811\t1.84052287954811\\\\\n102270.885599624\t18.6534024509903\t0.244662856478561\t0.244662856478561\\\\\n15625.3491197509\t23.0212986293325\t9.68121139016299\t9.68121139016299\\\\\n98275.2673711873\t18.6797685109276\t0.262281703155193\t0.262281703155193\\\\\n31352.5742431042\t21.0124223239215\t2.41763424066977\t2.41763424066977\\\\\n12313.9582502865\t22.5336653922509\t15.5170405633573\t15.5170405633573\\\\\n118521.184105338\t18.4634946805162\t0.191715543444072\t0.191715543444072\\\\\n27954.591413931\t21.1733665963443\t3.03909219686198\t3.03909219686198\\\\\n23661.526874057\t21.8398598857805\t4.23960949267591\t4.23960949267591\\\\\n70936.4289641694\t19.2203716274935\t0.481640104330054\t0.481640104330054\\\\\n43616.6098039867\t20.3724031756756\t1.24623498410928\t1.24623498410928\\\\\n};\n\\addlegendentry{13.2 bar, 45 $^\\circ$C}\n\n\\addplot [color=red, only marks, mark=o, mark options={solid, red}]\n plot [error bars/.cd, y dir=both, y explicit, error bar style={line width=0.5pt}, error mark options={line width=0.5pt, mark size=6.0pt, rotate=90}]\n table[row sep=crcr, y error plus index=2, y error minus index=3]{%\n17867.5515609687\t21.7652508894877\t9.15368581910848\t9.15368581910848\\\\\n125637.055996345\t18.3877470989716\t0.20747930927834\t0.20747930927834\\\\\n49304.731241175\t19.807149989706\t1.22247182825836\t1.22247182825836\\\\\n107667.483438579\t18.6074812032667\t0.27078355428531\t0.27078355428531\\\\\n13536.3513622991\t22.9216117473262\t16.0120267998002\t16.0120267998002\\\\\n71994.5089139876\t19.1461599074966\t0.579982264504498\t0.579982264504498\\\\\n58949.4992802703\t19.4584247735011\t0.863655495599455\t0.863655495599455\\\\\n22441.0358182932\t20.9345419939241\t5.80047673858736\t5.80047673858736\\\\\n44296.5080074942\t19.8307916472566\t1.50683347198268\t1.50683347198268\\\\\n36163.6188854124\t20.1076548679491\t2.265078120627\t2.265078120627\\\\\n121252.135326159\t18.4363699283627\t0.220566362796363\t0.220566362796363\\\\\n85072.0354168332\t18.8324850607434\t0.418963400171204\t0.418963400171204\\\\\n103030.125538593\t18.6109968334098\t0.292673058569925\t0.292673058569925\\\\\n62664.4453756571\t19.3182930613143\t0.76166308494462\t0.76166308494462\\\\\n66814.802347003\t19.1511266386389\t0.671621933741905\t0.671621933741905\\\\\n40023.6860323227\t20.3563108994464\t1.84868057936682\t1.84868057936682\\\\\n98428.0786967929\t18.7052786521598\t0.318212576297495\t0.318212576297495\\\\\n94101.3387888276\t18.7365240146046\t0.345945890970535\t0.345945890970535\\\\\n112249.405136342\t18.541593643746\t0.2517944419942\t0.2517944419942\\\\\n31272.4427821611\t20.5767680935139\t3.01988954371356\t3.01988954371356\\\\\n76452.8638484087\t19.0625190030148\t0.518185514149112\t0.518185514149112\\\\\n53939.2603758079\t19.6676345378916\t1.02315173365127\t1.02315173365127\\\\\n130240.937716863\t18.3435824135538\t0.195735083846963\t0.195735083846963\\\\\n27281.4692961602\t20.8755273958803\t3.96092444894359\t3.96092444894359\\\\\n81017.1760328248\t18.9834687699148\t0.462576998836875\t0.462576998836875\\\\\n90129.3849290184\t18.7809056600762\t0.376175674619081\t0.376175674619081\\\\\n134854.212682816\t18.3289989496668\t0.185163179879921\t0.185163179879921\\\\\n116773.970377645\t18.4532827516731\t0.235074764576524\t0.235074764576524\\\\\n};\n\\addlegendentry{16.6 bar, 55 $^\\circ$C}\n\n\\end{axis}\n\n\\begin{axis}[%\n% width=8.167in,\n% height=7.365in,\n% at={(0in,0in)},\nscale only axis,\nxmin=0,\nxmax=1,\nymin=0,\nymax=1,\naxis line style={draw=none},\nticks=none,\naxis x line*=bottom,\naxis y line*=left\n]\n\\end{axis}\n\\end{tikzpicture}%\n"
  },
  {
    "path": "data/matlab2tikz_table_example_data.csv",
    "content": "Pressure, Temperature, Reynolds, Drag_Coefficient, Drag_Coefficient_Error_Pos, Drag_Coefficient_Error_Neg\n9, 30, 91450.4005348642, 18.8206494302446, 0.22784420833039, 0.22784420833039\n9, 30, 9600.2287009917, 17.0940855567971, 18.8769483727188, 18.8769483727188\n9, 30, 98040.7874556726, 18.6728583096816, 0.202036909770865, 0.202036909770865\n9, 30, 65157.2349669312, 19.3095953696594, 0.418204806276939, 0.418204806276939\n9, 30, 49337.9741089259, 19.8795961310237, 0.722764642682136, 0.722764642682136\n9, 30, 16355.6858822063, 21.6588058718839, 6.48504129977849, 6.48504129977849\n9, 30, 68662.1156767816, 19.2826158073702, 0.379906394244728, 0.379906394244728\n9, 30, 88193.8884388812, 18.8512612583498, 0.241587510229639, 0.241587510229639\n9, 30, 52897.2052503459, 19.7556610691345, 0.63682805169426, 0.63682805169426\n9, 30, 45361.2310463829, 19.9283864286216, 0.857322986465614, 0.857322986465614\n9, 30, 35629.1264772871, 20.5353610928944, 1.37414627818398, 1.37414627818398\n9, 30, 95043.2938482082, 18.7591297797428, 0.213416328531058, 0.213416328531058\n9, 30, 61640.0699375336, 19.465583058119, 0.466703246588861, 0.466703246588861\n9, 30, 58751.4523099524, 19.4914842217088, 0.508777380354382, 0.508777380354382\n9, 30, 41886.8624922781, 20.2213805881069, 0.988945957346638, 0.988945957346638\n9, 30, 71787.1923690876, 19.183171510498, 0.349958881481435, 0.349958881481435\n9, 30, 55566.6189222481, 19.6884300185046, 0.57492765151384, 0.57492765151384\n9, 30, 22414.4905749956, 21.4563894028588, 3.46477796770842, 3.46477796770842\n9, 30, 29891.5116045859, 20.8072061681644, 1.95317002720734, 1.95317002720734\n9, 30, 81648.5561586976, 18.9338775855205, 0.276308105964505, 0.276308105964505\n9, 30, 84915.3205825358, 18.9018965006065, 0.25775055811768, 0.25775055811768\n9, 30, 12748.6992906755, 20.956252098279, 10.6964468685791, 10.6964468685791\n9, 30, 19702.7655801537, 21.3720690437585, 4.47489311485873, 4.47489311485873\n9, 30, 78363.5688516276, 19.0751370068433, 0.297546198952902, 0.297546198952902\n9, 30, 32704.8269868436, 20.8291059476584, 1.63441062956786, 1.63441062956786\n9, 30, 39454.0447791576, 20.3956969160794, 1.11850790152941, 1.11850790152941\n9, 30, 25852.5857440217, 21.5131319639883, 2.60715319679087, 2.60715319679087\n9, 30, 75047.302268985, 19.1129078534408, 0.322186799342343, 0.322186799342343\n13.2, 45, 90364.8194858743, 18.851972315629, 0.305217342375055, 0.305217342375055\n13.2, 45, 8076.2640578434, 24.0111558434839, 35.8029501848227, 35.8029501848227\n13.2, 45, 50772.0591562781, 19.7992917932574, 0.928394801097195, 0.928394801097195\n13.2, 45, 66195.4322434412, 19.2914810641625, 0.550235869227531, 0.550235869227531\n13.2, 45, 47363.6661097263, 20.0685366715685, 1.0630574120011, 1.0630574120011\n13.2, 45, 19902.7764508919, 21.2759580135189, 5.98521694141482, 5.98521694141482\n13.2, 45, 39900.5151261104, 20.5397185970455, 1.48849529409474, 1.48849529409474\n13.2, 45, 74866.732832787, 19.0900594677447, 0.434436734327329, 0.434436734327329\n13.2, 45, 82545.9819399738, 18.9439559950128, 0.361002096005894, 0.361002096005894\n13.2, 45, 106171.719883028, 18.6283535384433, 0.229496342278619, 0.229496342278619\n13.2, 45, 94122.014260214, 18.7599655960001, 0.282619972807026, 0.282619972807026\n13.2, 45, 55431.0307804117, 19.61223734667, 0.783444980800781, 0.783444980800781\n13.2, 45, 59322.7541290298, 19.6319108649163, 0.684931628377185, 0.684931628377185\n13.2, 45, 114221.038645558, 18.4694576373584, 0.203347977101083, 0.203347977101083\n13.2, 45, 78925.5166005358, 19.0282740070502, 0.393135093952, 0.393135093952\n13.2, 45, 63096.2993854333, 19.3936301169532, 0.605948000756784, 0.605948000756784\n13.2, 45, 86358.0944477848, 18.8993234493532, 0.331341638288088, 0.331341638288088\n13.2, 45, 110454.377590452, 18.567036984956, 0.214660611248231, 0.214660611248231\n13.2, 45, 35864.0452240558, 20.7795087552391, 1.84052287954811, 1.84052287954811\n13.2, 45, 102270.885599624, 18.6534024509903, 0.244662856478561, 0.244662856478561\n13.2, 45, 15625.3491197509, 23.0212986293325, 9.68121139016299, 9.68121139016299\n13.2, 45, 98275.2673711873, 18.6797685109276, 0.262281703155193, 0.262281703155193\n13.2, 45, 31352.5742431042, 21.0124223239215, 2.41763424066977, 2.41763424066977\n13.2, 45, 12313.9582502865, 22.5336653922509, 15.5170405633573, 15.5170405633573\n13.2, 45, 118521.184105338, 18.4634946805162, 0.191715543444072, 0.191715543444072\n13.2, 45, 27954.591413931, 21.1733665963443, 3.03909219686198, 3.03909219686198\n13.2, 45, 23661.526874057, 21.8398598857805, 4.23960949267591, 4.23960949267591\n13.2, 45, 70936.4289641694, 19.2203716274935, 0.481640104330054, 0.481640104330054\n13.2, 45, 43616.6098039867, 20.3724031756756, 1.24623498410928, 1.24623498410928\n16.6, 55, 17867.5515609687, 21.7652508894877, 9.15368581910848, 9.15368581910848\n16.6, 55, 125637.055996345, 18.3877470989716, 0.20747930927834, 0.20747930927834\n16.6, 55, 49304.731241175, 19.807149989706, 1.22247182825836, 1.22247182825836\n16.6, 55, 107667.483438579, 18.6074812032667, 0.27078355428531, 0.27078355428531\n16.6, 55, 13536.3513622991, 22.9216117473262, 16.0120267998002, 16.0120267998002\n16.6, 55, 71994.5089139876, 19.1461599074966, 0.579982264504498, 0.579982264504498\n16.6, 55, 58949.4992802703, 19.4584247735011, 0.863655495599455, 0.863655495599455\n16.6, 55, 22441.0358182932, 20.9345419939241, 5.80047673858736, 5.80047673858736\n16.6, 55, 44296.5080074942, 19.8307916472566, 1.50683347198268, 1.50683347198268\n16.6, 55, 36163.6188854124, 20.1076548679491, 2.265078120627, 2.265078120627\n16.6, 55, 121252.135326159, 18.4363699283627, 0.220566362796363, 0.220566362796363\n16.6, 55, 85072.0354168332, 18.8324850607434, 0.418963400171204, 0.418963400171204\n16.6, 55, 103030.125538593, 18.6109968334098, 0.292673058569925, 0.292673058569925\n16.6, 55, 62664.4453756571, 19.3182930613143, 0.76166308494462, 0.76166308494462\n16.6, 55, 66814.802347003, 19.1511266386389, 0.671621933741905, 0.671621933741905\n16.6, 55, 40023.6860323227, 20.3563108994464, 1.84868057936682, 1.84868057936682\n16.6, 55, 98428.0786967929, 18.7052786521598, 0.318212576297495, 0.318212576297495\n16.6, 55, 94101.3387888276, 18.7365240146046, 0.345945890970535, 0.345945890970535\n16.6, 55, 112249.405136342, 18.541593643746, 0.2517944419942, 0.2517944419942\n16.6, 55, 31272.4427821611, 20.5767680935139, 3.01988954371356, 3.01988954371356\n16.6, 55, 76452.8638484087, 19.0625190030148, 0.518185514149112, 0.518185514149112\n16.6, 55, 53939.2603758079, 19.6676345378916, 1.02315173365127, 1.02315173365127\n16.6, 55, 130240.937716863, 18.3435824135538, 0.195735083846963, 0.195735083846963\n16.6, 55, 27281.4692961602, 20.8755273958803, 3.96092444894359, 3.96092444894359\n16.6, 55, 81017.1760328248, 18.9834687699148, 0.462576998836875, 0.462576998836875\n16.6, 55, 90129.3849290184, 18.7809056600762, 0.376175674619081, 0.376175674619081\n16.6, 55, 134854.212682816, 18.3289989496668, 0.185163179879921, 0.185163179879921\n16.6, 55, 116773.970377645, 18.4532827516731, 0.235074764576524, 0.235074764576524\n"
  },
  {
    "path": "images/bitmaps/README.md",
    "content": "# Bitmaps Graphics Directory\n\nThis directory holds bitmaps (JPG, PNG, ...), to be used with `\\includegraphics{}`.\nIf there's a file `abc` in here, include it in the document with `\\includegraphics{abc}`:\n\n- no leading path (`includegraphics` knows to look in here),\n- no file suffix (`includegraphics` looks for the common ones automatically).\n\n**PDFs files (even if they're vectors) also go in here** and are usable via `\\includegraphics` in the same way.\n"
  },
  {
    "path": "images/vectors/README.md",
    "content": "# Vector Graphics Directory\n\nThis directory holds vector graphics SVG files, to be used with `\\includesvg{}`.\nIf there's a file `abc` in here, include it in the document with `\\includesvg{abc}`:\n\n- no leading path (`includesvg` knows to look in here),\n- no file suffix (`includesvg` can only handle `.svg` anyway).\n"
  },
  {
    "path": "lib/README.md",
    "content": "# Library code\n\nThis directory might contain, for example:\n\n- Lua files for usage alongside `lualatex`.\n    Embedding Lua for `lualatex` to consume is quite powerful and neat, and we are gladly making use of it.\n    However, embedding Lua verbatim into `\\directlua` is a bit ugly [and has annoying issues with escaping](https://web.archive.org/web/20210208133949if_/https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua).\n    Therefore, prefer to load external, proper Lua files using `\\dofile`.\n    These files might live in here, if required.\n- Outsourced LaTeX source code that is better off modularized, like custom packages.\n"
  },
  {
    "path": "lib/example.lua",
    "content": "--[[\n    The following import is not required since in LuaTeX's `\\directlua` environment,\n    `token` etc. is already available. However, this is nice to keep linters from\n    complaining about an undefined variable.\n--]]\nlocal token = require(\"token\")\nlocal texio = require(\"texio\")\nlocal status = require(\"status\")\n\n--[[\n    Trying to incorporate dynamic values into certain newcommand macros. Their\n    contents are set at build-time according to environment variables. This is useful\n    for automatic workflows in CI environments. See also:\n    https://tex.stackexchange.com/a/1739/120853.\n    An alternative to using environment variables are command line arguments:\n    https://tex.stackexchange.com/a/18813/120853\n    However, this seems more error-prone and requires more steps, e.g. piping arguments\n    to `lualatex` through `latexmk` first, etc.\n    The previous approach was to `sed` for certain `newcommand` definitions in an\n    additional CI job. This was much more error-prone (bash scripting) and less\n    easily expanded than the below approach.\n    LuaTeX provides excellent access to TeX, making this implementation much easier.\n--]]\n\nlocal function get_cmd_stdout(cmd)\n    -- See: https://stackoverflow.com/a/326715/11477374\n    local fh = assert(io.popen(cmd))\n    local first_line = assert(fh:read())\n    fh:close()\n    return first_line\nend\n\n-- Environment variables as used e.g. in GitLab CI.\n-- Otherwise, e.g. when developing locally, use commands as a fallback.\nlocal macro_content_sources = {\n    GitRefName = {\n        env = \"CI_COMMIT_REF_NAME\",\n        cmd = \"git rev-parse --abbrev-ref HEAD\",\n    },\n    GitShortSHA = {\n        env = \"CI_COMMIT_SHORT_SHA\",\n        cmd = \"git rev-parse --short HEAD\",\n    },\n}\n\nfor macro_name, content_sources in pairs(macro_content_sources) do\n    -- Default: check for environment variable:\n    local env = content_sources.env\n    local cmd = content_sources.cmd\n    local content = \"n.a.\"  -- Default value\n    local env_content = os.getenv(env)\n\n    if env_content and env_content ~= \"\" then  -- Empty string evaluates to true\n        texio.write_nl(\"Found and will be using environment variable '\"..env..\"'.\")\n        content = env_content\n    else\n        texio.write_nl(\"Environment variable '\"..env..\"' undefined or empty, trying fallback command.\")\n        -- luatex reference for shell escape:\n        -- \"0 means disabled, 1 means anything is permitted, and 2 is restricted\"\n        if status.shell_escape == 1 then\n            local cmd_success, cmd_stdout = pcall(get_cmd_stdout, cmd)\n            if cmd_success then\n                texio.write_nl(\"Fallback command '\"..cmd..\"' succeeded.\")\n                content = cmd_stdout\n            else\n                texio.write_nl(\"Fallback command '\"..cmd..\"' unsuccessful.\")\n            end\n        else\n            texio.write_nl(\"shell-escape is disabled, cannot use fallback command.\")\n        end\n    end\n\n    -- Shouldn't happen, would be programmer error, therefore assert Python-style\n    assert(content, \"Content not defined (neither success nor fallback present)\")\n\n    --[[\n        The `content` can contain unprintable characters, like underscores in git branch\n        names. Towards this end, use detokenize in the macro itself, which will make all\n        characters printable (assigns category code 12). See also:\n        https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua\n    --]]\n    local escaped_content = \"\\\\detokenize{\"..content..\"}\"\n\n    texio.write_nl(\"Providing new macro '\"..macro_name..\"' with contents: '\"..escaped_content..\"'.\")\n    --  Set a macro (`\\newcommand`) see also: https://tex.stackexchange.com/a/450892/120853\n    token.set_macro(macro_name, escaped_content)\nend\n"
  },
  {
    "path": "pandoc/README.md",
    "content": "# Pandoc\n\n`pandoc` is a tool almost completely separate from LaTeX, but goes hand-in-hand with it.\nIt is not relevant to the main project and used here only as an interesting showcase on how to convert Markdown READMEs to PDF (which uses LaTeX in the background).\nThis directory contains configuration files for `pandoc`.\n"
  },
  {
    "path": "pandoc/defaults.yaml",
    "content": "# Instead of command-line options, configure pandoc here and point it to this file.\n# See also: https://pandoc.org/MANUAL.html#default-files\n\n# -------------------------------------------------------------------------------------\n# Basics\n# -------------------------------------------------------------------------------------\n# lualatex for Unicode and all the other good stuff. Better than xelatex and pdflatex.\npdf-engine: lualatex\n\n# When calling `pandoc` from this project's root using `--defaults=subdir/defaults.yaml`,\n# the filter filters are resolved in relation to where `pandoc` is called, NOT relative\n# to the `defaults.yaml` file.\n# The same is true for metadata files.\n# Therefore, keep this ugly hack (specifying paths relative to project root dir)\n# until https://github.com/jgm/pandoc/issues/5982 is resolved:\nmetadata-file: pandoc/metadata.yaml\n\n# Custom filter programs modify the document (pandoc AST) before it is written out:\nfilters:\n  - pandoc/promote-headers.lua\n\n# -------------------------------------------------------------------------------------\n# Style\n# -------------------------------------------------------------------------------------\n# Core pandoc options, see https://pandoc.org/MANUAL.html#default-files:\ntable-of-contents: true\nnumber-sections: true\n\ntemplate: eisvogel\nvariables:\n  # These are used by the Eisvogel pandoc template, i.e. not by core pandoc itself.\n  # See also https://github.com/Wandmalfarbe/pandoc-latex-template#custom-template-variables\n  titlepage: true\n  colorlinks: true\n  lang: \"en\"\n# -------------------------------------------------------------------------------------\n# Other\n# -------------------------------------------------------------------------------------\n# ERROR, WARNING, INFO:\nverbosity: WARNING\n"
  },
  {
    "path": "pandoc/metadata.yaml",
    "content": "author: [Alex Povel]\nsubject: \"Advantages of a workflow using LaTeX with GitLab, GitHub Actions etc.\"\nkeywords: [LaTeX, CI, CD, Markdown]\n"
  },
  {
    "path": "pandoc/promote-headers.lua",
    "content": "-- From https://stackoverflow.com/a/56005271/11477374:\n-- Automatically get \"Document Title\" from Markdown top-level heading by promoting all\n-- headings one level up (for Markdown, # becomes %, ## becomes # etc.).\n-- See also:\n-- https://github.com/jgm/pandoc/issues/5615\n\n-- Stop linters from complaining about missing variable:\nlocal pandoc = require(\"pandoc\")\n\nlocal title\n\n-- Promote all headers by one level. Set title from level 1 headers,\n-- unless it has been set before.\nfunction promote_header (header)\n\n  if header.level >= 2 then\n    header.level = header.level - 1\n    return header\n  end\n\n  if not title then\n    title = header.content\n    return {}\n  end\n\n  local msg = '[WARNING] title already set; discarding header \"%s\"\\n'\n  io.stderr:write(msg:format(pandoc.utils.stringify(header)))\n  return {}\nend\n\nreturn {\n  {Meta = function (meta) title = meta.title end}, -- init title\n  {Header = promote_header},\n  {Meta = function (meta) meta.title = title; return meta end}, -- set title\n}\n"
  },
  {
    "path": "tests/Makefile",
    "content": "# Get this file's directory, allows this Makefile to be run on its own or via\n# `include` from a root Makefile. From:\n# https://www.systutorials.com/how-to-get-a-makefiles-directory-for-including-other-makefiles/\nSELF_DIR = $(dir $(lastword $(MAKEFILE_LIST)))\n\n# No Docker image available for this yet. Refer to the CI config to configure this for\n# local use.\nTEST = pytest\nTESTS_DIR = tests\n\n.PHONY: test test-self test-pdfs\n\ndefine run_test\n\tcd $(SELF_DIR) && \\\n\t\t$(TEST) $(TESTS_DIR)/$(subst -,_,$(1)).py $(TEST_FLAGS)\nendef\n\nifdef CI\n\tTEST_FLAGS = --verbose\nelse\n\tTEST_FLAGS =\nendif\n\ntest: test-self test-pdfs # Runs all tests.\n\t@echo \"All tests passed.\"\n\n# Target names correspond to actual Python test files, with some modifications made, see\n# the `run_test` function.\n\ntest-self:  # Runs tests on the tests themselves.\n\t@$(call run_test,$@)\n\ntest-pdfs:  # Runs tests on found PDFs.\n\t@$(call run_test,$@)\n"
  },
  {
    "path": "tests/README.md",
    "content": "# Automated Testing\n\nThis sub-project contains Python-based code for testing the PDF output produced by\nearlier CI stages, or by you locally.\n\nThe desired properties of the PDFs under test (by default, all PDFs in the project root),\nare configured in the [tests config file](config.yml).\nOnce that is done to your liking, [set up the testing framework](#setup) and [run](#running)\nthe tests (or don't and use CI instead, where everything is done for you already and\nJust Works™).\n\nThis is helpful to check for basic stuff.\nA more involved approach is shown [here](https://blog.martisak.se/2020/05/16/latex-test-cases/).\nThis includes checking for publisher-specific requirements, allowing us to detect errors\nand iterate much faster.\n\n## Setup\n\nRun\n\n```bash\npython -m venv .venv\n. .venv/bin/activate\npip install .\n```\n\nin the directory containing [pyproject.toml](./pyproject.toml).\n\n## Running\n\nAfter the setup, you can simply run:\n\n```bash\npytest\n```\n\n### Makefile\n\nOtherwise, the testing procedure is tucked away and made accessible via the [Makefile](Makefile).\nIt requires you to have [GNU `make`](https://www.gnu.org/software/make/) installed.\nIf you are on Linux you might already have it, since a lot of development workflows rely\non it.\nThe tests can then be run using:\n\n```bash\nmake test\n```\n\nor any of the other *targets* in that Makefile:\n\n```bash\nmake test-self\nmake test-pdfs\n```\n\n## Side note\n\nSadly, an inherent issue is that [PDF parsing/text extraction](https://news.ycombinator.com/item?id=22473263)\nis incredibly hard.\nVisually, PDFs might look fine to human eyes, but trying to tell a computer, in an\nautomated fashion, what *it* sees and have it parse that correctly is as of today\nbasically impossible.\n"
  },
  {
    "path": "tests/config.yml",
    "content": "metadata:\n  encryption: null  # why tho\n  pdf_version: \"1.5\"  # Versions are strings, not floats (see semantic versioning)\n\npages:\n  n_min: 1\n  n_max: null  # Null will ignore this boundary\n  papersize:\n    # This is either a mapping of <name>.pdf to <allowed papersize>, or one value for\n    # *all* PDFs, for example: `papersize: \"a4\"`.\n    # Possible values: https://papersize.readthedocs.io/en/latest/#papersize.parse_papersize\n    cookbook: \"a4\"\n    README: \"a4\"\n\nfile:\n  # File sizes in human-readable format, or null to ignore.\n  min_size: \"10K\"  # Some rough minimum, maybe useful to detect corrupted files\n  max_size: \"5M\"\n  bookmarks: true  # Check if those are present\n  # For age, d, h, m and s (or null to skip test) are available. Order matters.\n  # Could be useful to detect old files that crept in, e.g. from a cache.\n  max_age: null\n\ncontent:\n  required_strings: null\n"
  },
  {
    "path": "tests/pyproject.toml",
    "content": "\n[build-system]\nrequires = [\"hatchling >= 1.26\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"tests\"\nversion = \"4.0.0\"\ndescription = \"Checks for PDFs.\"\nauthors = [{ name = \"Alex Povel\", email = \"alex.povel@tuhh.de\" }]\nrequires-python = \">= 3.10, <4.0\"\ndependencies = [\n    \"pymupdf~=1.27.0\",\n    \"pytest~=7.4.0\",\n    \"PyYAML~=6.0.0\",\n    \"python-dateutil~=2.8.0\",\n    \"PaperSize~=1.7.0\",\n]\noptional-dependencies = { dev = [\"ipython~=8.14\", \"black~=26.3\"] }\n"
  },
  {
    "path": "tests/tests/__init__.py",
    "content": "\"\"\"Strictly required for `pytest` to find this Python package and import from it.\"\"\"\n"
  },
  {
    "path": "tests/tests/conftest.py",
    "content": "\"\"\"File to configure pytest, e.g. to implement hooks.\nSee also: https://stackoverflow.com/q/34466027/11477374\nList of hooks: https://pytest.org/en/latest/reference.html#hook-reference\n\"\"\"\n\nfrom tests.utils import PROJECT_ROOT\n\n\ndef pytest_make_parametrize_id(config, val, argname):\n    \"\"\"Provide IDs aka names for test cases.\n    pytest generates automatic IDs. Using this function, they can be altered to\n    whatever more legible representation, see\n    https://doc.pytest.org/en/latest/example/parametrize.html#different-options-for-test-ids.\n    Implementing this function in a specific file using a specific name will hook it\n    into pytest and use it for *all* ID generation automatically, so no need to specify\n    `ids=<func>` all the time.\n    Demo: https://raphael.codes/blog/ids-for-pytest-fixtures-and-parametrize/\n    \"\"\"\n    try:\n        # Shorten filepath significantly, in relation to project root.\n        val = val.relative_to(PROJECT_ROOT)\n    except AttributeError:\n        pass\n    return str(val)\n"
  },
  {
    "path": "tests/tests/test_pdfs.py",
    "content": "\"\"\"Tests whether PDFs documents fulfill certain criteria.\n\nThis is a bit backwards: `pytest` ordinarily tests functions/units, with sample data\nbeing generated as needed. This module tests *data*, not the logic working on them.\nFor this, a package like `datatest` is maybe more suitable. However, the framework\nprovided by `pytest` works just fine. It gets us pretty summaries and the like, much\nbetter than crafting that ourselves.\nOne core downside is that there is way too much logic in the tests themselves, with\nno way of testing the tests that test the data. If these are wrong (likelihood increases\nwith more complexity), we are in for a bad time.\n\nIdea from: https://blog.martisak.se/2020/05/16/latex-test-cases/\n\"\"\"\n\nfrom __future__ import annotations\n\nimport math\nfrom datetime import datetime as dt\nfrom decimal import Decimal\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any, Generator, NamedTuple, cast\nfrom warnings import warn\n\nimport pymupdf\nimport pytest\nimport yaml  # PyYAML\nfrom dateutil.parser import parse as parse_date\nfrom papersize import parse_papersize\n\nfrom tests.utils import (  # type: ignore[import-untyped]\n    PROJECT_ROOT,\n    fix_tzoffset,\n    parse_duration,\n    parse_size,\n)\n\nif TYPE_CHECKING:\n    from _pytest.fixtures import FixtureRequest\n\n\nclass Rect(NamedTuple):\n    width: Decimal\n    height: Decimal\n\n\ndef et_project_root_files(suffix: str) -> Generator[Path, None, None]:\n    yield from PROJECT_ROOT.glob(\"*.\" + suffix)\n\n\n@pytest.fixture\ndef config() -> dict[str, Any]:\n    with open(PROJECT_ROOT / \"tests\" / \"config.yml\") as f:\n        return yaml.safe_load(f)\n\n\n@pytest.fixture(params=et_project_root_files(\"pdf\"))\ndef pdf(request: FixtureRequest) -> Generator[pymupdf.Document, None, None]:\n    doc = pymupdf.open(request.param)\n    # Context manager doesn't work, it closes too soon.\n    yield doc\n    doc.close()\n\n\ndef test_page_numbers(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests that number of pages is within limits.\n\n    Zero-length PDFs don't exist, but perhaps some form of file corruption could produce\n    them.\n    \"\"\"\n    n = len(pdf)\n\n    page_config = config[\"pages\"]\n    n_min = page_config[\"n_min\"] or 1\n    n_max = page_config[\"n_max\"] or math.inf\n\n    msg = (\n        f\"Document page count out of bounds: {n} pages not within {n_min} and {n_max}.\"\n    )\n    assert n_min <= n <= n_max, msg\n\n\n@pytest.mark.skip(reason=\"README doesn't have bookmarks, but no one cares.\")\ndef test_bookmarks(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Checks if a table of contents (ToC) is present.\"\"\"\n    bookmarks = config[\"file\"][\"bookmarks\"]\n    not_ = \"\\b\" if bookmarks else \"not\"  # ASCII backspace, remove on space char\n    toc = cast(list[Any], pdf.get_toc())\n    assert bool(toc) == bool(\n        bookmarks\n    ), f\"Bookmarks presence {not_} requested, but opposite found.\"\n\n\ndef test_required_strings(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests whether each required text is found in the document.\"\"\"\n    content_config = config[\"content\"]\n    required_strings: list[str] = content_config[\"required_strings\"] or []\n    for text in required_strings:\n        hits = sum(text in page.get_text() for page in pdf)  # type: ignore[operator]\n        assert hits, f\"Text '{text}' not found in document.\"\n\n\ndef test_file_size(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests that filesize is within limits.\"\"\"\n    file_config = config[\"file\"]\n    assert pdf.name is not None\n    pdf_path = Path(str(pdf.name))\n    size = pdf_path.stat().st_size\n    min_size = parse_size(file_config[\"min_size\"]) or 0\n    max_size = parse_size(file_config[\"max_size\"]) or math.inf\n    assert min_size <= size <= max_size\n\n\ndef test_metadata(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests file metadata.\"\"\"\n    meta_config = config[\"metadata\"]\n\n    expectations: dict[str, Any] = {\n        # Fields as returned by `pymupdf.Document.metadata`\n        \"encryption\": meta_config[\"encryption\"],\n        \"format\": f\"PDF {meta_config['pdf_version']}\",\n    }\n\n    assert pdf.metadata is not None\n    metadata: dict[str, str] = pdf.metadata  # type: ignore[assignment]\n    for field, content in metadata.items():\n        try:\n            expectation = expectations[field]\n        except KeyError:\n            # Couldn't get successfully, no expected value present. However, the\n            # user might still want to be warned about empty metadata fields.\n            if not content:\n                warn(f\"File metadata field '{field}' is empty.\")\n        else:\n            msg = f\"Field '{field}' is '{content}', not '{expectation}'.\"\n            assert content == expectation, msg\n\n\ndef test_freshness(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests if file is recently created or stale (e.g. from cache).\n\n    If file was fetched from e.g. a CI cache and not regenerated properly, it's a\n    warning sign.\n\n    `pymupdf.Document.metadata` dates look like: \"D:20201103155304+01'00'\".\n    \"\"\"\n    max_age = config[\"file\"][\"max_age\"]\n    if max_age is None:\n        pytest.skip(\"No maximum age set, skipping.\")\n\n    max_age = parse_duration(max_age)\n\n    categories = [\"mod\", \"creation\"]\n    prefix = \"D:\"  # No idea what it stands for\n\n    assert pdf.metadata is not None\n    metadata: dict[str, str] = pdf.metadata  # type: ignore[assignment]\n    dates: dict[str, dt] = {}\n    for cat in categories:\n        date_str = metadata[cat + \"Date\"]\n        date_str = fix_tzoffset(date_str)\n        # In Python 3.9, we would use `str.removeprefix`:\n        dates[cat] = parse_date(date_str[len(prefix) :])\n\n    assert dates[\"mod\"] == dates[\"creation\"], \"Modification and Creation dates differ.\"\n    # From here, both dates are equal, so it doesn't matter which we work with.\n    mod_date = dates[\"mod\"]\n\n    now = dt.now()\n    try:\n        file_age = now - mod_date\n    except TypeError:  # can't subtract offset-naive and offset-aware datetimes\n        file_age = now.astimezone() - mod_date\n\n    # Multiple asserts per unit test is terrible, but so is this entire thing.\n    assert file_age <= max_age, f\"File is older than {max_age}\"\n\n\ndef test_page_size(pdf: pymupdf.Document, config: dict[str, Any]) -> None:\n    \"\"\"Tests if all pages sizes are within allowed bounds.\n\n    We require some rounding black-magic, since page dimensions in pt deviate between\n    official definitions and what the used packages return from the metadata.\n    \"\"\"\n    size = config[\"pages\"][\"papersize\"]\n    if size is None:\n        pytest.skip(\"No page size specified, skipping.\")\n\n    unit = \"cm\"  # Cast to same unit for comparison\n    tolerance = 0.01  # Tolerance for value comparison\n\n    # When rounding for display, round roughly according to the actual tolerance we\n    # compare at. This is probably buggy as hell.\n    n_round = abs(round(math.log(tolerance, 10)))\n\n    assert pdf.name is not None\n    pdf_name = str(pdf.name)\n    try:\n        # Allow to either have a single string for 'papersize' that is valid for *all*\n        # PDFs, or a mapping of PDF stem names to their allowed sizes. This allows to\n        # have mixed page sizes for multiple PDFs.\n        size = size.get(Path(pdf_name).stem)\n    except AttributeError:\n        # Hopefully already a string\n        pass\n\n    target = Rect(*parse_papersize(size, unit=unit))\n    assert target.height >= target.width  # Not a test, just correctness assertion\n\n    for page in pdf:\n        rect = page.cropbox  # cropbox always sets rotation to 0 first\n\n        # Convert width and height floats (unit pt) to string for papersize to parse.\n        # This is a stupid move, but ensures we get nice output with the same units and\n        # also that both dimension sets are sent through the parser, aka get the same\n        # treatment. Any bugs in `papersize` would then cancel out.\n        rect_width: float = rect.width  # type: ignore[assignment]\n        rect_height: float = rect.height  # type: ignore[assignment]\n        actual = Rect(*parse_papersize(f\"{rect_width} {rect_height}\", unit=unit))\n        assert actual.height >= actual.width  # Not a test, just correctness assertion\n\n        for dimension, target_val, actual_val in zip(Rect._fields, target, actual):\n            # Due to different ideas of what page sizes are exactly, compare with some\n            # tolerance. Otherwise, the various floats would never compare equal.\n            is_close = math.isclose(target_val, actual_val, rel_tol=tolerance)\n            msg = (\n                f\"{dimension.capitalize()} mismatch (rel. tol.: {tolerance}):\"\n                + f\" {round(actual_val, n_round)}{unit} found, but\"\n                + f\" {round(target_val, n_round)}{unit} requested.\"\n            )\n            assert is_close, msg\n"
  },
  {
    "path": "tests/tests/test_self.py",
    "content": "from tests.utils import parse_size, fix_tzoffset, parse_duration\nfrom datetime import timedelta as td\nimport pytest\n\n\n@pytest.mark.parametrize(\n    [\"size\", \"n\"],\n    [\n        (\"0\", 0),\n        (\"0.0000\", 0),\n        (\"00000.0000\", 0),\n        (\"  0  \", 0),\n        (\"  0  B\", 0),\n        (\"0.1\", 0),\n        (\"0.5\", 0),\n        (\"0.0009K\", 0),\n        (\"0.0009k\", 0),\n        (\"0.009K\", 9),\n        (\"1\", 1),\n        (\"01\", 1),\n        (\"1.0\", 1),\n        (\"00022\", 22),\n        (\"105\", 105),\n        (\"106B\", 106),\n        (\"0000106B\", 106),\n        (\"769B\", 769),\n        (\"12.234K\", 12234),\n        (\"12.2349K\", 12234),\n        (\"0.000009G\", 9_000),\n        (\"497K\", 497_000),\n        (\"0.3G\", 300_000_000),\n        (\"554M\", 554_000_000),\n        (\"155G\", 155_000_000_000),\n        (\"664G\", 664_000_000_000),\n        (\"864G\", 864_000_000_000),\n        (\"155.3G\", 155_300_000_000),\n        (\"853T\", 853_000_000_000_000),\n        (\"999P\", 999_000_000_000_000_000),\n        (\"100E\", 100_000_000_000_000_000_000),\n        # Case insensitive\n        (\"1b\", 1),\n        (\"1k\", 1_000),\n        (\"1m\", 1_000_000),\n        (\"1g\", 1_000_000_000),\n        (\"1t\", 1_000_000_000_000),\n        (\"1p\", 1_000_000_000_000_000),\n        (\"1e\", 1_000_000_000_000_000_000),\n    ],\n)\ndef test_parse_size(size, n):\n    assert parse_size(size) == n\n\n\n@pytest.mark.parametrize(\n    [\"raw_date\", \"date\"],\n    [\n        # Unchanged:\n        # No timezone info:\n        (\"D:20201103155304\", \"D:20201103155304\"),\n        #\n        (\"D:20201103155304+1000\", \"D:20201103155304+1000\"),\n        (\"D:20201103155304-1000\", \"D:20201103155304-1000\"),\n        # Examples for %z from\n        # https://docs.python.org/3/library/datetime.html#tzinfo-objects\n        (\"D:20201103155304+063415\", \"D:20201103155304+063415\"),\n        (\"D:20201103155304+1030\", \"D:20201103155304+1030\"),\n        (\"D:20201103155304-0400\", \"D:20201103155304-0400\"),\n        (\"D:20201103155304-0000\", \"D:20201103155304-0000\"),\n        (\"D:20201103155304+0000\", \"D:20201103155304+0000\"),\n        # Changed due to malformed tzinfo:\n        (\"D:20201103155304+01'00'\", \"D:20201103155304+0100\"),\n        (\"D:20201103155304-01'00'\", \"D:20201103155304-0100\"),\n        (\"D:20201103155304-11'11'\", \"D:20201103155304-1111\"),\n        (\"D:20201103155304+10-10\", \"D:20201103155304+1010\"),\n        (\"D:20201103155304+10-10.347289\", \"D:20201103155304+1010.347289\"),\n        (\"D:20201103155304+01foifre00shfs\", \"D:20201103155304+0100\"),\n    ],\n)\ndef test_fix_tzoffset(raw_date, date):\n    assert fix_tzoffset(raw_date) == date\n\n\n@pytest.mark.parametrize(\n    [\"raw_duration\", \"duration\"],\n    [\n        (\"\", None),\n        (\"    \", None),\n        (\"Shouldnt match\", None),\n        (\"???\", None),\n        # Since words start with the actual short letters (duh!), this works:\n        (\"1 day\", td(days=1)),\n        (\"1 hour\", td(hours=1)),\n        (\"1 minute\", td(minutes=1)),\n        (\"1 second\", td(seconds=1)),\n        # But they cannot be combined:\n        (\"1 day 1 hour 1 minute 1 second\", td(days=1)),\n        (\"10 hours 100 second\", td(hours=10)),\n        (\"10 hours DOESNT MATTER\", td(hours=10)),\n        (\"10 h DOESNT MATTER\", td(hours=10)),\n        #\n        (\"1 hour\", td(hours=1)),\n        (\"1 minute\", td(minutes=1)),\n        (\"1 second\", td(seconds=1)),\n        # It also means these work:\n        (\"1 durr\", td(days=1)),\n        (\"1 hurr\", td(hours=1)),\n        (\"1 mailbox\", td(minutes=1)),\n        (\"1 sand\", td(seconds=1)),\n        # Zero\n        (\"0d\", td(minutes=0, hours=0, days=0)),\n        (\"0h\", td(minutes=0, hours=0, days=0)),\n        (\"0m\", td(minutes=0, hours=0, days=0)),\n        (\"0d0m\", td(minutes=0, hours=0, days=0)),\n        (\"0d0h\", td(minutes=0, hours=0, days=0)),\n        (\"0m0h\", td(minutes=0, hours=0, days=0)),\n        (\"0d0h0m\", td(minutes=0, hours=0, days=0)),\n        # Whitespace\n        (\"1d 1h 1m\", td(minutes=1, hours=1, days=1)),\n        (\" 1d 1h 1m \", td(minutes=1, hours=1, days=1)),\n        (\"     1d     1h     1m \", td(minutes=1, hours=1, days=1)),\n        (\"\\t1d\\t1h\\t1m\", td(minutes=1, hours=1, days=1)),\n        (\"1d1h1m\", td(minutes=1, hours=1, days=1)),\n        # Negative\n        (\"-1d-1h-1m-1s\", td(seconds=-1, minutes=-1, hours=-1, days=-1)),\n        # We would write \"1 day, 6 hours\", but there is not limit:\n        (\"30h\", td(hours=30)),\n        (\"300h\", td(hours=300)),\n        (\"300m\", td(minutes=300)),\n        (\"300s\", td(seconds=300)),\n        #\n        (\"-30h\", td(hours=-30)),\n        (\"-300h\", td(hours=-300)),\n        (\"-300m\", td(minutes=-300)),\n        (\"-300s\", td(seconds=-300)),\n        # See: https://gist.github.com/santiagobasulto/698f0ff660968200f873a2f9d1c4113c#file-tests-py\n        (\"3d\", td(days=3)),\n        (\"-3d\", td(days=-3)),\n        (\"-37D\", td(days=-37)),\n        (\"18h\", td(hours=18)),\n        (\"-5h\", td(hours=-5)),\n        (\"11H\", td(hours=11)),\n        (\"129m\", td(minutes=129)),\n        (\"-68m\", td(minutes=-68)),\n        (\"12M\", td(minutes=12)),\n        (\"3d5h\", td(days=3, hours=5)),\n        (\"-3d-5h\", td(days=-3, hours=-5)),\n        (\"13d4h19m\", td(days=13, hours=4, minutes=19)),\n        (\"13d19m\", td(days=13, minutes=19)),\n        (\"-13d-19m\", td(days=-13, minutes=-19)),\n        (\"-13d19m\", td(days=-13, minutes=19)),\n        (\"13d-19m\", td(days=13, minutes=-19)),\n        (\"4h19m\", td(hours=4, minutes=19)),\n        (\"-4h-19m\", td(hours=-4, minutes=-19)),\n        (\"-4h19m\", td(hours=-4, minutes=19)),\n        (\"4h-19m\", td(hours=4, minutes=-19)),\n    ],\n)\ndef test_parse_duration(raw_duration, duration):\n    assert parse_duration(raw_duration) == duration\n"
  },
  {
    "path": "tests/tests/utils.py",
    "content": "import datetime\nimport logging\nimport re\nimport string\nfrom pathlib import Path\n\n_THIS_DIR = Path(__file__).parent\n\n# `resolve` gets rid of \"..\" representation, important for `relative_to` to work.\nPROJECT_ROOT = (_THIS_DIR / \"..\" / \"..\").resolve()\n\n\ndef parse_size(size: str) -> int:\n    \"\"\"Parses a string file size (e.g. \"32G\") into a bytes number.\n\n    Works on the basis of 1000 steps, so not 1024. Probably wrong for that reason.\n\n    Args:\n        size: A human-readable file size, e.g. \"32G\", \"10M\". That is, without the \"B\"\n            for \"Bytes\".\n\n    Returns:\n        Number of bytes for that file size.\n    \"\"\"\n    si_prefixes = [\"B\", \"K\", \"M\", \"G\", \"T\", \"P\", \"E\"]\n\n    try:\n        size = size.strip()\n    except AttributeError:\n        # Not a string, can't work with this, return this filth to the offender\n        return size\n\n    n = float(re.match(r\"\\d+(\\.\\d+)?\", size).group())\n    for i, prefix in enumerate(si_prefixes):\n        if re.search(prefix, size, re.IGNORECASE):\n            factor = 10 ** (i * 3)\n            break\n    else:  # nobreak\n        logging.info(f\"No unit prefix found in '{size}', interpreting as bytes.\")\n        factor = 1\n    return int(factor * n)\n\n\ndef fix_tzoffset(date: str) -> str:\n    \"\"\"Fixes malformed timezone info in a string, without parsing it further.\n\n    The dates returned by `fitz.Document.metadata` have timezone information in the\n    form \"±HH'MM'\", i.e. with extra apostrophes. These will be filtered out so that the\n    resulting string can be parsed correctly by `datetime`'s `%z`, or automatically by\n    `dateutil`. The latter fails for the malformed timezone returned by\n    `fitz.Document.metadata`.\n\n    The return of this function is designed to be fed into `dateutil.parser.parse`.\n\n    Args:\n        date: A date string to be parsed, with potentially malformed timezone\n            information.\n\n    Returns:\n        Input date with all disallowed characters removed from the timezone info.\n    \"\"\"\n\n    def clean(match: re.Match) -> str:\n        \"\"\"Rebuilds match string to only contain allowed characters.\n\n        See also: https://docs.python.org/3/library/re.html#re.sub\n        \"\"\"\n        allowed = string.digits + \".\"\n        return \"\".join(char for char in match.group() if char in allowed)\n\n    # Positive lookbehind: match only if *preceded* by that regex, however that regex\n    # will not be part of the match. This allows us to clean just the timezone info\n    # w/o having to deal w/ the ±.\n    return re.sub(r\"(?<=[+-]).+\", clean, date)\n\n\ndef parse_duration(duration: str) -> datetime.timedelta:\n    \"\"\"Parses a human-readable duration like \"1d5h30m\"\n\n    Credit: https://gist.github.com/santiagobasulto/698f0ff660968200f873a2f9d1c4113c\n\n    Args:\n        duration: The human-readable string.\n\n    Returns:\n        A proper, parsed object to work with.\n    \"\"\"\n    duration = re.sub(r\"\\s+\", \"\", duration)  # Remove any whitespace\n    pattern = re.compile(\n        # Order here matters:\n        r\"((?P<days>-?\\d+)d)?\"\n        + r\"((?P<hours>-?\\d+)h)?\"\n        + r\"((?P<minutes>-?\\d+)m)?\"\n        + r\"((?P<seconds>-?\\d+)s)?\",\n        re.IGNORECASE | re.VERBOSE,\n    )\n    match = pattern.match(duration)\n    # Check if any match *content*, not just match object. All capture groups are\n    # optional, so *any* string can match. See:\n    # https://gist.github.com/santiagobasulto/698f0ff660968200f873a2f9d1c4113c#gistcomment-3518604\n    if match.group():\n        parts = {k: int(v) for k, v in match.groupdict().items() if v}\n        return datetime.timedelta(**parts)\n"
  }
]