diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2025-10-03 18:26:05 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2025-10-13 14:48:27 +0200 |
| commit | 9da40e7bc3ac957395977748274893702e7207f3 (patch) | |
| tree | b03a785dbdc89ad4d7c52f45d4afeb5182e71b37 /doc/guix-cookbook.texi | |
| parent | e0e64be8de3d220a12612b3a2e4aee428277d865 (diff) | |
doc: cookbook: Add “Reproducible Research” chapter.
* doc/guix-cookbook.texi (Reproducible Research): New node.
Change-Id: I73d12771a2c2b5717b8f553dacae272f509a9fed
Diffstat (limited to 'doc/guix-cookbook.texi')
| -rw-r--r-- | doc/guix-cookbook.texi | 253 |
1 files changed, 252 insertions, 1 deletions
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi index 64421365fad..53d72a4b4d2 100644 --- a/doc/guix-cookbook.texi +++ b/doc/guix-cookbook.texi | |||
| @@ -22,10 +22,13 @@ Copyright @copyright{} 2020 André Batista@* | |||
| 22 | Copyright @copyright{} 2020 Christine Lemmer-Webber@* | 22 | Copyright @copyright{} 2020 Christine Lemmer-Webber@* |
| 23 | Copyright @copyright{} 2021 Joshua Branson@* | 23 | Copyright @copyright{} 2021 Joshua Branson@* |
| 24 | Copyright @copyright{} 2022, 2023 Maxim Cournoyer@* | 24 | Copyright @copyright{} 2022, 2023 Maxim Cournoyer@* |
| 25 | Copyright @copyright{} 2023-2024 Ludovic Courtès@* | 25 | Copyright @copyright{} 2023-2025 Ludovic Courtès@* |
| 26 | Copyright @copyright{} 2023 Thomas Ieong@* | 26 | Copyright @copyright{} 2023 Thomas Ieong@* |
| 27 | Copyright @copyright{} 2024 Florian Pelz@* | 27 | Copyright @copyright{} 2024 Florian Pelz@* |
| 28 | Copyright @copyright{} 2025 45mg@* | 28 | Copyright @copyright{} 2025 45mg@* |
| 29 | Copyright @copyright{} 2023 Marek Felšöci@* | ||
| 30 | Copyright @copyright{} 2023 Konrad Hinsen@* | ||
| 31 | Copyright @copyright{} 2023 Philippe Swartvagher@* | ||
| 29 | 32 | ||
| 30 | Permission is granted to copy, distribute and/or modify this document | 33 | Permission is granted to copy, distribute and/or modify this document |
| 31 | under the terms of the GNU Free Documentation License, Version 1.3 or | 34 | under the terms of the GNU Free Documentation License, Version 1.3 or |
| @@ -90,6 +93,7 @@ Manual}). | |||
| 90 | * Advanced package management:: Power to the users! | 93 | * Advanced package management:: Power to the users! |
| 91 | * Software Development:: Environments, continuous integration, etc. | 94 | * Software Development:: Environments, continuous integration, etc. |
| 92 | * Environment management:: Control environment | 95 | * Environment management:: Control environment |
| 96 | * Reproducible Research:: A foundation for reproducible research. | ||
| 93 | * Installing Guix on a Cluster:: High-performance computing. | 97 | * Installing Guix on a Cluster:: High-performance computing. |
| 94 | * Guix System Management:: System Management specifics. | 98 | * Guix System Management:: System Management specifics. |
| 95 | 99 | ||
| @@ -210,6 +214,13 @@ Environment management | |||
| 210 | 214 | ||
| 211 | * Guix environment via direnv:: Setup Guix environment with direnv | 215 | * Guix environment via direnv:: Setup Guix environment with direnv |
| 212 | 216 | ||
| 217 | Using Guix for Reproducible Research | ||
| 218 | |||
| 219 | * Setting Up the Environment:: Step 1: using `guix shell'. | ||
| 220 | * Recording the Environment:: Step 2: using `guix describe'. | ||
| 221 | * Ensuring Long-Term Source Code Archiving:: Step 3: Software Heritage. | ||
| 222 | * Referencing the Software Environment:: Step 4: SWHIDs. | ||
| 223 | |||
| 213 | Installing Guix on a Cluster | 224 | Installing Guix on a Cluster |
| 214 | 225 | ||
| 215 | * Setting Up a Head Node:: The node that runs the daemon. | 226 | * Setting Up a Head Node:: The node that runs the daemon. |
| @@ -5657,6 +5668,246 @@ Run @command{direnv allow} to setup the environment for the first time. | |||
| 5657 | 5668 | ||
| 5658 | 5669 | ||
| 5659 | @c ********************************************************************* | 5670 | @c ********************************************************************* |
| 5671 | @node Reproducible Research | ||
| 5672 | @chapter Using Guix for Reproducible Research | ||
| 5673 | |||
| 5674 | @cindex reproducible research | ||
| 5675 | Because it supports reproducible deployment, Guix is a solid foundation | ||
| 5676 | for @dfn{reproducible research workflows}. This section is targeted at | ||
| 5677 | scientists; it shows how to add Guix to one's reproducible research | ||
| 5678 | toolbox@footnote{This chapter is adapted from a | ||
| 5679 | @uref{https://hpc.guix.info/blog/2023/06/a-guide-to-reproducible-research-papers/, | ||
| 5680 | blog post published on the Guix-HPC web site in 2023.}.}. | ||
| 5681 | |||
| 5682 | With Guix as the basis of your computational workflow, you can get | ||
| 5683 | what's in essence @emph{executable provenance meta-data}: it's like the | ||
| 5684 | list of package name/version pairs some provide as an appendix to their | ||
| 5685 | publication, except more precise and immediately deployable. | ||
| 5686 | |||
| 5687 | This section is a guide in just four steps on how to make your | ||
| 5688 | computational experiments reproducible using Guix, and how to provide | ||
| 5689 | that information in your research paper. | ||
| 5690 | |||
| 5691 | @menu | ||
| 5692 | * Setting Up the Environment:: Step 1: using `guix shell'. | ||
| 5693 | * Recording the Environment:: Step 2: using `guix describe'. | ||
| 5694 | * Ensuring Long-Term Source Code Archiving:: Step 3: Software Heritage. | ||
| 5695 | * Referencing the Software Environment:: Step 4: SWHIDs. | ||
| 5696 | @end menu | ||
| 5697 | |||
| 5698 | @node Setting Up the Environment | ||
| 5699 | @section Step 1: Setting Up the Environment | ||
| 5700 | |||
| 5701 | The first step is to identify precisely what packages you need in | ||
| 5702 | your software environment to run your computational experiment. | ||
| 5703 | |||
| 5704 | Assuming you have a Python script that uses NumPy, you can start by | ||
| 5705 | creating an environment that contains these two packages and | ||
| 5706 | to run your code in that environment (@pxref{Invoking guix shell,,, | ||
| 5707 | guix, GNU Guix Reference Manual}): | ||
| 5708 | |||
| 5709 | @example | ||
| 5710 | guix shell -C python python-numpy -- python3 ./myscript.py | ||
| 5711 | @end example | ||
| 5712 | |||
| 5713 | The @code{-C} flag here (or @code{--container}) instructs @command{guix | ||
| 5714 | shell} to create that environment in an isolated container with nothing | ||
| 5715 | but the two packages you asked for. That way, if | ||
| 5716 | @command{./myscript.py} needs more than these two packages, it'll fail | ||
| 5717 | to run and you'll immediately notice. On some systems | ||
| 5718 | @code{--container} is not supported; in that case, you can resort to | ||
| 5719 | @code{--pure} instead. | ||
| 5720 | |||
| 5721 | Perhaps you'll find that you also need Pandas and add it to the | ||
| 5722 | environment: | ||
| 5723 | |||
| 5724 | @example | ||
| 5725 | guix shell -C python python-numpy python-pandas -- \ | ||
| 5726 | python3 ./myscript.py | ||
| 5727 | @end example | ||
| 5728 | |||
| 5729 | If you fail to guess the name of the package (this one was easy!), try | ||
| 5730 | @code{guix search}. | ||
| 5731 | |||
| 5732 | Environments for Python, R, and similar high-level languages are | ||
| 5733 | relatively easy to set up. For C/C++ code, you may find need many more | ||
| 5734 | packages: | ||
| 5735 | |||
| 5736 | @example | ||
| 5737 | guix shell -C gcc-toolchain cmake coreutils grep sed make -- @dots{} | ||
| 5738 | @end example | ||
| 5739 | |||
| 5740 | Or perhaps you'll find that you could just as well provide a | ||
| 5741 | for your package---@pxref{Defining Packages,,, guix, GNU Guix Reference | ||
| 5742 | Manual}, to learn more on how to do that. | ||
| 5743 | |||
| 5744 | Eventually, you'll have a list of packages that satisfies your needs. | ||
| 5745 | |||
| 5746 | @quotation What if a package is missing? | ||
| 5747 | Guix and the main scientific channels provide about | ||
| 5748 | @uref{https://hpc.guix.info/browse, tens of thousands of packages}. | ||
| 5749 | Yet, there's always the possibility that the one package you need is | ||
| 5750 | missing. | ||
| 5751 | |||
| 5752 | In that case, you will need to provide a definition for it | ||
| 5753 | (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}) in a | ||
| 5754 | dedicated channel of yours (@pxref{Creating a Channel,,, guix, GNU Guix | ||
| 5755 | Reference Manual}). For software in Python, R, and other high-level | ||
| 5756 | languages, most of the work can usually be automated by using | ||
| 5757 | @command{guix import} (@pxref{Invoking guix import,,, guix, GNU Guix | ||
| 5758 | Reference Manual}). | ||
| 5759 | |||
| 5760 | Join | ||
| 5761 | @uref{https://guix.gnu.org/contact/,the friendly Guix community} to get | ||
| 5762 | help! | ||
| 5763 | @end quotation | ||
| 5764 | |||
| 5765 | @node Recording the Environment | ||
| 5766 | @section Step 2: Recording the Environment | ||
| 5767 | |||
| 5768 | Now that you have that @code{guix shell} command line with a list of | ||
| 5769 | packages, the best course of action is to save it in a @emph{manifest} | ||
| 5770 | file---essentially a software bill of materials---that Guix can then | ||
| 5771 | ingest (@pxref{Writing Manifests,,, guix, GNU Guix Reference Manual}). | ||
| 5772 | The easiest way to get started is by ``translating'' your command line | ||
| 5773 | into a manifest: | ||
| 5774 | |||
| 5775 | @example | ||
| 5776 | guix shell python python-numpy python-pandas \ | ||
| 5777 | --export-manifest > manifest.scm | ||
| 5778 | @end example | ||
| 5779 | |||
| 5780 | Put that manifest under version control! From there anyone can redeploy | ||
| 5781 | the software environment described by the manifest and run code in that | ||
| 5782 | environment: | ||
| 5783 | |||
| 5784 | @example | ||
| 5785 | guix shell -C -m manifest.scm -- python3 ./myscript.py | ||
| 5786 | @end example | ||
| 5787 | |||
| 5788 | Here's what @file{manifest.scm} reads: | ||
| 5789 | |||
| 5790 | @lisp | ||
| 5791 | ;; What follows is a "manifest" equivalent to the command line you gave. | ||
| 5792 | ;; You can store it in a file that you may then pass to any 'guix' command | ||
| 5793 | ;; that accepts a '--manifest' (or '-m') option. | ||
| 5794 | |||
| 5795 | (specifications->manifest | ||
| 5796 | (list "python" "python-numpy" "python-pandas")) | ||
| 5797 | @end lisp | ||
| 5798 | |||
| 5799 | It's a code snippet that lists packages. Notice that there are no | ||
| 5800 | version numbers! Indeed, these version numbers are specified in package | ||
| 5801 | definitions, located in Guix channels. To allow others to reproduce the | ||
| 5802 | exact same environment as the one you're running, you need to @emph{pin | ||
| 5803 | Guix itself} , by capturing the current Guix channel commits with | ||
| 5804 | @command{guix describe} (@pxref{Replicating Guix,,, guix, GNU Guix | ||
| 5805 | Reference Manual}): | ||
| 5806 | |||
| 5807 | @example | ||
| 5808 | guix describe -f channels > channels.scm | ||
| 5809 | @end example | ||
| 5810 | |||
| 5811 | @cindex lock files, for reproducibility | ||
| 5812 | This @code{channels.scm} file is similar in spirit to ``lock files'' | ||
| 5813 | that some deployment tools employ to pin package revisions. You should | ||
| 5814 | also keep it under version control in your code, and possibly update it | ||
| 5815 | once in a while when you feel like running your code against newer | ||
| 5816 | versions of its dependencies. With this file, anyone, @emph{at any time | ||
| 5817 | and on any machine}, can now reproduce the exact same environment by | ||
| 5818 | running: | ||
| 5819 | |||
| 5820 | @example | ||
| 5821 | guix time-machine -C channels.scm -- \ | ||
| 5822 | shell -C -m manifest.scm -- \ | ||
| 5823 | python3 ./myscript.py | ||
| 5824 | @end example | ||
| 5825 | |||
| 5826 | In this example we rely solely on the @code{guix} channel, which | ||
| 5827 | provides the Python packages we need. Perhaps some of the packages you | ||
| 5828 | need live @uref{https://hpc.guix.info/channels,in other | ||
| 5829 | channels}---maybe @code{guix-cran} if you use R, maybe | ||
| 5830 | @code{guix-science}. That's fine: @code{guix describe} also captures | ||
| 5831 | that. | ||
| 5832 | |||
| 5833 | Of course do include a @file{README} file giving the exact command to | ||
| 5834 | run the code. Not everyone uses Guix so it can be helpful to also | ||
| 5835 | provide minimal non-Guix setup instructions: which package versions are | ||
| 5836 | used, how software is built, etc. As we have seen, such instructions | ||
| 5837 | would likely be inaccurate and inconvenient to follow at best. Yet, it | ||
| 5838 | can be a useful starting point to someone trying to recreate a | ||
| 5839 | @emph{similar} environment using different tools. It should probably be | ||
| 5840 | presented as such, with the understanding that the only way to get the | ||
| 5841 | @emph{same} environment is to use Guix. | ||
| 5842 | |||
| 5843 | @node Ensuring Long-Term Source Code Archiving | ||
| 5844 | @section Step 3: Ensuring Long-Term Source Code Archiving | ||
| 5845 | |||
| 5846 | We insisted on version control before: for the @file{manifest.scm} and | ||
| 5847 | @file{channels.scm} files, but of course also for your own code. Our | ||
| 5848 | recommendation is to have these two @file{.scm} files in the same | ||
| 5849 | repository as the code they're about. | ||
| 5850 | |||
| 5851 | Since the goal is enabling reproducibility, source code availability is | ||
| 5852 | a prime concern. Source code hosting services come and go and we don't | ||
| 5853 | want our code to vanish in a whim and render our published research work | ||
| 5854 | unverifiable. @uref{https://www.softwareheritage.org/,Software Heritage} | ||
| 5855 | (SWH for short) is @emph{the} solution for this: SWH archives public | ||
| 5856 | source code and provides unique intrinsic identifiers to refer to | ||
| 5857 | it---@uref{https://swhid.org, @dfn{SWHIDs}}. | ||
| 5858 | Guix itself is | ||
| 5859 | @uref{https://doi.org/10.1145/3641525.3663622,connected | ||
| 5860 | to SWH} to (1)@ ensure that the source code of its packages is archived, | ||
| 5861 | and (2)@ to fall back to downloading from the SWH archive should code | ||
| 5862 | vanish from its original site. | ||
| 5863 | |||
| 5864 | Once your own code is available in a public version-control repository, | ||
| 5865 | such as a Git repository on your lab's hosting service, you can ask SWH | ||
| 5866 | to archive it by going to its | ||
| 5867 | @uref{https://archive.softwareheritage.org/save/,Save Code Now} | ||
| 5868 | interface. SWH will process the request asynchronously and eventually | ||
| 5869 | you'll find your code has made it into | ||
| 5870 | @uref{https://archive.softwareheritage.org/,the archive}. | ||
| 5871 | |||
| 5872 | @node Referencing the Software Environment | ||
| 5873 | @section Step 4: Referencing the Software Environment | ||
| 5874 | |||
| 5875 | This brings us to the last step: referring to our code @emph{and} | ||
| 5876 | software environment in our beloved paper. We already have all our code | ||
| 5877 | and Guix files in the same repository, which is archived on SWH. Thanks | ||
| 5878 | to SWH, we now have a SWHID, which uniquely identifies the relevant | ||
| 5879 | revision of our code. | ||
| 5880 | |||
| 5881 | Following | ||
| 5882 | @uref{https://www.softwareheritage.org/howto-archive-and-reference-your-code/,SWH's | ||
| 5883 | own guide}, we'll pick an @code{swh:dir} kind of identifier, which | ||
| 5884 | refers to the directory of the relevant revision/commit of our | ||
| 5885 | repository, and we'll keep @emph{contextual info} for clarity---that | ||
| 5886 | includes the original URL. Putting it all together, we'll conclude our | ||
| 5887 | paper with a sentence along these lines: | ||
| 5888 | |||
| 5889 | @quotation Example | ||
| 5890 | The source code used to produce this study, as well as instructions to | ||
| 5891 | run it in the right software environment using GNU@ Guix, is archived on | ||
| 5892 | Software Heritage as | ||
| 5893 | @uref{https://archive.softwareheritage.org/swh:1:dir:cc8919d7705fbaa31efa677ce00bef7eb374fb80;origin=https://gitlab.inria.fr/lcourtes-phd/edcc-2006-redone;visit=swh:1:snp:71a4d08ef4a2e8455b67ef0c6b82349e82870b46;anchor=swh:1:rev:36fde7e5ba289c4c3e30d9afccebbe0cfe83853a,@code{swh:1:dir:cc8919d7705fbaa31efa677ce00bef7eb374fb80;origin=https://gitlab.inria.fr/lcourtes-phd/edcc-2006-redone;visit=swh:1:snp:71a4d08ef4a2e8455b67ef0c6b82349e82870b46;anchor=swh:1:rev:36fde7e5ba289c4c3e30d9afccebbe0cfe83853a}}. | ||
| 5894 | @end quotation | ||
| 5895 | |||
| 5896 | With this information, the reader can: | ||
| 5897 | |||
| 5898 | @itemize | ||
| 5899 | @item | ||
| 5900 | get the source code; | ||
| 5901 | @item | ||
| 5902 | reproduce its software environment with @code{guix time-machine} and run | ||
| 5903 | the code; | ||
| 5904 | @item | ||
| 5905 | inspect and possibly modify both the code and its environment. | ||
| 5906 | @end itemize | ||
| 5907 | |||
| 5908 | Mission accomplished! | ||
| 5909 | |||
| 5910 | @c ********************************************************************* | ||
| 5660 | @node Installing Guix on a Cluster | 5911 | @node Installing Guix on a Cluster |
| 5661 | @chapter Installing Guix on a Cluster | 5912 | @chapter Installing Guix on a Cluster |
| 5662 | 5913 | ||
