Slides

1. Foreword

Reproducibility of a research study in computer science has always been a complex matter. One of the biggest challenges is to recreate the original software environment. The latter is often built manually or using modules [1], especially on high-performance computing (HPC) platforms. The main issue with this approach is that modules and building instructions are likely to vary from one machine to another depending on system configuration and available software. Some package managers such as Spack [2] allow users to define their own package variants and leave them the choice of the configuration, the dependencies or the compiler. However, as the package manager still depends on compilers and other components provided by the underlying system, the reproducibility of software environments remains threatened. From this point of view, the container solutions such us Singularity [3] or Docker [4] are more robust but they do not make updating or management of multiple environment variants very easy. For example, if we want to use a different version of one or more packages, we either have to modify the container interactively, which would make it even less reproducible, or re-build it, which can take lot of time if performed regularly. Moreover, because the container is often based on an existing Linux distribution, we are limited to the versions of various core packages (compilers, MPI1, BLAS2, …) provided by that particular distribution in that particular release unless we want to manually re-build and re-configure a significant portion of the software environment. In the aim to cope with these limitations, take total control over our software environments and be able to adapt and reproduce them easily, we propose to explore and practice Guix [5], [6].

Another challenge to the reproducibility of an experimental research study is the ability to rerun the associated computational experiments. We often need to repeat experiments more than once, using different software versions and algorithmic options, possibly months or even years apart. The importance of maintaining a complete and well-structured documentation—allowing both ourselves and others to recreate the experimental software environment, rerun all the experiments, and post-process the results—is therefore critical. While a detailed README file and thoroughly commented source code address this need to some extent, we propose going further by adopting literate programming [7], a paradigm that combines source code with a natural language narrative. Among the many literate programming tools available, we will present Org mode [8], [9] for the Emacs editor. With Org mode, we can write a document that combines formatted text, images, and figures with blocks of source code. These code blocks can be extracted as files [10], for example to be compiled, or evaluated on the fly [11]. The results of the evaluation—such as a figure or the return value of a computation—can then be included directly in the document. We can export this document in various formats [12], and share it with the community, whether as a scientific publication, a research report, or a simple web page.

Finally, we will discuss the long-term availability of the elements of a research study and the associated source code, including external dependencies. Even when hosted in version-controlled repositories on a source code forge such as Inria Forge or BitBucket, they can suddenly become unavailable—for example, due to a repository migration or the permanent shutdown of the platform. We will therefore introduce the Software Heritage [13] and the Zenodo [14] projects, which are dedicated to the long-term archival of source code, experimental datasets and other artifacts.

2. Goals

The main focus of this tutorial is on the reproducibility of an experimental software environment. After a brief tour of Guix, Nix and other possible solutions, participants will learn the basics of software deployment with Guix by the means of a hands-on session.

Then, participants will use Guix to reproduce the experimental software environment of an existing research study and be able to observe its advantages over the aforementioned approaches.

Finally, participants will use Guix to build a reproducible experimental software environment from scratch.

Following the hands-on session, we will discuss how to improve the reproducibility of an experimental research study even further thanks to the association of a package manager such as Guix, the literate programming paradigm and an adapted long-term archival solution.

3. Target audience

This tutorial is intended for scientists and engineers looking for a complete software framework that enables them to:

  • create reproducible software environments, whether for high-performance computing (HPC) experiments, to achieve reproducible research results, or to share development environments,
  • maintain complete and structured documentation that makes it possible to reproduce a set of computational experiments along with the associated software environment,
  • ensure the long-term availability of the components of an experimental scientific study.

A basic knowledge of GNU/Linux is required: processes, command line, and software installation.

4. Pre-requisites

The hands-on session can take place:

  • on participants’ laptops, provided they have installed GNU Guix version 1.5.0 in advance by following the instructions; approximately 20 GiB of free space on the root partition (/) will be needed during the hands-on session;
  • on the Grid'5000 experimental testbed [15] accessible to participants via SSH; in that case, participants will need to have an SSH client and know how to use it.

5. Workspace

For the needs of the tutorial, we have created a special project group, namely Publish a reproducible result (JRFRR 2026), on GitLab.com with the following structure:

Publish a reproducible result (JRFRR 2026)
  ├── Channel
  ├── Slides
  ├── Study
  └── Tutorial

We address the Channel repository later in Section 6.4. The Tutorial repository contains the sources of the present document and Slides the sources of the companion slides (accessible by clicking the button on the left-side panel of this page). We do not report further on these two repositories.

Finally, the Studies repository contains an example experimental resarch study assessing the performance of minisolver [16], a simple application for solving dense linear systems arising from aeroacoustic simulations, by the means of a set of numerical experiments.

During the hands-on session, participants will work on the Studies repository which has the following structure:

Study
  ├── .guix
  │   ├── channels.scm
  │   └── manifest.scm
  ├── .gitattributes
  ├── .gitignore
  ├── .gitlab-ci.yml
  ├── AUTHORS
  ├── LICENSE
  ├── README.md
  ├── benchmarks.csv
  ├── cylinder.png
  ├── plot.py
  ├── references.bib
  ├── results.csv (LFS)
  └── study.tex

The .guix folder contains everything one needs to reproduce the experimental software environment of the study using Guix. The environment contains the necessary software packages to:

  • run the set of numerical experiments involving minisolver according to the parameters defined in benchmarks.csv, where each line represents one experiment, and store the results into results.csv;
  • post-process results.csv, i.e., format data and draw plots, using the plot.py Python script;
  • produce the PDF version of a manuscript presenting and analyzing the experimental results of the study by compiling its LaTeX source files, i.e., study.tex and references.bib.
Important

The main branch contains the complete configuration participants will reproduce in the first part of the hands-on session. The learn branch represents an incomplete configuration participants will complete in the second part of the session.

6. Hands-on session

In the first place, we will put the experimental studies aside and familiarize ourselves with Guix.

6.1. First use of Guix

Important

If you plan to use Guix on the Grid'5000 platform, connect over secure shell (SSH) to the frontal node in Lille (see configuration in the e-mail from Simon Tournier):

ssh -Y lille.g5k

and request a computational node from the Chiclet cluster:

oarsub -I -t inner=2145873 -l host=1,walltime=02:00:00 --project lab-2026-jrfrr

From here, you can jump directly to Section 6.2.

Here, we assume that we are running a third-party Linux distribution such as Debian, Fedora or Manjaro.

After the installation (see instructions), we proceed with a short sequence of commands to ensure a smooth user experience with Guix onward. At the beginning, we install our first package using Guix, i.e. glibc-locales to allow the system to switch locales.

guix install glibc-locales

Then, to be able to acquire new versions of installed packages, we will need to pull the latest version of Guix first. The following command can take a while to execute, especially when run for the first time.

guix pull

Once the process finishes, we need to follow the hint the command gives us and add the following lines to our .bash_profile or .bashrc to always get access to the most recent Guix built by guix pull.

GUIX_PROFILE="$HOME/.config/guix/current"
. "$GUIX_PROFILE/etc/profile"

We also have to tell to our shell to use this new Guix.

hash guix

Finally, we can update our installed packages.

guix upgrade

To get information on the generation (revision in Guix terminology) of Guix being used, we can use:

guix describe

6.2. Familiarization with Guix

Let us enter our first Guix environment containing two packages, bash and cowsay, using the guix shell command and launch a shell inside of that environment. Here, we use the --container or -C switch to span the new environment within an isolated container. By default, we don't have access to host filesystem (except for the current working directory), to host network or environment variables. See guix shell --help for more details.

guix shell --container bash cowsay -- bash

To test the cowsay package within the Guix shell, try to type cowsay "Hello world", for example.

Hint

On some systems, using --container fails with an error along these lines:

$ guix shell --container bash cowsay
guix shell: error: clone: 2114060305: Invalid argument

This indicates that the system lacks support for Linux's unprivileged user namespaces. Worry not: you can fall back to --pure, which is weaker, but still gives good control over the environment. See documentation for more details.

We can simply type exit to get back to our original shell. Also, we do not have to run an interactive shell inside of the environment. We can directly execute a given command like for example:

guix shell --container cowsay -- cowsay "Hello world"

Note that we did not include bash this time, we did not need it. The above command line should give us the following output:

 ______________ 
< Hello world >
 -------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

6.2.1. Manifests

The guix shell command seems very convenient. However, let us imagine that we do not need only two but 26 packages in our environment. The command line would become quiet long, right? The good news is that we can instead put our list of packages into a file, referred to as manifest, then use the --manifest or -m option to pass the manifest to our guix shell command line.

Manifest files [17] use the Scheme language [18] syntax which can be intimidating in the beginning. Fortunately, guix shell has got the --export-manifest option allowing one to automatically generate the manifest file corresponding to the environment specified on the command line. Let us thus create the manifest corresponding to our latest single-package environment and save it to a Scheme file named cowsay.scm.

guix shell --export-manifest cowsay > cowsay.scm

Our manifest should look like this. Not so scary in the end, is it?

(specifications->manifest
  (list "cowsay"))

Finally, we can enter the target environment using the manifest file and retry a cowsay command.

guix shell --container -m cowsay.scm -- cowsay "Hello from the manifest"

6.2.2. Channels

Note that, by default, guix shell considers the latest versions of the specified packages available in our current revision of Guix. Well, maybe we are fine with that at this point but what happens if we want to enter the exact same environment on a different computer or a couple of weeks, months, years later? Maybe the packages will not be even available anymore, or at least, not in the same version.

Software packages in Guix are provided through dedicated git repositories called channels [19]. The official Guix channel guix, automatically set up in our Guix installation, currently provides more than 31,000 packages [20]. However, many other channels are available, e.g., for scientific HPC software and so on. We will discuss the usage of multiple channels later. For the moment, let us focus on the default guix channel.

To ensure the same revision of Guix providing the same packages in the same versions, we can accompany our manifest with a channel file, also written in Scheme. In the latter we can specify the channel or channels to use together with the desired revision number, i.e., commit.

We can obtain the currently used commit of the guix channel (and other channels, if any) by typing guix describe. The output should look like follows, modulo the language, date and time ;-).

Pokolenie 1	17. december 2024 02:27:16	(súčasné)
  guix c3290ce
    zdroj repozitára: https://git.savannah.gnu.org/git/guix.git
    vetva: master
    úprava: c3290cee6add60b7e56f5f919d9498d78542790a

Using the -f option of guix describe, we can generate the corresponding channel file, e.g. channels.scm, as follows.

guix describe -f channels > channels.scm

The contents of channels.scm then should look like this.

(list
 (channel
  (name 'guix)
  (url "https://codeberg.org/guix/guix.git")
  (branch "master")
  (commit
   "c3290cee6add60b7e56f5f919d9498d78542790a")
  (introduction
   (make-channel-introduction
    "9edb3f66fd807b096b48283debdcddccfea34bad"
    (openpgp-fingerprint
     "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

Finally, to execute the guix shell command using our channel file, we can use the guix time-machine command with the --channels, or -C, option.

guix time-machine --channels=channels.scm -- shell --container --manifest=cowsay.scm -- cowsay -f tux "I <3 Reproducibility"

The output should look like this:

 ______________________
< I <3 Reproducibility >
 ----------------------
   \
    \
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/

If it does, it means that you have at your hands everything you need to create and deploy reproducible software environments with Guix.

Excellent!

6.3. Reproducing an environment

We are now ready for the core part of the hands-on session. At first, we are going to reproduce the experimental research study on the minisolver application from Section 5 including all the numerical experiments and the final manuscript.

To begin, we need to clone the corresponding Study repository.

git clone https://gitlab.com/jrfrr-2026-p2r/study.git
Hint

If you want to keep a copy of the repository with all you'll have done during the session, feel free to fork it first!

Then, we navigate to the root of the local clone.

cd study

Inside, the .guix folder contains the channel file as well as the manifest file specifying the original experimental software environment of the study. Our goal is to deploy this environment thanks the association of the guix time-machine and guix shell commands discussed in Section 6.2 so as to:

  1. reproduce the experiments (parameters in benchmarks.csv, results in results.csv),

    guix time-machine --channels=.guix/channels.scm -- shell --container --manifest=.guix/manifest.scm -- minisolver --batch-input benchmarks.csv --batch-output results.csv
    
  2. post-process the results (from results.csv into the plots sequential.pdf and parallel.pdf),

    guix time-machine --channels=.guix/channels.scm -- shell --container --manifest=.guix/manifest.scm -- python3 plot.py
    
  3. reproduce the manuscript of the study (featuring the plots sequential.pdf and parallel.pdf).

    guix time-machine --channels=.guix/channels.scm -- shell --container --manifest=.guix/manifest.scm -- latexmk -f -pdf -bibtex -interaction=nonstopmode study
    
Hint

To visualize the resulting manuscript including the reproduced experimental results, you can use the command below.

guix shell xpdf -- xpdf study.pdf 

Rather straightforward, isn't it?

6.4. Building an environment

We are now going to practice the construction of reproducible software environments, i.e., the preparation of manifests and channel files as seen in Section 6.2, but on a more complex example involving multiple packages and more than the default guix channel.

We continue to work on the minisolver experimental study, but we are going to switch to the learn branch

git checkout learn

where the .guix folder is empty. In this part of the tutorial, our goal is to use Guix to:

  1. build a software environment featuring multiple packages from multiple channels,
  2. capture and preserve the description of the final environment in the form of a manifest and a channel files so as to ensure the reproducibility of the environment on another copmputer or at another time.

6.4.1. Towards a manifest file

The numerical experiments of the study require only the minisolver application to run. However, minisolver is not (yet) available from the default guix channel. It is provided by a custom channel.

Follow the instructions in the README.md file of the channel (section 'How does it work?') to be able to access the packages it provides. To check the availability of the minisolver package in your profile, try to spawn an environment containing minisolver and run a quick experiment.

guix shell --container minisolver -- minisolver --size 1000

If everything worked well, the standard output should end with something like:

[minisolver] relative error = 1.6739e-14
[minisolver] test-specific cleaning ... done
[minisolver] computation completed
[minisolver] cleaning ... done
[minisolver] total computation time = 0.046672 s
[minisolver] memory usage peak = 6 MiB

Do you remember the option of guix shell that allows one to produce the manifest file corresponding to the current command line? If you need a refresher, have a quick look on Section 6.2.1. Otherwise, create the manifest describing the previous environment with minisolver and save the result to minisolver.scm. The result should look like this:

;; What follows is a "manifest" equivalent to the command line you gave.
;; You can store it in a file that you may then pass to any 'guix' command
;; that accepts a '--manifest' (or '-m') option.

(specifications->manifest (list "minisolver"))

We are now going to enrich this environment with the following packages in order to be able to post-process the experimental results and produce the final manuscript:

  • packages to perform basic operations,

    bash coreutils which
    
  • packages to manipulate and plot experimental results,

    python python-pandas python-matplotlib
    
  • packages to produce the final manuscript written in LaTeX.

    texlive-scheme-basic texlive-collection-fontsrecommended texlive-type1cm texlive-underscore texlive-dvipng texlive-babel-english texlive-latexmk texlive-wrapfig texlive-ulem texlive-capt-of texlive-listings texlive-fancyvrb texlive-upquote texlive-lineno texlive-biblatex texlive-biber texlive-xcolor
    
Did you know?

The list of Texlive packages is a bit long. Indeed, we could have simply used the global texlive package, but the latter weights almost 4 GiB and provides a lot of LaTeX packages we do not need.

Use the guix shell --container command to deploy a new environment featuring minisolver as well as all the aforementioned packages and spawn a Bash shell in it.

Then, from within the environment:

  1. run the experiments (parameters in benchmarks.csv, results in results.csv),

    minisolver --batch-input benchmarks.csv --batch-output results.csv
    
  2. post-process the results (from results.csv into the plots sequential.pdf and parallel.pdf),

    python3 plot.py
    
  3. produce the manuscript of the study (featuring the plots sequential.pdf and parallel.pdf).

    latexmk -f -pdf -bibtex -interaction=nonstopmode study
    

If everything worked well, quit the environment using the exit command and export the corresponding manifest into .guix/manifest.scm.

Hint

To visualize the resulting manuscript including the reproduced experimental results, you can use the command below.

guix shell xpdf -- xpdf study.pdf 

6.4.2. Channels

As we state in Section 6.2.2, the manifest file alone is not enough to ensure the reproducibility of a software environment built with Guix. The second ingredient is a channel file capturing the sources and the versions of the channels in use while building the environment.

Do you remember the guix describe command that allows one to retrieve the information about the channels currently in use? Let us try.

The result should look like the following. Notice the presence of the jrfrr-2026-p2r channel we added in Section 6.4.1. The commits of both channels changed too!

Generation 1	May 18 2026 11:26:33	(current)
  jrfrr-2026-p2r d14fee4
    repository URL: https://gitlab.com/jrfrr-2026-p2r/channel.git
    branch: main
    commit: d14fee41b8f536f089916df9a39432216cfec2cc
  guix aa16403
    repository URL: https://git.guix.gnu.org/guix.git
    branch: master
    commit: aa164034801fab25681cac772c2dcd4b8498d8ad

And what about the option conveniently producing the output in a form of a channel file? If you need a refresher, have a quick look on Section 6.2.2. Otherwise, capture the current channel configuration into .guix/channels.scm and test both your channel and your manifest files using:

guix time-machine --channels=.guix/channels.scm -- shell --container --manifest=.guix/manifest.scm -- minisolver --size 1000

If everything worked well, the standard output should end with something like:

[minisolver] relative error = 1.6739e-14
[minisolver] test-specific cleaning ... done
[minisolver] computation completed
[minisolver] cleaning ... done
[minisolver] total computation time = 0.046672 s
[minisolver] memory usage peak = 6 MiB

well-done.png

6.5. Modular environment

Now that we have reached the goal of the hands-on session, let us go a little bit further in our usage of the guix shell command. The latter provides the so-called transformation options, such as --with-input, allowing one to tweak the resulting software environment without further manual intervention.

For instance, the --with-input=<a>=<b> option replaces the package <a> by the package <b> in the entire dependency graph of the software environment spawned by the corresponding guix shell command without having to manually recompile the packages depending on <a>.

Let us illustrate this particular option on a concrete example. The custom channel (see Section 6.4.1) provides the fibonacci package. As its name suggests, it computes the Fibonacci sequence for a given input value, e.g., Fibonacci​(8) = 21. To perform the computation, it resorts to the libfibonacci library.

This library has two implementations: a naive recursive implementation provided by the package libfibonacci-recursive as well as a significantly faster iterative implementation provided by the libfibonacci-iterative package. Both are available from the same channel as the fibonacci package itself.

By default, fibonacci links to the slower libfibonacci-recursive implementation. For example, if we try to compute Fibonacci​(48) like so,

guix shell --container fibonacci -- fibonacci 48

the program takes several seconds to compute the result:

Implementation : Recursive Fibonacci
Fibonacci(48) : 4807526976
Computation time : 5 s

Try to apply the --with-input option on the above guix shell command so as to swap libfibonacci-recursive for libfibonacci-iterative in the resulting environment. Then, compute Fibonacci​(48) again and observe the difference!

Although this is a very simple example, the --with-input option becomes handy in many real-life situations. In high-performance computing, we often swap between multiple implementations of the same communication library, such as MPI1, the same linear algebra routines, such as BLAS2 or LAPACK [21], and so on.

Hint

Do not hesitate to try out to apply the --with-input option of guix shell on the experimental software environment involving minisolver. The latter uses the BLAS2 and LAPACK [21] linear algebra routines. By default, it links to the open-source OpenBLAS implementation of those [22] (package openblas in the guix channel). However, in practice, we often resort to vendor-specific implementations such as the Math Kernel Library (MKL) [23] from Intel(R) (package intel-oneapi-mkl in the guix-science-nonfree channel).

7. Pointers

In addition to the bibliography at the end of the document, the following pointers may be of interest for those who would like to learn further on how to use Guix, Org mode for Emacs or long-term archival solutions:

8. References

[1]
J. L. Furlani, “Providing a flexible user environment,” dans Proceedings of the fifth large installation syst. administration (lisa v), 1991, pp. 141–152 [En ligne]. Disponible: http://modules.sourceforge.net/docs/Modules-Paper.pdf
[2]
T. Gamblin, M. LeGendre, M. R. Collette, G. L. Lee, A. Moody, B. R. de Supinski, and S. Futral, “The Spack Package Manager: Bringing Order to HPC Software Chaos,” 2015, DOI: 10.1145/2807591.2807623 [En ligne]. Disponible: https://github.com/spack/spack
[3]
G. M. Kurtzer, V. Sochat, and M. W. Bauer, “Singularity: Scientific containers for mobility of compute,” PLOS ONE, vol. 12, no. 5, pp. 1–20, 2017, DOI: 10.1371/journal.pone.0177459. [En ligne]. Disponible: https://doi.org/10.1371/journal.pone.0177459
[4]
D. Merkel, “ Docker: Lightweight Linux Containers for Consistent Development and Deployment ,” Linux journal, vol. 2014, no. 239, Mar. 2014.
[5]
L. Courtès and R. Wurmus, “Reproducible and user-controlled software environments in HPC with Guix,” dans Euro-par 2015: Parallel processing workshops, 2015, pp. 579–591 [En ligne]. Disponible: https://hal.inria.fr/hal-01161771/en
[6]
N. Vallet, D. Michonneau, and S. Tournier, “Toward practical transparent verifiable and long-term reproducible research using Guix,” Nature scientific data, vol. 9, 2022, DOI: 10.1038/s41597-022-01720-9.
[7]
D. E. Knuth, “Literate Programming,” Comput. J., vol. 27, no. 2, pp. 97–111, May 1984, DOI: 10.1093/comjnl/27.2.97. [En ligne]. Disponible: https://doi.org/10.1093/comjnl/27.2.97
[8]
C. Dominik, The Org Mode 9.1 Reference Manual. 12th Media Services, 2018.
[9]
“Org mode for Emacs.” https://orgmode.org/.
[10]
“Org mode documentation (Extracting source code).” https://orgmode.org/manual/Extracting-Source-Code.html.
[11]
“Org mode documentation (Evaluating source code).” https://orgmode.org/manual/Evaluating-Code-Blocks.html.
[12]
“Org mode documentation (Exporting).” https://orgmode.org/manual/Exporting.html.
[13]
“Software Heritage.” https://www.softwareheritage.org/.
[14]
European Organization For Nuclear Research and OpenAIRE, “Zenodo.” CERN, 2013 [En ligne]. Disponible: https://www.zenodo.org/
[15]
D. Balouek, A. Carpen Amarie, G. Charrier, F. Desprez, E. Jeannot, E. Jeanvoine, A. Lèbre, D. Margery, N. Niclausse, L. Nussbaum, O. Richard, C. Pérez, F. Quesnel, C. Rohr, and L. Sarzyniec, “Adding virtualization capabilities to the Grid’5000 testbed,” dans Cloud computing and services science, vol. 367, I. I. Ivanov, M. van Sinderen, F. Leymann, and T. Shan, Eds. Springer International Publishing, 2013, pp. 3–20.
[16]
“A simple application for testing dense solvers with pseudo-BEM matrices. Based on the test\_FEMBEM suite (https://gitlab.inria.fr/solverstack/test_fembem), it has been simplified for educational purposes.” https://codeberg.org/felsoci/minisolver.
[17]
“GNU Guix Cookbook: Basic setup with manifests.” https://guix.gnu.org/cookbook/en/html_node/Basic-setup-with-manifests.html.
[18]
R. Dybvig and J. Hébert, The Scheme Programming Language, Fourth Edition. 2009 [En ligne]. Disponible: https://www.scheme.com/tspl4/
[19]
“GNU Guix Reference Manual: Channels.” https://guix.gnu.org/manual/en/html_node/Channels.html.
[20]
“Packages - GNU Guix.” https://packages.guix.gnu.org/.
[21]
“LAPACK - Linear Algebra PACKage.” https://www.netlib.org/lapack/.
[22]
“OpenBLAS: An optimized BLAS library.” http://www.openblas.net/.
[23]
“Intel(R) Math Kernel Library: Intel(R) - Optimized Math Library for Numerical Computing.” https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html.

Footnotes

1

Message Passing Interface - a message-passing library interface specification addressing primarily the message-passing parallel programming model, in which data is moved from the address space of one process to that of another process through cooperative operations on each proces.

2

Basic Linear Algebra Subprograms - routines that provide standard building blocks for performing basic vector and matrix operations.


Last modified on 18/05/2026 at 22:55.

This page was crafted in Org mode for Emacs.

The content is available under the terms of the Creative Commons BY NC 4.0 International license unless otherwise stated.