diff --git a/README.md b/README.md index 0cfa066..a392290 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,18 @@ The slides for this workshop can be viewed on the [website of this course](https ### Exercises -TODO +The exercises for this course are listed in the quarto markdown files which can be found in the [exercises](exercises/) directory. The tasks are +divided into those that can be answered/solved during the session, and also "Extension" tasks which can be worked on outside of the session. -The exercises for the course can be found in the [exercises](exercises/) directory. -These take the form of \. +There is a small group of python scripts in the [problem](exercises/problem/) sub-directory. These act as an example of a non-reproducible workflow. The tasks involve understanding and +improving the reproducibility of the scripts using what is covered in the session. It is recommended to download these scripts to a seperate location on your local machine for +this purpose. ### Worked Solution -TODO Worked solutions for all of the exercises can be found in the [worked solutions](worked-solutions/) directory. -These are for recapping after the course in case you missed anything, and contain example solutions. +These cover the tasks that require any modifications/improvements to the example workflow provided. They are not exhaustive, but use common technologies and approaches +to solving the tasks. ### Mini ReproHack @@ -66,7 +68,11 @@ If you want to follow along with the exercises, basic Python coding skills and a ## Installation and setup -TODO +To complete the exercises, you will need to download the dataset used by the python scripts. This can be found [here](https://www.metoffice.gov.uk/hadobs/hadcrut5/data/HadCRUT.5.0.0.0/download.html) +As part of the exercises will be assessing the data dependencies of the scripts, it will be left as a task to find out which of the datasets you need! + +It is recommended to download the python scripts from [exercises/problem](exercises/problem/) to your local machine, in a new directory. +This will allow you to develop the code as you would in practice. ## License diff --git a/exercises/README b/exercises/README deleted file mode 100644 index 3a13423..0000000 --- a/exercises/README +++ /dev/null @@ -1,52 +0,0 @@ -# Exercises in reproducibility - -After going through the slides on how to make our research projects reproducible, -it is time to go through a practice scenario! - -The code in `problem` is an example of a research project which has not taken -reproducibility into account. - -## Instructions: - -1. Create a new repository on your local machine with `git init repro-examples` -2. Copy the files in the `problem` directory into the new repository -3. Download the data needed for the analysis from https://zenodo.org/records/16875985 - -## Section 1: Version control - -Try to answer the following questions: - -1. Which files should be tracked? -2. Are there any files in the project that should not be tracked? -3. Are there any files missing that are needed to run the analysis? - -## Section 2: Dependencies - -Try to answer the following questions: - -1. What are the python dependencies for the analysis? -2. What are the system dependencies? - -Task: Document the dependencies that you find -Extension: Using your favourite dependency management tool (e.g. Conda, Nix), -create a reproducible environment configuration. - -## Section 3: Automation - -Tasks: - -1. Create an automated pipeline for producing all the figures -2. Automate the fetching of the necessary data - -## Section 4: Documentation - -Tasks: - -1. Create a README for the repository - -## Section 5: Try it out! - -Tasks: - -1. Share your repository with the person near you -2. Try to reproduce the results using the repo that you have been shared diff --git a/exercises/README.md b/exercises/README.md new file mode 100644 index 0000000..8b77cdc --- /dev/null +++ b/exercises/README.md @@ -0,0 +1,20 @@ +# Exercises in reproducibility + +After going through the slides on how to make our research projects reproducible, +it is time to go through a practice scenario! + +The code in `problem/` is an example of a research project which has not taken +reproducibility into account. + +## Data + +If you are trying to work through these exercises, you will need the data that +the scripts rely on, which can be found here: https://www.metoffice.gov.uk/hadobs/hadcrut5/data/HadCRUT.5.0.0.0/download.html. + +## Instructions: + +1. Create a new repository on your local machine with `git init repro-examples` +2. Copy the files in the `problem` directory into the new repository +3. Download the data needed for the analysis from https://doi.org/10.5281/zenodo.7014332 +4. Try to complete the tasks in the files named `*_exercises.qmd`. Some of these are +achievable during the session, others are tasks that could be worked on in your own time. diff --git a/exercises/automation_exercises.qmd b/exercises/automation_exercises.qmd new file mode 100644 index 0000000..24cd1ba --- /dev/null +++ b/exercises/automation_exercises.qmd @@ -0,0 +1,9 @@ +## Automation Exercises + +1. What tools/technologies could be used to automate producing the plots? +2. How could we automatically fetch the data needed for the plots + +### Extension + +1. Create an automated pipeline for producing all the figures +2. Automate the fetching of the necessary data diff --git a/exercises/dependencies_exercises.qmd b/exercises/dependencies_exercises.qmd new file mode 100644 index 0000000..82ebe69 --- /dev/null +++ b/exercises/dependencies_exercises.qmd @@ -0,0 +1,14 @@ +## Dependencies exercises + +Returning to the Python scripts, try to answer the following questions: + +1. What are the python dependencies? +2. What are the system dependencies? +3. What are the data dependencies? + +### Extension + +Using your favourite dependency management tool (e.g. Conda, Nix), create a +reproducible environment configuration to handle the python and system dependencies. + +Create a way to automatically fetch the data dependencies when using the scripts. diff --git a/exercises/documentation_exercises.qmd b/exercises/documentation_exercises.qmd new file mode 100644 index 0000000..7caccbb --- /dev/null +++ b/exercises/documentation_exercises.qmd @@ -0,0 +1,12 @@ +## Documentation Exercises + +Tasks: + +1. Create a README for the repository +2. Add comments and docstrings where you think is necessary + +### Extension + +Use an documentation tool, such as Sphinx, to automate building the +documentation. + diff --git a/exercises/final_exercises.qmd b/exercises/final_exercises.qmd new file mode 100644 index 0000000..437862f --- /dev/null +++ b/exercises/final_exercises.qmd @@ -0,0 +1,15 @@ +## Try it out! + +Tasks: + +1. Try running some of the worked examples in the repository + - Which ones work? Which do you find the easiest to use? + +### Extensions + +1. Share your repository with someone, see if they can reproduce the plotd +2. Try to reproduce the results using the repo that you have been shared +3. Try to use a different dataset (e.g. a different version of the HadCrut data) + - Does it work? + - What changes did you need to make? + diff --git a/exercises/problem/plot1.py b/exercises/problem/plot1.py index 2256204..07248cc 100644 --- a/exercises/problem/plot1.py +++ b/exercises/problem/plot1.py @@ -1,7 +1,24 @@ import xarray import matplotlib.pyplot as plt -ds = xarray.open_dataset("../data/CARS2009_temp20-40S_69-88W.nc") +# Recreate the "warming stripes" visualisation +# https://showyourstripes.info/ + +ds = xarray.open_dataset("../data/HadCRUT.5.0.0.0_analysis_summary-series_global_annual.nc") + +fig, axs = plt.subplots(2, 1, figsize=(10,6), layout='constrained') + +x = ds['time'].data + +y_lower = ds['tas_lower'].data +y = ds['tas_mean'].data +y_upper = ds['tas_upper'].data + +axs[0].pcolor(y.reshape(1, -1), cmap="coolwarm") +axs[0].axis('off') + +axs[1].errorbar(x, y, yerr=[y - y_lower, y_upper - y]) +axs[1].set_ylabel("Annual Temperature Anomalies Compared to 1961-1990, \N{DEGREE SIGN}C") +axs[1].set_xlabel("Year") -ds['temp'].plot() plt.show() diff --git a/exercises/problem/plot2.py b/exercises/problem/plot2.py new file mode 100644 index 0000000..0537204 --- /dev/null +++ b/exercises/problem/plot2.py @@ -0,0 +1,28 @@ +import xarray +import matplotlib.pyplot as plt + +global_ds = xarray.open_dataset("../data/HadCRUT.5.0.0.0_analysis_summary-series_global_annual.nc") +northern_ds = xarray.open_dataset("../data/HadCRUT.5.0.0.0_analysis_summary-series_northern-hemisphere_annual.nc") +southern_ds = xarray.open_dataset("../data/HadCRUT.5.0.0.0_analysis_summary-series_southern-hemisphere_annual.nc") + +def plot_temp_with_error(ax, ds, label): + axs.fill_between(ds['time'].data, ds['tas_lower'].data, ds['tas_upper'].data, + color="grey", alpha=0.3, edgecolor=None) + axs.plot(ds['time'].data, ds['tas_mean'].data) + + +fig, axs = plt.subplots(1, 1, figsize=(10,6), layout='constrained') + +plot_temp_with_error(axs, global_ds, label="global") +plot_temp_with_error(axs, northern_ds, label="northern") +plot_temp_with_error(axs, southern_ds, label="southern") + +t_min = global_ds['time'].min() +t_max = global_ds['time'].max() + +axs.hlines(0.0, t_min, t_max, color="black", linestyle="--") + +axs.set_xlabel("Year") +axs.set_ylabel("Annual Temperature Anomalies Compared to 1961-1990, \N{DEGREE SIGN}C") + +plt.show() diff --git a/exercises/problem/plot3.py b/exercises/problem/plot3.py new file mode 100644 index 0000000..b618092 --- /dev/null +++ b/exercises/problem/plot3.py @@ -0,0 +1,39 @@ +import xarray + +import matplotlib.pyplot as plt +import matplotlib as mpl + +ds = xarray.open_dataset("../data/HadCRUT.5.0.0.0_analysis_summary-series_global_monthly.nc") + +fig, axs = plt.subplots(1, 1, figsize=(10,6), layout='constrained') + +N_years = ds.time.size / 12 + +alpha = 0.001 +delta_alpha = (1.0 - alpha)/N_years + +year_group = ds.groupby("time.year") + +years = [ year for year, _ in year_group] + +first_year = years[0] +last_year = years[-1] + +delta_years = last_year - first_year + +cmap = mpl.colormaps['rainbow'] + +for year, year_data in year_group: + alpha += delta_alpha + yearly_mean = year_data['tas_mean'].mean() + axs.plot(year_data.time.dt.strftime("%b"), year_data['tas_mean'], + label=year, color=cmap((year - first_year)/delta_years), alpha=alpha) + + +axs.set_ylabel("Temperature Anomalies Compared to 1961-1990, \N{DEGREE SIGN}C") +axs.set_xlabel("Month") + +colorizer = mpl.colorizer.Colorizer(norm=mpl.colors.Normalize(first_year, last_year), cmap='rainbow') +fig.colorbar(mpl.colorizer.ColorizingArtist(colorizer), ax=axs) + +plt.show() diff --git a/exercises/version_control_exercises.qmd b/exercises/version_control_exercises.qmd new file mode 100644 index 0000000..4adbf48 --- /dev/null +++ b/exercises/version_control_exercises.qmd @@ -0,0 +1,16 @@ +## Version Control Exercises + +Hopefully, at this point in the week, you will all be comfortable with version control! + +The exercises in this course will work on improving an example set of python scripts, +to make them more reproducible! + +These scripts are hosted on the same GitHub repository as these slides: +(https://github.com/Cambridge-ICCS/ReproducibilityInComputingCourse) +Specifically in the directory `exercises/problem`. + +Tasks: + +1. Download the Python scripts from the GitHub repository +2. Create a new git repository on your local machine +3. Add the Python scripts to git for version control! diff --git a/src/slides.qmd b/src/slides.qmd index cab3cf5..c8565c4 100644 --- a/src/slides.qmd +++ b/src/slides.qmd @@ -15,14 +15,18 @@ authors: {{< include introduction.qmd >}} {{< include version_control.qmd >}} +{{< include ../exercises/version_control_exercises.qmd >}} {{< include dependencies.qmd >}} +{{< include ../exercises/dependencies_exercises.qmd >}} {{< include automation.qmd >}} +{{< include ../exercises/automation_exercises.qmd >}} {{< include testing.qmd >}} {{< include documentation.qmd >}} +{{< include ../exercises/documentation_exercises.qmd >}} {{< include fair_principles.qmd >}}