├── .github
└── workflows
│ ├── build.yml
│ ├── deploy.yml
│ └── preview.yml
├── .gitignore
├── LICENSE
├── README.md
├── check-one-sentence-per-line.sh
├── docs
├── README.md
├── community
│ ├── README.md
│ ├── case-studies
│ │ ├── README.md
│ │ ├── campbell-pen-and-paper-version-control.md
│ │ ├── moss-incorrect-data-pre-print.md
│ │ └── moss-pypfilt-earlier-states.md
│ ├── meetings
│ │ ├── 2023-04-17.md
│ │ ├── 2023-06-13.md
│ │ ├── 2023-08-15.md
│ │ ├── 2023-10-18.md
│ │ ├── 2024-02-19.md
│ │ ├── 2024-04-11.md
│ │ ├── 2024-05-09.md
│ │ ├── 2024-06-13-pros-and-cons.png
│ │ ├── 2024-06-13.md
│ │ ├── 2024-07-11.md
│ │ ├── 2024-08-08.md
│ │ ├── 2024-09-12.md
│ │ ├── 2024-10-10.md
│ │ ├── 2024-11-14.md
│ │ └── README.md
│ └── training
│ │ ├── README.md
│ │ └── debugging
│ │ ├── README.md
│ │ ├── acknowledgements.md
│ │ ├── building-your-skills.md
│ │ ├── debugging-manifesto-poster.jpg
│ │ ├── example-square-numbers.md
│ │ ├── exercise-perfect-numbers.md
│ │ ├── exercise-python-vs-r.md
│ │ ├── first_demo.R
│ │ ├── first_demo.py
│ │ ├── headless-horse.jpg
│ │ ├── learning-objectives.md
│ │ ├── long_stacktrace.py
│ │ ├── manifesto.md
│ │ ├── perfect-numbers-first-run.cast
│ │ ├── perfect_numbers.R
│ │ ├── perfect_numbers.py
│ │ ├── real-world-stories.md
│ │ ├── resources.md
│ │ ├── sir_ode.R
│ │ ├── sir_ode.py
│ │ ├── sir_ode_python.png
│ │ ├── sir_ode_r.png
│ │ ├── solutions.md
│ │ ├── square-numbers-demo.cast
│ │ ├── square-numbers-demo.toml
│ │ ├── square-numbers-pdb.cast
│ │ ├── square-numbers-pdb.yaml
│ │ ├── square-numbers-r-debug.cast
│ │ ├── square-numbers-r-debug.yaml
│ │ ├── square_numbers.R
│ │ ├── square_numbers.py
│ │ ├── stacktrace.R
│ │ ├── stacktrace.py
│ │ ├── understanding-error-messages.md
│ │ ├── using-a-debugger.md
│ │ ├── what-is-debugging.md
│ │ ├── when-something-fails.md
│ │ └── why-are-debuggers-useful.md
├── contributors.md
├── extra
│ ├── asciinema-player.css
│ ├── asciinema-player.min.js
│ ├── asciinema-theme-gimlb.css
│ ├── larger-admonitions.css
│ └── wrapper.js
├── guides
│ ├── README.md
│ ├── collaborating
│ │ ├── README.md
│ │ ├── an-example-pull-request.md
│ │ ├── coding-style-guides.md
│ │ ├── collaborating-on-a-paper.md
│ │ ├── collaborating-on-code.md
│ │ ├── continuous-integration.md
│ │ ├── merge-pull-requests.md
│ │ ├── peer-code-review.md
│ │ ├── sharing-a-branch.md
│ │ └── sharing-a-repository.md
│ ├── high-performance-computing
│ │ └── README.md
│ ├── learning-objectives.md
│ ├── prerequisites.md
│ ├── project-structure
│ │ ├── README.md
│ │ ├── automating-tasks.md
│ │ ├── exercise-a-good-readme.md
│ │ ├── exercise-what-works-for-you.md
│ │ ├── explain-how-it-works.md
│ │ └── workflow.md
│ ├── reproducibility
│ │ ├── README.md
│ │ └── what-is-reproducible-research.md
│ ├── resources.md
│ ├── testing
│ │ └── README.md
│ ├── using-git
│ │ ├── README.md
│ │ ├── choosing-a-license.md
│ │ ├── choosing-your-git-editor.md
│ │ ├── cloning-an-existing-repository.md
│ │ ├── creating-a-commit.md
│ │ ├── creating-a-remote-repository.md
│ │ ├── creating-a-repository.md
│ │ ├── exercise-create-a-local-repository.md
│ │ ├── exercise-resolve-a-merge-conflict.md
│ │ ├── exercise-use-a-remote-repository.md
│ │ ├── first-time-git-setup.md
│ │ ├── git-editor-example.cast
│ │ ├── graphical-git-clients.md
│ │ ├── how-to-create-and-use-tags.md
│ │ ├── how-to-ignore-certain-files.md
│ │ ├── how-to-resolve-merge-conflicts.md
│ │ ├── how-to-structure-a-repository.md
│ │ ├── how-to-use-branches.md
│ │ ├── inspecting-your-history.md
│ │ ├── pushing-and-pulling-commits.md
│ │ ├── solution-resolve-a-merge-conflict.cast
│ │ ├── where-did-this-line-come-from.cast
│ │ ├── where-did-this-line-come-from.md
│ │ └── where-did-this-problem-come-from.md
│ ├── version-control
│ │ ├── README.md
│ │ ├── branch-1.png
│ │ ├── branch-2.png
│ │ ├── branch-3.png
│ │ ├── exercise-using-version-control.md
│ │ ├── how-do-I-write-a-commit-message.md
│ │ ├── what-is-a-branch.md
│ │ ├── what-is-a-commit.md
│ │ ├── what-is-a-merge-conflict.md
│ │ ├── what-is-a-repository.md
│ │ ├── what-is-a-tag.md
│ │ ├── what-is-version-control.md
│ │ └── what-should-I-commit.md
│ └── writing-code
│ │ ├── README.md
│ │ ├── behave-nicely.md
│ │ ├── check-your-code.md
│ │ ├── coding-advice.md
│ │ ├── cohesion-coupling.md
│ │ ├── create-packages.md
│ │ ├── document-your-code.md
│ │ ├── exercise-seek-feedback.md
│ │ ├── format-your-code.md
│ │ └── how-we-learn-to-write-code.md
├── how-to-contribute.md
├── logo.png
├── logo.svg
└── orientation
│ └── README.md
├── figures
├── .gitignore
├── Makefile
├── README.md
├── tikzfig.cls
└── version-control
│ ├── branch-1.tex
│ ├── branch-2.tex
│ └── branch-3.tex
├── mkdocs.yml
├── pyproject.toml
└── requirements.txt
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Build, but do not deploy, the book on all branches except `master`.
2 |
3 | name: Build
4 |
5 | on:
6 | push:
7 | branches-ignore:
8 | - master
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Check out
15 | uses: actions/checkout@v4
16 |
17 | - name: Set up Python
18 | uses: actions/setup-python@v5
19 | with:
20 | python-version: '3.10'
21 | cache: 'pip'
22 |
23 | - name: Install Material for MkDocs
24 | run: |
25 | python -m pip install --upgrade pip
26 | pip install -r requirements.txt
27 |
28 | - name: Build the book
29 | run: |
30 | mkdocs build
31 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | # Build the `master` branch and deploy.
2 |
3 | name: Deploy
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 |
10 | jobs:
11 | deploy:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Check out
15 | uses: actions/checkout@v4
16 |
17 | - name: Set up Python
18 | uses: actions/setup-python@v5
19 | with:
20 | python-version: '3.10'
21 | cache: 'pip'
22 |
23 | - name: Install Material for MkDocs
24 | run: |
25 | python -m pip install --upgrade pip
26 | pip install -r requirements.txt
27 |
28 | - name: Build the book
29 | run: |
30 | mkdocs build
31 |
32 | - name: Deploy GitHub Pages
33 | uses: JamesIves/github-pages-deploy-action@v4
34 | with:
35 | folder: site
36 | force: false
37 | clean-exclude: pr-preview/
38 |
--------------------------------------------------------------------------------
/.github/workflows/preview.yml:
--------------------------------------------------------------------------------
1 | # Build pull requests and deploy.
2 |
3 | name: Deploy PR previews
4 |
5 | on:
6 | pull_request:
7 | types:
8 | - opened
9 | - reopened
10 | - synchronize
11 | - closed
12 |
13 | concurrency: preview-${{ github.ref }}
14 |
15 | jobs:
16 | deploy-preview:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Check out
20 | uses: actions/checkout@v4
21 |
22 | - name: Set up Python
23 | uses: actions/setup-python@v5
24 | with:
25 | python-version: '3.10'
26 | cache: 'pip'
27 |
28 | - name: Install Material for MkDocs
29 | run: |
30 | python -m pip install --upgrade pip
31 | pip install -r requirements.txt
32 |
33 | - name: Build the book
34 | run: |
35 | mkdocs build
36 |
37 | # NOTE: we can only deploy PR previews from the original repository.
38 | # This action fails when the PR originates from a forked repository;
39 | # see https://github.com/rossjrw/pr-preview-action/issues/3 for details.
40 | - name: Deploy preview
41 | if: github.event.pull_request.head.repo.full_name == github.repository
42 | uses: rossjrw/pr-preview-action@v1
43 | with:
44 | source-dir: site
45 | force: false
46 | clean-exclude: pr-preview/
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | site/
2 | venv/
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Git is my lab book
2 |
3 | [][book]
4 | [][license]
5 |
6 | These materials aim to support
7 | early- and mid-career researchers (EMCRs) in the
8 | [SPECTRUM](https://www.spectrum.edu.au/) and [SPARK](https://www.spark.edu.au/) networks to develop their computing skills, and to make effective use of available tools and infrastructure.
9 |
10 | You can [view this book online][book].
11 |
12 | ## License
13 |
14 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License][license].
15 |
16 | ## Requirements
17 |
18 | To build this book, you must have [Material for MkDocs][matmkdocs] installed.
19 | For example:
20 |
21 | ```sh
22 | python3 -m venv venv
23 | source venv/bin/activate
24 | pip install -r requirements.txt
25 | ```
26 |
27 | ## Building the book
28 |
29 | You can view this book in your browser by running the following commands in this directory:
30 |
31 | ```shell
32 | source venv/bin/activate
33 | mkdocs serve
34 | ```
35 |
36 | This will automatically rebuild the book whenever you edit the contents.
37 |
38 | [book]: https://git-is-my-lab-book.net/
39 | [license]: https://creativecommons.org/licenses/by-sa/4.0/
40 | [matmkdocs]: https://squidfunk.github.io/mkdocs-material/
41 |
--------------------------------------------------------------------------------
/check-one-sentence-per-line.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Detect lines that contain more than one sentence.
4 | #
5 | # We use a regular expression to identify lines that satisfy the following:
6 | #
7 | # 1. They contain at least one letter ('.*[A-Za-z].*'), to ignore numbered
8 | # list items;
9 | #
10 | # 2. They contain a literal period that is not preceded by a literal period
11 | # ('[^.]\.'), to ignore ellipses ('...');
12 | #
13 | # 3. The literal period is followed by a regular space ('\. '), to ignore
14 | # inline periods in common abbreviations (such as 'e.g.,' and 'i.e.,') and
15 | # in author names where non-breaking spaces should be used to separate
16 | # initials (e.g., 'Jesse M. Alston' rather than 'Jesse M. Alston').
17 | #
18 | grep --recursive --include='*.md' '^.*[A-Za-z].*[^.]\. ' docs/ && exit 2
19 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | These materials aim to support
4 | early- and mid-career researchers (EMCRs) in the
5 | [SPECTRUM](https://www.spectrum.edu.au/) and [SPARK](https://www.spark.edu.au/) networks to develop their computing skills, and to make effective use of available tools[^tools] and infrastructure[^infra].
6 |
7 | ## Structure
8 |
9 | **Start with the basics:** Our [orientation](orientation/README.md) tutorials provide overviews of essential skills, tools, templates, and suggested workflows.
10 |
11 | **Learn more about best practices:** Our [topical guides](guides/README.md) explain a range of topics and provide exercises to test your understanding.
12 |
13 | **Come together as a community:** Our [Community of Practice](community/README.md) is how we come together to share skills, knowledge, and experience.
14 |
15 | ## Motivation
16 |
17 | !!! question
18 |
19 | Why dedicate time and effort to learning these skills?
20 | There are **many reasons!**
21 |
22 | The overall aim of these materials is help you conduct code-driven research **more efficiently** and with **greater confidence**.
23 |
24 | Hopefully some of the following reasons resonate with you.
25 |
26 | - **Fearlessly modify your code**, knowing that your past work is never lost, by using [version control](./guides/version-control/README.md) with [git](./guides/using-git/README.md).
27 |
28 | - **Verify that your code behaves as expected**, and get notified when it doesn't, by [writing tests](./guides/testing/README.md).
29 |
30 | - **Ensure that your results won't change** when running on a different computer by "baking in" [reproducibility](./guides/reproducibility/README.md).
31 |
32 | - **Improve your coding skills**, and those of your colleagues, by working [collaboratively](./guides/collaborating/README.md) and making use of [peer code review](./guides/collaborating/peer-code-review.md).
33 |
34 | - **Run your code quickly**, and without relying on your own laptop or computer, by using [high-performance computing](./guides/high-performance-computing/README.md).
35 |
36 | !!! tip "Foundations of effective research"
37 |
38 | A piece of code is often useful beyond a single project or study.
39 |
40 | By applying the above skills in your research, you will be able to easily reproduce past results, extend your code to address new questions and problems, and allow others to build on your code in their own research.
41 |
42 | **The benefits of good practices can continue to pay off long after the project is finished**.
43 |
44 | ## License
45 |
46 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
47 |
48 | [^tools]: Such as [version control](./guides/version-control/README.md) and [testing frameworks](./guides/testing/README.md).
49 |
50 | [^infra]: Such as the [ARDC Nectar Research Cloud][nectar] and [Spartan].
51 |
52 | [nectar]: https://ardc.edu.au/services/nectar-research-cloud/
53 | [Spartan]: https://dashboard.hpc.unimelb.edu.au/
54 |
--------------------------------------------------------------------------------
/docs/community/README.md:
--------------------------------------------------------------------------------
1 | # Community of Practice
2 |
3 | !!! info
4 |
5 | *Communities of Practice* are groups of people who share a concern or a passion for something they do and learn how to do it better as they interact regularly.
6 |
7 | The community acts as a **living curriculum** and involves **learning on the part of everyone**.
8 |
9 | The aim of a *Community of Practice* (*CoP*) is to come together as a community and engage in a process of **collective learning** in a shared domain.
10 | The [three characteristics](https://www.communityofpractice.ca/background/what-is-a-community-of-practice/) of a *CoP* are:
11 |
12 | 1. Community: An environment for learning through interaction;
13 |
14 | 2. Practice: Specific knowledge shared by community members; and
15 |
16 | 3. Domain: A shared interest, problem, or concern.
17 |
18 | We regularly meet as a community, report [meeting summaries](meetings/README.md), and collect [case studies](case-studies/README.md) that showcase good practices.
19 |
20 | ## Training events
21 |
22 | To support skill development, we have the capacity to prepare and deliver bespoke training events as standalone session and as part of larger meetings and conferences.
23 | See our [Training events](training/README.md) page for further details.
24 |
--------------------------------------------------------------------------------
/docs/community/case-studies/README.md:
--------------------------------------------------------------------------------
1 | # Case studies
2 |
3 | This section contains interesting and useful examples of incorporating Git into a research activity, as contributed by EMCRs in our network.
4 |
--------------------------------------------------------------------------------
/docs/community/case-studies/campbell-pen-and-paper-version-control.md:
--------------------------------------------------------------------------------
1 | # Pen and paper - a less user-friendly form of version control than Git
2 |
3 | Author: Trish Campbell (`patricia.campbell@unimelb.edu.au`)
4 |
5 | Project: Pertussis modelling
6 |
7 | ## The problem
8 |
9 | In this project, I developed a compartmental model of pertussis to determine appropriate vaccination strategies.
10 | While plotting some single model simulations, I noticed anomalies in the modelled output for two experiments.
11 | The first experiment had an order of magnitude more people in the infectious compartments than in the second experiment, even though there seemed to be far fewer infections occurring.
12 | This scenario did not fit with the parameter values that were being used.
13 | In the differential equation file for my model, in addition to extracting the state of the model (i.e., the population in each compartment at each time step), for ease of analysis I also extracted the cumulative number of infections up to that time step.
14 | The calculation for this extraction of cumulative incidence was incorrect.
15 |
16 | ## The solution
17 |
18 | The error occurred because susceptible people in my model were not all equally susceptible, and I failed to account for this when I calculated the cumulative number of infections at each time step.
19 | I identified that this was the problem by running some targeted test parameter sets and observing the changes in model output.
20 | The next step was to find out how long this bug had existed in the code and which analyses had been affected.
21 | While I was using version control, I tended to make large infrequent commits.
22 | I did, however, keep extensive hand-written notes in lab books, which played the role of a detailed history of commits.
23 | Searching through my historical lab books, I identified that I had introduced this bug into the code two years earlier.
24 | I was able to determine which parts of my results would have been affected by the bug and made the decision that all experiments needed to be re-run.
25 |
26 | ## How version control helped
27 |
28 | Using a **pen and paper** form of version control enabled me to pinpoint the introduction of the error and identify the affected analyses, but it was a tedious process.
29 | While keeping an immaculate record of changes that I had made was invaluable, imagine how much simpler and faster the process would have been if I had been a regular user of an electronic version control system such as Git!
30 |
--------------------------------------------------------------------------------
/docs/community/case-studies/moss-incorrect-data-pre-print.md:
--------------------------------------------------------------------------------
1 | # Incorrect data in a pre-print figure
2 |
3 | Author: Rob Moss (`rgmoss@unimelb.edu.au`)
4 |
5 | Project: COVID-19 scenario modelling ([public repository](https://bitbucket.org/robmoss/covid19-aus-scenario-model))
6 |
7 | ## The problem
8 |
9 | Our colleague James Trauer notified us that they suspected there was an error in Figure 2 of our COVID-19 scenario modelling [pre-print article](https://doi.org/10.1101/2020.04.07.20056184).
10 | This figure showed model predictions of the daily ICU admission demand in an unmitigated COVID-19 pandemic, and in a COVID-19 pandemic with case targeted public health measures.
11 | I inspected the script responsible for plotting this figure, and confirmed that I had mistakenly plotted the combined demand for ward and ICU beds, instead of the demand for ICU beds alone.
12 |
13 | ## The solution
14 |
15 | This mistake was [simple to correct](https://bitbucket.org/robmoss/covid19-aus-scenario-model/commits/7ed7d45f731e153f72b77b83c81a6a3aac888995), but the obvious concern was whether any other outputs related to ICU bed demand were affected.
16 |
17 | We conducted a detailed review of all data analysis scripts and outputs, and confirmed that this error only affected this single manuscript figure.
18 | It had no bearing on the impact of the interventions in each model scenario.
19 | Importantly, it did not affect any of the simulation outputs, summary tables, and/or figures that were included in our reports to government.
20 |
21 | The corrected figure can be seen in the [published article](https://doi.org/10.3201/eid2612.202530).
22 |
23 | ## How version control helped
24 |
25 | Because we used version control to record the development history of the model and all of the simulation analyses, we were able to easily inspect the repository state at the time of each prior analysis.
26 | This greatly simplified the review process, and ensured that we were inspecting the code **exactly as it was** when we produced each analysis.
27 |
--------------------------------------------------------------------------------
/docs/community/case-studies/moss-pypfilt-earlier-states.md:
--------------------------------------------------------------------------------
1 | # Fixing a bug in pypfilt
2 |
3 | Author: Rob Moss (`rgmoss@unimelb.edu.au`)
4 |
5 | Project: [pypfilt], a bootstrap particle filter for Python
6 |
7 | Date: 27 October 2021
8 |
9 | ## Overview
10 |
11 | I introduced a bug when I modified a function in my [pypfilt] package, and only detected the bug after I had created several more commits.
12 |
13 | To resolve this bug, I had to:
14 |
15 | 1. Notice the bug;
16 |
17 | 2. Identify the cause of the bug;
18 |
19 | 3. Write a test case to check whether the bug is present; and
20 |
21 | 4. Fix the bug.
22 |
23 | ## Notice the bug
24 |
25 | I noticed that a regression test[^regression] was failing: re-running a set of model simulations was no longer generating the same output.
26 | The results had changed, but none of my recent commits should have had this effect.
27 |
28 | **I should have noticed this** when I created the commit that introduced this bug, but:
29 |
30 | - I had not pushed the most recent commits to the upstream [repository], where all of the test cases are run automatically every time a new commit is pushed; and
31 |
32 | - I had not run the test cases on my laptop after making each of the recent commits, because this takes a few minutes and I was lazy.
33 |
34 | ## Identify the cause of the bug
35 |
36 | I knew that the bug had been introduced quite recently, and I knew that it affected a specific function: [`earlier_states()`][earlier_states()].
37 | Running `git blame src/pypfilt/state.py` indicated that the recent commit [`408b5f1`][408b5f1] was a likely culprit, because it changed many lines in this function.
38 |
39 | In particular, I suspected the bug was occurring in the following loop, which steps backwards in time and handles the case where model simulations are reordered:
40 |
41 | ```python
42 | # Start with the parent indices for the current particles, which allow us
43 | # to look back one time-step.
44 | parent_ixs = np.copy(hist['prev_ix'][ix])
45 |
46 | # Continue looking back one time-step, and only update the parent indices
47 | # at time-step T if the particles were resampled at time-step T+1.
48 | for i in range(1, steps):
49 | step_ix = ix - i
50 | if hist['resampled'][step_ix + 1, 0]:
51 | parent_ixs = hist['prev_ix'][step_ix, parent_ixs]
52 | ```
53 |
54 | In stepping through this code, I identified that the following line was incorrect:
55 |
56 |
57 | ```python
58 | if hist['resampled'][step_ix + 1, 0]:
59 | ```
60 |
61 | and that changing `step_ix + 1` to `step_ix` **should** fix the bug.
62 |
63 | **Note:** I could have used `git bisect` to identify the commit that introduced this bug, but running all of the test cases for each commit is relatively time-consuming; since I knew that the bug had been introduced quite recently, I chose to use `git blame`.
64 |
65 | ## Write a test case
66 |
67 | I wrote a test case [`test_earlier_state()`][test_earlier_state()] that called this [`earlier_states()`][earlier_states()] function a number of times, and checked that each set of model simulations were returned in the correct order.
68 |
69 | This test case checks that:
70 |
71 | 1. If the model simulations were not reordered, the original ordering is always returned;
72 |
73 | 2. If the model simulations were reordered at some time `t_0`, the original ordering is returned for times `t < t_0`; and
74 |
75 | 3. If the model simulations were reordered at some time `t_0`, the new ordering is returned for times `t >= t_0`.
76 |
77 | This test case failed when I reran the testing pipeline, which indicated that it identified the bug.
78 |
79 | ## Fix the bug
80 |
81 | With the test case now written, I was able to verify that that changing `step_ix + 1` to `step_ix` **did** fix the bug.
82 |
83 | I added the test case and the bug fix in commit [`9dcf621`][9dcf621].
84 |
85 | In the commit message I indicated:
86 |
87 | 1. Where the bug was located: the [`earlier_states()`][earlier_states()] function;
88 |
89 | 2. When the bug was introduced: commit [`408b5f1`][408b5f1]; and
90 |
91 | 3. Why the bug was not detected when I created commit [`408b5f1`][408b5f1].
92 |
93 | [^regression]: A regression test checks that a commit hasn't changed an existing behaviour or functionality.
94 |
95 | [pypfilt]: https://pypfilt.readthedocs.io/
96 | [earlier_states()]: https://pypfilt.readthedocs.io/en/latest/api/state.html#pypfilt.state.earlier_states
97 | [repository]: https://gitlab.unimelb.edu.au/rgmoss/particle-filter-for-python
98 | [408b5f1]: https://gitlab.unimelb.edu.au/rgmoss/particle-filter-for-python/-/commit/408b5f13302e5edb5ae7866286927873ed0f0c96
99 | [test_earlier_state()]: https://gitlab.unimelb.edu.au/rgmoss/particle-filter-for-python/-/blob/9dcf621618fe76281a486af7bfba364e7bd26c13/tests/test_earlier_state.py
100 | [9dcf621]: https://gitlab.unimelb.edu.au/rgmoss/particle-filter-for-python/-/commit/9dcf621618fe76281a486af7bfba364e7bd26c13
101 |
--------------------------------------------------------------------------------
/docs/community/meetings/2024-06-13-pros-and-cons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/community/meetings/2024-06-13-pros-and-cons.png
--------------------------------------------------------------------------------
/docs/community/meetings/2024-09-12.md:
--------------------------------------------------------------------------------
1 | # 12 September 2024
2 |
3 | In this meeting we did a test run through our **Introduction to Debugging** workshop, prior to running this workshop at the SPECTRUM Annual Meeting (23–25 September, 2024).
4 |
5 | Attendance: 3 in person, 7 online
6 |
7 | ## Introduction to Debugging workshop
8 |
9 | Feedback was generally positive.
10 | However, attendees noted that the errors in the provided code exercises were simple enough that they could be identified without using a debugger.
11 |
12 | - We may need code examples that are more complex, to ensure that participants actually need to use a debugger.
13 |
14 | - The final exercise may be sufficiently complex?
15 |
16 | - We might also include an SIR-type compartmental model with some logic errors (although these can be hard to hide!).
17 |
18 | - We can also ask participants to practice using a debugger with a code example **where there is no error**.
19 |
20 | Based on her past experiences, Nefel suggested including an example of triggering a breakpoint only when an error occurs (e.g., using a `try` statement in Python and calling `breakpoint()` in an `except` clause).
21 |
--------------------------------------------------------------------------------
/docs/community/meetings/README.md:
--------------------------------------------------------------------------------
1 | # Meetings
2 |
3 | This section contains summaries of each Community of Practice meeting.
4 |
5 | - [14 November 2024](2024-11-14.md): presentation from Eamon Conway about coding tools and workflow.
6 |
7 | - [10 October 2024](2024-10-10.md): workshop retrospective, identify future workshops.
8 |
9 | - [12 September 2024](2024-09-12.md): test run of our Introduction to Debugging workshop.
10 |
11 | - [8 August 2024](2024-08-08.md): orientation guide planning.
12 |
13 | - [11 July 2024](2024-07-11.md): presentation from Nefel Tellioglu.
14 |
15 | - [13 June 2024](2024-06-13.md): presentation from Cam Zachreson.
16 |
17 | - [9 May 2024](2024-05-09.md): presentation from TK Le.
18 |
19 | - [11 April 2024](2024-04-11.md): ideas and resources for the orientation guide.
20 |
21 | - [19 February 2024](2024-02-19.md): identify goals and activities for 2024.
22 |
23 | - [18 October 2023](2023-10-18.md): sharing experiences about good ways to structure a project.
24 |
25 | - [15 August 2023](2023-08-15.md): changing our research and reproducibility practices.
26 |
27 | - [13 June 2023](2023-06-13.md): exploration of version control, reproducibility, and testing exercises.
28 |
29 | - [17 April 2023](2023-04-17.md): our initial meeting.
30 |
--------------------------------------------------------------------------------
/docs/community/training/README.md:
--------------------------------------------------------------------------------
1 | # Training events
2 |
3 | We will be running an [Introduction to Debugging](debugging/README.md) workshop at the [SPECTRUM](https://spectrum.edu.au/) Annual Meeting 2024 (23-25 September).
4 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/README.md:
--------------------------------------------------------------------------------
1 | # Introduction to Debugging
2 |
3 | This workshop was prepared for the [SPECTRUM](https://spectrum.edu.au/) Annual Meeting 2024 (23-25 September).
4 |
5 | !!! tip
6 |
7 | **We all make mistakes** when writing code and introduce errors.
8 |
9 | Having good debugging skills means that you can spend **less time fixing your code**.
10 |
11 | See the discussion in our [August 2024 meeting](../../meetings/2024-08-08.md#debugging) for further background.
12 |
13 | !!! note
14 |
15 | Please download the workshop scripts from the [Resources](resources.md) page.
16 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/acknowledgements.md:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 |
3 | Thank you to everyone who contributed to these materials, participated in the practice run, and/or provided feedback.
4 | This includes, in no particular order:
5 |
6 | - Eamon Conway
7 | - James Ong
8 | - Michael Lydeamore
9 | - Ada Yan
10 | - Ruarai Tobin
11 | - Lauren Smith
12 | - Roben Delos Reyes
13 | - Nefel Tellioglu
14 | - Tanaphum Wichaita
15 | - Jiahao Diao
16 | - TK Le
17 | - Dionne Argyropoulos
18 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/building-your-skills.md:
--------------------------------------------------------------------------------
1 | # Building your skills
2 |
3 | !!! tip
4 |
5 | Whenever you debug some code, consider it as an opportunity to learn, reflect, and [build your debugging skills](manifesto.md).
6 |
7 | Pay attention to your experience — what worked well, and what would you do differently next time?
8 |
9 | ## Identifying errors
10 |
11 | Write a failing test case, this allows you to verify that the bug can be reproduced.
12 |
13 | ## Developing a plan
14 |
15 | What information might help you decide how to begin?
16 |
17 | Can you identify a recent "known good" version of the code that doesn't include the error?
18 |
19 | If you're using version control, have a look at your recent commits and check whether any of them are likely to have introduced or exposed this error.
20 |
21 | ## Searching for the root cause
22 |
23 | We've shown how a debugger allows you to pause your code and see what it's actually doing.
24 | This is extremely helpful!
25 |
26 | !!! tip
27 |
28 | Other approaches may be useful, but avoid using trial-and-error.
29 |
30 | To quickly confirm or rule out specific suspicions, you might consider using:
31 |
32 | - `print()` statements;
33 | - using `assert()` to verify whether specific conditions are met;
34 | - manually calling functions from an interactive session (a "[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)");
35 | - reverting or commenting out the most recent changes; or
36 | - using `git bisect` to [identify the commit](../../../guides/using-git/where-did-this-problem-come-from.md) that introduced the error.
37 |
38 | ## Fixing the root cause
39 |
40 | Is there an optimal solution?
41 |
42 | This might be the solution that changes as little code as possible, or it might be a solution that involves modifying and/or restructuring other parts of your code.
43 |
44 | ## After it's fixed
45 |
46 | If you didn't write a test case to identify the error (see above), now is the time to write a test case to ensure you don't even make the same error again.
47 |
48 | Are there other parts of your code where you might make a similar mistake, for which you could also write test cases?
49 |
50 | Are there coding practices that might make this kind of error easier to find next time?
51 | For example, this might involve dividing your code into smaller functions, using version control to record commits [early and often](../../../guides/version-control/what-should-I-commit.md).
52 |
53 | Have you considered defensive programming practices?
54 | For example, at the start of a function it can often be a good idea to check that all of the arguments have valid values.
55 |
56 | Are there tools or approaches that you haven't used before, and which might be worth trying next time?
57 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/debugging-manifesto-poster.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/community/training/debugging/debugging-manifesto-poster.jpg
--------------------------------------------------------------------------------
/docs/community/training/debugging/example-square-numbers.md:
--------------------------------------------------------------------------------
1 | # Example: Square numbers
2 |
3 | [Square numbers](https://en.wikipedia.org/wiki/Square_number) are positive integers that are equal to the square of an integer.
4 | Here we have provided example Python and R scripts that print all of the square numbers between 1 and 100:
5 |
6 |
7 |
8 | You can download these scripts to run on your own computer:
9 |
10 | - [square_numbers.py](square_numbers.py)
11 | - [square_numbers.R](square_numbers.R)
12 |
13 | Each script contains three functions:
14 |
15 | - `main()`
16 | - `find_squares(lower_bound, upper_bound)`
17 | - `is_square(value)`
18 |
19 | The diagram below shows how `main()` calls `find_squares()`, which in turn calls `is_square()` many times.
20 |
21 | ```mermaid
22 | sequenceDiagram
23 | participant M as main()
24 | participant F as find_squares()
25 | participant I as is_square()
26 | activate M
27 | M ->>+ F: lower_bound = 1, upper_bound = 100
28 | Note over F: squares = [ ]
29 | F ->>+ I: value = 1
30 | I ->>- F: True/False
31 | F ->>+ I: value = 2
32 | I ->>- F: True/False
33 | F -->>+ I: ...
34 | I -->>- F: ...
35 | F ->>+ I: value = 100
36 | I ->>- F: True/False
37 | F ->>- M: squares = [...]
38 | Note over M: print(squares)
39 | deactivate M
40 | ```
41 |
42 | ??? info "Source code"
43 |
44 | === "Python"
45 |
46 | ```py title="square_numbers.py" linenums="1"
47 | --8<-- "square_numbers.py"
48 | ```
49 |
50 | === "R"
51 |
52 | ```R title="square_numbers.R" linenums="1"
53 | --8<-- "square_numbers.R"
54 | ```
55 |
56 | ## Stepping through the code
57 |
58 | These recorded terminal sessions demonstrate how to use Python and R debuggers from the command line.
59 | They cover:
60 |
61 | - How to define breakpoints;
62 | - How to inspect the current values of variables; and
63 | - How to step through, and over, lines of code.
64 |
65 | !!! info "Manual breakpoints"
66 |
67 | You can also create breakpoints in your code by calling [`breakpoint()`](https://docs.python.org/3/library/pdb.html) in Python, and [`browser()`](https://adv-r.hadley.nz/debugging.html#browser) in R.
68 |
69 | !!! tip "Interactive debugger sessions"
70 |
71 | If your editor supports running a debugger, **use this feature!**
72 | See these examples for [RStudio](https://support.posit.co/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE), [PyCharm](https://www.jetbrains.com/pycharm/features/debugger.html), [Spyder](https://docs.spyder-ide.org/current/panes/debugging.html), and [VS Code](https://code.visualstudio.com/docs/editor/debugging).
73 |
74 | === "Python debugger"
75 |
76 |
77 |
78 | Video timeline:
79 |
80 | 1. Set a breakpoint
81 | 2. Show current location
82 | 3. Step into `is_square()`
83 | 4. Return from `is_square()`
84 | 5. Show updated `squares` list
85 | 6. Add a conditional breakpoint
86 | 7. Stop at the conditional breakpoint
87 | 8. Continue until the script ends
88 |
89 | === "R debugger"
90 |
91 |
92 |
93 | Video timeline:
94 |
95 | 1. Set a breakpoint
96 | 2. Step into `is_square()`
97 | 3. Return from `is_square()`
98 | 4. Show updated `squares` list
99 | 5. Add a conditional breakpoint
100 | 6. Stop at the conditional breakpoint
101 | 7. Continue until the script ends
102 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/exercise-perfect-numbers.md:
--------------------------------------------------------------------------------
1 | # Exercise: Perfect numbers
2 |
3 | === "Overview"
4 |
5 | [Perfect numbers](https://en.wikipedia.org/wiki/Perfect_number) are positive integers that are equal to the sum of their divisors.
6 | Here we have provided example Python and R scripts that should print all of the perfect numbers up to 1,000.
7 |
8 | You can download each script to debug on your own computer:
9 |
10 | - [perfect_numbers.py](perfect_numbers.py)
11 | - [perfect_numbers.R](perfect_numbers.R)
12 |
13 | === "Python"
14 |
15 | ```py title="perfect_numbers.py" linenums="1"
16 | --8<-- "perfect_numbers.py"
17 | ```
18 |
19 | === "R"
20 |
21 | ```R title="perfect_numbers.R" linenums="1"
22 | --8<-- "perfect_numbers.R"
23 | ```
24 |
25 | !!! bug "But there's a problem ..."
26 |
27 | If we run these scripts, we see that **they don't print anything**:
28 |
29 |
30 |
31 | How should we begin investigating?
32 |
33 | !!! tip "Interactive debugger sessions"
34 |
35 | If your editor supports running a debugger, **use this feature!**
36 | See these examples for [RStudio](https://support.posit.co/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE), [PyCharm](https://www.jetbrains.com/pycharm/features/debugger.html), [Spyder](https://docs.spyder-ide.org/current/panes/debugging.html), and [VS Code](https://code.visualstudio.com/docs/editor/debugging).
37 |
38 | ??? note "Some initial thoughts ..."
39 |
40 | - Are we actually running the `main()` function at all?
41 |
42 | - The `main()` function is almost certainly not the cause of this error.
43 |
44 | - The `is_perfect()` function is very simple, so it's unlikely to be the cause of this error.
45 |
46 | - The `divisors_of()` function doesn't look obviously wrong.
47 |
48 | - But there must be a mistake **somewhere**!
49 |
50 | - Let's **use a debugger** to investigate.
51 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/exercise-python-vs-r.md:
--------------------------------------------------------------------------------
1 | # Exercise: Python vs R
2 |
3 | === "Overview"
4 |
5 | Here we have provided SIR ODE model implementations in Python and in R.
6 | Each script runs several scenarios and produces a plot of infection prevalence for each scenario.
7 |
8 | You can download each script to debug on your computer:
9 |
10 | - [sir_ode.py](sir_ode.py)
11 | - [sir_ode.R](sir_ode.R)
12 |
13 | === "Python"
14 |
15 | ```py title="sir_ode.py" linenums="1"
16 | --8<-- "sir_ode.py"
17 | ```
18 |
19 | === "R"
20 |
21 | ```R title="sir_ode.R" linenums="1"
22 | --8<-- "sir_ode.R"
23 | ```
24 |
25 | !!! bug "The model outputs differ!"
26 |
27 | Here are prevalence time-series plots produced by each script:
28 |
29 | === "Python plot"
30 |
31 |
32 | 
33 | Model outputs for the Python script.
34 |
35 |
36 | === "R plot"
37 |
38 |
39 | 
40 | Model outputs for the R script.
41 |
42 |
43 | !!! tip "Interactive debugger sessions"
44 |
45 | If your editor supports running a debugger, **use this feature!**
46 | See these examples for [RStudio](https://support.posit.co/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE), [PyCharm](https://www.jetbrains.com/pycharm/features/debugger.html), [Spyder](https://docs.spyder-ide.org/current/panes/debugging.html), and [VS Code](https://code.visualstudio.com/docs/editor/debugging).
47 |
48 | ??? note "Some initial thoughts ..."
49 |
50 | - Is it obvious whether one of the figures is correct and the other is wrong?
51 |
52 | - The `sir_rhs()` functions in the two scripts appear to be equivalent — but are they?
53 |
54 | - The `default_settings()` functions appear to be equivalent — but are they?
55 |
56 | - The `run_model_scaled_beta()` and `run_model_scaled_gamma()` functions also appear to be equivalent.
57 |
58 | - Where might you begin looking?
59 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/first_demo.R:
--------------------------------------------------------------------------------
1 | first_function <- function() {
2 | total <- 0
3 | for (x in seq(49)) {
4 | y <- second_function(x)
5 | total <- total + y
6 | }
7 | total
8 | }
9 |
10 | second_function <- function(a) {
11 | result <- 3 * a^2 + 5 * a
12 | result
13 | }
14 |
15 | total <- first_function()
16 | cat("Total =", total, "\n")
17 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/first_demo.py:
--------------------------------------------------------------------------------
1 | def first_function():
2 | total = 0
3 | for x in range(1, 50):
4 | y = second_function(x)
5 | total = total + y
6 |
7 | return total
8 |
9 |
10 | def second_function(a):
11 | result = 3 * a**2 + 5 * a
12 | return result
13 |
14 |
15 | total = first_function()
16 | print(f'Total = {total}')
17 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/headless-horse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/community/training/debugging/headless-horse.jpg
--------------------------------------------------------------------------------
/docs/community/training/debugging/learning-objectives.md:
--------------------------------------------------------------------------------
1 | # Learning objectives
2 |
3 | In this workshop, we will introduce the concept of "debugging", and demonstrate techniques and tools that can help us efficiently identify and remove errors from our code.
4 |
5 | After completing this workshop, participants will:
6 |
7 | + Understand that debugging can be divided into a sequence of actions;
8 |
9 | + Understand the purpose of each of these actions;
10 |
11 | + Be familiar with techniques and tools that can help perform these actions;
12 |
13 | + Be able to apply these techniques and tools to their own code.
14 |
15 | !!! info
16 |
17 | By achieving these learning objectives, participants should be able to find and correct errors in their code more quickly and with greater confidence.
18 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/long_stacktrace.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import matplotlib.pyplot as plt
4 | import matplotlib.cm as cm
5 |
6 | example_counts = [1, 2, 3, 4, 5]
7 | plt.plot(example_counts, cbap=cm.Blues)
8 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/manifesto.md:
--------------------------------------------------------------------------------
1 | # Debugging manifesto
2 |
3 |
4 | { align=left, width="50%" }
5 |
6 | [Julia Evans](https://jvns.ca/) and [Tanya Brassie](https://tanyabrassie.com/): [Debugging Manifesto Poster](https://store.wizardzines.com/products/poster-debugging-manifesto), 2024.
7 |
8 |
9 |
10 | !!! info
11 |
12 | See the [Resources](resources.md) page for links to more of Julia Evans' articles, stories, and zines about debugging.
13 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/perfect-numbers-first-run.cast:
--------------------------------------------------------------------------------
1 | {"version": 2, "width": 80, "height": 4, "timestamp": 1723508323, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
2 | [0.106254, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
3 | [1.439464, "o", "."]
4 | [1.511348, "o", "/"]
5 | [1.735208, "o", "p"]
6 | [1.815337, "o", "e"]
7 | [1.879152, "o", "r"]
8 | [2.063205, "o", "f"]
9 | [2.151301, "o", "e"]
10 | [2.271034, "o", "c"]
11 | [2.46335, "o", "t"]
12 | [2.663166, "o", "_"]
13 | [2.823218, "o", "n"]
14 | [3.007567, "o", "u"]
15 | [3.199264, "o", "m"]
16 | [3.271363, "o", "b"]
17 | [3.439513, "o", "e"]
18 | [3.487438, "o", "r"]
19 | [3.607177, "o", "s"]
20 | [3.687383, "o", "."]
21 | [3.847072, "o", "p"]
22 | [3.991135, "o", "y"]
23 | [4.967213, "o", "\r\n"]
24 | [4.967292, "o", "\u001b[?2004l\r"]
25 | [5.065072, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
26 | [6.879247, "o", "."]
27 | [7.079536, "o", "/"]
28 | [7.319153, "o", "p"]
29 | [7.415356, "o", "e"]
30 | [7.479395, "o", "r"]
31 | [7.639271, "o", "f"]
32 | [7.727076, "o", "e"]
33 | [7.823333, "o", "c"]
34 | [8.00743, "o", "t"]
35 | [8.151241, "o", "_"]
36 | [8.407055, "o", "n"]
37 | [8.527353, "o", "u"]
38 | [8.71911, "o", "m"]
39 | [8.783422, "o", "b"]
40 | [8.967451, "o", "e"]
41 | [9.015325, "o", "r"]
42 | [9.151235, "o", "s"]
43 | [9.247291, "o", "."]
44 | [9.575237, "o", "R"]
45 | [10.167232, "o", "\r\n"]
46 | [10.167313, "o", "\u001b[?2004l\r"]
47 | [10.450741, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
48 | [12.800104, "o", "\u001b[?2004l"]
49 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/perfect_numbers.R:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S Rscript --vanilla
2 | #
3 | # This script prints perfect numbers.
4 | #
5 | # Perfect numbers are positive integers that are equal to the sum of their
6 | # divisors.
7 | #
8 |
9 |
10 | main <- function() {
11 | start <- 2
12 | end <- 1000
13 | for (value in seq.int(start, end)) {
14 | if (is_perfect(value)) {
15 | print(value)
16 | }
17 | }
18 | }
19 |
20 |
21 | is_perfect <- function(value) {
22 | divisors <- divisors_of(value)
23 | sum(divisors) == value
24 | }
25 |
26 |
27 | divisors_of <- function(value) {
28 | divisors <- c()
29 | candidate <- 2
30 | while (candidate < value) {
31 | if (value %% candidate == 0) {
32 | divisors <- c(divisors, candidate)
33 | }
34 | candidate <- candidate + 1
35 | }
36 | divisors
37 | }
38 |
39 |
40 | main()
41 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/perfect_numbers.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | This script prints perfect numbers.
4 |
5 | Perfect numbers are positive integers that are equal to the sum of their
6 | divisors.
7 | """
8 |
9 |
10 | def main():
11 | start = 2
12 | end = 1_000
13 | for value in range(start, end + 1):
14 | if is_perfect(value):
15 | print(value)
16 |
17 |
18 | def is_perfect(value):
19 | divisors = divisors_of(value)
20 | return sum(divisors) == value
21 |
22 |
23 | def divisors_of(value):
24 | divisors = []
25 | candidate = 2
26 | while candidate < value:
27 | if value % candidate == 0:
28 | divisors.append(candidate)
29 | candidate += 1
30 | return divisors
31 |
32 |
33 | if __name__ == '__main__':
34 | main()
35 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/resources.md:
--------------------------------------------------------------------------------
1 | # Resources
2 |
3 | ## Workshop scripts
4 |
5 | **Understanding error messages:** [stacktrace.py](stacktrace.py), [stacktrace.R](stacktrace.R), and [long_stacktrace.py](long_stacktrace.py).
6 |
7 | **Using a debugger:** [first_demo.py](first_demo.py) and [first_demo.R](first_demo.R).
8 |
9 | **Square numbers:** [square_numbers.py](square_numbers.py) and [square_numbers.R](square_numbers.R).
10 |
11 | **Perfect numbers:** [perfect_numbers.py](perfect_numbers.py) and [perfect_numbers.R](perfect_numbers.R).
12 |
13 | **Python vs R:** [sir_ode.py](sir_ode.py) and [sir_ode.R](sir_ode.R).
14 |
15 | ## Useful materials
16 |
17 | - [Julia Evans](https://jvns.ca/) has written a lot of great materials about debugging:
18 | - [Debugging articles](https://jvns.ca/#debugging)
19 | - [Debugging stories](https://jvns.ca/#debugging-stories)
20 | - [The Pocket Guide to Debugging](https://jvns.ca/blog/2022/12/21/new-zine--the-pocket-guide-to-debugging/) (see the [table of contents](https://jvns.ca/images/debugging-guide-toc.png))
21 | - [Notes on building debugging puzzles](https://jvns.ca/blog/2021/04/16/notes-on-debugging-puzzles/)
22 | - [Debug with pdb and breakpoint](https://hamatti.org/posts/debug-with-pdb-and-breakpoint/)
23 | - [Advanced R: Debugging](https://adv-r.hadley.nz/debugging.html)
24 | - [RStudio Cheatsheet: Debugging](https://rstudio.github.io/cheatsheets/html/rstudio-ide.html#debug-mode)
25 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/sir_ode.R:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S Rscript --vanilla
2 |
3 | library(deSolve)
4 | suppressPackageStartupMessages(library(dplyr))
5 | suppressPackageStartupMessages(library(ggplot2))
6 |
7 |
8 | # The right-hand side for the vanilla SIR compartmental model.
9 | sir_rhs <- function(time, state, params) {
10 | s_to_i <- params$beta * state["I"] * state["S"] / params$popn
11 | i_to_r <- params$gamma * state["I"]
12 | list(c(-s_to_i, s_to_i - i_to_r, i_to_r))
13 | }
14 |
15 |
16 | # Return the SIR ODE solution for the given model settings.
17 | run_model <- function(settings) {
18 | # Define the time span and evaluation times.
19 | times <- seq(0, settings$sim_days)
20 | # Define the initial state.
21 | popn <- settings$population
22 | exposures <- settings$exposures
23 | initial_state <- c(S = popn - exposures, I = exposures, R = 0)
24 | # Define the SIR parameters.
25 | params <- list(
26 | popn = settings$population,
27 | beta = settings$beta,
28 | gamma = settings$gamma
29 | )
30 | # Return the daily number of people in S, I, and R.
31 | ode(initial_state, times, sir_rhs, params)
32 | }
33 |
34 |
35 | # The default model settings.
36 | default_settings <- function() {
37 | list(
38 | sim_days = 20,
39 | population = 100,
40 | exposures = 2,
41 | beta = 1.0,
42 | gamma = 0.5
43 | )
44 | }
45 |
46 |
47 | # Adjust the value of ``beta`` before running the model.
48 | run_model_scaled_beta <- function(settings, scale) {
49 | settings$beta <- scale * settings$beta
50 | run_model(settings)
51 | }
52 |
53 |
54 | # Adjust the value of ``gamma`` before running the model.
55 | run_model_scaled_gamma <- function(settings, scale) {
56 | settings$gamma <- scale * settings$gamma
57 | run_model(settings)
58 | }
59 |
60 |
61 | # Plot daily prevalence of infectious individuals for one or more scenarios.
62 | plot_prevalence_time_series <- function(solutions) {
63 | df <- lapply(
64 | names(solutions),
65 | function(name) {
66 | solutions[[name]] |>
67 | as.data.frame() |>
68 | mutate(scenario = name)
69 | }
70 | ) |>
71 | bind_rows() |>
72 | mutate(
73 | scenario = factor(scenario, levels = names(solutions), ordered = TRUE)
74 | )
75 | fig <- ggplot() +
76 | geom_line(aes(time, I), df) +
77 | xlab(NULL) +
78 | scale_y_continuous(
79 | name = NULL,
80 | limits = c(0, 40),
81 | breaks = c(0, 20, 40)
82 | ) +
83 | facet_wrap(~ scenario, ncol = 1) +
84 | theme_bw(base_size = 10) +
85 | theme(
86 | strip.background = element_blank(),
87 | panel.grid = element_blank(),
88 | )
89 | png_file <- "sir_ode_r.png"
90 | ggsave(png_file, fig, width = 640, height = 480, units = "px", dpi = 150)
91 | }
92 |
93 |
94 | demonstration <- function() {
95 | settings <- default_settings()
96 | default_scenario <- run_model(settings)
97 | scaled_beta_scenario <- run_model_scaled_beta(settings, scale=1.5)
98 | scaled_gamma_scenario <- run_model_scaled_gamma(settings, scale=0.7)
99 |
100 | plot_prevalence_time_series(
101 | list(
102 | Default = default_scenario,
103 | `Scaled Beta` = scaled_beta_scenario,
104 | `Scaled Gamma` = scaled_gamma_scenario
105 | )
106 | )
107 | }
108 |
109 | demonstration()
110 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/sir_ode.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | from scipy.integrate import solve_ivp
6 |
7 |
8 | def sir_rhs(time, state, popn, beta, gamma):
9 | """
10 | The right-hand side for the vanilla SIR compartmental model.
11 | """
12 | s_to_i = beta * state[1] * state[0] / popn # beta * I(t) * S(t) / N
13 | i_to_r = gamma * state[1] # gamma * I(t)
14 | return [-s_to_i, s_to_i - i_to_r, i_to_r]
15 |
16 |
17 | def run_model(settings):
18 | """
19 | Return the SIR ODE solution for the given model settings.
20 | """
21 | # Define the time span and evaluation times.
22 | sim_days = settings['sim_days']
23 | time_span = [0, sim_days]
24 | times = np.linspace(0, sim_days, num=sim_days + 1)
25 | # Define the initial state.
26 | popn = settings['population']
27 | exposures = settings['exposures']
28 | initial_state = [popn - exposures, exposures, 0]
29 | # Define the SIR parameters.
30 | params = (popn, settings['beta'], settings['gamma'])
31 | # Return the daily number of people in S, I, and R.
32 | return solve_ivp(
33 | sir_rhs, time_span, initial_state, t_eval=times, args=params
34 | )
35 |
36 |
37 | def default_settings():
38 | """
39 | The default model settings.
40 | """
41 | return {
42 | 'sim_days': 20,
43 | 'population': 100,
44 | 'exposures': 2,
45 | 'beta': 1.0,
46 | 'gamma': 0.5,
47 | }
48 |
49 |
50 | def run_model_scaled_beta(settings, scale):
51 | """
52 | Adjust the value of ``beta`` before running the model.
53 | """
54 | settings['beta'] = scale * settings['beta']
55 | return run_model(settings)
56 |
57 |
58 | def run_model_scaled_gamma(settings, scale):
59 | """
60 | Adjust the value of ``gamma`` before running the model.
61 | """
62 | settings['gamma'] = scale * settings['gamma']
63 | return run_model(settings)
64 |
65 |
66 | def plot_prevalence_time_series(solutions):
67 | """
68 | Plot daily prevalence of infectious individuals for one or more scenarios.
69 | """
70 | fig, axes = plt.subplots(
71 | constrained_layout=True,
72 | nrows=len(solutions),
73 | sharex=True,
74 | sharey=True,
75 | )
76 | for ix, (scenario_name, solution) in enumerate(solutions.items()):
77 | ax = axes[ix]
78 | ax.title.set_text(scenario_name)
79 | ax.plot(solution.y[1], label='I')
80 | ax.set_xticks([0, 5, 10, 15, 20])
81 | # Save the figure.
82 | png_file = 'sir_ode_python.png'
83 | fig.savefig(png_file, format='png', metadata={'Software': None})
84 |
85 |
86 | def demonstration():
87 | settings = default_settings()
88 | default_scenario = run_model(settings)
89 | scaled_beta_scenario = run_model_scaled_beta(settings, scale=1.5)
90 | scaled_gamma_scenario = run_model_scaled_gamma(settings, scale=0.7)
91 |
92 | plot_prevalence_time_series(
93 | {
94 | 'Default': default_scenario,
95 | 'Scaled Beta': scaled_beta_scenario,
96 | 'Scaled Gamma': scaled_gamma_scenario,
97 | }
98 | )
99 |
100 |
101 | if __name__ == '__main__':
102 | demonstration()
103 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/sir_ode_python.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/community/training/debugging/sir_ode_python.png
--------------------------------------------------------------------------------
/docs/community/training/debugging/sir_ode_r.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/community/training/debugging/sir_ode_r.png
--------------------------------------------------------------------------------
/docs/community/training/debugging/solutions.md:
--------------------------------------------------------------------------------
1 | # Exercise solutions
2 |
3 | !!! info
4 |
5 | Please don't look as these solutions until you have attempted the exercises.
6 |
7 | ??? abstract "Perfect numbers"
8 |
9 | Perfect numbers are equal to the sum of their proper divisors — all divisors except the number itself.
10 |
11 | For example, 6 is a perfect number.
12 | Its proper divisors are 1, 2, and 3, and 1 + 2 + 3 = 6.
13 |
14 | The mistake here is that the `divisors_of()` function only returns divisors **greater than one**, and so the code fails to identify any of the true perfect numbers.
15 |
16 | Interestingly, this mistake did not result in the code mistakenly identifying any other numbers as perfect numbers.
17 |
18 | ??? abstract "Python vs R"
19 |
20 | If you're only familiar with one of these two languages, you may be surprised to discover that they have some fundamental differences.
21 | In this exercise we demonstrated one consequence of the ways that these languages handle function arguments.
22 |
23 | !!! quote "The R Language Definition"
24 |
25 | The semantics of invoking a function in R argument are **call-by-value**.
26 | In general, supplied arguments behave as if they are **local variables** initialized with the value supplied and the name of the corresponding formal argument.
27 | Changing the value of a supplied argument within a function **will not affect** the value of the variable in the calling frame.
28 |
29 | — [Argument Evaluation](https://cran.r-project.org/doc/manuals/r-patched/R-lang.html#Argument-evaluation)
30 |
31 | !!! quote "Python Programming FAQ"
32 |
33 | Remember that arguments are **passed by assignment** in Python.
34 | Since assignment just **creates references** to objects, there's no alias between an argument name in the caller and callee, and so no call-by-reference per se.
35 |
36 | — [How do I write a function with output parameters (call by reference)?](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference)
37 |
38 | - In R the `run_model_scaled_beta()` and `run_model_scaled_gamma()` functions **do not modify** the value of `settings` in the `demonstration()` function.
39 | This produces model outputs for the following parameter combinations:
40 |
41 | - β = 1.0 and γ = 0.5;
42 | - β = 1.5 and γ = 0.5; and
43 | - **β = 1.0 and γ = 0.35**.
44 |
45 | - In Python the `run_model_scaled_beta()` and `run_model_scaled_gamma()` functions **do modify** the value of `settings` in the `demonstration()` function.
46 | This produces model outputs for the following parameter combinations:
47 |
48 | - β = 1.0 and γ = 0.5;
49 | - β = 1.5 and γ = 0.5; and
50 | - **β = 1.5 and γ = 0.35**.
51 |
52 | !!! success "Answer"
53 |
54 | The value of β is different in the third combination.
55 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square-numbers-demo.cast:
--------------------------------------------------------------------------------
1 | {"version": 2, "width": 80, "height": 5, "timestamp": 1724287506, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
2 | [0.085762, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
3 | [0.304444, "o", "."]
4 | [0.450345, "o", "/"]
5 | [0.613627, "o", "s"]
6 | [0.873455, "o", "q"]
7 | [1.108823, "o", "u"]
8 | [1.287488, "o", "a"]
9 | [1.454263, "o", "r"]
10 | [1.674393, "o", "e"]
11 | [1.812098, "o", "_"]
12 | [2.047097, "o", "n"]
13 | [2.335861, "o", "u"]
14 | [2.485753, "o", "m"]
15 | [2.776119, "o", "b"]
16 | [3.009771, "o", "e"]
17 | [3.129275, "o", "r"]
18 | [3.317859, "o", "s"]
19 | [3.595679, "o", "."]
20 | [3.835811, "o", "p"]
21 | [4.001456, "o", "y"]
22 | [4.448924, "o", "\r\n\u001b[?2004l\r"]
23 | [4.475384, "o", "[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]\r\n"]
24 | [4.490576, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
25 | [5.316432, "o", "."]
26 | [5.448534, "o", "/"]
27 | [5.617079, "o", "s"]
28 | [5.810295, "o", "q"]
29 | [5.963872, "o", "u"]
30 | [6.227657, "o", "a"]
31 | [6.366643, "o", "r"]
32 | [6.492842, "o", "e"]
33 | [6.611395, "o", "_"]
34 | [6.831541, "o", "n"]
35 | [7.102805, "o", "u"]
36 | [7.323411, "o", "m"]
37 | [7.610398, "o", "b"]
38 | [7.855683, "o", "e"]
39 | [8.127994, "o", "r"]
40 | [8.414289, "o", "s"]
41 | [8.623942, "o", "."]
42 | [8.911873, "o", "R"]
43 | [9.311594, "o", "\r\n"]
44 | [9.311712, "o", "\u001b[?2004l\r"]
45 | [9.489246, "o", " [1] 1 4 9 16 25 36 49 64 81 100\r\n"]
46 | [9.507689, "o", "\u001b[?2004h\u001b]2;(x1::debugging)\u0007\u001b[32;1m(x1::debugging)\u001b[0m "]
47 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square-numbers-demo.toml:
--------------------------------------------------------------------------------
1 | output_file = "square-numbers-demo.cast"
2 | start_delay = 0.3
3 | end_delay = 0.5
4 | typing_delay = [
5 | 0.05,
6 | 0.25,
7 | ]
8 | pre_nl_delay = [
9 | 0.2,
10 | 0.2,
11 | ]
12 | post_nl_delay = [
13 | 0.8,
14 | 1.0,
15 | ]
16 | with_comments = false
17 | comments_at_top = false
18 | actions = [
19 | "./square_numbers.py",
20 | "./square_numbers.R",
21 | { action_id = "Marker", label = "END" },
22 | "exit",
23 | ]
24 | cols = 80
25 | rows = 5
26 |
27 | [[filters]]
28 | filter_id = "EndMarkerFilter"
29 | end_label = "END"
30 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square-numbers-pdb.yaml:
--------------------------------------------------------------------------------
1 | output_file: square-numbers-pdb.cast
2 | start_delay: 0.3
3 | end_delay: 0.5
4 | typing_delay:
5 | - 0.05
6 | - 0.1
7 | pre_nl_delay:
8 | - 0.2
9 | - 0.2
10 | post_nl_delay:
11 | - 0.8
12 | - 1.0
13 | with_comments: true
14 | comments_at_top: false
15 | actions:
16 | - python3 -m pdb square_numbers.py
17 | - action_id: Marker
18 | label: Set a breakpoint
19 | - break 16
20 | - continue
21 | - action_id: Marker
22 | label: Show current location
23 | - action_id: Input
24 | text: list
25 | pre_nl_delay: 1
26 | post_nl_delay: 2
27 | - action_id: Input
28 | text: print(value)
29 | pre_nl_delay: 1
30 | post_nl_delay: 2
31 | - action_id: Marker
32 | label: Step into `is_square()`
33 | - step
34 | - step
35 | - action_id: Input
36 | text: list
37 | pre_nl_delay: 1
38 | post_nl_delay: 2
39 | - up
40 | - action_id: Input
41 | text: list
42 | pre_nl_delay: 1
43 | post_nl_delay: 2
44 | - action_id: Comment
45 | comment: we can check the value of squares
46 | - print(squares)
47 | - down
48 | - action_id: Comment
49 | comment: ''
50 | - step
51 | - step
52 | - action_id: Marker
53 | label: Return from `is_square()`
54 | - step
55 | - step
56 | - action_id: Marker
57 | label: Show updated `squares` list
58 | - print(squares)
59 | - step
60 | - print(squares)
61 | - action_id: Comment
62 | comment: the value of squares has changed!
63 | - step
64 | - step
65 | - next
66 | - action_id: Comment
67 | comment: ''
68 | - print(value)
69 | - print(squares)
70 | - action_id: Comment
71 | comment: the value of squares has not changed!
72 | - action_id: Marker
73 | label: Add a conditional breakpoint
74 | - action_id: Input
75 | text: clear 1
76 | pre_nl_delay: 1
77 | post_nl_delay: 2
78 | - action_id: Input
79 | text: break 18, value == 49
80 | pre_nl_delay: 1
81 | post_nl_delay: 2
82 | - action_id: Comment
83 | comment: ''
84 | - continue
85 | - action_id: Marker
86 | label: Stop at the conditional breakpoint
87 | - print(value)
88 | - action_id: Input
89 | text: print(squares)
90 | pre_nl_delay: 1
91 | post_nl_delay: 2
92 | - action_id: Marker
93 | label: Continue until the script ends
94 | - action_id: Input
95 | text: continue
96 | pre_nl_delay: 1
97 | post_nl_delay: 2
98 | - action_id: Input
99 | text: quit
100 | pre_nl_delay: 1
101 | post_nl_delay: 2
102 | - action_id: Marker
103 | label: END
104 | - exit
105 | filters:
106 | - filter_id: RegexReplacementFilter
107 | regex: /home/.*/git-is-my-lab-book/docs/community/training/
108 | replacement: ''
109 | - filter_id: EndMarkerFilter
110 | end_label: END
111 | - filter_id: CommentFilter
112 | cols: 80
113 | rows: 24
114 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square-numbers-r-debug.yaml:
--------------------------------------------------------------------------------
1 | output_file: square-numbers-r-debug.cast
2 | cols: 80
3 | rows: 24
4 | start_delay: 0.3
5 | end_delay: 0.5
6 | typing_delay:
7 | - 0.05
8 | - 0.1
9 | pre_nl_delay:
10 | - 0.2
11 | - 0.2
12 | post_nl_delay:
13 | - 0.8
14 | - 1.0
15 | with_comments: true
16 | comments_at_top: false
17 | actions:
18 | - R --vanilla
19 | - source("square_numbers.R")
20 | - action_id: Marker
21 | label: Set a breakpoint
22 | - setBreakpoint("square_numbers.R", line = 17, verbose = FALSE)
23 | - main()
24 | - action_id: Input
25 | text: value
26 | pre_nl_delay: 1
27 | post_nl_delay: 2
28 | - action_id: Input
29 | text: squares
30 | pre_nl_delay: 1
31 | post_nl_delay: 2
32 | - action_id: Marker
33 | label: Step into `is_square()`
34 | - s
35 | - s
36 | - n
37 | - n
38 | - action_id: Marker
39 | label: Return from `is_square()`
40 | - n
41 | - n
42 | - n
43 | - action_id: Marker
44 | label: Show updated `squares` list
45 | - action_id: Input
46 | text: squares
47 | pre_nl_delay: 1
48 | post_nl_delay: 2
49 | - action_id: Comment
50 | comment: the value of squares has changed!
51 | - c
52 | - action_id: Input
53 | text: value
54 | pre_nl_delay: 1
55 | post_nl_delay: 2
56 | - action_id: Input
57 | text: squares
58 | pre_nl_delay: 1
59 | post_nl_delay: 2
60 | - action_id: Comment
61 | comment: ''
62 | - Q
63 | - action_id: Marker
64 | label: Add a conditional breakpoint
65 | - action_id: Input
66 | text: setBreakpoint("square_numbers.R", line = 20, tracer = quote(if (value == 49) browser()), verbose = FALSE)
67 | pre_nl_delay: 1
68 | post_nl_delay: 4
69 | - main()
70 | - action_id: Marker
71 | label: Stop at the conditional breakpoint
72 | - action_id: Input
73 | text: value
74 | pre_nl_delay: 1
75 | post_nl_delay: 2
76 | - action_id: Input
77 | text: squares
78 | pre_nl_delay: 1
79 | post_nl_delay: 2
80 | - action_id: Comment
81 | comment: the value of squares has changed!
82 | - action_id: Marker
83 | label: Continue until the script ends
84 | - action_id: Input
85 | text: c
86 | pre_nl_delay: 1
87 | post_nl_delay: 4
88 | - action_id: Comment
89 | comment: ''
90 | - q()
91 | - action_id: Marker
92 | label: END
93 | - exit
94 | filters:
95 | - filter_id: EndMarkerFilter
96 | end_label: END
97 | - filter_id: CommentFilter
98 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square_numbers.R:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S Rscript --vanilla
2 | #
3 | # Print the square numbers between 1 and 100.
4 | #
5 |
6 |
7 | main <- function() {
8 | squares <- find_squares(1, 100)
9 | print(squares)
10 | }
11 |
12 |
13 | find_squares <- function(lower_bound, upper_bound) {
14 | squares <- c()
15 | value <- lower_bound
16 | while (value <= upper_bound) {
17 | if (is_square(value)) {
18 | squares <- c(squares, value)
19 | }
20 | value <- value + 1
21 | }
22 | squares
23 | }
24 |
25 |
26 | is_square <- function(value) {
27 | for (i in seq(value)) {
28 | if (i * i == value) {
29 | return(TRUE)
30 | }
31 | }
32 | FALSE
33 | }
34 |
35 | if (! interactive()) {
36 | main()
37 | }
38 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/square_numbers.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Print the square numbers between 1 and 100.
4 | """
5 |
6 |
7 | def main():
8 | squares = find_squares(1, 100)
9 | print(squares)
10 |
11 |
12 | def find_squares(lower_bound, upper_bound):
13 | squares = []
14 | value = lower_bound
15 | while value <= upper_bound:
16 | if is_square(value):
17 | squares.append(value)
18 | value += 1
19 | return squares
20 |
21 |
22 | def is_square(value):
23 | for i in range(1, value + 1):
24 | if i * i == value:
25 | return True
26 | return False
27 |
28 |
29 | if __name__ == '__main__':
30 | main()
31 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/stacktrace.R:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S Rscript --vanilla
2 |
3 | options(error = rlang::entrace)
4 |
5 |
6 | main <- function() {
7 | do_big_tasks()
8 | invisible(0)
9 | }
10 |
11 | do_big_tasks <- function(num_tasks = 20, quiet = TRUE) {
12 | for (i in seq_len(num_tasks)) {
13 | prepare_things(i, quiet = quiet)
14 | do_first_step(i, quiet = quiet)
15 | do_second_step(i, quiet = quiet)
16 | if (i > 15) {
17 | do_third_step(i, quiet = quiet)
18 | }
19 | }
20 | }
21 |
22 | prepare_things <- function(task_num, quiet = TRUE) {
23 | if (!quiet) {
24 | cat("Preparing for task #", task_num, "\n", sep = "")
25 | }
26 | }
27 |
28 | do_first_step <- function(task_num, quiet = TRUE) {
29 | if (!quiet) {
30 | cat("Task #", task_num, ": doing step #1\n", sep = "")
31 | }
32 | }
33 |
34 | do_second_step <- function(task_num, quiet = TRUE) {
35 | if (!quiet) {
36 | cat("Task #", task_num, ": doing step #2\n", sep = "")
37 | }
38 | }
39 |
40 | do_third_step <- function(task_num, quiet = TRUE) {
41 | if (!quiet) {
42 | cat("Task #", task_num, ": doing step #3\n", sep = "")
43 | }
44 | try_something()
45 | }
46 |
47 | try_something <- function() {
48 | stop("Whoops, this failed")
49 | }
50 |
51 | if (! interactive()) {
52 | status <- main()
53 | quit(status = status)
54 | }
55 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/stacktrace.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 |
5 |
6 | def main():
7 | do_big_tasks()
8 | return 0
9 |
10 |
11 | def do_big_tasks(num_tasks=20, quiet=True):
12 | for i in range(num_tasks):
13 | prepare_things(i, quiet=quiet)
14 | do_first_step(i, quiet=quiet)
15 | do_second_step(i, quiet=quiet)
16 | if i > 15:
17 | do_third_step(i, quiet=quiet)
18 |
19 |
20 | def prepare_things(task_num, quiet=True):
21 | if not quiet:
22 | print(f'Preparing for task #{task_num}')
23 |
24 |
25 | def do_first_step(task_num, quiet=True):
26 | if not quiet:
27 | print(f'Task #{task_num}: doing step #1')
28 |
29 |
30 | def do_second_step(task_num, quiet=True):
31 | if not quiet:
32 | print(f'Task #{task_num}: doing step #2')
33 |
34 |
35 | def do_third_step(task_num, quiet=True):
36 | if not quiet:
37 | print(f'Task #{task_num}: doing step #3')
38 | try_something()
39 |
40 |
41 | def try_something():
42 | raise ValueError('Whoops, this failed')
43 |
44 |
45 | if __name__ == '__main__':
46 | status = main()
47 | sys.exit(status)
48 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/understanding-error-messages.md:
--------------------------------------------------------------------------------
1 | # Understanding error messages
2 |
3 | !!! tip
4 |
5 | The visible error and its root cause may be located in very different parts of your code.
6 |
7 | If there's an error in your code that causes the program to terminate, **read the error message** and see what it can tell you.
8 |
9 | Most of the time, the error message should allow you to identify:
10 |
11 | - **What went wrong?**
12 | For example, did it try to read data from a file that does not exist?
13 |
14 | - **Where did this happen?**
15 | On which line of which file did the error occur?
16 |
17 | ## Stack traces
18 |
19 | When an error occurs, one useful piece of information is knowing which functions were called in order to make the error occur.
20 |
21 | Below we have example Python and R scripts that produce an error.
22 |
23 | !!! question
24 |
25 | Can you identify where the error occurred, just by looking at the error message?
26 |
27 | !!! tip
28 |
29 | R may not give you a useful stack trace unless you instruct it do so.
30 | In the example, we use:
31 |
32 | ```R
33 | options(error = rlang::entrace)
34 | ```
35 |
36 | === "Overview"
37 |
38 | You can download each script and run them on your own computer:
39 |
40 | - [stacktrace.py](stacktrace.py)
41 | - [stacktrace.R](stacktrace.R)
42 |
43 | === "Python"
44 |
45 | The error message is:
46 |
47 | ```text
48 | Traceback (most recent call last):
49 | File "stacktrace.py", line 46, in
50 | status = main()
51 | File "stacktrace.py", line 7, in main
52 | do_big_tasks()
53 | File "stacktrace.py", line 17, in do_big_tasks
54 | do_third_step(i, quiet=quiet)
55 | File "stacktrace.py", line 38, in do_third_step
56 | try_something()
57 | File "stacktrace.py", line 42, in try_something
58 | raise ValueError("Whoops, this failed")
59 | ValueError: Whoops, this failed
60 | ```
61 |
62 | ??? info "Source code"
63 |
64 | ```py title="stacktrace.py" linenums="1"
65 | --8<-- "stacktrace.py"
66 | ```
67 |
68 | === "R"
69 |
70 | The error message is:
71 |
72 | ```text
73 | Error in try_something() : Whoops, this failed
74 | Calls: main -> do_big_tasks -> do_third_step -> try_something
75 | Backtrace:
76 | ▆
77 | 1. └─global main()
78 | 2. └─global do_big_tasks()
79 | 3. └─global do_third_step(i, quiet = quiet)
80 | 4. └─global try_something()
81 | Execution halted
82 | ```
83 |
84 | ??? info "Source code"
85 |
86 | ```R title="stacktrace.R" linenums="1"
87 | --8<-- "stacktrace.R"
88 | ```
89 |
90 | ## Very long stack traces
91 |
92 | You may get a very long stack trace when a error occurs deep within a software package or library.
93 | This means that the **cause** of the error, and location where the error is **reported** can be very far apart.
94 |
95 | For example, the following Python script has an incorrect parameter name on line 7 (``cbap`` should instead be ``cmap``):
96 |
97 | ```py title="long_stacktrace.py" linenums="1" hl_lines="7"
98 | --8<-- "long_stacktrace.py"
99 | ```
100 |
101 | And here is the stacktrace you should see when running this Python script:
102 |
103 | ```text linenums="1" hl_lines="3 24"
104 | Traceback (most recent call last):
105 | File "long_stacktrace.py", line 7, in
106 | plt.plot(example_counts, cbap=cm.Blues)
107 | File "venv/lib/python3.10/site-packages/matplotlib/pyplot.py", line 3794, in plot
108 | return gca().plot(
109 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_axes.py", line 1779, in plot
110 | lines = [*self._get_lines(self, *args, data=data, **kwargs)]
111 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 296, in __call__
112 | yield from self._plot_args(
113 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 534, in _plot_args
114 | return [l[0] for l in result]
115 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 534, in
116 | return [l[0] for l in result]
117 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 527, in
118 | result = (make_artist(axes, x[:, j % ncx], y[:, j % ncy], kw,
119 | File "venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 335, in _makeline
120 | seg = mlines.Line2D(x, y, **kw)
121 | File "venv/lib/python3.10/site-packages/matplotlib/lines.py", line 407, in __init__
122 | self._internal_update(kwargs)
123 | File "venv/lib/python3.10/site-packages/matplotlib/artist.py", line 1216, in _internal_update
124 | return self._update_props(
125 | File "venv/lib/python3.10/site-packages/matplotlib/artist.py", line 1190, in _update_props
126 | raise AttributeError(
127 | AttributeError: Line2D.set() got an unexpected keyword argument 'cbap'
128 | ```
129 |
130 | While it **does** tell you the cause of the error, there are **ten function calls** between the root cause (line 3 of the stack trace) and the error (line 24 of the stack trace).
131 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/using-a-debugger.md:
--------------------------------------------------------------------------------
1 | # Using a debugger
2 |
3 | The main features of a debugger are:
4 |
5 | - **Breakpoints:** pause the program when a particular line of code is about to be executed;
6 |
7 | - **Display/print:** show the current value of local variables;
8 |
9 | - **Next:** execute the current line of code and pause at the next line;
10 |
11 | - **Continue:** continue executing code until the next breakpoint, or the code finishes.
12 |
13 | Slightly more advanced features include:
14 |
15 | - **Conditional breakpoints:** pause the program when a particular line of code is about to be executed **and** a specific condition is satisfied.
16 |
17 | - **Step:** execute the current line of code and pause at the first possible point — either the line in the current function **or** the first line in a function that is called.
18 |
19 | - **Manual breakpoints:** call [`breakpoint()`](https://docs.python.org/3/library/pdb.html) in Python, and [`browser()`](https://adv-r.hadley.nz/debugging.html#browser) in R, to pause the program at the current line.
20 |
21 | For example, consider the following code example:
22 |
23 | === "Python"
24 |
25 | ```py title="first_demo.py" linenums="1" hl_lines="4"
26 | --8<-- "first_demo.py"
27 | ```
28 |
29 | === "R"
30 |
31 | ```R title="first_demo.R" linenums="1" hl_lines="4"
32 | --8<-- "first_demo.R"
33 | ```
34 |
35 | - We can use a **conditional breakpoint** to pause on line 4 (highlighted) only when `x = 42`.
36 |
37 | - We can then use **step** to begin executing line 4 and pause on line 11, where we will see that `a = 42`.
38 |
39 | - If we instead used **next** at line 4 (highlighted), the debugger would execute line 4 and then pause on line 5.
40 |
41 | ## Try this yourself
42 |
43 | Download either demo script and try setting breakpoints and stepping through the code.
44 |
45 | - [first_demo.py](first_demo.py)
46 | - [first_demo.R](first_demo.R)
47 |
48 | !!! tip "Interactive debugger sessions"
49 |
50 | If your editor supports running a debugger, **use this feature!**
51 | See these examples for [RStudio](https://support.posit.co/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE), [PyCharm](https://www.jetbrains.com/pycharm/features/debugger.html), [Spyder](https://docs.spyder-ide.org/current/panes/debugging.html), and [VS Code](https://code.visualstudio.com/docs/editor/debugging).
52 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/what-is-debugging.md:
--------------------------------------------------------------------------------
1 | # What is debugging?
2 |
3 | !!! info
4 |
5 | Debugging is the process of identifying and removing errors from computer software.
6 |
7 | You need to **identify (and reproduce) the problem** and **only then** begin fixing it.
8 |
9 | ## Action 1: Identify the error
10 |
11 | !!! tip
12 |
13 | First make sure that you can reproduce the error.
14 |
15 | - What observations or outputs indicate the presence of this error?
16 |
17 | - Is the error reproducible, or does it come and go?
18 |
19 | - Can you write a test case that identifies the error?
20 | This can help ensure you don't introduce a similar error in the future.
21 |
22 | ## Action 2: Develop a plan
23 |
24 | !!! tip
25 |
26 | The visible error and its root cause may be located in very different parts of your code.
27 |
28 | - Identify which parts of your code are likely (and unlikely) to be the cause.
29 |
30 | - What parts of your code recently changed?
31 |
32 | - When was the last time you might have noticed this error?
33 |
34 | ## Action 3: Search for the root cause
35 |
36 | !!! tip
37 |
38 | The search should be guided by **facts**, not **assumptions**.
39 | Simple errors can often hide **in plain sight**.
40 |
41 | - Thinking "this looks right" is **not a reliable indicator** of whether a piece of code contains an error.
42 |
43 | - Our assumptions about the code can help us to develop a plan, but we need to **verify whether our assumptions are actually true**.
44 |
45 | - This can be done indirectly by adding print statements or writing test cases.
46 |
47 | - It can also be done by directly inspecting the state of the program with a debugger — more on that shortly!
48 |
49 |
50 | { align=left, width="50%" }
51 | Searching at random is like looking for a needle in a haystack.
52 |
53 | ([Perry McKenna](https://flickr.com/photos/63567936@N00/4210167891/), Flickr, 2009; CC BY 2.0)
54 |
55 |
56 |
57 | ## Action 4: Fix the root cause
58 |
59 | !!! tip
60 |
61 | It's worth considering if the root cause is a result of deliberate decisions or unintentional mistakes.
62 |
63 | - Don't start modifying/adding/removing lines based on suspicions or relying on luck.
64 |
65 | - Without identifying the **root cause**, making the visible error disappear may not fix the root cause.
66 |
67 | ## Action 5: After it's fixed
68 |
69 | !!! tip
70 |
71 | This is the perfect time to reflect on your experience!
72 |
73 | - What can you learn from this experience?
74 |
75 | - Can you avoid this mistake in the future?
76 |
77 | - What parts of the process were the hardest or took the longest?
78 |
79 | - Are the tools and techniques that might help you next time?
80 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/when-something-fails.md:
--------------------------------------------------------------------------------
1 | # When something fails
2 |
3 | You may want to create a breakpoint when an error occurs.
4 |
5 | In Python, you can use a `try` statement to catch exceptions and create a breakpoint:
6 |
7 | ```py linenums="1" hl_lines="8"
8 | def print_c(data):
9 | print(data['c'])
10 |
11 | x = {'a': 1, 'b': 2}
12 | try:
13 | print_c(x)
14 | except KeyError:
15 | breakpoint()
16 | ```
17 |
18 | In R, you can take a similar approach and use `tryCatch()`:
19 |
20 | ```R linenums="1" hl_lines="12"
21 | f <- function(x) {
22 | if (x == 10) { stop("ten") }
23 | x
24 | }
25 |
26 | g <- function(x_max) {
27 | result <- tryCatch(
28 | sapply(seq_len(x_max), f),
29 | error = function(e) NULL
30 | )
31 | if (is.null(result)) {
32 | browser()
33 | }
34 | result
35 | }
36 |
37 | g(9) # This completes without an error.
38 | g(12) # This triggers the breakpoint.
39 | ```
40 |
41 | In R, you can also define a global error handler (e.g., `browser` or `recover`):
42 |
43 | ```R linenums="19"
44 | options(error=recover)
45 |
46 | g(12)
47 | ```
48 |
--------------------------------------------------------------------------------
/docs/community/training/debugging/why-are-debuggers-useful.md:
--------------------------------------------------------------------------------
1 | # Why are debuggers useful?
2 |
3 | !!! tip
4 |
5 | A debugger is a tool for examining the state of a running program.
6 |
7 | Debuggers are useful because they show us what the code **is actually doing**.
8 |
9 | Many of the errors that take a long time for us to find are relatively simple **once we find them**.
10 |
11 | We usually have a hard time finding these errors because:
12 |
13 | 1. **We read what we expect to see**, rather than what is actually written; and
14 |
15 | 2. **We rely on assumptions** about where the mistake might be, and our intuition is often wrong.
16 |
17 | Here are some common mistakes that can be difficult to identify when reading through your own code:
18 |
19 | - Using an incorrect index into an array, matrix, list, etc;
20 |
21 | - Using incorrect bounds on a loop or sequence;
22 |
23 | - Confusing the digit "1" with letter "l";
24 |
25 | - Confusing the digit "0" with letter "O".
26 |
--------------------------------------------------------------------------------
/docs/contributors.md:
--------------------------------------------------------------------------------
1 | # Contributors
2 |
3 | Here is a list of the contributors who have helped develop these materials:
4 |
5 | - Rob Moss ([robmoss](https://github.com/robmoss))
6 | - Eamon Conway ([EamonConway](https://github.com/EamonConway))
7 | - James Ong ([jomonman537](https://github.com/jomonman537))
8 | - Trish Campbell ([TrishC](https://github.com/TrishC))
9 | - Isobel Abell ([iabell](https://github.com/iabell))
10 | - Nefel Tellioglu ([nefeltellioglu](https://github.com/nefeltellioglu))
11 |
--------------------------------------------------------------------------------
/docs/extra/asciinema-theme-gimlb.css:
--------------------------------------------------------------------------------
1 | /* Tomorrow Day colour palette. */
2 | .asciinema-player-theme-gimlb-auto {
3 | --term-color-foreground: #4d4d4c;
4 | --term-color-background: #ffffff;
5 | --term-color-0: #e0e0e0;
6 | --term-color-1: #c82829;
7 | --term-color-2: #718c00;
8 | --term-color-3: #eab700;
9 | --term-color-4: #4271ae;
10 | --term-color-5: #8959a8;
11 | --term-color-6: #3e999f;
12 | --term-color-7: #4d4d4c;
13 | --term-color-8: #8e908c;
14 | --term-color-9: #c82829;
15 | --term-color-10: #718c00;
16 | --term-color-11: #eab700;
17 | --term-color-12: #4271ae;
18 | --term-color-13: #8959a8;
19 | --term-color-14: #3e999f;
20 | --term-color-15: #1d1f21;
21 | }
22 |
23 | /* Tomorrow Night colour palette. */
24 | @media (prefers-color-scheme: dark) {
25 | .asciinema-player-theme-gimlb-auto {
26 | --term-color-foreground: #c5c8c6;
27 | --term-color-background: #1d1f21;
28 | --term-color-0: #282a2e;
29 | --term-color-1: #cc6666;
30 | --term-color-2: #b5bd68;
31 | --term-color-3: #f0c674;
32 | --term-color-4: #81a2be;
33 | --term-color-5: #b294bb;
34 | --term-color-6: #8abeb7;
35 | --term-color-7: #c5c8c6;
36 | --term-color-8: #969896;
37 | --term-color-9: #cc6666;
38 | --term-color-10: #b5bd68;
39 | --term-color-11: #f0c674;
40 | --term-color-12: #81a2be;
41 | --term-color-13: #b294bb;
42 | --term-color-14: #8abeb7;
43 | --term-color-15: #ffffff;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/docs/extra/larger-admonitions.css:
--------------------------------------------------------------------------------
1 | /* Display admonitions with the same font size as the surrounding text. */
2 | .md-typeset .admonition,
3 | .md-typeset details {
4 | font-size: inherit;
5 | }
6 |
--------------------------------------------------------------------------------
/docs/extra/wrapper.js:
--------------------------------------------------------------------------------
1 | /* Convenience wrapper for asciinema-player. */
2 | /* SPDX-License-Identifier: MIT OR CC-BY-SA-4.0 */
3 | /* SPDX-FileCopyrightText: 2023 Rob Moss */
4 |
5 | /**
6 | * Create asciinema players for elements that have "id" and "data-cast-file"
7 | * attributes.
8 | *
9 | * For example:
10 | *
11 | *
12 | *
13 | * You can also define links that jump the player to a specific time.
14 | * For each link, set the "data-video" attribute to the video's "id" attribute
15 | * and set the "data-seek-to" attribute to the time (in seconds).
16 | *
17 | * For example:
18 | *
19 | *
20 | *
22 | *
23 | *
24 | */
25 |
26 | (function() {
27 | "use strict";
28 |
29 | function addAsciinemaPlayer(cast_file, container_id) {
30 | const player = AsciinemaPlayer.create(
31 | cast_file,
32 | document.getElementById(container_id),
33 | { poster: 'npt:0:0.1', theme: 'gimlb-auto', fit: 'width' });
34 |
35 | // Find all elements that seek to specific times in this video.
36 | const selector = '[data-video="' + container_id + '"][data-seek-to]'
37 | const time_stamps = document.querySelectorAll(selector);
38 |
39 | // Add an event handler for each element that seeks to the specified time.
40 | time_stamps.forEach(elt => {
41 | // Ignore elements with invalid seek times.
42 | const seek_to = parseInt(elt.getAttribute('data-seek-to'));
43 | if (isNaN(seek_to) || seek_to < 0) {
44 | return
45 | }
46 |
47 | elt.addEventListener('click', () => {
48 | player.seek(elt.getAttribute('data-seek-to'));
49 | });
50 |
51 | // Add a time-stamp to the end of the link text.
52 | if (elt.tagName === 'A') {
53 | const minutes = Math.floor(seek_to / 60).toString();
54 | var seconds = (seek_to % 60).toString();
55 | if (seconds.length < 2) {
56 | seconds = '0' + seconds;
57 | }
58 | const time_stamp = ' (' + minutes + ':' + seconds + ')';
59 | elt.insertAdjacentHTML('beforeend', time_stamp);
60 | }
61 | });
62 | }
63 |
64 | function addPlayers() {
65 | // Final all video place-holders.
66 | const selector = '[id][data-cast-file]';
67 | const players = document.querySelectorAll(selector);
68 |
69 | // Create an asciinema player for each place-holder element.
70 | players.forEach(elt => {
71 | const cast_file = elt.getAttribute('data-cast-file');
72 | const container_id = elt.getAttribute('id');
73 | addAsciinemaPlayer(cast_file, container_id);
74 | })
75 | }
76 |
77 | // Create a player for each place-holder in the document.
78 | if (document.readyState === 'loading') {
79 | document.addEventListener('DOMContentLoaded', addPlayers);
80 | } else {
81 | addPlayers();
82 | }
83 |
84 | })();
85 |
--------------------------------------------------------------------------------
/docs/guides/README.md:
--------------------------------------------------------------------------------
1 | # Topical guides
2 |
3 | These materials are divided into the following sections:
4 |
5 | 1. Understanding [version control](./version-control/README.md), which provides you with a complete and annotated history of your work, and with powerful ways to search and examine this history.
6 |
7 | 2. Learning to use [Git](./using-git/README.md), the most widely used version control system, which is the foundation of popular code-hosting services such as [GitHub](https://github.com/), [GitLab](https://gitlab.com/public), and [Bitbucket](https://bitbucket.org/).
8 |
9 | 3. Using Git to [collaborate with colleagues](./collaborating/README.md) in a precisely controlled and manageable way.
10 |
11 | 4. Learn how to [structure your project](./project-structure/README.md) so that it is easier for yourself and others to navigate.
12 |
13 | 5. Learn how to [write code](./writing-code/README.md) so that it clearly expresses your intent and ideas.
14 |
15 | 6. Ensuring that your research is [reproducible by others](./reproducibility/README.md).
16 |
17 | 7. Using [testing frameworks](./testing/README.md) to verify that your code behaves as intended, and to automatically detect when you introduce a bug or mistake into your code.
18 |
19 | 8. Running your code on various [computing platforms]() that allow you to obtain results efficiently and without relying on your own laptop/computer.
20 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/README.md:
--------------------------------------------------------------------------------
1 | # Collaborating
2 |
3 | This section demonstrates how to use Git for collaborative research, enabling multiple people to work on the same code or paper in parallel.
4 | This includes deciding how to structure your repository, how to use branches for each collaborator, and how to use tags to track your progress.
5 |
6 | !!! info
7 |
8 | We also show how these skills support **peer code review**, so that you can share knowledge with, and learn from, your colleagues as part of your regular activity.
9 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/an-example-pull-request.md:
--------------------------------------------------------------------------------
1 | # An example pull request
2 |
3 | The initial draft of each chapter in this section were proposed in a [pull request](https://github.com/robmoss/git-is-my-lab-book/pull/8).
4 |
5 | When this pull request was created, the branch added four new commits:
6 |
7 | ```text
8 | 85594bf Add some guidelines for collaboration workflows
9 | 678499b Discuss coding style guides
10 | 2b9ff70 Discuss merge/pull requests and peer code review
11 | 6cc6f54 Discuss repository structure and licenses
12 | ```
13 |
14 | and the author (Rob Moss) asked the reviewer (Eamon Conway) to address several details in particular.
15 |
16 | Eamon made several suggestions in their [initial response](https://github.com/robmoss/git-is-my-lab-book/pull/8#issuecomment-1139216530), including:
17 |
18 | - Moving the [How to structure a repository](../using-git/how-to-structure-a-repository.md) and [Choosing a license](../using-git/choosing-a-license.md) chapters to the [Effective use of git](../using-git/README.md) section;
19 |
20 | - Starting this section with the [Collaborating on code](collaborating-on-code.md) chapter; and
21 |
22 | - Agreeing that we should use [this pull request](https://github.com/robmoss/git-is-my-lab-book/pull/8) as an example in this book.
23 |
24 | In response, Rob pushed two commits that addressed the first two points above:
25 |
26 | ```text
27 | e1d1dd9 Move collaboration guidelines to the start
28 | 3f78ef8 Move the repository structure and license chapters
29 | ```
30 |
31 | and then wrote this chapter to show how **we used [a pull request](https://github.com/robmoss/git-is-my-lab-book/pull/8) to draft this book section**.
32 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/coding-style-guides.md:
--------------------------------------------------------------------------------
1 | # Coding style guides
2 |
3 | A style guide defines rules and guidelines for how to structure and format your code.
4 | This can make code **easier to write**, because you don't need to worry about how to format your code.
5 | It can also make code **easier to read**, because consistent styling allows you to focus on the content.
6 |
7 | There are two types of tools that can help you use a style guide:
8 |
9 | - A **formatter** formats your code to make it consistent with a specific style; and
10 |
11 | - A **linter** checks whether your code is consistent with a specific style.
12 |
13 | ## Recommended style guides
14 |
15 | Because programming languages can be very different from each other, style guides are usually defined for a single programming language.
16 |
17 | Here we list some of the most widely-used style guides for several common programming languages:
18 |
19 | - For R there is a [tidyverse style guide](https://style.tidyverse.org/).
20 | - You can apply this style to your code with [styler](http://styler.r-lib.org/).
21 | - You can check that your code conforms to this style with [lintr](https://github.com/jimhester/lintr).
22 |
23 | - For Python there is [Black](https://black.readthedocs.io/), which defines a coding style and applies this style to your code.
24 |
25 | - For C++ there is a [Google C++ style guide](https://google.github.io/styleguide/cppguide.html).
26 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/collaborating-on-a-paper.md:
--------------------------------------------------------------------------------
1 | # Collaborating on a paper
2 |
3 | Once you are comfortable with creating commits, working in branches, and merging branches, you can use these skills to **write papers collaboratively as a team**.
4 | This approach is particularly useful if you are writing a paper in LaTeX.
5 |
6 | Here are some general guidelines that you may find useful:
7 |
8 | - Divide the paper into [separate LaTeX files](https://www.overleaf.com/learn/latex/Management_in_a_large_project) for each section.
9 |
10 | - Use [tags](../using-git/how-to-create-and-use-tags.md) to identify milestones such as draft versions and revisions.
11 |
12 | - Consider creating a [separate branch](sharing-a-branch.md) for each collaborator.
13 |
14 | - Merge these branches when completing a major draft or revision.
15 |
16 | - Use [latexdiff](https://www.overleaf.com/learn/latex/Articles/Using_Latexdiff_For_Marking_Changes_To_Tex_Documents) to show tracked changes between the current version and a previous commit/tag:
17 |
18 | ```sh
19 | latexdiff-git --flatten -r tag-name paper.tex
20 | ```
21 |
22 | - Collaborators who will provide feedback, rather than contributing directly to the writing process, can do this by:
23 |
24 | - Annotating PDF versions of the paper; or
25 | - Providing comments in response to a [merge/pull request](merge-pull-requests.md).
26 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/collaborating-on-code.md:
--------------------------------------------------------------------------------
1 | # Collaborating on code
2 |
3 | Once you are comfortable with creating commits, working in branches, and merging branches, you can use these skills to **write code collaboratively as a team**.
4 |
5 | The precise workflow will depend on the nature of your research and on the collaborators in your team, but there are some general guidelines that you may find helpful:
6 |
7 | - Agree on a [style guide](coding-style-guides.md).
8 |
9 | - Work on separate features in [separate branches](sharing-a-branch.md).
10 |
11 | - Use [peer code review](peer-code-review.md) before merging changes from these branches.
12 |
13 | - Consider using [continuous integration](continuous-integration.md) to:
14 |
15 | - Run [test cases](../testing/README.md) and detect bugs as early as possible; and
16 | - Verify that code meets your chosen style guide.
17 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/continuous-integration.md:
--------------------------------------------------------------------------------
1 | # Continuous integration
2 |
3 | Continuous Integration (CI) is an automated process where code changes are merged in a central repository in order to run automated tests and other processes.
4 | This can provide rapid feedback while you develop your code and collaborate with others, as long as commits are regularly pushed to the central repository.
5 |
6 | !!! info
7 |
8 | This book is an example of Continuous Integration: every time a commit is pushed to the [central repository](https://github.com/robmoss/git-is-my-lab-book), the [online book](https://git-is-my-lab-book.net/) is automatically updated.
9 |
10 | Because the central repository is hosted on GitHub, we use [GitHub Actions](https://docs.github.com/en/actions/quickstart).
11 | Note that this is a GitHub-specific CI system.
12 | You can view the update action for this book [here](https://github.com/robmoss/git-is-my-lab-book/blob/master/.github/workflows/deploy.yml).
13 |
14 | We also use CI to publish each pull request, so that contributions can be previewed during the review process.
15 | We added this feature in [this pull request](https://github.com/robmoss/git-is-my-lab-book/pull/26).
16 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/merge-pull-requests.md:
--------------------------------------------------------------------------------
1 | # Merge/Pull requests
2 |
3 | Recall that [incorporating the changes from one branch into another branch](../using-git/how-to-use-branches.md#merging-branches) is referred to as a "merge".
4 | You can merge one branch into another branch by taking the following steps:
5 |
6 | 1. Checking out the branch you want to merge the changes **into**:
7 |
8 | ```sh
9 | git checkout -b my-branch
10 | ```
11 |
12 | 2. Merging the changes **from** the other branch:
13 |
14 | ```sh
15 | git merge other-branch
16 | ```
17 |
18 | !!! tip
19 |
20 | It's a good idea to **review these changes** before you merge them.
21 |
22 | If possible, it's even better to have **someone else** review the changes.
23 |
24 | You can use `git diff` to [view differences between branches](../using-git/how-to-use-branches.md#inspecting-branch-histories).
25 | However, platforms such as GitHub and GitLab offer an easier approach: "pull requests" (also called "merge requests").
26 |
27 | ## Creating a pull request on GitHub
28 |
29 | The steps required to create a pull request differ depending on which platform you are using.
30 | Here, we will describe how to create a pull request on GitHub.
31 | For further details, see the [GitHub documentation](https://docs.github.com/en/pull-requests).
32 |
33 | - Open the main page of your GitHub repository.
34 |
35 | - In the "Branch" menu, select the branch that contains the changes you want to merge.
36 |
37 | - Open the "Contribute" menu.
38 | This should be located on the right-hand side, above the list of files.
39 |
40 | - Click the "Open pull request" button.
41 |
42 | - In the "base" menu, select the branch you want to merge the changes **into**.
43 |
44 | - Enter a descriptive title for the pull request.
45 |
46 | - In the message editor, write a summary of the changes in this branch, and identify **specific questions or objectives** that you want the reviewer to address.
47 |
48 | - Select **potential reviewers** by clicking on the "Reviewers" link in the right-hand sidebar.
49 |
50 | - Click the "Create pull request" button.
51 |
52 | Once the pull request has been created, the reviewer(s) can review your changes and discuss their feedback and suggestions with you.
53 |
54 | ## Merging a pull request on GitHub
55 |
56 | When the pull request has been reviewed to your satisfaction, you can merge these changes by clicking the "Merge pull request" button.
57 |
58 | !!! info
59 |
60 | If the pull request has merge conflicts (e.g., if the branch you're merging **into** contains new commits), you will need to [resolve these conflicts](../using-git/how-to-resolve-merge-conflicts.md).
61 |
62 | For further details about merging pull requests on GitHub, see the [GitHub documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request).
63 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/peer-code-review.md:
--------------------------------------------------------------------------------
1 | # Peer code review
2 |
3 | Once you're comfortable in using [merge/pull requests](merge-pull-requests.md) to review changes in a branch, you can use this approach for peer code review.
4 |
5 | !!! info
6 |
7 | Remember that code review is a **discussion and critique** of a person's work.
8 | The code author will naturally feel that they own the code, and the reviewer needs to respect this.
9 |
10 | For further advice and suggestions on how to conduct peer code review, please see the [Performing peer code review](../resources.md#performing-peer-code-review) resources.
11 |
12 | !!! tip
13 |
14 | Mention people who have reviewed your code in the acknowledgements section of the paper.
15 |
16 | ## Define the goals of a peer review
17 |
18 | In creating a pull request and inviting someone to review your work, the pull request description should include the following details:
19 |
20 | - An overview of the work included in the pull request: what have you done, why have you done it?
21 |
22 | - You may also want to explain how this work fits into the broader context of your research project.
23 |
24 | - Identify **specific questions or tasks** that you would like the reviewer to address.
25 | For example, you might ask the reviewer to address one or more of the following questions:
26 |
27 | - Can the reviewer run your code and reproduce the outputs?
28 |
29 | - Is the code easy to understand?
30 |
31 | - If you have a [style guide](coding-style-guides.md), is the code formatted appropriately?
32 |
33 | - Do the model equation or data analysis steps seem sensible?
34 |
35 | - If you have written documentation, is it easy to understand?
36 |
37 | - Can the reviewer suggest how to improve or rewrite a specific piece of code?
38 |
39 | !!! tip
40 |
41 | Make the reviewer's job easier by giving them small amounts of code to review.
42 |
43 | ## Finding a reviewer
44 |
45 | On GitHub we have started a [peer-review team](https://github.com/orgs/spectrum-spark/teams/peer-review).
46 | We encourage you to post on the discussion board, to find like-minded members to review your code.
47 |
48 | ## Guidelines for reviewing other people's code
49 |
50 | Peer code review is an opportunity for the author and the reviewer to **learn from each other** and improve a piece of code.
51 |
52 | !!! tip
53 |
54 | The most important guideline for the reviewer is to **be kind**.
55 |
56 | Treat other people's code the way you would want them to treat your code.
57 |
58 | - [**Avoid saying "you"**](https://www.alexandra-hill.com/2018/06/25/the-art-of-giving-and-receiving-code-reviews/).
59 | Instead, say "we" or make the code the subject of the sentence.
60 |
61 | - Don't say "You don't have a test for this function", but instead say "We should test this function".
62 |
63 | - Don't say "Why did you write it this way?", but instead say "What are the advantages of this approach?".
64 |
65 | - **Ask questions** rather than stating criticisms.
66 |
67 | - Don't say "This code is unclear", but instead say "Can you help me understand how this code works?".
68 |
69 | - Treat peer review as an opportunity to **praise good work**!
70 |
71 | - Don't be afraid to tell the author that a piece of code was very clear, easy to understand, or well written.
72 |
73 | - Tell the author if reading their code made you aware of a useful function or package.
74 |
75 | - Tell the author if reading their code gave you some ideas for your own code.
76 |
77 | ## Complete the review
78 |
79 | Once the peer code review is complete, and any corresponding updates to the code have been made, you can [merge the branch](merge-pull-requests.md).
80 |
81 | ## Retain a record of the review
82 |
83 | By using merge/pull requests to review code, the discussion between the author and the reviewer is recorded.
84 | This can be a useful reference for future code reviews.
85 |
86 | !!! tip
87 |
88 | Try to record all of the discussion in the pull request comments, even if the author and reviewer meet in person, so that you have a complete record of the review.
89 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/sharing-a-branch.md:
--------------------------------------------------------------------------------
1 | # Sharing a branch
2 |
3 | You might want a collaborator to work on a specific branch of your repository, so that you can keep their changes separate from your own work.
4 | Remember that you can merge commits from their branch into your own branches at any time.
5 |
6 | !!! info
7 |
8 | You need to ensure that your collaborator [has access to the remote repository](sharing-a-repository.md).
9 |
10 | 1. Create a new branch for the collaborator, and give it a descriptive name.
11 |
12 | ```sh
13 | git checkout -b collab/jamie
14 | ```
15 |
16 | In this example we created a branch called "collab/jamie", where "collab" is a prefix used to identify branches intended for collaborators, and the collaborator is called Jamie.
17 |
18 | Remember that you can [choose your own naming conventions](../using-git/how-to-use-branches.md).
19 |
20 | 2. Push this branch to your remote repository:
21 |
22 | ```sh
23 | git push -u origin collab/jamie
24 | ```
25 |
26 | 3. Your collaborator can then make a local copy of this branch:
27 |
28 | ```sh
29 | git clone --single-branch --branch collab/jamie repository-url
30 | ```
31 |
32 | 4. They can then create commits and push them to your remote repository with `git push`.
33 |
--------------------------------------------------------------------------------
/docs/guides/collaborating/sharing-a-repository.md:
--------------------------------------------------------------------------------
1 | # Sharing a repository
2 |
3 | The easiest way to share a repository with collaborators is to have a single remote repository that all collaborators can access.
4 | This repository could be located on a platform such as GitHub, GitLab, or Bitbucket, or on a platform provided by your University or Institute.
5 |
6 | Theses platforms allow you to create **public** repositories and **private** repositories.
7 |
8 | - Everybody can view the contents of a public repository.
9 |
10 | - You control who can view the contents of a private repository.
11 |
12 | - For both types of repository, **you control who can make changes** to the repository, such as creating commits and branches.
13 |
14 | !!! info
15 |
16 | You should decide whether a public repository or a private repository suits you best.
17 |
18 | ## Giving collaborators access to your remote repository
19 |
20 | The steps required to do this differ depending on which platform you are using.
21 | Here, we will describe how to give collaborators access to a repository on GitHub.
22 | For further details, see the [GitHub documentation](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository).
23 |
24 | - Open the main page of your GitHub repository.
25 |
26 | - Click on the "Settings" tab in the top navigation bar.
27 |
28 | - Click on the "Collaborators" item in the left sidebar.
29 |
30 | - Click on the "Add people" button.
31 |
32 | - Search for collaborators by entering their GitHub user name, their full name, or their email address.
33 |
34 | - Click the "Add to this repository" button.
35 |
36 | This will send an invitation to the collaborator.
37 | If they accept this invitation, they will have access to your repository.
38 |
--------------------------------------------------------------------------------
/docs/guides/high-performance-computing/README.md:
--------------------------------------------------------------------------------
1 | # Cloud and HPC platforms
2 |
3 | This section introduces computing platforms that allow you to generate outputs more quickly, and without relying on your own laptop or desktop computer.
4 | It also demonstrates how to use version control to ensure that the code running on these platforms is the same as the code on your laptop.
5 |
--------------------------------------------------------------------------------
/docs/guides/learning-objectives.md:
--------------------------------------------------------------------------------
1 | # Learning objectives
2 |
3 | This page defines the learning objectives for individual sections.
4 | These are skills that the reader should be able to demonstrate after reading through the relevant section, and completing any exercises in that section.
5 |
6 | ## Version control concepts
7 |
8 | After completing [this section](version-control/README.md), you should be able to identify how to apply version control concepts to your existing work.
9 | This includes being able to:
10 |
11 | - Identify projects and tasks for which version control would be suitable;
12 |
13 | - Categorise recent work activities into one or more commits;
14 |
15 | - Write commit messages that describe what changes you made and why you made them; and
16 |
17 | - Identify pieces of work that could be carried out in separate branches of a repository.
18 |
19 | ## Effective use of git
20 |
21 | After completing [this section](using-git/README.md), you should be able to:
22 |
23 | - Create a local repository;
24 |
25 | - Create commits in your local repository;
26 |
27 | - Search your commit history to identify commits that made a specific change;
28 |
29 | - Create a remote repository;
30 |
31 | - Push commits from your local repository to a remote repository;
32 |
33 | - Pull commits from a remote repository to your local repository;
34 |
35 | - Use tags to identify important milestones;
36 |
37 | - Work in a separate branch and then merge your changes into your main branch; and
38 |
39 | - Resolve merge conflicts.
40 |
41 | ## Collaborating
42 |
43 | After completing [this section](collaborating/README.md), you should be able to:
44 |
45 | - **Share a repository** with one or more collaborators;
46 |
47 | - Create a **pull request**;
48 |
49 | - Use a pull request to **review a collaborator's work**;
50 |
51 | - Use a pull request to **merge a collaborator's work** into your main branch; and
52 |
53 | - **Conduct peer code review** in a respectful manner.
54 |
55 | ## Project structure
56 |
57 | After completing [this section](project-structure/README.md), you should be able to:
58 |
59 | - Understand how to structure a new project;
60 |
61 | - Understand how to separate "what to do" from "how to do it"; and
62 |
63 | - Structure your code to enable new experiments and analyses.
64 |
65 | ## Writing code
66 |
67 | After completing [this section](writing-code/README.md), you should be able to:
68 |
69 | - Divide your code into functions and modules;
70 |
71 | - Ensure that your code is a clear expression of your ideas;
72 |
73 | - Structure your code into reusable packages; and
74 |
75 | - Take advantage of code formatters and code linters.
76 |
--------------------------------------------------------------------------------
/docs/guides/prerequisites.md:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 |
3 | These materials assume that the reader has a basic knowledge of the Bash command-line shell and using SSH to connect to remote computers.
4 | You should be comfortable with using the command-line to perform the following tasks:
5 |
6 | - Navigate your files and directories;
7 | - Create, copy, move, and delete files and directories; and
8 | - Work remotely using SSH.
9 |
10 | Please refer to the following materials for further details:
11 |
12 | - [The Unix Shell](https://swcarpentry.github.io/shell-novice/): an introduction to using Bash.
13 | - [Extra Unix Shell Material](https://carpentries-incubator.github.io/shell-extras/): additional shell lessons, including SSH.
14 |
15 | !!! info
16 |
17 | If you use Windows, you may want to use PowerShell instead of Bash, in which case please refer to this [Introduction to the Windows Command Line with Powershell](https://doi.org/10.46430/phen0054).
18 |
19 | Some chapters also assume that the reader has an account on [GitHub](https://github.com/) and has [added an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) to their account.
20 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/README.md:
--------------------------------------------------------------------------------
1 | # Project structure
2 |
3 | How we choose to structure a project can affect how readily someone else — or even yourself, after a period of absence — can understand, use, and extend the work.
4 |
5 | !!! question
6 |
7 | Have you ever looked at your old code and wondered how it worked or how to make it run?
8 |
9 | !!! tip
10 |
11 | A good project structure can serve as a table of contents and help the reader to navigate.
12 |
13 | In an earlier section we provided some guidelines for [how to structure a repository](../using-git/how-to-structure-a-repository.md).
14 | In this section we present further guidelines and examples to help you choose a sensible structure for your current project and future projects.
15 |
16 | This includes high-level recommendations that should apply to any project, and more detailed recommendations that may be specific to a particular type of project or choice of programming language.
17 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/automating-tasks.md:
--------------------------------------------------------------------------------
1 | # Automate common tasks
2 |
3 | If you reach the point where you need to run a specific sequence of commands or actions to achieve something — e.g., running a model simulation, or producing an output figure — it is a **very good idea** to write a script that performs all of these actions correctly.
4 |
5 | This is because while you may remember exactly what needs to be done **right now**, you may not remember next week, or next month, or next year.
6 | We're all human, and we all make mistakes, but these kinds of mistakes are **easy to avoid**!
7 |
8 | !!! info
9 |
10 | Mistakes are a fact of life. It is the response to the error that counts.
11 |
12 | — Nikki Giovanni
13 |
14 | There are many tools that can help you to automate tasks, some of which are smart enough that they will only do as little as possible (e.g., avoid re-running steps if the inputs have not changed).
15 |
16 | There are popular tools aimed at specific programming languages, such as:
17 |
18 | - **R:** [targets](https://books.ropensci.org/targets/);
19 |
20 | - **Python**: [nox](https://nox.thea.codes/) and [tox](https://tox.wiki/); and
21 |
22 | - **Julia:** [pipelines](https://juliapackages.com/p/pipelines).
23 |
24 | There are many generic automation tools (see, e.g., Wikipedia's list of [build automation software](https://en.wikipedia.org/wiki/List_of_build_automation_software)), although these can be rather complex to learn.
25 | We recommend using a language-specific automation tool where possible, and only using a generic automation tool as a last resort.
26 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/exercise-a-good-readme.md:
--------------------------------------------------------------------------------
1 | # Exercise: a good README
2 |
3 | Remember that the README file (usually one of `README.md`, `README.rst`, or `README.txt`) is often **the very first thing** that a user will see when looking at your project.
4 |
5 | - Have you seen any README files that were particularly helpful, or were not very helpful?
6 |
7 | - What information do you find helpful in a README file?
8 |
9 | Consider the `README.md` file in the [Australian 2020 COVID-19 forecasts repository](https://gitlab.unimelb.edu.au/rgmoss/aus-2020-covid-forecasts).
10 |
11 | - What content, if any, would you **add** to this file?
12 |
13 | - What content, if any, would you **remove** from this file?
14 |
15 | - Would you change its structure in any way?
16 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/exercise-what-works-for-you.md:
--------------------------------------------------------------------------------
1 | # Exercise: what works for you?
2 |
3 | Look back at your past projects and identify aspects of their structure that you have found helpful.
4 |
5 | - What features or choices have worked well in past projects and might help you structure your future projects?
6 |
7 | - What problems or issues have you experienced with the structure of your past projects, which you could avoid in your future projects?
8 |
9 | - Can any of your colleagues and collaborators share similar insights?
10 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/explain-how-it-works.md:
--------------------------------------------------------------------------------
1 | # Explain how it all works
2 |
3 | Once you've chosen a project structure, you need to write down **how it all works** — regardless of how simple and clear your project structure is!
4 |
5 | !!! tip
6 |
7 | The best place to do this is in a `README.md` file (or equivalent) in the project root directory.
8 |
9 | Begin with an overview of the project:
10 |
11 | - What question(s) are you trying to address?
12 |
13 | - What data, hypotheses, methods, etc, are you using?
14 |
15 | - What outputs does this generate?
16 |
17 | You can then provide further detail, such as:
18 |
19 | - What software environment and/or packages must be available for your code to run?
20 |
21 | - How can the user generate each of the outputs?
22 |
23 | - What license [have you chosen](../using-git/choosing-a-license.md)?
24 |
25 |
26 | ## An example README.md
27 |
28 | See the [Australian 2020 COVID-19 forecasts repository](https://gitlab.unimelb.edu.au/rgmoss/aus-2020-covid-forecasts) for an example `README.md` file.
29 |
30 | This repository was used to generate the results, tables, and figures presented in the paper "[Forecasting COVID-19 activity in Australia to support pandemic response: May to October 2020](https://doi.org/10.1038/s41598-023-35668-6)", *Scientific Reports* 13, 8763 (2023).
31 |
32 | **Strengths:**
33 |
34 | - It includes installation and usage instructions;
35 |
36 | - It identifies the paper; and
37 |
38 | - It identifies the license under which the code is distributed.
39 |
40 | **Weaknesses:**
41 |
42 | - It only explains some of the project structure.
43 |
44 | - It doesn't provide an overview of the project, it only links to the paper.
45 |
46 | - The root directory contains a number of scripts and input files that aren't described.
47 |
--------------------------------------------------------------------------------
/docs/guides/project-structure/workflow.md:
--------------------------------------------------------------------------------
1 | # Define your workflow
2 |
3 | A good first step in deciding how to structure a project is to ask yourself:
4 |
5 | - What are the different project phases?
6 |
7 | - What are the major activities in each phase?
8 |
9 | ## An example of phases and activities
10 |
11 | For example, a project might involve the following phases:
12 |
13 | 1. Clean an existing data set;
14 |
15 | 2. Build models with different hypotheses or features;
16 |
17 | 3. Fit each model to the data; and
18 |
19 | 4. Decide which model best explains the data.
20 |
21 | The data-cleaning phase might involve the following activities:
22 |
23 | - Obtain the raw data;
24 |
25 | - Identify the quality checks that should be applied;
26 |
27 | - Decide how to resolve data that fail each quality check; and
28 |
29 | - Generate and record the cleaned data.
30 |
31 | The model-building phase might involve the following activities:
32 |
33 | - Perform a literature search to identify relevant modelling studies;
34 |
35 | - Identify competing hypotheses or features that might explain the data;
36 |
37 | - Design a model that implements each hypothesis; and
38 |
39 | - Define the relationship between each model and the cleaned data.
40 |
41 | ## Reflect this workflow in your project structure
42 |
43 | You can use the phases and activities to guide your choice of directory structure.
44 | For this example project, one possible structure is:
45 |
46 | - `project/`: the root directory of your project
47 |
48 | - `input/`: a sub-directory that contains input data;
49 |
50 | - `raw/`: the raw data **before** cleaning;
51 |
52 | - `cleaned/`: the cleaned data;
53 |
54 | - `code/`: a sub-directory that contains the project code;
55 |
56 | - `cleaning/`: the data cleaning code;
57 |
58 | - `model-first-hypothesis/`: the first model;
59 |
60 | - `model-second-hypothesis/`: the second model;
61 |
62 | - `fitting/`: the code that fits each model to the data;
63 |
64 | - `evaluation/`: the code the compares the model fits;
65 |
66 | - `plotting/`: the code that plots output figures;
67 |
68 | - `paper/`: a sub-directory for the project manuscript;
69 |
70 | - `figures/`: the output figures;
71 |
--------------------------------------------------------------------------------
/docs/guides/reproducibility/README.md:
--------------------------------------------------------------------------------
1 | # Reproducibility
2 |
3 | This section demonstrates how to use version control and software testing to ensure that your research results can be independently reproduced by others.
4 |
5 | !!! tip
6 |
7 | Reproducibility is just as much about simple work habits as the tools used to share data and code.
8 |
9 | — [Jesse M. Alston and Jessica A. Rick](https://doi.org/10.1002/bes2.1801)
10 |
--------------------------------------------------------------------------------
/docs/guides/reproducibility/what-is-reproducible-research.md:
--------------------------------------------------------------------------------
1 | # What is reproducible research?
2 |
3 | Various scientific disciplines have defined and used the terms "replication" and "reproducible" in different (and sometimes contradictory) ways.
4 | But in recent years there have been efforts to standardise these terms, particularly in the context of computational research.
5 | Here we will use the definitions from [Reproducibility and Replicability in Science](https://doi.org/10.17226/25303):
6 |
7 | - **Replication:** obtaining consistent results across studies aimed at answering the same scientific question, each of which has obtained its own data.
8 |
9 | - **Reproducible:** obtaining consistent computational results using the same input data, computational steps, methods, code, and conditions of analysis.
10 |
11 |
12 | !!! question
13 |
14 | If you can't explain your research well enough for someone else to reproduce the results, can you really call what you did "research"?
15 |
16 | Creating reproducible research requires good work habits and practices, and also a way to **verify** that the results are reproducible.
17 |
18 | It is sometimes said that reproducibility can be achieved by sharing all of the code and data with a published article, but **this is not necessarily sufficient** for computationally complex studies.
19 | There are [many reasons](http://www.tdda.info/why-code-rusts) why running the same code with the same data may produce different results.
20 |
21 | !!! tip
22 |
23 | It is easier to make our research reproducible by starting at the planning stage, rather than waiting until we've produced results.
24 |
--------------------------------------------------------------------------------
/docs/guides/testing/README.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | This section introduces the topic of software testing.
4 | Testing your code is an important part of any code-based research activity.
5 | Tests check whether your code behaves as intended, and can warn you if you introduce a bug or mistake into your code.
6 |
7 | !!! tip
8 |
9 | Tests can show the presence of bugs, but **not** their absence.
10 |
11 | — [Edsger W. Dijkstra](https://en.wikiquote.org/wiki/Edsger_W._Dijkstra)
12 |
--------------------------------------------------------------------------------
/docs/guides/using-git/README.md:
--------------------------------------------------------------------------------
1 | # Effective use of git
2 |
3 | This section shows how to use the `git` command-line program to record your work, to inspect your commit history, and to search this commit history to identify commits that make specific changes or have specific effects.
4 |
5 | !!! tip "Reminder"
6 |
7 | Remember to [commit early and commit often](../version-control/what-should-I-commit.md).
8 | **Do not wait** until your code is "perfect".
9 |
--------------------------------------------------------------------------------
/docs/guides/using-git/choosing-a-license.md:
--------------------------------------------------------------------------------
1 | # Choosing a license
2 |
3 | A license specifies the conditions under which others may use, modify, and/or distribute your work.
4 |
5 | !!! info
6 |
7 | Simply making a repository publicly accessible is **not sufficient** to allow others to make use of your work.
8 | Unless you include a license that specifies otherwise, [nobody else](https://choosealicense.com/no-permission/) can copy, distribute, or modify your work.
9 |
10 | There are many different types of licenses that you can use, and the number of options can seem overwhelming.
11 | But it is usually straightforward to narrow down your options.
12 |
13 | - If you're working on an **existing project**, the easiest option is to use that project's license.
14 |
15 | - If you're working with an **existing community**, they may have a [preferred license](https://choosealicense.com/community/).
16 |
17 | - If you want to choose an **open source license**, the [Choose an open source license](https://choosealicense.com/) website provides advice for selecting a license that meets your needs.
18 |
19 | For further information about the various types of available licenses, and some advice for selecting a suitable license for academic software, see [A Quick Guide to Software Licensing for the Scientist-Programmer](https://doi.org/10.1371/journal.pcbi.1002598).
20 |
--------------------------------------------------------------------------------
/docs/guides/using-git/choosing-your-git-editor.md:
--------------------------------------------------------------------------------
1 | # Choosing your Git editor
2 |
3 | In this video, we show how to use [nano](https://www.nano-editor.org/) and [vim](https://www.vim.org/) for writing commit messages.
4 | See below for brief instructions on how to use these editors.
5 |
6 | !!! tip
7 |
8 | This editor is **only used for writing commit messages**.
9 | It is entirely separate from your choice of editor for any other task, such as writing code.
10 |
11 | === "Git editor example"
12 |
13 |
14 |
15 | Video timeline:
16 |
17 | 1. Overview
18 | 2. Show how to use nano
19 | 3. Show how to use vim
20 |
21 | !!! note
22 |
23 | You can pause the video to **select and copy any of the text**, such as the ` git config --global core.editor` commands.
24 |
25 | ## How to use nano
26 |
27 | Once you have written your commit message, press Ctrl + O and then Enter to save the commit message, then press Ctrl + X to quit the editor.
28 |
29 | **To quit without saving** press Ctrl + X.
30 | If you have made any changes, `nano` will ask if you want to save them.
31 | Press n to quit without saving these changes.
32 |
33 | ## How to use vim
34 |
35 | You need to press i (switch to insert mode) before you can write your commit message.
36 | Once you have written your commit message, press Esc and then type :wq to save your changes and quit the editor.
37 |
38 | **To quit without saving** press Esc and then type :q!.
39 |
--------------------------------------------------------------------------------
/docs/guides/using-git/cloning-an-existing-repository.md:
--------------------------------------------------------------------------------
1 | # Cloning an existing repository
2 |
3 | If there is an existing repository that you want to work on, you can "clone" the repository and have a local copy.
4 | To do this, you need to know the remote repository's URL.
5 |
6 | !!! tip
7 |
8 | For GitHub repositories, there should be a green button labelled "Code".
9 | Click on this button, and it will provide you with the URL.
10 |
11 | You can then make a local copy of the repository by running:
12 |
13 | ```sh
14 | git clone URL
15 | ```
16 |
17 | For example, to make a local copy of this book, run the following command:
18 |
19 | ```sh
20 | git clone https://github.com/robmoss/git-is-my-lab-book.git
21 | ```
22 |
23 | This will create a local copy in the directory `git-is-my-lab-book`.
24 |
25 | !!! note
26 |
27 | If you have a GitHub account and have set up an SSH key, you can clone GitHub repositories using your SSH key.
28 | This will allow you to push commits to the remote repository (if you are permitted to do so) without having to enter your user name and password.
29 |
30 | You can obtain the SSH URL from GitHub by clicking on the green "Code" button, and selecting the "SSH" tab.
31 |
32 | For example, to make a local copy of this book using SSH, run the following command:
33 |
34 | ```sh
35 | git clone git@github.com:robmoss/git-is-my-lab-book.git
36 | ```
37 |
--------------------------------------------------------------------------------
/docs/guides/using-git/creating-a-commit.md:
--------------------------------------------------------------------------------
1 | # Creating a commit
2 |
3 | Creating a commit involves two steps:
4 |
5 | 1. Identify the changes that should be included in the commit.
6 | These changes are then "staged" and ready to be included in the next commit.
7 |
8 | 2. Create a new commit that records these staged changes.
9 | This should be accompanied by [a useful commit message](../version-control/how-do-I-write-a-commit-message.md).
10 |
11 | We will now show how to perform these steps.
12 |
13 | !!! note
14 |
15 | At any time, you can see a summary of the changes in your repository, and which ones are staged to be committed, by running:
16 |
17 | ```sh
18 | git status
19 | ```
20 |
21 | This will show you:
22 |
23 | 1. The files (if any) that contain changes that have been staged;
24 | 2. The files (if any) that contain changes that have not been staged; and
25 | 3. The files (if any) that are not recorded in the repository history.
26 |
27 | ## Adding a new file
28 |
29 | If you've created a new file, you can include this file in the next commit by running:
30 |
31 | ```sh
32 | git add filename
33 | ```
34 |
35 | ## Adding all changes in an existing file
36 |
37 | If you've made changes to an existing file, you can include all of these changes in the next commit by running:
38 |
39 | ```sh
40 | git add filename
41 | ```
42 |
43 | ## Adding some changes in an existing file
44 |
45 | If you've made changes to an existing file and only want to include **some of these changes** in the next commit, you can select the changes to include by running:
46 |
47 | ```sh
48 | git add -p filename
49 | ```
50 |
51 | This will show you each of the changes in turn, and allow you select which ones to stage.
52 |
53 | !!! tip
54 |
55 | This interactive selection mode is very flexible; you can enter `?` at any of the prompts to see the range of available actions.
56 |
57 | ## Renaming a file
58 |
59 | If you want to rename a file, you can use `git mv` to rename the file **and** stage this change for inclusion in the next commit:
60 |
61 | ```sh
62 | git mv filename newname
63 | ```
64 |
65 | ## Removing a file
66 |
67 | If you want to remove a file, you can use `git rm` to remove the file **and** stage this change for inclusion in the next commit:
68 |
69 | ```sh
70 | git rm filename
71 | ```
72 |
73 | !!! tip
74 |
75 | If the file has any uncommitted changes, git will refuse to remove the file.
76 | You can override this behaviour by running:
77 |
78 | ```sh
79 | git rm --force filename
80 | ```
81 |
82 | ## Inspecting the staged changes
83 |
84 | To verify that you have staged all of the desired changes, you can view the staged changes by running:
85 |
86 | ```sh
87 | git diff --cached
88 | ```
89 |
90 | You can view the staged changes for a specific file by running:
91 |
92 | ```sh
93 | git diff --cached filename
94 | ```
95 |
96 | ## Undoing a staged change
97 |
98 | You may sometimes stage a change for inclusion in the next commit, but decide later that you don't want to include it in the next commit.
99 | You can undo staged changes to a file by running:
100 |
101 | ```sh
102 | git restore --staged filename
103 | ```
104 |
105 | !!! note
106 |
107 | This **will not modify** the contents of the file.
108 |
109 | ## Creating a new commit
110 |
111 | Once you have staged all of the changes that you want to include in the commit, create the commit by running:
112 |
113 | ```sh
114 | git commit
115 | ```
116 |
117 | This will open your [chosen editor](first-time-git-setup.md) and prompt you to write the [commit message](../version-control/how-do-I-write-a-commit-message.md).
118 |
119 | !!! tip
120 |
121 | Note that the commit **will not be created until you exit the editor**.
122 |
123 | If you decide that you don't want to create the commit, you can abort this action by closing your editor without saving a commit message.
124 |
125 | Please see [Choosing your Git editor](choosing-your-git-editor.md) for details.
126 |
127 | ## Modifying the most recent commit
128 |
129 | After you create a commit, you might decide that there are other changes that should be included in the commit.
130 | Git provides a simple way of modifying the most recent commit.
131 |
132 | !!! warning
133 |
134 | **Do not modify the commit** if you have already pushed it to another repository.
135 | Instead, record a new commit that includes the desired changes.
136 |
137 | Remember that your commit history should not be a highly-edited, polished view of your work, but should instead act as a lab book.
138 |
139 | **Do not worry about creating ["perfect"](../version-control/what-should-I-commit.md) commits!**
140 |
141 | To modify the most recent commit, stage the changes that you want to commit (see the sections above) and add them to the most recent commit by running:
142 |
143 | ```sh
144 | git commit --amend
145 | ```
146 |
147 | This will open your [chosen editor](first-time-git-setup.md) and allow you to modify the commit message.
148 |
--------------------------------------------------------------------------------
/docs/guides/using-git/creating-a-remote-repository.md:
--------------------------------------------------------------------------------
1 | # Creating a remote repository
2 |
3 | Once you have created a "local" repository (i.e., a repository that exists on your own computer), it is [generally a good idea](../version-control/what-is-a-repository.md) to create a "remote" repository.
4 | You may choose to store this remote repository on a service such as GitHub, or on a University-provided platform.
5 |
6 | If you are using GitHub, you can choose to create a **public** repository (viewable by anyone, but you control who can make changes) or a **private** repository (you control who can view and/or make changes).
7 |
8 | ## Linking your local and remote repositories
9 |
10 | Once you have created the remote repository, you need to link it to your local repository.
11 | This will allow you to "push" commits from your local repository to the remote repository, and to "pull" commits from the remote repository to your local repository.
12 |
13 | !!! note
14 |
15 | When you create a new repository on services such as GitHub, they will give you instructions on how to link this new repository to your local repository.
16 | We also provide an example, below.
17 |
18 | A repository can be linked to more than one remote repository, so we need to choose a name to identify this remote repository.
19 |
20 | !!! info
21 |
22 | The name "origin" is commonly used to identify the main remote repository.
23 |
24 | In this example, we link our local repository to the remote repository for this book (`https://github.com/robmoss/git-is-my-lab-book`) with the following command:
25 |
26 | ```sh
27 | git remote add origin git@github.com:robmoss/git-is-my-lab-book.git
28 | ```
29 |
30 | !!! note
31 |
32 | Notice that the URL is similar to, **but not identical to**, the URL you use to view the repository in your web browser.
33 |
--------------------------------------------------------------------------------
/docs/guides/using-git/creating-a-repository.md:
--------------------------------------------------------------------------------
1 | # Creating a repository
2 |
3 | You can create repositories by running `git init`.
4 | This will create a `.git` directory that will contain all of the repository information.
5 |
6 | There are two common ways to use `git init`:
7 |
8 | 1. Create an empty repository **in the current directory**, by running:
9 |
10 | ```sh
11 | git init
12 | ```
13 |
14 | 2. Create an empty repository **in a specific directory**, by running:
15 |
16 | ```sh
17 | git init path/to/repository
18 | ```
19 |
20 | !!! info
21 |
22 | Git will create the repository directory if it does not exist.
23 |
--------------------------------------------------------------------------------
/docs/guides/using-git/exercise-create-a-local-repository.md:
--------------------------------------------------------------------------------
1 | # Exercise: create a local repository
2 |
3 |
23 |
24 | In this exercise you will create a local repository, and use this repository to create multiple commits, switch between branches, and inspect the repository history.
25 |
26 | 1. Create a new, empty repository in a directory called `git-exercise`.
27 |
28 | 2. Create a `README.md` file and write a [brief description](how-to-structure-a-repository.md#include-a-readme-file) for this repository.
29 | Record the contents of `README.md` in a new commit, and write a [commit message](../version-control/how-do-I-write-a-commit-message.md).
30 |
31 | 3. Write a script that generates a small data set, and saves the data to a CSV file.
32 | For example, this script could sample values from a probability distribution with fixed shape parameters.
33 | Explain how to use this script in `README.md`.
34 | Record your changes in a new commit.
35 |
36 | 4. Write a script that plots these data, and saves the figure in a suitable file format.
37 | Explain how to use this script in `README.md`.
38 | Record your changes in a new commit.
39 |
40 | 5. Add a tag `milestone-1` to the commit you created in the previous step.
41 |
42 | 6. Create a new branch called `feature/new-data`.
43 | Check out this branch and modify the data-generation script so that it produces new data and/or more data.
44 | Record your changes in one or more new commits.
45 |
46 | 7. Create a new branch called `feature/summarise` from the tag you created in step #5.
47 | Check out this branch and modify the plotting script so that it also prints some summary statistics of the data.
48 | Record your changes in one or more new commits.
49 |
50 | 8. In your `main` or `master` branch, and [add a license](choosing-a-license.md).
51 | Record your changes in a new commit.
52 |
53 | 9. In your `main` or `master` branch, merge the two feature branches created in steps #6 and #7, and add a new tag `milestone-2`.
54 |
55 | ## Self evaluation
56 |
57 | Now that you have started a repository, created commits in multiple branches, and merged these branches, here are some questions for you to consider:
58 |
59 | - Have you committed the generated data file and/or the plot figure?
60 |
61 | - If you haven't committed either or both of these files, have you instructed `git` to ignore them?
62 |
63 | - Did you add a meaningful description to each milestone tag?
64 |
65 | - How many commits modified your data-generation script?
66 |
67 | - How many commits modified your plotting script?
68 |
69 | - What changes, if any, were made to `README.md` since it was first created?
70 |
71 | !!! tip
72 |
73 | To answer some of these questions, you may need to run `git` commands.
74 |
--------------------------------------------------------------------------------
/docs/guides/using-git/exercise-resolve-a-merge-conflict.md:
--------------------------------------------------------------------------------
1 | # Exercise: resolve a merge conflict
2 |
3 | We have created a [public repository](https://github.com/robmoss/gimlb-simple-merge-example) that you can use to try resolving a merge conflict yourself.
4 | This repository includes some example data and a script that performs some basic data analysis.
5 |
6 | First, obtain a local copy (a "clone") of this repository by running:
7 |
8 | ```sh
9 | git clone https://github.com/robmoss/gimlb-simple-merge-example.git
10 | cd gimlb-simple-merge-example
11 | ```
12 |
13 | ## The repository history
14 |
15 | You can inspect the repository history by running `git log`.
16 | Some key details to notice are:
17 |
18 | 1. The first commit created the following files:
19 | - `README.md`
20 | - `LICENSE`
21 | - `analysis/initial_exploration.R`
22 | - `input_data/data.csv`
23 |
24 | 2. The second commit created the following file:
25 | - `outputs/summary.csv`
26 |
27 | This commit has been given the **tag** `first_milestone`.
28 |
29 | 3. From this `first_milestone` tag, two branches were created:
30 |
31 | - The `feature/second-data-set` branch adds a second data set and updates the analysis script to inspect both data sets.
32 |
33 | - The `feature/calculate-rate-of-change` branch changes which summary statistics are calculated for the original data set.
34 |
35 | 4. The `example-solution` branch merges both feature branches and resolves any merge conflicts.
36 | This branch has been given the **tag** `second_milestone`.
37 |
38 | ## Your task
39 |
40 | You will start with the `master` branch, which contains the commits up to the `first_milestone` tag, and then merge the two feature branches into this branch, resolving any merge conflicts that arise.
41 | You can then compare your results to the `example-solution` branch.
42 |
43 | 1. Obtain a local copy of this repository, by running:
44 |
45 | ```sh
46 | git clone https://github.com/robmoss/gimlb-simple-merge-example.git
47 | cd gimlb-simple-merge-example
48 | ```
49 |
50 | 2. Create local copies of the two feature branches and the example solution, by running:
51 |
52 | ```sh
53 | git checkout feature/second-data-set
54 | git checkout feature/calculate-rate-of-change
55 | git checkout example-solution
56 | ```
57 |
58 | 3. Return to the `master` branch, by running:
59 |
60 | ```sh
61 | git checkout master
62 | ```
63 |
64 | 4. Merge the `feature/second-data-set` branch into `master`, by running:
65 |
66 | ```sh
67 | git merge feature/second-data-set
68 | ```
69 |
70 | 5. Merge the `feature/calculate-rate-of-change` branch into `master`, by running:
71 |
72 | ```sh
73 | git merge feature/calculate-rate-of-change
74 | ```
75 |
76 | This will result in a **merge conflict**, and now you need to decide how to resolve each conflict!
77 | Once you have resolved the conflicts, create a commit that records all of your changes (see the [previous chapter](how-to-resolve-merge-conflicts.md) for an example).
78 |
79 | !!! tip
80 |
81 | You may find it helpful to inspect the commits in each of the feature branches to understand how they have changed the files in which the conflicts have occurred.
82 |
83 | ## Self evaluation
84 |
85 | Once you have created a commit that resolves these conflicts, see how similar or different the contents of your commit are to the corresponding commit in the `example-solution` branch (which has been tagged `second_milestone`).
86 | You can inspect this commit by running:
87 |
88 | ```sh
89 | git show example-solution
90 | ```
91 |
92 | You can compare this commit to your solution by running:
93 |
94 | ```sh
95 | git diff example-solution
96 | ```
97 |
98 | How does your resolution compare to this commit?
99 |
100 | !!! note
101 |
102 | You may have resolved the conflicts differently to the `example-solution` branch, **and that's perfectly fine** as long as they have the same effect.
103 |
104 | ## Example solution
105 |
106 | Here we present a recorded terminal session in which we clone this repository and resolve the merge conflict.
107 |
108 | !!! tip
109 |
110 | You can use the video timeline (below) to jump to specific moments in this exercise.
111 | Remember that you can pause the recording at any point to **select and copy** any of the text.
112 |
113 | === "Resolving a merge conflict"
114 |
115 |
116 |
117 | Video timeline:
118 |
119 | 1. Start: a quick look around
120 | 2. Create local copies of branches
121 | 3. Inspect the feature/second-data-set branch
122 | 4. Inspect the feature/calculate-rate-of-change branch
123 | 5. Merge the feature/second-data-set branch
124 | 6. Merge the feature/calculate-rate-of-change branch
125 | 7. Resolve the merge conflicts
126 | 8. Compare to the example solution
127 |
--------------------------------------------------------------------------------
/docs/guides/using-git/exercise-use-a-remote-repository.md:
--------------------------------------------------------------------------------
1 | # Exercise: use a remote repository
2 |
3 | In this exercise, you will use a remote repository to synchronise and merge changes between multiple local repositories, starting from the local `git-exercise` repository that you created in [the previous exercise](exercise-create-a-local-repository.md).
4 |
5 | ## Create a remote repository
6 |
7 | 1. Create a new remote repository on a platform such as GitHub.
8 | You can make this a **private** repository, because you won't need to share it with anyone.
9 |
10 | 2. Link your local `git-exercise` repository to this remote repository, and push all branches and tags to this remote repository.
11 |
12 | ## Clone the remote repository
13 |
14 | 1. Make a local copy of this remote repository called `git-exercise-2`.
15 |
16 | 2. Check out the `main` or `master` branch.
17 | The files should be identical to the `milestone-2` tag in your original `git-exercise` repository.
18 |
19 | ## Work on the new local repository
20 |
21 | 1. Create a new branch called `feature/report`.
22 | Check out this branch and create a new file called `report.md`.
23 | Edit this file so that it contains:
24 |
25 | - A brief description of the generated data set;
26 | - A table of the summary statistics printed by the plotting scripting (see the [Markdown Guide](https://www.markdownguide.org/extended-syntax/#tables)); and
27 | - The figure produced by the plotting script (see the [Markdown Guide](https://www.markdownguide.org/basic-syntax/#images-1)).
28 |
29 | Record your changes in a new commit.
30 |
31 | 2. Push this new branch to the remote repository.
32 |
33 | ## Merge the report into the original repository
34 |
35 | 1. In your original `git-exercise` repository, checkout the `feature/report` branch from the remote repository and verify that it now contains the file `report.md`.
36 |
37 | 2. Merge this branch into your `main` or `master` branch, and add a new tag `milestone-3-report`.
38 |
39 | 3. Push the updated `main` or `master` branch to the remote repository.
40 |
41 | ## Update the new local repository
42 |
43 | 1. In your `git-exercise-2` repository, checkout the `main` or `master` branch and pull changes from the remote repository.
44 | It should now contain the file `report.md`.
45 |
46 | !!! info
47 |
48 | Congratulations!
49 | You have used a remote repository to synchronise and merge changes between two local repositories.
50 | You can use this workflow to [collaborate with colleagues](../collaborating/README.md).
51 |
52 | ## Self evaluation
53 |
54 | Now that you have used commits and branches to share work between multiple repositories, here are some questions for you to consider:
55 |
56 | - Do you feel comfortable in deciding which changes to record in a single commit?
57 |
58 | - Do you feel that your commit messages help describe the changes that you have made in this repository?
59 |
60 | - Do you feel comfortable in using multiple branches to work on separate ideas in parallel?
61 |
62 | - Do you have any current projects that you might want to work on using local and remote `git` repositories?
63 |
--------------------------------------------------------------------------------
/docs/guides/using-git/first-time-git-setup.md:
--------------------------------------------------------------------------------
1 | # First-time Git setup
2 |
3 | Once you've installed Git, you should define some important settings before you starting using Git.
4 |
5 | !!! info
6 |
7 | We assume that you will want to set the git configuration for all repositories owned by your user.
8 | Therefore, we use the `--global` flag.
9 | Configuration files can be set for a single repository or the whole computer by replacing `--global` with `--local` or `--system` respectively.
10 |
11 | 1. Define your user name and email address.
12 | These details are included in **every commit that you create**.
13 |
14 | ```sh
15 | git config --global user.name "My Name"
16 | git config --global user.email "my.name@some-university.edu.au"
17 | ```
18 | 2. Define the text editor that Git should use for tasks such as writing commit messages:
19 |
20 | ```sh
21 | git config --global core.editor editor-name
22 | ```
23 |
24 | **NOTE:** on Windows you need to specify the full path to the editor:
25 |
26 | ```sh
27 | git config --global core.editor "C:/Program Files/My Editor/editor.exe"
28 | ```
29 |
30 | !!! tip
31 |
32 | Please see [Choosing your Git editor](choosing-your-git-editor.md) for details.
33 |
34 | 3. By default, Git will create a branch called `master` when you create a new repository.
35 | You can set a different name for this initial branch:
36 |
37 | ```sh
38 | git config --global init.defaultBranch main
39 | ```
40 |
41 | 4. Ensure that repository histories always record when branches were merged:
42 |
43 | ```sh
44 | git config --global merge.ff no
45 | ```
46 |
47 | This prevents Git from ["fast-forwarding"](https://www.atlassian.com/git/tutorials/using-branches/git-merge) when the destination branch contains no new commits.
48 | For example, it ensures that when you merge the green branch into the blue branch (as shown below) it records that commits *D*, *E*, and *F* came from the green branch.
49 |
50 | 
51 |
52 | 5. Adjust how Git shows merge conflicts:
53 |
54 | ```sh
55 | git config --global merge.conflictstyle diff3
56 | ```
57 |
58 | This will be useful when we look at [how to use branches](how-to-use-branches.md) and [how to resolve merge conflicts](how-to-resolve-merge-conflicts.md).
59 |
60 | !!! info
61 |
62 | If you use Windows, there are tools that can [improve your Git experience in PowerShell](https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-PowerShell).
63 |
64 | There are also tools for integrating Git into many common text editors.
65 | See *Git in other environments*, Appendix A of the [Pro Git book](https://git-scm.com/book/en/v2).
66 |
--------------------------------------------------------------------------------
/docs/guides/using-git/graphical-git-clients.md:
--------------------------------------------------------------------------------
1 | # Graphical Git clients
2 |
3 | In this book we will primarily show how to use Git **from the command-line**.
4 | If you don't have Git already installed on your computer, see these [instructions for installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
5 |
6 | In addition to using the command-line, there are other ways to work with Git repositories:
7 |
8 | - There are many [graphical clients](https://git-scm.com/downloads/guis) that you can download and use;
9 |
10 | - Many editors include **built-in** Git support (e.g., [Atom](https://atom.io/), [RStudio](https://www.rstudio.com/), [Visual Studio Code](https://code.visualstudio.com/)); and
11 |
12 | - Online platforms such as [GitHub](https://github.com/), [GitLab](https://gitlab.com/public), and [Bitbucket](https://bitbucket.org/) also provide a graphical interface for common Git actions.
13 |
14 | All of the concepts and terminology you will learn in this book should also apply to all of the tools listed above.
15 |
--------------------------------------------------------------------------------
/docs/guides/using-git/how-to-create-and-use-tags.md:
--------------------------------------------------------------------------------
1 | # How to create and use tags
2 |
3 | Tags allow you to [bookmark](../version-control/what-is-a-tag.md) important points in your commit history.
4 |
5 | You can use tags to identify milestones such as:
6 |
7 | - Adding specific features to your model or data analysis (e.g., `feature-age-dependent-mixing`);
8 | - Completing objectives in your research plan (e.g., `objective-1`, `objective-2`);
9 | - Completed manuscript drafts (e.g., `draft-1`, `draft-2`); and
10 | - Manuscript submission and revisions (e.g., `submitted`, `revision-1`).
11 |
12 | ## Tagging the current commit
13 |
14 | You can add a tag (in this example, "my-tag") to the current commit by running:
15 |
16 | ```sh
17 | git tag -a my-tag
18 | ```
19 |
20 | This will open your [chosen editor](first-time-git-setup.md) and ask you to write a description for this tag.
21 |
22 | ## Pushing tags to a remote repository
23 |
24 | By default, `git push` **doesn't push tags to remote repositories**.
25 | Instead, you have to explicitly push tags.
26 | You can push a tag (in this example, called "my-tag") to a remote repository (in this example, called "origin") by running:
27 |
28 | ```sh
29 | git push origin my-tag
30 | ```
31 |
32 | You can push all of your tags to a remote repository (in this example, called "origin") by running:
33 |
34 | ```sh
35 | git push origin --tags
36 | ```
37 |
38 | ## Tagging a past commit
39 |
40 | To add a tag to a previous commit, you can identify the commit by its hash.
41 | For example, you can inspect your commit history by running:
42 |
43 | ```sh
44 | git log --oneline --no-decorate
45 | ```
46 |
47 | If your commit history looks like:
48 |
49 | ```text
50 | 003cf6b Show how to ignore certain files
51 | 339eb5a Show how to prepare and record commits
52 | 6a7fb8b Show how to clone remote repositories
53 | ...
54 | ```
55 | where the current commit is `003cf6b` ("Show how to ignore certain files"), you can tag the previous commit ("Show how to prepare and record commits") by running:
56 |
57 | ```sh
58 | git tag -a my-tag 339eb5a
59 | ```
60 |
61 | ## Listing tags
62 |
63 | You can list all tags by running:
64 |
65 | ```sh
66 | git tag
67 | ```
68 |
69 | You can also list only tags that match a specific pattern (in this example, all tags beginning with "my") by running:
70 |
71 | ```sh
72 | git tag --list 'my*'
73 | ```
74 |
75 | ## Deleting tags
76 |
77 | You can delete a tag by running:
78 |
79 | ```sh
80 | git tag --delete my-tag
81 | ```
82 |
83 | ## Creating a branch from a tag
84 |
85 | You can check out a tag and begin working on a new branch by running:
86 |
87 | ```sh
88 | git checkout -b my-branch my-tag
89 | ```
90 |
--------------------------------------------------------------------------------
/docs/guides/using-git/how-to-ignore-certain-files.md:
--------------------------------------------------------------------------------
1 | # How to ignore certain files
2 |
3 | Your repository may contain files that you don't want to include in your commit history.
4 | For example, you may not want to include files of the following types:
5 |
6 | + **Sensitive data files** for which access must be strictly controlled.
7 | + **Temporary files** that do not contain useful information, such as:
8 | + `.aux` files, which are generated when compiling LaTeX documents; and
9 | + `.pyc` files, which are generated when running Python code.
10 | + **Files that can be automatically generated** from your commit history, such as:
11 | + `.pdf` versions of LaTeX documents; and
12 | + documentation generated from your code files.
13 |
14 | You can instruct Git to ignore certain files by creating a `.gitignore` file.
15 | This is a plain text file, where each line defines a pattern that identifies files and directories which should be ignored.
16 | You can also add comments, which must start with a `#`, to explain the purpose of these patterns.
17 |
18 | !!! tip
19 |
20 | If your editor will not accept `.gitignore` as a file name, you can create a `.gitignore` file in your repository by running:
21 |
22 | ```sh
23 | touch .gitignore
24 | ```
25 |
26 | For example, the following `.gitignore` file would make Git ignore all `.aux` and `.pyc` files, and the file `my-paper.pdf`:
27 |
28 | ```text
29 | # Ignore all .aux files generated by LaTeX.
30 | *.aux
31 | # Ignore all byte-code files generated by Python.
32 | *.pyc
33 | # Ignore the PDF version of my paper.
34 | my-paper.pdf
35 | ```
36 |
37 | If you have **sensitive data files**, one option is to store them all in a dedicated directory and add this directory to your `.gitignore` file:
38 |
39 | ```text
40 | # Ignore all data files in the "sensitive-data" directory.
41 | sensitive-data
42 | ```
43 |
44 | !!! tip
45 |
46 | You **can** force Git to add an ignored file to a commit by running:
47 |
48 | ```sh
49 | git add --force my-paper.pdf
50 | ```
51 |
52 | But it would generally be better to update your `.gitignore` file so that it stops ignoring these files.
53 |
--------------------------------------------------------------------------------
/docs/guides/using-git/how-to-resolve-merge-conflicts.md:
--------------------------------------------------------------------------------
1 | # How to resolve merge conflicts?
2 |
3 | A merge conflict can occur when we try to merge one branch into another, if the two branches introduce any conflicting changes.
4 |
5 | For example, consider trying to merge two branches that make the following changes to the same line of the file `test.txt`:
6 |
7 | 1. On the branch `my-new-branch`:
8 |
9 | ```diff
10 | First line
11 | -Second line
12 | +My new second line
13 | Third line
14 | ```
15 |
16 | 2. On the main branch:
17 |
18 | ```diff
19 | First line
20 | -Second line
21 | +A different second line
22 | Third line
23 | ```
24 |
25 | When we attempt to merge `my-new-branch` into the main branch, `git merge my-new-branch` will tell us:
26 |
27 | ```text
28 | Auto-merging test.txt
29 | CONFLICT (content): Merge conflict in test.txt
30 | Automatic merge failed; fix conflicts and then commit the result.
31 | ```
32 |
33 | The `test.txt` file will now include the conflicting changes, which we can inspect with `git diff`:
34 |
35 | ```diff
36 | diff --cc test.txt
37 | index 18712c4,bc576a6..0000000
38 | --- a/test.txt
39 | +++ b/test.txt
40 | @@@ -1,3 -1,3 +1,7 @@@
41 | First line
42 | ++<<<<<<< ours
43 | +A different second line
44 | ++=======
45 | + My new second line
46 | ++>>>>>>> theirs
47 | Third line
48 | ```
49 |
50 | Note that this two-day diff shows:
51 |
52 | 1. "our" changes: from the commits on the branch that we are **merging into**; and
53 | 2. "their" changes: from the commits on the branch that we are **merging from**.
54 |
55 | Each conflict is surrounded by `<<<<<<<` and `>>>>>>>` markers, and the conflicting changes are separated by a `=======` marker.
56 |
57 | If we instruct Git to use a three-way diff (see [first-time Git setup](first-time-git-setup.md)), the conflict will be reported slightly differently:
58 |
59 | ```diff
60 | diff --cc test.txt
61 | index 18712c4,bc576a6..0000000
62 | --- a/test.txt
63 | +++ b/test.txt
64 | @@@ -1,3 -1,3 +1,7 @@@
65 | First line
66 | ++<<<<<<< ours
67 | +A different second line
68 | ++||||||| base
69 | ++Second line
70 | ++=======
71 | + My new second line
72 | ++>>>>>>> theirs
73 | Third line
74 | ```
75 |
76 | In addition to showing "our" changes and "their changes", this three-way diff also shows the **original lines**, between the `|||||||` and `=======` markers.
77 | This extra information can help you decide how to best resolve the conflict.
78 |
79 | ## Resolving the conflicts
80 |
81 | We can edit `test.txt` to reconcile these changes, and the commit our fix.
82 | For example, we might decide that `test.txt` should have the following contents:
83 |
84 | ```text
85 | First line
86 | The corrected second line
87 | Third line
88 | ```
89 |
90 | We can then commit these changes to resolve the merge conflict:
91 |
92 | ```sh
93 | git add test.txt
94 | git commit -m "Resolved the merge conflict"
95 | ```
96 |
97 | ## Cancelling the merge
98 |
99 | Alternatively, you may decide you don't want to merge these two branches, in which case you cancel the merge by running:
100 |
101 | ```sh
102 | git merge --abort
103 | ```
104 |
--------------------------------------------------------------------------------
/docs/guides/using-git/how-to-structure-a-repository.md:
--------------------------------------------------------------------------------
1 | # How to structure a repository
2 |
3 | While there is no single "best" way to structure a repository, there are some guidelines that you can follow.
4 | The key aims are to ensure that your files are logically organised, and that others can easily navigate the repository.
5 |
6 | ## Divide your repository into multiple directories
7 |
8 | It is generally a good idea to have separate directories for different types of files.
9 | For example, your repository might contain any of these different file types, and you should at least consider storing each of them in a separate directory:
10 |
11 | - Input data files (which you may have received from a collaborator);
12 | - Cleaned and/or processed input files (e.g., if you aggregate the input data before using it);
13 | - Data analysis code;
14 | - Simulation/model code;
15 | - Output data files;
16 | - Plotting scripts that extract results from the output data files;
17 | - Output figures produced by the plotting scripts; and
18 | - Manuscript text and bibliography files.
19 |
20 | ## Use descriptive names for directories and files
21 |
22 | Choosing file names that indicate what each file/directory contains can help other people, such as your collaborators, navigate your repository.
23 | They can also **help you** when you return to a project after several weeks or months.
24 |
25 | !!! tip
26 |
27 | Have you ever asked yourself "where is the file that contains X"?
28 |
29 | Use descriptive file names, and the answer might be right in front of you!
30 |
31 | ## Include a `README` file
32 |
33 | You can write this in Markdown (`README.md`), in plain text (`README` or `README.txt`), or in any other suitable format.
34 | For example, Python projects often use reStructuredText and have a `README.rst` file.
35 |
36 | This file should begin with a brief description of **why** the repository was created and **what** it contains.
37 |
38 | Importantly, this file should also mention:
39 |
40 | - How the files and directories are arranged.
41 | Help your collaborators understand where they need to look in order to find something.
42 |
43 | - How to run important pieces of code (e.g., to generate output data files or figures).
44 |
45 | - The software packages and/or libraries that are required run any of the code in this repository.
46 |
47 | - The [license](choosing-a-license.md) (if any) under which the repository contents are being made available.
48 |
--------------------------------------------------------------------------------
/docs/guides/using-git/how-to-use-branches.md:
--------------------------------------------------------------------------------
1 | # How to use branches?
2 |
3 | Recall that [branches](../version-control/what-is-a-branch.md) allow you to work on different ideas or tasks in parallel, within a single repository.
4 | In this chapter, we will show you how create and use branches.
5 | In the [Collaborating](../collaborating/README.md) section, we will show you how branches can allow multiple people to work together on code and papers, and how you can use branches for **peer code review**.
6 |
7 | !!! info
8 |
9 | Branches, like [tags](how-to-create-and-use-tags.md), are identified by name.
10 | Common naming conventions include:
11 |
12 | + `feature/some-new-thing` for adding something new (a new data analysis, a new model feature, etc); and
13 | + `bugfix/some-problem` for fixing something that isn't working as intended (e.g., perhaps there's a mistake in a data analysis script).
14 |
15 | You can choose your own conventions, but make sure that you choose **meaningful** names.
16 |
17 | **Do not** use names like `branch1`, `branch2`, etc.
18 |
19 | ## Creating a new branch
20 |
21 | You can create a new branch (in this example, called "my-new-branch") that starts from the current commit by running:
22 |
23 | ```sh
24 | git checkout -b my-new-branch
25 | ```
26 |
27 | You can also create a new branch that starts from a specific commit, tag, or branch in your repository:
28 |
29 | ```sh
30 | git checkout -b my-new-branch 95eaae5 # From an existing commit
31 | git checkout -b my-new-branch my-tag-name # From an existing tag
32 | git checkout -b my-new-branch my-other-branch # From an existing branch
33 | ```
34 |
35 | You can then create a corresponding **upstream branch** in your remote repository (in this example, called "origin") by running:
36 |
37 | ```sh
38 | git push -u origin my-new-branch
39 | ```
40 |
41 | ## Working on a remote branch
42 |
43 | If there is a branch in your remote repository that you want to work on, you can make a local copy by running:
44 |
45 | ```sh
46 | git checkout remote-branch-name
47 | ```
48 |
49 | This will create a local branch with the same name (in this example, "remote-branch-name").
50 |
51 | ## Listing branches
52 |
53 | You can list all of the branches in your repository by running:
54 |
55 | ```sh
56 | git branch
57 | ```
58 |
59 | This will also highlight the current branch.
60 |
61 | ## Switching between branches
62 |
63 | You can switch from your current branch to another branch (in this example, called "other-branch") by running:
64 |
65 | ```sh
66 | git checkout other-branch
67 | ```
68 |
69 | !!! info
70 |
71 | Git will not let you switch branches if you have any uncommitted changes.
72 |
73 | One way to avoid this issue is to record the current changes as a new commit, and explain in the commit message that this is a snapshot of work in progress.
74 |
75 | A second option is to discard the uncommitted changes to each file by running:
76 |
77 | ```sh
78 | git restore file1 file2 file3 ... fileN
79 | ```
80 |
81 | ## Pushing and pulling commits
82 |
83 | Once you have created a branch, you can use `git push` to "push" your commits to the remote repository, and `git pull` to "pull" commits from the remote repository.
84 | See [Pushing and pulling commits](pushing-and-pulling-commits.md) for details.
85 |
86 | ## Inspecting branch histories
87 |
88 | You can use `git log` to inspect the commit history of any branch:
89 |
90 | ```sh
91 | git log branch-name
92 | ```
93 |
94 | Remember that there are [many ways to control](inspecting-your-history.md) what `git log` will show you.
95 |
96 | Similarly, you can use `git diff` to compare the changes in any two branches:
97 |
98 | ```sh
99 | git diff first-branch second-branch
100 | ```
101 |
102 | Again, there are [ways to control](inspecting-your-history.md) what `git diff` will show you.
103 |
104 | ## Merging branches
105 |
106 | You may reach a point where you want to incorporate the changes from one branch into another branch.
107 | This is referred to as "merging" one branch into another, and is illustrated in the [What is a branch?](../version-control/what-is-a-branch.md) chapter.
108 |
109 | For example, you might have completed a new feature for your model or data analysis, and now want to merge this back into your main branch.
110 |
111 | First, **ensure that the current branch** is the branch you want to merge the changes **into** (this is often your main or master branch).
112 | You can them merge the changes **from** another branch (in this example, called "other-branch") by running:
113 |
114 | ```sh
115 | git merge other-branch
116 | ```
117 |
118 | This can have two different results:
119 |
120 | 1. The commits from `other-branch` were merged successfully into the current branch; or
121 |
122 | 2. There were **conflicting changes** (referred to as a "merge conflict").
123 |
124 | In the next chapter we will show you [how to resolve merge conflicts](how-to-resolve-merge-conflicts.md).
125 |
--------------------------------------------------------------------------------
/docs/guides/using-git/pushing-and-pulling-commits.md:
--------------------------------------------------------------------------------
1 | # Pushing and pulling commits
2 |
3 | In general, we "push" commits from our local repository to a remote repository by running:
4 |
5 | ```sh
6 | git push
7 | ```
8 |
9 | and "pull" commits from a remote repository into our local repository by running:
10 |
11 | ```sh
12 | git pull
13 | ```
14 |
15 | where `` is either a URL **or** the name of a [remote repository](creating-a-remote-repository.md).
16 |
17 | However, we generally want to push to, and pull from, the same remote repository every time.
18 | See the next section for an example of linking the main branch in your local repository with a corresponding "upstream" branch in your remote repository.
19 |
20 | ## Pushing your first commit to a remote repository
21 |
22 | In order to push commits from your local repository to a [remote repository](creating-a-remote-repository.md), we need to create a branch in the remote repository that corresponds to the main branch of our local repository.
23 | This requires that you have **created at least one commit** in your local repository.
24 |
25 | !!! tip
26 |
27 | This is a good time to create a `README.md` file and write a brief description of what this repository will contain.
28 |
29 | Once you have at least one commit in your local repository, you can create a corresponding **upstream branch** in the remote repository with the following command:
30 |
31 | ```sh
32 | git push -u origin
33 | ```
34 |
35 | The default branch will probably be called `"main"` or `"master"`, depending on your [Git settings](first-time-git-setup.md).
36 | You can identify the branch name by running:
37 |
38 | ```sh
39 | git branch
40 | ```
41 |
42 | !!! note
43 |
44 | Recall that we identify remote repositories by name.
45 | In this example, the remote repository is call "origin".
46 | You can choose a different name when [linking your local and remote repositories](creating-a-remote-repository.md#linking-your-local-and-remote-repositories).
47 |
48 | Once you have defined the **upstream branch**, you can push commits by running:
49 |
50 | ```sh
51 | git push
52 | ```
53 |
54 | and pull commits by running:
55 |
56 | ```sh
57 | git pull
58 | ```
59 |
60 | without having to specify the remote repository or branch name.
61 |
62 | ## Forcing updates to a remote repository
63 |
64 | By default, Git will refuse to push commits from a local branch to a remote branch if the remote branch contains any commits that are not in your local branch.
65 | This situation **should not arise** in general, and typically indicates that either someone else has pushed new commits to the remote branch (see the [Collaborating](../collaborating/README.md) section) or that you have altered the history of your local branch.
66 |
67 | If you are **absolutely confident** that your local history of commits should replace the contents of the remote branch, you can force this update by running:
68 |
69 | ```sh
70 | git push --force
71 | ```
72 |
73 | !!! tip
74 |
75 | Unless you are confident that you understand **why** this situation has occurred, it is probably a good idea to ask for advice before running the above command.
76 |
--------------------------------------------------------------------------------
/docs/guides/using-git/where-did-this-line-come-from.md:
--------------------------------------------------------------------------------
1 | # Where did this line come from?
2 |
3 | Consider the [What should I commit?](../version-control/what-should-I-commit.md) chapter.
4 | Imagine that we want to know when **and why** the following text was added:
5 |
6 | ```md
7 | A helpful guideline is "**commit early, commit often**".
8 | ```
9 |
10 | If we can identify the relevant commit, we can then inspect the commit (using `git show `) to see all of the changes that it introduced.
11 | Ideally, the commit message will explain the reasons why this commit was made.
12 | This is one way in which **your commit messages can act as a lab book**.
13 |
14 | At the time of writing (commit `2a96324`), the contents of the [What should I commit?](../version-control/what-should-I-commit.md) came from two commits:
15 |
16 | ```sh
17 | git log --oneline src/version-control/what-should-I-commit.md
18 | ```
19 |
20 | ```txt
21 | 3dfff1f Add notes about committing early and often
22 | 9be780b Briefly describe key version control concepts
23 | ```
24 |
25 | We can use the `git blame` command to identify the commit that last modified each line in this file:
26 |
27 | ```sh
28 | git blame -s src/version-control/what-should-I-commit.md
29 | ```
30 |
31 | ```txt
32 | 9be780b8 1) # What should I commit?
33 | 9be780b8 2)
34 | 9be780b8 3) A commit should represent a **unit of work**.
35 | 9be780b8 4)
36 | 9be780b8 5) If you've made changes that represent multiple units of work (e.g., changing how input data are processed, and adding a new model parameter) these should be saved as separate commits.
37 | 9be780b8 6)
38 | 9be780b8 7) Try describing out loud the changes you have made, and if you find yourself saying something like "I did X and Y and Z", then the changes should probably divided into multiple commits.
39 | 3dfff1fe 8)
40 | 3dfff1fe 9) A helpful guideline is "**commit early, commit often**".
41 | 3dfff1fe 10)
42 | 3dfff1fe 11) ## Commit early
43 | 3dfff1fe 12)
44 | 3dfff1fe 13) - Don't delay creating a commit because "it's not ready yet".
45 | 3dfff1fe 14)
46 | 3dfff1fe 15) - A commit doesn't have to be "perfect".
47 | 3dfff1fe 16)
48 | 3dfff1fe 17) ## Commit often
49 | 3dfff1fe 18)
50 | 3dfff1fe 19) - Small, focused commits are **extremely helpful** when trying to identify the cause of an unintended change in your code's behaviour or output.
51 | 3dfff1fe 20)
52 | 3dfff1fe 21) - There is no such thing as too many commits.
53 | ```
54 |
55 | You can see that the first seven lines were last modified by commit `9be780b` (*Briefly describe key version control concepts*), while the rest of the file was last modified by commit `3dfff1f` (*Add notes about committing early and often*).
56 | So the text that we're interested in (line 9) was **introduced by commit `3dfff1f`**.
57 |
58 | You can inspect this commit by running the following command:
59 |
60 | ```sh
61 | git show 3dfff1f
62 | ```
63 |
64 | === "Video demonstration"
65 |
66 |
67 |
--------------------------------------------------------------------------------
/docs/guides/using-git/where-did-this-problem-come-from.md:
--------------------------------------------------------------------------------
1 | # Where did this problem come from?
2 |
3 | Let's find the commit that created the file `src/version-control/what-is-a-repository.md`.
4 | We could find this out using `git log`, but the point here is to illustrate how to use a script to **find the commit that causes any arbitrary change** to our repository.
5 |
6 | Once the commit has been found, you can inspect it (using `git show `) to see all of the changes this commit introduced **and** the commit message that (hopefully) explains the reasons why this commit was made.
7 | This is one way in which **your commit messages can act as a lab book**.
8 |
9 | 1. Create a Python script called `my_test.py` with the following contents:
10 |
11 | ```py
12 | #!/usr/bin/env python3
13 | from pathlib import Path
14 | import sys
15 |
16 | expected_file = Path('src') / 'version-control' / 'what-is-a-repository.md'
17 |
18 | if expected_file.exists():
19 | # This file is the "new" thing that we want to detect.
20 | sys.exit(1)
21 | else:
22 | # The file does not exist, this commit is "old".
23 | sys.exit(0)
24 | ```
25 |
26 | For reference, here is an equivalent R script:
27 |
28 | ```R
29 | #!/usr/bin/Rscript --vanilla
30 |
31 | expected_file <- file.path('src', 'version-control', 'what-is-a-repository.md')
32 |
33 | if (file.exists(expected_file)) {
34 | # This file is the "new" thing that we want to detect.
35 | quit(status = 1)
36 | } else {
37 | # The file does not exist, this commit is "old".
38 | quit(status = 0)
39 | }
40 | ```
41 |
42 | 2. Select the commit range over which to search.
43 | We know that the file exists in the commit `3dfff1f` (*Add notes about committing early and often*), and it did not exist in the very first commit (`5a19b02`).
44 |
45 | 3. Instruct Git to start searching with the following command:
46 |
47 | ```sh
48 | git bisect start 3dfff1f 5a19b02
49 | ```
50 |
51 | Note that we specify **the newer commit first**, and then the older commit.
52 |
53 | Git will inform you about the search progress, and which commit is currently being investigated.
54 |
55 | ```txt
56 | Bisecting: 7 revisions left to test after this (roughly 3 steps)
57 | [92f1375db21dd8a35ca141365a477b963dbbf6dc] Add CC-BY-SA license text and badge
58 | ```
59 |
60 | 4. Instruct Git to use the script `my_test.py` to check each commit with the following command:
61 |
62 | ```sh
63 | git bisect run ./my_test.py
64 | ```
65 |
66 | It will continue to report the search progress and **automatically identify** the commit that we're looking for:
67 |
68 | ```txt
69 | running './my_test.py'
70 | Bisecting: 3 revisions left to test after this (roughly 2 steps)
71 | [9be780b8785d67ee191b2c0b113270059c9e0c3a] Briefly describe key version control concepts
72 | running './my_test.py'
73 | Bisecting: 1 revision left to test after this (roughly 1 step)
74 | [055906f28da146a2d012b7c1c0e4707503ed1b11] Display example commit message as plain text
75 | running './my_test.py'
76 | Bisecting: 0 revisions left to test after this (roughly 0 steps)
77 | [1251357ab5b41d511deb48cd5386cae37eec6751] Rename the "What is a repository?" source file
78 | running './my_test.py'
79 | 1251357ab5b41d511deb48cd5386cae37eec6751 is the first bad commit
80 | commit 1251357ab5b41d511deb48cd5386cae37eec6751
81 | Author: Rob Moss
82 | Date: Sun Apr 17 21:41:43 2022 +1000
83 |
84 | Rename the "What is a repository?" source file
85 |
86 | The file name was missing the word "a" and did not match the title.
87 |
88 | src/SUMMARY.md | 2 +-
89 | src/version-control/what-is-a-repository.md | 18 ++++++++++++++++++
90 | src/version-control/what-is-repository.md | 18 ------------------
91 | 3 files changed, 19 insertions(+), 19 deletions(-)
92 | create mode 100644 src/version-control/what-is-a-repository.md
93 | delete mode 100644 src/version-control/what-is-repository.md
94 | ```
95 |
96 | 5. To quit the search and return to your current commit, run the following command:
97 |
98 | ```sh
99 | git bisect reset
100 | ```
101 |
102 | 6. You can then [inspect this commit](inspecting-your-history.md) by running the following command:
103 |
104 | ```sh
105 | git show 1251357
106 | ```
107 |
--------------------------------------------------------------------------------
/docs/guides/version-control/README.md:
--------------------------------------------------------------------------------
1 | # Version control concepts
2 |
3 | This section provides a high-level introduction to the concepts that you should understand in order to make effective use of version control.
4 |
5 | !!! info
6 |
7 | Version control can turn your files into a lab book that captures the broader context of your research activities and that you can easily search and reproduce.
8 |
--------------------------------------------------------------------------------
/docs/guides/version-control/branch-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/guides/version-control/branch-1.png
--------------------------------------------------------------------------------
/docs/guides/version-control/branch-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/guides/version-control/branch-2.png
--------------------------------------------------------------------------------
/docs/guides/version-control/branch-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/guides/version-control/branch-3.png
--------------------------------------------------------------------------------
/docs/guides/version-control/exercise-using-version-control.md:
--------------------------------------------------------------------------------
1 | # Exercise: using version control
2 |
3 | In this section we have introduced version control, and outlined how it can be [useful for academic research activities](what-is-version-control.md), including:
4 |
5 | - Capturing a detailed, annotated record of your research;
6 | - Inspecting changes made between any two moments in time;
7 | - Identifying when a specific change was made; and
8 | - Sharing your research with collaborators.
9 |
10 | !!! info
11 |
12 | We'd now like you think about how version control might be useful to you and your research.
13 |
14 | Have you experienced any issues or challenges in your career where version control would have been helpful?
15 | For example:
16 |
17 | - Have you ever looked at some of your older code and had difficulty understanding what it is doing, how it works, or why it was written?
18 |
19 | - Have you ever had difficulties identifying what code and/or data were used to generate a particular analysis or output?
20 |
21 | - Have you ever discovered a bug in your code and tried to identify when it was introduced, or what outputs it might have affected?
22 |
23 | - When collaborating on a research project, have you ever had challenges in making sure that everyone was working with the most recent files?
24 |
25 | How can you use version control in your current research project(s)?
26 |
27 | - Do you have an existing project or piece of code that could benefit from being stored in a repository?
28 |
29 | - Have you recently written any code that could be recorded as one or more commits?
30 |
31 | - If so, what would you write for the commit messages?
32 |
33 | - Have you written some exploratory code or analysis that could be stored in a separate branch?
34 |
35 | Having looked at the use of version control in the past and present, how would using version control benefit you?
36 |
--------------------------------------------------------------------------------
/docs/guides/version-control/how-do-I-write-a-commit-message.md:
--------------------------------------------------------------------------------
1 | # How do I write a commit message?
2 |
3 | Commit messages are shown as part of the repository history (e.g., when running `git log`).
4 | Each message consists of a short one-line description, followed by as much or as little text as required.
5 |
6 | You should treat these messages as **entries in a log book**.
7 | Explain what changes were made and **why** they were made.
8 | This can help collaborators understand what we have done, but more importantly is acts as a record for our future selves.
9 |
10 | !!! info
11 |
12 | Have you ever looked at code you wrote a long time ago *and wondered what you were thinking?*
13 |
14 | A history of detailed commit messages should allow you to answer this question!
15 |
16 | Remember that **code is harder to read than it is to write** ([Joel Spolsky](https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/)).
17 |
18 | For example, rather than writing:
19 |
20 | > Added model
21 |
22 | You could write something like:
23 |
24 | > Implemented the initial model
25 | >
26 | > This model includes all of the core features that we need to fit the data,
27 | > but there several other features that we intend to add:
28 | >
29 | > \- Parameter X is currently constant, but we may need to allow it to vary
30 | > over time;
31 | >
32 | > \- Parameter Y should probably be a hyperparameter; and
33 | >
34 | > \- The population includes age-structured mixing, but we need to also include
35 | > age-specific outcomes, even though there is very little data to suggest
36 | > what the age effects might be.
37 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-a-branch.md:
--------------------------------------------------------------------------------
1 | # What is a branch?
2 |
3 | A branch allows you create a series of commits that are separate from the main history of your repository.
4 | They can be used for units of work that are too large to be a single commit.
5 |
6 | !!! info
7 |
8 | It is easy to switch between branches!
9 | You can work on multiple ideas or tasks in parallel.
10 |
11 | Consider a repository with three commits: commit A, followed by commit B, followed by commit C:
12 |
13 | 
14 |
15 | At this point, you might consider two ways to implement a new model feature.
16 | One way to do this is to create a separate branch for each implementation:
17 |
18 | 
19 |
20 | You can work on each branch, **and switch between them**, in the same local repository.
21 |
22 | If you decide that the first implementation (the green branch) is the best way to proceed, you can then **merge** this branch back into your main branch.
23 | This means that your main branch now contains six commits (A to F), and you can continue adding new commits to your main branch:
24 |
25 | 
26 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-a-commit.md:
--------------------------------------------------------------------------------
1 | # What is a commit?
2 |
3 | A "commit" is a set of changes to one or more files in a repository.
4 | These changes can include:
5 |
6 | - Adding lines to a file;
7 | - Removing lines from a file;
8 | - Changing lines in a file;
9 | - Adding new files; and
10 | - Deleting existing files.
11 |
12 | Each commit also includes the date and time that it was created, the user that created it, and a [commit message](how-do-I-write-a-commit-message.md).
13 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-a-merge-conflict.md:
--------------------------------------------------------------------------------
1 | # What is a merge conflict?
2 |
3 | In [What is a branch?](what-is-a-branch.md) we presented an example of successfully merging a branch into another.
4 | However, when we try to merge one branch into another, we may find that the two branches have conflicting changes.
5 | This is known as a **merge conflict**.
6 |
7 | Consider two branches that make conflicting changes to the same line of a file:
8 |
9 | 1. Replace "Second line" with "My new second line":
10 |
11 | ```diff
12 | First line
13 | -Second line
14 | +My new second line
15 | Third line
16 | ```
17 |
18 | 2. Replace "Second line" with "A different second line":
19 |
20 | ```diff
21 | First line
22 | -Second line
23 | +A different second line
24 | Third line
25 | ```
26 |
27 | There is no way to automatically reconcile these two branches, and **we have to fix this conflict manually**.
28 | This means that we need to decide what the true result should be, edit the file to resolve these conflicting changes, and commit our modifications.
29 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-a-repository.md:
--------------------------------------------------------------------------------
1 | # What is a repository?
2 |
3 | A repository records a set of files managed by a version control system, including the historical record of changes made to these files.
4 |
5 | You can create as many repositories as you want.
6 | Each repository should be a single "thing", such as a research project or a journal article, and should be located in a separate directory.
7 |
8 | You will generally have at least two copies of each repository:
9 |
10 | 1. A **local repository** on your computer; and
11 |
12 | 2. A **remote repository** on a service such as GitHub, or a University-provided platform (such as the University of Melbourne's [GitLab instance](https://gitlab.unimelb.edu.au/)).
13 |
14 | You make changes in your local repository and "push" them to the remote repository.
15 | You can share this remote repository with your collaborators and supervisors, and they will be able to see all of the changes that you have pushed.
16 |
17 | You can also allow collaborators to push their own changes to the remote repository, and then "pull" them into your local repository.
18 | This is one way in which you can use version control to work collaboratively on a project.
19 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-a-tag.md:
--------------------------------------------------------------------------------
1 | # What is a tag?
2 |
3 | A tag is a short, unique name that identifies a specific commit.
4 | You can use tags as bookmarks for interesting or important commits.
5 | Common uses of tags include:
6 |
7 | - Identifying manuscript revisions: `draft-1`, `submitted-version`, `revision-1`, etc.
8 |
9 | - Identifying software package versions: `v1.0`, `v1.1`, `v2.0`, etc.
10 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-is-version-control.md:
--------------------------------------------------------------------------------
1 | # What is version control?
2 |
3 | Version control is a way of systematically recording changes to files (such as computer code and data files).
4 | This allows you to restore any previous version of a file.
5 | More importantly, this history of changes can be queried, and each set of changes can include additional information, such as who made the changes and an explanation of why the changes were made.
6 |
7 | > A core component of making great decisions is understanding the rationale behind previous decisions.
8 | > If we don't understand how we got "here", we run the risk of making things much worse.
9 | >
10 | > — [Chesterton's Fence](https://fs.blog/chestertons-fence/)
11 |
12 | For academic research activities that involve data analysis or simulation modelling, some key uses of version control are:
13 |
14 | - You can use it as a **log book**, and capture a detailed and permanent record of every step of your research.
15 | This is extremely helpful for people — **including you!** — who want to understand and make use of your work.
16 |
17 | - You can **collaborate** with others in a systematic way, ensuring that everyone has access to the most recent files and data, and review everyone's contributions.
18 |
19 | - You can **inspect the changes** made over a period of interest (e.g., "What have I done in the last week?").
20 |
21 | - You can **identify when a specific change occurred**, and what other changes were made at the same time (e.g., "What changes did I make that affected this output figure?").
22 |
23 | In this book we will focus on the [Git](https://git-scm.com/) version control system, which is used by popular online platforms such as [GitHub](https://github.com/), [GitLab](https://gitlab.com/public), and [Bitbucket](https://bitbucket.org/).
24 |
--------------------------------------------------------------------------------
/docs/guides/version-control/what-should-I-commit.md:
--------------------------------------------------------------------------------
1 | # What should I commit?
2 |
3 | A commit should represent a **unit of work**.
4 |
5 | If you've made changes that represent multiple units of work (e.g., changing how input data are processed, and adding a new model parameter) these should be saved as separate commits.
6 |
7 | Try describing out loud the changes you have made, and if you find yourself saying something like "I did X and Y and Z", then the changes should probably divided into multiple commits.
8 |
9 | A helpful guideline is "**commit early, commit often**".
10 |
11 | ## Commit early
12 |
13 | - Don't delay creating a commit because "it's not ready yet".
14 |
15 | - A commit doesn't have to be "perfect".
16 |
17 | ## Commit often
18 |
19 | - Small, focused commits are **extremely helpful** when trying to identify the cause of an unintended change in your code's behaviour or output.
20 |
21 | - There is no such thing as too many commits.
22 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/README.md:
--------------------------------------------------------------------------------
1 | # Writing code
2 |
3 | For computational research, code is an important scientific artefact for the author, for colleagues and collaborators, and for the scientific community.
4 | It is the **ultimate form** of expressing **what you did** and **how you did it**.
5 | With good version control and documentation practices, it can also capture **when and why** you made important decisions.
6 |
7 | !!! tip
8 |
9 | [W]e want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for **expressing ideas about methodology**.
10 | Thus, programs must be **written for people to read**, and only incidentally for machines to execute.
11 |
12 | — [Structure and Interpretation of Computer Programs](https://mitpress.mit.edu/9780262510875/).
13 | Abelson, Sussman, and Sussman, 1984.
14 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/behave-nicely.md:
--------------------------------------------------------------------------------
1 | # Behave nicely
2 |
3 | Would you feel comfortable running someone else's code if you thought it might affect your other files, applications, settings, or do something else that's unexpected?
4 |
5 | !!! tip
6 |
7 | Your code should be **encapsulated:** it should assume as little as possible about the computer on which it is running, and it shouldn't mess with the user's environment.
8 |
9 | !!! tip
10 |
11 | Your code should follow the **principal of least surprise:** behave in a way that most users will expect it to behave, and not astonish or surprise them.
12 |
13 | ## A cake analogy
14 |
15 | Suppose you have two colleagues who regularly bake cakes, and you decide you'd like one of them to bake you a chocolate cake.
16 |
17 | - **A nice colleague:**
18 |
19 | - That evening, they go home and bake a cake.
20 | - They bring the cake to work the next day.
21 | - The cake tastes of chocolate.
22 |
23 | - **A messy colleague:**
24 |
25 | - They bring the ingredients and a portable oven into your office.
26 | - They make a huge mess, splattering your desk and computer.
27 | - The oven is noisy and makes the office uncomfortably warm.
28 | - The cake tastes of vanilla, not chocolate.
29 |
30 | ## Some specific tips
31 |
32 | - Avoid modifying files outside of the project directory!
33 |
34 | - Avoid using hard-coded absolute paths, such as `C:\Users\My Name\Some Project\...` or `/Users/My Name/Some other directory`.
35 | These make it harder for other people to use the code, or to run the code on high-performance computing platforms.
36 |
37 | - Prefer using paths that are relative to the root directory of your project, such as `input-data/case-data/cases-for-2023.csv`.
38 | If you're using R, the [here](https://here.r-lib.org/) package is extremely helpful.
39 |
40 | - Warn the user before running tasks that take a long time to complete.
41 |
42 | - Notify the user before downloading large files.
43 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/check-your-code.md:
--------------------------------------------------------------------------------
1 | # Check your code
2 |
3 | A "linter" is a tool that checks your code for syntax errors, possible mistakes, inconsistent formatting, and other potential issues.
4 |
5 | We **strongly recommend** using an editor that displays linter warnings as you write your code.
6 | Having instant feedback allows you to rapidly resolve many common issues and substantially improve your code.
7 |
8 | We list here some of the most commonly used linters:
9 |
10 | - **R:** [lintr](https://lintr.r-lib.org/)
11 |
12 | - **Python:** [ruff](https://docs.astral.sh/ruff/)
13 |
14 | - **Julia:** [Lint.jl](https://lintjl.readthedocs.org/en/stable/)
15 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/coding-advice.md:
--------------------------------------------------------------------------------
1 | # Coding advice
2 |
3 | - Think about how to cleanly structure your code.
4 | Take a **similar approach to how we write papers and grants**.
5 |
6 | - Break the overall problem into pieces, and then decide how to structure each piece in turn.
7 |
8 | - Divide your code into functions that each do one "thing", and group related functions into separate files or modules.
9 |
10 | - It can sometimes help to think about how you want the final code to look, and then design the functions and components that are needed.
11 |
12 | - Avoid global variables, aim to pass everything as function arguments.
13 | This makes the code more robust and easier to run.
14 |
15 | - Avoid passing lots of individual parameters as separate arguments, this is prone to error — you might not pass them in the correct order.
16 | Instead, collect the parameters into a single structure (e.g, a Python dictionary, an R named list).
17 |
18 | - Avoid making multiple copies of a model if you want to change some aspect of its behaviour.
19 | Instead, add a new model parameter that enables/disables this new behaviour.
20 | This allows you to use the same code to run the older and newer versions of the model.
21 |
22 | - Try to collect common or related tasks into a single script, and allow the user to select which task(s) to run, rather than creating many scripts that perform very similar tasks.
23 |
24 | - Write test cases to check key model properties.
25 |
26 | - You want to identify problems and mistakes as soon as possible!
27 |
28 | - Thinking about how to make your code testable can help you improve its structure!
29 |
30 | - Well-written tests can also demonstrate **how to use your code**!
31 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/cohesion-coupling.md:
--------------------------------------------------------------------------------
1 | # Cohesion and coupling
2 |
3 | **Divide your code** into modules, each of which does one thing ("high cohesion") and depends as little as possible on other pieces ("low coupling").
4 |
5 | ## Common project components
6 |
7 | For example, an infectious diseases modelling project might often be divided into some of the following components:
8 |
9 | - The model parameters — what are their values or prior distributions?
10 |
11 | - The initial model state — how is this created from the model parameters?
12 |
13 | - The model equations or update rules — how does the model evolve over time?
14 |
15 | - Summary statistics — what do you want to record for each simulation?
16 | This might be the entire state history, a subset of the history, some aggregate statistics, or any combination of these things.
17 |
18 | - The input data (if any) — these may be case data, serological data, within-host specimen counts, etc.
19 |
20 | - The relationship between data and the model state ("observation model").
21 |
22 | - Simulated data generated from a model simulation.
23 |
24 | As much as possible, each of these components (where relevant to your project) should be represented as **a separate piece of code**.
25 |
26 | ## Separating the "what" from the "how"
27 |
28 | Dividing your code into separate components is especially important if you want to use a model for multiple purposes, such as:
29 |
30 | - Exploring different scenarios;
31 | - Fitting to various data sets;
32 | - Performing sensitivity and uncertainty analyses; and
33 | - Forecasting future data.
34 |
35 | !!! tip
36 |
37 | In particular, keep the following aspects of your project separate:
38 |
39 | - **What to do:** fitting to different data sets, exploring different scenarios, performing a sensitivity analysis, etc; and
40 |
41 | - **How to do it:** the model implementation.
42 |
43 | If you want to explore a range of model scenarios, for example, define the parameter values (or sampling distributions) for each scenario in a separate input file.
44 | Then write a script that takes an input file name as an argument, reads the parameter values, and uses these values to run the model simulations.
45 |
46 | This makes it extremely simple to define and run new scenarios without modifying your code.
47 |
48 | ## Interactions between components
49 |
50 | Choosing how your components interact (e.g., by calling functions or passing data) is **just as important** as deciding how to divide your code into components.
51 |
52 | Here are some key recommendations from [Object-Oriented Software Construction (2nd ed)](https://bertrandmeyer.com/OOSC2/):
53 |
54 | - Small interfaces: if two modules communicate, they should exchange as little information as possible.
55 |
56 | - Explicit interfaces: if two modules communicate, it should be obvious from the code in one or both of these modules.
57 |
58 | - Self documentation: strive to make all information about a module part of the module itself.
59 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/create-packages.md:
--------------------------------------------------------------------------------
1 | # Create packages
2 |
3 | For languages such as R, Python, and Julia, it is generally a good idea to **write your code as a package/library**.
4 | This can make it easier to install and run your code on a new computer, on a high-performance computing platform, and for others to use on their own computers.
5 |
6 | !!! info
7 |
8 | This is **a simple process** and entirely separate from **publishing** your package or making it publicly available.
9 |
10 | It also means you can avoid using `source()` in R, or adding directories to `sys.path` in Python.
11 |
12 | To create a package you need to provide some necessary information, such as a package name, and the list of the packages that your code depends on ("dependencies").
13 | You can then use packaging tools to **verify** that you've correctly identified these dependencies and that your package can be successfully installed and used!
14 |
15 | This is an important step towards **ensuring your work is reproducible**.
16 |
17 | There are some great online resources that can help you get started.
18 | We list here some widely-recommended resources for specific languages.
19 |
20 | ## Writing R packages
21 |
22 | For [R](https://www.r-project.org/), see [R Packages (2nd ed)](https://r-pkgs.org/) and the [devtools package](https://devtools.r-lib.org/).
23 |
24 | Other useful references include:
25 |
26 | - [rOpenSci Packages: Development, Maintenance, and Peer Review](https://devguide.ropensci.org/);
27 | - [Writing an R package from scratch](https://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/) by Hilary Parker;
28 | - [How to develop good R packages](https://masalmon.eu/2017/12/11/goodrpackages/) by Maëlle Salmon;
29 | - [Making your first R package](https://tinyheero.github.io/jekyll/update/2015/07/26/making-your-first-R-package.html) by Fong Chun Chan; and
30 | - [Writing an R package from scratch](https://r-mageddon.netlify.app/post/writing-an-r-package-from-scratch/) by Tomas Westlake.
31 |
32 |
33 | !!! info
34 |
35 | rOpenSci offers [peer review of statistical software](https://stats-devguide.ropensci.org/).
36 |
37 | ## Writing Python packages
38 |
39 | The [Python Packaging User Guide](https://packaging.python.org/en/latest/) provides a tutorial on [Packaging Python Projects](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
40 |
41 | Other useful references include:
42 |
43 | - The [pyOpenSci project](https://www.pyopensci.org/) also provide a [Python Packaging Guide](https://www.pyopensci.org/python-package-guide/).
44 | This includes information about [code style, formatting, and linters](https://www.pyopensci.org/python-package-guide/package-structure-code/code-style-linting-format.html).
45 |
46 | - This [example Python project](https://gitlab.unimelb.edu.au/rgmoss/example-python-project/) demonstrates one way of structuring a Python project as a package.
47 |
48 | !!! info
49 |
50 | pyOpenSci offers [peer review of scientific software](https://www.pyopensci.org/software-peer-review/)
51 |
52 | ## Writing Julia Packages
53 |
54 | The Julia's [package manager documentation](https://pkgdocs.julialang.org/dev/) provides a guide to [Creating Packages](https://pkgdocs.julialang.org/dev/creating-packages/)
55 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/document-your-code.md:
--------------------------------------------------------------------------------
1 | # Document your code
2 |
3 | Writing clear, well-structured code, can make it easier for someone to understand what your code does.
4 | You might think that this means your code is so clear and obvious that it needs no further explanation.
5 |
6 | But this is not true!
7 | There is **always** a role for writing comments and documentation.
8 | By itself, your code cannot always explain:
9 |
10 | - **What** goal you are trying to achieve;
11 |
12 | - **How** you are achieving this goal; and
13 |
14 | - **Why** you've chosen this approach.
15 |
16 | !!! question
17 |
18 | What can you do to make your code more easily understandable?
19 |
20 | ## Naming
21 |
22 | Use good names for functions, parameters, and variables.
23 | This can be **deceptively hard**.
24 |
25 | !!! quote
26 |
27 | There are only two hard things in Computer Science: cache invalidation and naming things.
28 |
29 | — Phil Karlton
30 |
31 | ## Explaining
32 |
33 | Have you explained the **intention** of your code?
34 |
35 | !!! tip
36 |
37 | Good comments don't say **what the code does**; instead, they **explain why** the code does what it does.
38 |
39 | For each function, write a comment that explains what the function does, describes the purpose of each parameter, and describes what values the function returns (if any).
40 |
41 | ## Documenting
42 |
43 | Many programming languages support "docstrings".
44 | These are usually comments with additional structure and formatting, and can be used to automatically generate documentation:
45 |
46 | - **R:** [roxygen2](https://roxygen2.r-lib.org/)
47 |
48 | - **Python:** there are [several formats](http://web.archive.org/web/20230128071653/http://daouzli.com/blog/docstring.html)
49 |
50 | - **Julia:** [Writing Documentation](https://docs.julialang.org/en/v1/manual/documentation/)
51 |
52 | See the CodeRefinery [In-code documentation](https://coderefinery.github.io/documentation/in-code-documentation/#what-are-docstrings-and-how-can-they-be-useful) lesson for some good examples of docstrings.
53 |
54 | ## Commenting out code
55 |
56 | Avoid commenting out code.
57 | If it's no longer useful, delete it and save this as a commit!
58 | Make sure you write a helpful commit message.
59 | You can always recover the deleted code if you need it later.
60 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/exercise-seek-feedback.md:
--------------------------------------------------------------------------------
1 | # Exercise: seek feedback
2 |
3 | !!! question
4 |
5 | One goal to keep in mind is to ensure your work is **conceptually accessible**: how readily could someone else (or even yourself, after a period of absence) understand your code?
6 |
7 | - Seek feedback on some code that you are **currently writing** — before the code is "finished".
8 | You may want to refer to our [peer code review guidelines](../collaborating/peer-code-review.md) and consider [what you want to learn](how-we-learn-to-write-code.md).
9 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/format-your-code.md:
--------------------------------------------------------------------------------
1 | # Format your code
2 |
3 | !!! question
4 |
5 | Have you ever looked at someone else's code and found it hard to read because they formatted it differently to your code?
6 |
7 | Using a consistent code style can help make your code more legible and accessible to others, in much the same way that standard use of punctuation and spacing makes written text easier to read.
8 |
9 | !!! tip
10 |
11 | Good coding style is like using correct punctuation: you can manage without it, butitsuremakesthingseasiertoread.
12 |
13 | — Hadley Wickham, [the tidyverse style guide](https://style.tidyverse.org/)
14 |
15 | We **strongly recommend** using an editor that can automatically format your code whenever you save.
16 | This allows you to completely forget about formatting and focus on the content.
17 |
18 | We list here some of the most commonly used style guides and code formatters:
19 |
20 | | Language | Style guide(s) | Formatter |
21 | |----------|-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
22 | | R | [tidyverse](https://style.tidyverse.org/) | [styler](https://styler.r-lib.org/) |
23 | | Python | [PEP 8](https://peps.python.org/pep-0008/) and [The Hitchhiker's Style Guide](https://docs.python-guide.org/writing/style/) | [black](https://black.readthedocs.io/en/stable/) |
24 | | Julia | [style guide](https://docs.julialang.org/en/v1/manual/style-guide/) | [Lint.jl](https://lintjl.readthedocs.org/en/stable/) |
25 |
--------------------------------------------------------------------------------
/docs/guides/writing-code/how-we-learn-to-write-code.md:
--------------------------------------------------------------------------------
1 | # How we learn to write code
2 |
3 | !!! question
4 |
5 | How have you learned to write code?
6 | Were you given any formal training?
7 |
8 | Unless you studied Software Engineering, you may never have had any formal training.
9 | And that's okay!
10 | **Nobody writes perfect code**.
11 |
12 | There are various resources available (including this book) that can help you to improve your coding skills.
13 | But the most effective way to improve is to write code **and get feedback**.
14 |
15 | !!! tip
16 |
17 | You can practice shooting eight hours a day, but if your technique is wrong, then all you become is very good at shooting the wrong way.
18 |
19 | — Michael Jordan
20 |
21 | ## How we learn to write papers
22 |
23 | Throughout our research careers, we are continually learning and developing our ability to write scientific papers.
24 | One of the main ways that we develop this ability is to seek **feedback early and often**, by circulating drafts to co-authors, supervisors, and trusted colleagues.
25 |
26 | This feedback not only helps us improve the paper that we're currently working on, but also improves our ability to write papers in the future.
27 |
28 | We gradually learn how to express ourselves clearly at multiple levels:
29 |
30 | - Writing individual sentences that clearly convey a single thought or observation;
31 |
32 | - Constructing paragraphs that span a single topic or idea;
33 |
34 | - Structuring an entire paper so that the reader can easily navigate it.
35 |
36 | ## How we ***currently*** learn to code
37 |
38 | Many of us learn to write code as a by-product of our chosen research area, and may not have any formal computer programming training.
39 | However, while we may make our finished code available as a support material for our published papers, we don't typically show our code to our co-authors.
40 |
41 | !!! info
42 |
43 | While there are many reasons why we are reluctant to share our code, perhaps the biggest factor is a sense of shame.
44 | We may feel that our code is "bad" — too bad to share with others! — and that if we've ever made a mistake in our code, we're the only person who has ever done so.
45 |
46 | **This is simply untrue!**
47 |
48 | ## How we ***should*** learn to code
49 |
50 | We should treat writing code the same way that we treat writing papers, grant applications, and fellowship applications: **seek feedback early, and seek feedback often**.
51 |
52 | !!! question
53 |
54 | Wouldn't you prefer that the first person who looks at your code is a trusted colleague, rather than a random person who has read your paper and now wants to see how the code works?
55 |
56 | [Peer code review](../collaborating/peer-code-review.md) offers a structured way to:
57 |
58 | - Discuss and critique a person's work in a kind and supportive manner;
59 |
60 | - Praise good work;
61 |
62 | - Identify where code is well-structured and clear, and where it could be improved; and
63 |
64 | - Share relevant knowledge and expertise.
65 |
66 | Similar to writing papers, we should **seek feedback at multiple levels**:
67 |
68 | - Are individual lines of code clear and correct?
69 |
70 | - Are strongly-related lines of code grouped into functions that each do a single thing?
71 |
72 | - Are functions grouped into modules that focus on specific aspects or features?
73 |
74 | - Can the reader easily navigate the code?
75 |
--------------------------------------------------------------------------------
/docs/how-to-contribute.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | ## Add a case study
4 |
5 | If you've made use of Git in your research activities, **please let us know!**
6 | We're looking for [case studies](community/case-studies/README.md) that highlight how EMCRs are using Git.
7 | See the instructions for suggesting new content (below).
8 |
9 | ## Provide comments and feedback
10 |
11 | The easiest way to provide comments and feedback is to [create an issue](https://github.com/robmoss/git-is-my-lab-book/issues).
12 | Note that this requires a GitHub account.
13 | If you do not have a GitHub account, you can email any of the authors.
14 | Please include "Git is my lab book" in the subject line.
15 |
16 | ## Suggest modifications and new content
17 |
18 | This book is written in Markdown and is published using [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/).
19 | See the [Material for MkDocs Reference](https://squidfunk.github.io/mkdocs-material/reference/) for an overview of the supported features.
20 |
21 | You can suggest modifications and new content by:
22 |
23 | - Forking [the book repository](https://github.com/robmoss/git-is-my-lab-book);
24 |
25 | - Adding, deleting, and/or modifying book chapters in the `docs/` directory;
26 |
27 | - Recording your changes in one or more git commits; and
28 |
29 | - [Creating a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request), so that we can review your suggestions.
30 |
31 | !!! info
32 |
33 | You can also edit any page by clicking the "Edit this page" button (:material-file-edit:) in the top-right corner.
34 | This will start the process described above by forking the book repository.
35 |
36 | !!! tip
37 |
38 | When editing Markdown content, please **start each sentence on a separate line**.
39 | Also check that your text editor **removes trailing whitespace**.
40 |
41 | This ensures that each commit will contain only the modified sentences, and makes it easier to inspect the repository history.
42 |
43 | !!! tip
44 |
45 | When you add a new page, you must also **add the page to the `nav` block** in [`mkdocs.yml`](https://github.com/robmoss/git-is-my-lab-book/edit/master/mkdocs.yml).
46 |
47 | ## Adding tabbed code blocks
48 |
49 | You can display content in [multiple tabs](https://squidfunk.github.io/mkdocs-material/reference/content-tabs/) by using `===`.
50 | For example:
51 |
52 | ~~~md
53 | === "Python"
54 |
55 | ```py
56 | print("Hello world")
57 | ```
58 |
59 | === "R"
60 |
61 | ```R
62 | cat("Hello world\n")
63 | ```
64 |
65 | === "C++"
66 |
67 | ```cpp
68 | #include
69 |
70 | int main() {
71 | std::cout << "Hello World";
72 | return 0;
73 | }
74 | ```
75 |
76 | === "Shell"
77 |
78 | ```sh
79 | echo "Hello world"
80 | ```
81 |
82 | === "Rust"
83 |
84 | ```rust
85 | fn main() {
86 | println!("Hello World");
87 | }
88 | ```
89 | ~~~
90 |
91 | produces:
92 |
93 | === "Python"
94 |
95 | ```py
96 | print("Hello world")
97 | ```
98 |
99 | === "R"
100 |
101 | ```R
102 | cat("Hello world\n")
103 | ```
104 |
105 | === "C++"
106 |
107 | ```cpp
108 | #include
109 |
110 | int main() {
111 | std::cout << "Hello World";
112 | return 0;
113 | }
114 | ```
115 |
116 | === "Shell"
117 |
118 | ```sh
119 | echo "Hello world"
120 | ```
121 |
122 | === "Rust"
123 |
124 | ```rust
125 | fn main() {
126 | println!("Hello World");
127 | }
128 | ```
129 |
130 | ## Adding terminal session recordings
131 |
132 | You can use [asciinema](https://asciinema.org/) to record a terminal session, and display this recorded session with a small amount of HTML and JavaScript.
133 | For example, the following code is used to display the `where-did-this-line-come-from.cast` recording in a tab called "Video demonstration", as shown in [Where did this line come from?](guides/using-git/where-did-this-line-come-from.md) chapter:
134 |
135 | ```md
136 | === "Video demonstration"
137 |
138 |
139 | ```
140 |
141 | You can also add links that jump to specific times in the video.
142 | Each link must have:
143 |
144 | + A `data-video` attribute that identifies the video (in the example above, this is `"demo"`);
145 | + A `data-seek-to` attribute that identifies the time (in seconds) to jump to; and
146 | + A `href` attribute that is set to `"javascript:;"` (so that the link doesn't scroll the page).
147 |
148 | For example, the following code is used to display the video recording on the [Choosing your Git Editor](guides/using-git/choosing-your-git-editor.md):
149 |
150 | ```md
151 | === "Git editor example"
152 |
153 |
154 |
155 | Video timeline:
156 |
157 | 1. Overview
158 | 2. Show how to use nano
159 | 3. Show how to use vim
160 | ```
161 |
162 | You can use the [asciinema-scripted](https://github.com/robmoss/asciinema-scripted) tool to generate scripted recordings.
163 |
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmoss/git-is-my-lab-book/5473060cdf950f429cdf8e7862e44a54e864307a/docs/logo.png
--------------------------------------------------------------------------------
/docs/orientation/README.md:
--------------------------------------------------------------------------------
1 | # Orientation
2 |
3 | One of [our goals for 2024](../community/meetings/2024-02-19.md#orientation-materials) is to develop orientation materials for new students, postdocs, etc.
4 | There was broad interest in having a checklist, and example workflows for people to follow — particularly for projects that involve some form of code "hand over", to ensure that the recipients experience few problems in running the code themselves.
5 |
6 | !!! info "How to contribute"
7 |
8 | To **suggest a new topic**:
9 |
10 | * Use the search box (top of the page) and check if the topic already exists;
11 |
12 | * If the topic does not exist, submit a ["New Topic" issue](https://github.com/robmoss/git-is-my-lab-book/issues/new?labels=orientation&title=New Topic:&body=Please enter a short, descriptive title (above) and explain your idea here).
13 |
14 | To **suggest a useful resource**: submit a ["Useful Resource" issue](https://github.com/robmoss/git-is-my-lab-book/issues/new?labels=orientation&title=Useful Resource:&body=Please enter a short, descriptive title (above) and include a link to the resource here).
15 |
16 | To **provide feedback about existing content**: submit a ["Feedback" issue](https://github.com/robmoss/git-is-my-lab-book/issues/new?labels=orientation&title=Feedback:&body=Please enter a short, descriptive title (above) and provide your feedback here).
17 |
18 | To **contribute new content**:
19 |
20 | * Use the search box (top of the page) and check if similar content already exists;
21 |
22 | * If there is no similar content, please [create a fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) of [this repository](https://github.com/robmoss/git-is-my-lab-book), add your contributions, and create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
23 |
24 | * See our [How to contribute](../how-to-contribute.md) page for more details, such as formatting guidelines.
25 |
26 | Current issues for the orientation guide are [listed here](https://github.com/robmoss/git-is-my-lab-book/issues?q=is%3Aissue+is%3Aopen+label%3Aorientation).
27 |
28 | Suggested topics included:
29 |
30 | - How to set up common tools on your laptop (e.g., Python and R);
31 | - How to [define a workflow](../guides/project-structure/workflow.md) and [organise your files](../guides/using-git/how-to-structure-a-repository.md);
32 | - How to write Markdown documents (see Nick Tierney's book [RMarkdown for Scientists](https://rmd4sci.njtierney.com/));
33 | - How to [format](../guides/writing-code/format-your-code.md) and [check](../guides/writing-code/check-your-code.md) your code;
34 | - How to set up git [on your own device](../guides/using-git/README.md) and [using platforms such as GitHub](../guides/collaborating/README.md);
35 | - How to recover [old versions of files](../guides/using-git/inspecting-your-history.md);
36 | - How to make your code device-agnostic, so it can run on HPC platforms, virtual machines, and can easily be migrated to new devices; and
37 | - How to plan for reproducibility from the beginning, rather than waiting until you're preparing a publication.
38 |
39 | !!! note
40 |
41 | In addition to the topical guides, the [Useful resources](../guides/resources.md) section includes:
42 |
43 | - [A beginner's guide](../guides/resources.md#education-and-commentary-articles) to conducting reproducible research;
44 | - [A quick guide](../guides/resources.md#how-to-structure-your-project) to organising computational biology projects;
45 | - [Examples](../guides/resources.md#examples-of-making-models-publicly-available) of making models publicly available; and
46 | - [Examples](../guides/resources.md#continuous-integration-ci-examples) of using GitHub Actions for Python and for R.
47 |
--------------------------------------------------------------------------------
/figures/.gitignore:
--------------------------------------------------------------------------------
1 | *.aux
2 | *.log
3 | *.pdf
4 | *.png
5 |
--------------------------------------------------------------------------------
/figures/Makefile:
--------------------------------------------------------------------------------
1 | TEX_FILES = $(shell find . -type f -name '*.tex')
2 | PDF_FILES := $(TEX_FILES:.tex=.pdf)
3 | PNG_FILES := $(TEX_FILES:.tex=.png)
4 |
5 | TEX_CLS := tikzfig.cls
6 |
7 | TMP_EXTS := aux log
8 | TMP_FILES := $(foreach EXT,$(TMP_EXTS),$(TEX_FILES:.tex=.$(EXT)))
9 |
10 | # Convert PDFs to 150 dpi PNG images.
11 | CONVERT_FLAGS := -density 150 -quality 90
12 | # Ensure that PNG files are reproducible by excluding timestamps.
13 | CONVERT_FLAGS += -define png:exclude-chunks=date,time
14 |
15 | help:
16 | @echo ""
17 | @echo "Build figures for Git is my lab book"
18 | @echo ""
19 | @echo " make all: build all figures"
20 | @echo " make clean: remove temporary files"
21 | @echo " make distclean: remove all generated files"
22 | @echo ""
23 |
24 | all: $(PNG_FILES)
25 | @for image in $(PNG_FILES); do cp $$image ../src/$$image; done
26 |
27 | %.png: %.pdf
28 | @convert $(CONVERT_FLAGS) $< $@
29 |
30 | %.pdf: %.tex $(TEX_CLS)
31 | @xelatex -output-directory=$(shell dirname "$@") $*
32 |
33 | clean:
34 | @rm -f $(PDF_FILES) $(TMP_FILES)
35 |
36 | distclean: clean
37 | @rm -f $(PNG_FILES)
38 |
39 | .PHONY: all clean distclean
40 | .SECONDARY: $(PDF_FILES)
41 |
--------------------------------------------------------------------------------
/figures/README.md:
--------------------------------------------------------------------------------
1 | # Figures for Git is my lab book
2 |
3 | This directory contains source files for the figures in "Git is my lab book".
4 | These figures are written in LaTeX and TikZ.
5 | The `tikzfig` document class defines commands and styles for drawing diagrams that describe the state of a Git repository.
6 |
7 | These figures can be generated and copied to the book directory by running:
8 |
9 | ```sh
10 | make all
11 | ```
12 |
--------------------------------------------------------------------------------
/figures/tikzfig.cls:
--------------------------------------------------------------------------------
1 | %
2 | % A LaTeX document class for stand-alone TikZ figures.
3 | %
4 | % Version 1.0 (2022/04/15)
5 | %
6 | % Authors:
7 | % Rob Moss
8 | %
9 | % License: CC BY-SA 4.0 (http://creativecommons.org/licenses/by-sa/4.0/)
10 | %
11 |
12 | \NeedsTeXFormat{LaTeX2e}
13 | \ProvidesClass{tizkfig}[2022/04/15 Standalone TikZ figures]
14 |
15 | \LoadClass[crop,tikz]{standalone}
16 |
17 | %
18 | % TikZ libraries.
19 | %
20 |
21 | % Provides "Latex" arrow tips.
22 | \usetikzlibrary{arrows.meta}
23 |
24 | % Allows positioning relative to other nodes (e.g., "1cm of X").
25 | \usetikzlibrary{positioning}
26 |
27 | % Add support for coordinate calculations.
28 | \usetikzlibrary{calc}
29 |
30 | %
31 | % Other packages.
32 | %
33 |
34 | % Add support for using OpenType fonts.
35 | \RequirePackage{fontspec}
36 |
37 | % Define custom colours.
38 | \RequirePackage{xcolor}
39 |
40 | %
41 | % Colour palette: Tomorrow
42 | %
43 |
44 | \definecolor{background}{RGB}{255,255,255}
45 | \definecolor{background2}{RGB}{239,239,239}
46 | \definecolor{background3}{RGB}{214,214,214}
47 | \definecolor{normtext}{RGB}{77,77,76}
48 | \definecolor{comment}{RGB}{142,144,140}
49 | \definecolor{green}{RGB}{113,140,0}
50 | \definecolor{orange}{RGB}{245,135,31}
51 | \definecolor{yellow}{RGB}{234,183,0}
52 | \definecolor{red}{RGB}{200,40,41}
53 | \definecolor{blue}{RGB}{66,113,174}
54 | \definecolor{violet}{RGB}{137,89,168}
55 | \definecolor{cyan}{RGB}{62,153,159}
56 |
57 | % Also define lighter versions of each colour.
58 | \colorlet{lightgreen}{green!75!white}
59 | \colorlet{lightorange}{orange!75!white}
60 | \colorlet{lightyellow}{yellow!75!white}
61 | \colorlet{lightred}{red!75!white}
62 | \colorlet{lightblue}{blue!75!white}
63 | \colorlet{lightviolet}{violet!75!white}
64 | \colorlet{lightcyan}{cyan!75!white}
65 |
66 | %
67 | % Define custom commands and TikZ styles for git diagrams.
68 | %
69 |
70 | % A custom node style for commits:
71 | %
72 | % \node[commit] (A) {A};
73 | % \node[commit] (B) [right = 1cm of A] {B};
74 | %
75 | \tikzstyle{commit}=[
76 | circle,
77 | minimum size = 0.75cm,
78 | draw=normtext,
79 | very thick,
80 | fill=lightblue,
81 | text=black,
82 | font=\bfseries
83 | ]
84 |
85 | \tikzstyle{link}=[
86 | -,
87 | draw=normtext,
88 | ultra thick,
89 | rounded corners = 0.25cm
90 | ]
91 |
92 | % Link one commit (A) to the next commit (B) on the same branch:
93 | %
94 | % \nextcommit{A}{B}
95 | %
96 | \newcommand{\nextcommit}[2]{%
97 | \draw[link] (#1) -- (#2);%
98 | }
99 |
100 | % Link one commit (A) to a commit (B) on a different branch:
101 | %
102 | % \changebranch{A}{B}
103 | %
104 | \newcommand{\changebranch}[2]{%
105 | \draw[link] (#1) -| ($(#1)!0.5!(#2)$) |- (#2);%
106 | }
107 |
--------------------------------------------------------------------------------
/figures/version-control/branch-1.tex:
--------------------------------------------------------------------------------
1 | \documentclass{tikzfig}
2 |
3 | \begin{document}
4 |
5 | \begin{tikzpicture}
6 | \node[commit] (A) {A};
7 | \node[commit] (B) [right = 1cm of A] {B};
8 | \node[commit] (C) [right = 1cm of B] {C};
9 |
10 | \nextcommit{A}{B}
11 | \nextcommit{B}{C}
12 | \end{tikzpicture}
13 |
14 | \end{document}
15 |
--------------------------------------------------------------------------------
/figures/version-control/branch-2.tex:
--------------------------------------------------------------------------------
1 | \documentclass{tikzfig}
2 |
3 | \begin{document}
4 |
5 | \begin{tikzpicture}
6 | % Define each of the commits.
7 | \node[commit] (A) {A};
8 | \node[commit] (B) [right = 1cm of A] {B};
9 | \node[commit] (C) [right = 1cm of B] {C};
10 | \node[commit,fill=lightgreen] (D) [below right = 0.5cm and 1cm of C] {D};
11 | \node[commit,fill=lightgreen] (E) [right = 1cm of D] {E};
12 | \node[commit,fill=lightgreen] (F) [right = 1cm of E] {F};
13 | \node[commit,fill=lightorange] (G) [below right = 1.5cm and 1cm of C] {G};
14 | \node[commit,fill=lightorange] (H) [right = 1cm of G] {H};
15 |
16 | % Define the connections between the commits.
17 | \nextcommit{A}{B}
18 | \nextcommit{B}{C}
19 | \changebranch{C}{D}
20 | \nextcommit{D}{E}
21 | \nextcommit{E}{F}
22 | \changebranch{C}{G}
23 | \nextcommit{G}{H}
24 | \end{tikzpicture}
25 |
26 | \end{document}
27 |
--------------------------------------------------------------------------------
/figures/version-control/branch-3.tex:
--------------------------------------------------------------------------------
1 | \documentclass{tikzfig}
2 |
3 | \begin{document}
4 |
5 | \begin{tikzpicture}
6 | % Define each of the commits.
7 | \node[commit] (A) {A};
8 | \node[commit] (B) [right = 1cm of A] {B};
9 | \node[commit] (C) [right = 1cm of B] {C};
10 | \node[commit,fill=lightgreen] (D) [below right = 0.5cm and 1cm of C] {D};
11 | \node[commit,fill=lightgreen] (E) [right = 1cm of D] {E};
12 | \node[commit,fill=lightgreen] (F) [right = 1cm of E] {F};
13 | \node[commit,fill=lightorange] (G) [below right = 1.5cm and 1cm of C] {G};
14 | \node[commit,fill=lightorange] (H) [right = 1cm of G] {H};
15 | \node[commit] (X) [above right=0.5cm and 1cm of F] {\dots};
16 |
17 | % Define the connections between the commits.
18 | \nextcommit{A}{B}
19 | \nextcommit{B}{C}
20 | \changebranch{C}{D}
21 | \nextcommit{D}{E}
22 | \nextcommit{E}{F}
23 | \changebranch{F}{X}
24 | \changebranch{C}{G}
25 | \nextcommit{G}{H}
26 | \end{tikzpicture}
27 |
28 | \end{document}
29 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | # Formatter and linter settings for Python code examples.
2 |
3 | [tool.ruff]
4 | line-length = 78
5 | target-version = "py310"
6 |
7 | [tool.ruff.lint]
8 | # Enable pyflakes (F), pycodestyle (E, W), flake8-bugbear (B), pyupgrade (UP),
9 | # flake8-debugger (T10), and NumPy (NPY).
10 | select = ["F", "E", "W", "B", "UP", "T10", "NPY"]
11 |
12 | [tool.ruff.format]
13 | quote-style = "single"
14 | docstring-code-format = true
15 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | babel==2.16.0
2 | certifi==2024.8.30
3 | charset-normalizer==3.3.2
4 | click==8.1.7
5 | colorama==0.4.6
6 | ghp-import==2.1.0
7 | idna==3.10
8 | Jinja2==3.1.4
9 | Markdown==3.7
10 | MarkupSafe==2.1.5
11 | mergedeep==1.3.4
12 | mkdocs==1.6.1
13 | mkdocs-get-deps==0.2.0
14 | mkdocs-material==9.5.35
15 | mkdocs-material-extensions==1.3.1
16 | packaging==24.1
17 | paginate==0.5.7
18 | pathspec==0.12.1
19 | platformdirs==4.3.6
20 | Pygments==2.18.0
21 | pymdown-extensions==10.9
22 | python-dateutil==2.9.0.post0
23 | PyYAML==6.0.2
24 | pyyaml_env_tag==0.1
25 | regex==2024.9.11
26 | requests==2.32.3
27 | six==1.16.0
28 | urllib3==2.2.3
29 | watchdog==5.0.2
30 |
--------------------------------------------------------------------------------