From 1dbed5d1ac89d620262925b49ac66ea9369521d9 Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Wed, 24 Jul 2024 17:56:56 +1000
Subject: [PATCH 01/49] Modify Gemfile for local deployment
---
Gemfile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Gemfile b/Gemfile
index 1ece4c01..7f28a7b1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,3 +8,5 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
ruby '>=2.5.3'
gem 'github-pages', group: :jekyll_plugins
+gem "json" # On Arch Linux system, Ruby does not ship with json
+gem "webrick"
From 376c28f843c9b55315a826306c5b97490fd9a257 Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Wed, 24 Jul 2024 20:42:18 +1000
Subject: [PATCH 02/49] Change deployment action
---
.../workflows/build-check-tutorial-site.yml | 31 -----
.../install-esmvaltool-run-recipes.yml | 42 ------
.github/workflows/website.yml | 125 ++++++++++++++++++
3 files changed, 125 insertions(+), 73 deletions(-)
delete mode 100644 .github/workflows/build-check-tutorial-site.yml
delete mode 100644 .github/workflows/install-esmvaltool-run-recipes.yml
create mode 100644 .github/workflows/website.yml
diff --git a/.github/workflows/build-check-tutorial-site.yml b/.github/workflows/build-check-tutorial-site.yml
deleted file mode 100644
index 0450d25e..00000000
--- a/.github/workflows/build-check-tutorial-site.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: Jekyll site CI
-
-on:
- push:
- # pull_request: # turn on when GA tests need to run on PRs too
-
-jobs:
- build:
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v2
- - name: Setup Ruby
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: 3.1
- - name: Ruby deps
- run: gem install json kramdown jekyll bundler
- - name: Setup Python
- uses: actions/setup-python@v2
- with:
- python-version: '3.x'
- - name: Python deps
- run: pip install pyyaml
- - name: Nokogiri deps
- run: sudo apt install -y pkg-config libxml2-dev libxslt-dev
- - name: Site deps
- run: bundle install
- - name: Build site
- run: bundle exec jekyll build
- - name: Check all lessons
- run: make lesson-check-all
diff --git a/.github/workflows/install-esmvaltool-run-recipes.yml b/.github/workflows/install-esmvaltool-run-recipes.yml
deleted file mode 100644
index 16627392..00000000
--- a/.github/workflows/install-esmvaltool-run-recipes.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: Test Tutorial Recipes
-
-on:
- push:
- # pull_request: # turn on for tests to run on PRs
- schedule:
- - cron: '0 4 * * *'
-
-jobs:
- install-esmvaltool-and-run-recipes:
- runs-on: "ubuntu-latest"
- steps:
- - uses: actions/checkout@v2
- - name: Cache conda
- uses: actions/cache@v1
- env:
- # Increase this value to reset cache if files/recipe_example.yml has not changed
- CACHE_NUMBER: 1
- with:
- path: ~/conda_pkgs_dir
- key: ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('files/recipe_example.yml') }}
- - uses: conda-incubator/setup-miniconda@v2
- with:
- python-version: "3.9"
- miniconda-version: "latest"
- channels: conda-forge
- - name: Install mamba
- shell: bash -l {0}
- run: conda install mamba
- - name: Install esmvaltool from conda
- shell: bash -l {0}
- run: mamba install esmvaltool
- # this step is currently unnecessary; might be useful depending on config customizations
- - name: Get config-user file
- shell: bash -l {0}
- run: esmvaltool config get_config_user
- - name: Run all warming stripes recipes in files/
- shell: bash -l {0}
- run: |
- mkdir ~/esmvaltool_tutorial
- cp files/warming_stripes.py ~/esmvaltool_tutorial/
- for file in files/recipe_warming_stripes*.yml; do $CONDA/envs/test/bin/esmvaltool run $PWD/$file --offline=False; done
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
new file mode 100644
index 00000000..0d46e851
--- /dev/null
+++ b/.github/workflows/website.yml
@@ -0,0 +1,125 @@
+name: Website
+on:
+ push:
+ branches:
+ - gh-pages
+ - main
+ pull_request: null
+jobs:
+ build-website:
+ if: ${{ !endsWith(github.repository, '/styles') }}
+ runs-on: ubuntu-20.04
+ env:
+ RSPM: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.0'
+ bundler-cache: true
+
+ - name: Set up Python
+ uses: actions/setup-python@v5.1.0
+ with:
+ python-version: '3.x'
+
+ - name: Install GitHub Pages, Bundler, and kramdown gems
+ run: |
+ gem install github-pages bundler kramdown kramdown-parser-gfm
+
+ - name: Install Python modules
+ run: |
+ python3 -m pip install --upgrade pip setuptools wheel pyyaml==5.3.1 requests
+
+ - name: Checkout the lesson
+ uses: actions/checkout@master
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: Look for R-markdown files
+ id: check-rmd
+ run: |
+ echo "count=$(shopt -s nullglob; files=($(find . -iname '*.Rmd')); echo ${#files[@]})" >> $GITHUB_OUTPUT
+
+ - name: Set up R
+ if: steps.check-rmd.outputs.count != 0
+ uses: r-lib/actions/setup-r@v2
+ with:
+ use-public-rspm: true
+ install-r: false
+
+ - name: Restore R Cache
+ if: steps.check-rmd.outputs.count != 0
+ uses: actions/cache@v2
+ with:
+ path: ${{ env.R_LIBS_USER }}
+ key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
+ restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
+
+ - name: Install needed packages
+ if: steps.check-rmd.outputs.count != 0
+ run: |
+ source('bin/dependencies.R')
+ install_required_packages()
+ shell: Rscript {0}
+
+ - name: Query dependencies
+ if: steps.check-rmd.outputs.count != 0
+ run: |
+ source('bin/dependencies.R')
+ deps <- identify_dependencies()
+ create_description(deps)
+ use_bioc_repos()
+ saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
+ writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
+ shell: Rscript {0}
+
+ - name: Install system dependencies for R packages
+ if: steps.check-rmd.outputs.count != 0
+ run: |
+ while read -r cmd
+ do
+ eval sudo $cmd || echo "Nothing to update"
+ done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")')
+
+ - name: Render the markdown and confirm that the site can be built
+ run: make site
+
+ - name: Checkout github pages
+ if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}}
+ uses: actions/checkout@master
+ with:
+ ref: gh-pages
+ path: gh-pages
+
+ - name: Validate workshop website
+ # https://github.com/carpentries/styles/issues/551 is no longer relevant as styles shouldn't be used for
+ # lessons but only workshop templates. So, always run the workshop checks now.
+ run: make workshop-check
+ if: always()
+
+ - name: Commit and Push
+ if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}}
+ run: |
+ # clean up gh-pages
+ cd gh-pages
+ git rm -rf . # remove all previous files
+ git restore --staged . # remove things from the stage
+ cd ..
+ # copy everything into gh-pages site
+ cp -r `ls -A | grep -v 'gh-pages' | grep -v '.git' | grep -v '.bundle/' | grep -v '_site'` gh-pages
+ # move into gh-pages, add, commit, and push
+ cd gh-pages
+ # setup git
+ git config --local user.email "actions@github.com"
+ git config --local user.name "GitHub Actions"
+ git add -A .
+ git commit --allow-empty -m "[Github Actions] render website (via ${{ github.sha }})"
+ git push origin gh-pages
+ # return
+ cd ..
From 7ab318e01fdd30af0d296e70c4db3f965ea0a196 Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Wed, 24 Jul 2024 20:50:25 +1000
Subject: [PATCH 03/49] Delete some files
---
_episodes/02-installation.md | 242 --------
_episodes/03-configuration.md | 364 ------------
_episodes/07-development-setup.md | 517 -----------------
_episodes/09-cmorization.md | 912 ------------------------------
4 files changed, 2035 deletions(-)
delete mode 100644 _episodes/02-installation.md
delete mode 100644 _episodes/03-configuration.md
delete mode 100644 _episodes/07-development-setup.md
delete mode 100644 _episodes/09-cmorization.md
diff --git a/_episodes/02-installation.md b/_episodes/02-installation.md
deleted file mode 100644
index 03d2f582..00000000
--- a/_episodes/02-installation.md
+++ /dev/null
@@ -1,242 +0,0 @@
----
-title: "Installation"
-teaching: 10
-exercises: 10
-compatibility: ESMValTool v2.10.0
-questions:
-- "What are the prerequisites for installing ESMValTool?"
-- "How do I confirm that the installation was successful?"
-objectives:
-- "Install ESMValTool"
-- "Demonstrate that the installation was successful"
-keypoints:
-- "All the required packages can be installed using mamba."
-- "You can find more information about installation in the
-[documentation](https://docs.esmvaltool.org/en/latest/quickstart/installation.html)."
----
-## Overview
-
-The instructions help with the installation of ESMValTool on operating systems
-like Linux/MacOSX/Windows.
-We use the [Mamba](https://mamba.readthedocs.io/en/latest/index.html)
-package manager to
-install the ESMValTool. Other installation methods are also available; they can
-be found in the
-[documentation](https://docs.esmvaltool.org/en/latest/quickstart/installation.html).
-We will first install Mamba, and then ESMValTool. We end this chapter by testing
-that the installation was successful.
-
-Before we begin, here are all the possible ways in which you can use ESMValTool
-depending on your level of expertise or involvement with ESMValTool and
-associated software such as GitHub and Mamba.
-
-1. If you have access to a server where ESMValTool is already installed
-as a module, for e.g., the [CEDA JASMIN](https://help.jasmin.ac.uk/article
-/4955-community-software-esmvaltool)
-server, you can simply load the module with the following command:
-~~~bash
-module load esmvaltool
-~~~
-After loading ``esmvaltool``, we can start using ESMValTool right away. Please
- see the [next lesson]({{ page.root }}{% link _episodes/03-configuration.md %}).
-2. If you would like to install ESMValTool as a mamba package, then this lesson
-will tell you how!
-3. If you would like to start experimenting with existing diagnostics or
-contributing to ESMvalTool, please see the instructions for
-source installation in the lesson [Development and
-contribution]({{ page.root }}{% link _episodes/07-development-setup.md %}) and
-in the [documentation](https://docs.esmvaltool.org/en/latest/quickstart/installation.html).
-
-> ## Install ESMValTool on Windows
->
-> ESMValTool does not directly support Windows, but successful usage has been
-> reported through the [Windows Subsystem for
-> Linux(WSL)](https://docs.microsoft.com/en-us/windows/wsl/),
-> available in Windows 10.
-> To install the WSL please follow the instructions [on the Windows Documentation
-> page](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
-> After installing the WSL, installation can be done using the same instructions for
-> [Linux/MacOSX](#install-esmvaltool-on-linuxmacosx).
-{: .callout}
-
-## Install ESMValTool on Linux/MacOSX
-
-### Install Mamba
-
-ESMValTool is distributed using [Mamba](https://mamba.readthedocs.io/en/latest/index.html).
-To install mamba on ``Linux`` or ``MacOSX``, follow the instructions below:
-
-1. Please download the installation file for the latest Mamba version
-[here](https://github.com/conda-forge/miniforge#mambaforge).
-
-2. Next, run the installer from the place where you downloaded it:
-
- On ``Linux``:
-
- ```bash
- bash Mambaforge-Linux-x86_64.sh
- ```
-
- On ``MacOSX``:
-
- ```bash
- bash Mambaforge-MacOSX-x86_64.sh
- ```
-
-3. Follow the instructions in the installer. The defaults should normally
- suffice.
-
-4. You will need to restart your terminal for the changes to have effect.
-
-5. We recommend updating mamba before the esmvaltool installation. To do so, run:
-
- ```bash
- mamba update --name base mamba
- ```
-
-6. Verify you have a working mamba installation by:
-
- ```bash
- which mamba
- ```
-
- This should show the path to your mamba executable, e.g. `~/mambaforge/bin/mamba`.
-
-For more information about installing mamba,
-see [the mamba installation documentation](https://docs.esmvaltool.org/en
-/latest/quickstart/installation.html#mamba-installation).
-
-### Install the ESMValTool package
-
-The ESMValTool package contains diagnostics scripts in four languages: R,
-Python, Julia and NCL. This introduces a lot of dependencies, and therefore the
-installation can take quite long. It is, however, possible to install
-'subpackages' for each of the languages. The following (sub)packages are
-available:
-
-- `esmvaltool-python`
-- `esmvaltool-ncl`
-- `esmvaltool-r`
-- `esmvaltool` --> the complete package, i.e. the combination of the above.
-
-For the tutorial, we will install the complete package. Thus, to install the
-ESMValTool package, run
-
-```bash
-mamba create --name esmvaltool esmvaltool
-```
-
-On MacOSX ESMValTool functionalities in Julia, NCL, and R are not supported. To install
-a Mamba environment on MacOSX, please refer to specific [information](https://
-docs.esmvaltool.org/en/latest/quickstart/installation.html#installation-on-
-macosx).
-
-This will create a new [Mamba
-environment](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks
-/manage-environments.html)
-called `esmvaltool`, with the ESMValTool package and all of its dependencies
-installed in it.
-
-
-> ## Common issues
->
-> You find a list of common installation problems and their solutions in the
-> [documentation](https://docs.esmvaltool.org/en/latest/quickstart/installation
-.html#common-installation-problems-and-their-solutions).
->
-{: .callout}
-
-### Install Julia
-
-Some ESMValTool diagnostics are written in the Julia programming language.
-If you want a full installation of ESMValTool including Julia diagnostics, you need
-to make sure Julia is installed before installing ESMValTool.
-
-In this tutorial, we will not use Julia, but for reference, we have listed the steps
-to install Julia below.
-Complete instructions for installing Julia can be found on the [Julia
-installation page](https://julialang.org/downloads/platform/#linux_and_freebsd).
-
-> ## Julia installation instructions
->
-> First, open a bash terminal and activate the newly created `esmvaltool` environment.
->
-> ```bash
-> conda activate esmvaltool
-> ```
->
-> Next, to install Julia via `mamba`, you can use the following command:
->
-> ```bash
-> mamba install julia
-> ```
->
-> To check that the Julia executable can be found, run
->
-> ```bash
-> which julia
-> ```
->
-> to display the path to the Julia executable, it should be
->
-> ```
-> ~/mambaforge/envs/esmvaltool/bin/julia
-> ```
-> {: .output}
->
-> To test that Julia is installed correctly, run
->
-> ```bash
-> julia
-> ```
->
-> to start the interactive Julia interpreter. Press `Ctrl+D` to exit.
-{: .solution}
-
-### Test that the installation was successful
-
-To test that the installation was successful, run
-
-```bash
-conda activate esmvaltool
-```
-
-to activate the conda environment called `esmvaltool`. In the shell prompt the
-active conda environment should have been changed from `(base)` to
-`(esmvaltool)`.
-
-Next, run
-
-```bash
-esmvaltool --help
-```
-
-to display the command line help.
-
-> ## Version of ESMValTool
->
-> Can you figure out which version of ESMValTool has been installed?
->
-> > ## Solution
-> >
-> > The `esmvaltool --help` command lists `version` as a
-> > command to get the version
-> >
-> > When you run
-> > ~~~
-> > esmvaltool version
-> > ~~~
-> > {: .bash}
-> > The version of ESMValTool installed should be displayed on the screen as:
-> > ~~~
-> > ESMValCore: 2.10.0
-> > ESMValTool: 2.10.0
-> > ~~~
-> > {: .output}
-> Note that on HPC servers such as JASMIN, sometimes a more recent development
-> version may be displayed for ESMValTool, for e.g.
-> `ESMValTool: 2.9.0.dev4+g6948d5512`
-> {: .solution}
-{: .challenge}
-
-{% include links.md %}
diff --git a/_episodes/03-configuration.md b/_episodes/03-configuration.md
deleted file mode 100644
index 8af64374..00000000
--- a/_episodes/03-configuration.md
+++ /dev/null
@@ -1,364 +0,0 @@
----
-title: "Configuration"
-teaching: 10
-exercises: 10
-compatibility: ESMValTool v2.10.0
-
-questions:
-- What is the user configuration file and how should I use it?
-
-objectives:
-- Understand the contents of the user-config.yml file
-- Prepare a personalized user-config.yml file
-- Configure ESMValTool to use some settings
-
-keypoints:
-- The ``config-user.yml`` tells ESMValTool where to find input data.
-- "``output_dir`` defines the destination directory."
-- "``rootpath`` defines the root path of the data."
-- "``drs`` defines the directory structure of the data."
-
----
-
-## The configuration file
-
-For the purposes of this tutorial, we will create a directory in our home directory
-called `esmvaltool_tutorial` and use that as our working directory. The following steps
-should do that:
-
-~~~bash
- mkdir esmvaltool_tutorial
- cd esmvaltool_tutorial
-~~~
-
-The ``config-user.yml`` configuration file contains all the global level
-information needed by ESMValTool to run.
-This is a [YAML file](https://yaml.org/spec/1.2/spec.html).
-
-You can get the default configuration file by running:
-
-~~~bash
- esmvaltool config get_config_user --path=
-~~~
-The default configuration file will be downloaded to the directory specified with
-the `--path` variable. For instance, you can provide the path to your working directory
-as the `target_dir`. If this option is not used, the file will be saved to the default
-location: `~/.esmvaltool/config-user.yml`, where `~` is the
-path to your home directory. Note that files and directories starting with a
-period are "hidden", to see the `.esmvaltool` directory in the terminal use
-`ls -la ~`. Note that if a configuration file by that name already exists in the default
-location, the `get_config_user` command will not update the file as ESMValTool will not
-overwrite the file. You will have to move the file first if you want an updated copy of the
-user configuration file.
-
-
-
-We run a text editor called ``nano`` to have a look inside the configuration file
-and then modify it if needed:
-
-~~~bash
- nano ~/.esmvaltool/config-user.yml
-~~~
-
-Any other editor can be used, e.g.vim.
-
-This file contains the information for:
-
-- Output settings
-- Destination directory
-- Auxiliary data directory
-- Number of tasks that can be run in parallel
-- Rootpath to input data
-- Directory structure for the data from different projects
-
-> ## Text editor side note
->
-> No matter what editor you use, you will need to know where it searches
-> for and saves files. If you start it from the shell, it will (probably)
-> use your current working directory as its default location. We use ``nano``
-> in examples here because it is one of the least complex text editors.
-> Press ctrl + O to save the file,
-> and then ctrl + X to exit ``nano``.
-{: .callout}
-
-## Output settings
-
-The configuration file starts with output settings that
-inform ESMValTool about your preference for output.
-You can turn on or off the setting by ``true`` or ``false``
-values. Most of these settings are fairly self-explanatory.
-
-
-> ## Saving preprocessed data
->
-> Later in this tutorial, we will want to look at the contents of the
-> `preproc` folder.
-> This folder contains preprocessed data and is removed by default when
-> ESMValTool is run.
-> In the configuration file, which settings can be modified to prevent
-> this from happening?
->
->> ## Solution
->>
->> If the option ``remove_preproc_dir`` is set to ``false``, then the
->> ``preproc/`` directory contains all the pre-processed data and the
->> metadata interface files.
->> If the option ``save_intermediary_cubes`` is set to ``true``
->> then data will also be saved after each preprocessor step in the folder
->> ``preproc``. Note that saving all intermediate results to file will result
->> in a considerable slowdown, and can quickly fill your disk.
-> {: .solution}
-{: .challenge}
-
-## Destination directory
-
-The destination directory is the rootpath where ESMValTool will store its
-output folders containing
-e.g. figures, data, logs, etc. With every run, ESMValTool automatically
-generates a new output folder determined by recipe name, and date and time
-using the format: YYYYMMDD_HHMMSS.
-
-> ## Set the destination directory
->
-> Let's name our destination directory ``esmvaltool_output`` in the working directory.
-> ESMValTool should write the output to this path, so make sure you have the disk space
-> to write output to this directory.
-> How do we set this in the `config-user.yml`?
->
->> ## Solution
->>
->> We use `output_dir` entry in the `config-user.yml` file as:
->>```yaml
->> output_dir: ./esmvaltool_output
->>```
->>
->> If the `esmvaltool_output` does not exist, ESMValTool will generate it for you.
-> {: .solution}
-{: .challenge}
-
-## Rootpath to input data
-
-ESMValTool uses several categories (in ESMValTool, this is referred to as projects)
-for input data based on their source. The current categories in the configuration
-file are mentioned below. For example, CMIP is used for a dataset from
-the Climate Model Intercomparison Project whereas OBS may be
-used for an observational dataset.
-More information about the projects used in ESMValTool is available in the
-[documentation](https://docs.esmvaltool.org/projects/esmvalcore/en/latest/
-quickstart/find_data.html).
-When using ESMValTool on your own machine, you can create a directory to download
-climate model data or observation data sets and let the tool use data from there.
-It is also possible to ask
-ESMValTool to download climate model data as needed. This can be done by specifying a
-download directory and by setting the option to download data as shown below.
-
-```yaml
-# Directory for storing downloaded climate data
-download_dir: ~/climate_data
-search_esgf: always
-```
-If you are working offline or do not want to download the data then set the
-option above to `never`. If you want to download data only when the necessary files
-are missing at the usual location, you can set the option to `when_missing`.
-
-The ``rootpath`` specifies the directories where ESMValTool will look for input data.
-For each category, you can define either one path or several paths as a list. For example:
-
-```yaml
-rootpath:
- CMIP5: [~/cmip5_inputpath1, ~/cmip5_inputpath2]
- OBS: ~/obs_inputpath
- RAWOBS: ~/rawobs_inputpath
- default: ~/climate_data
-```
-These are typically available in the default configuration file you downloaded, so simply
-removing the machine specific lines should be sufficient to access input data.
-
-> ## Set the correct rootpath
->
-> In this tutorial, we will work with data from
-> [CMIP5](https://esgf-node.llnl.gov/projects/cmip5/)
-> and [CMIP6](https://esgf-node.llnl.gov/projects/cmip6).
-> How can we modify the `rootpath` to make sure the data path is set correctly
-> for both CMIP5 and CMIP6?
-> Note:
-> to get the data, check the instructions in
-> [Setup]({{ page.root }}{% link setup.md %}).
->
->> ## Solution
->>
->> - Are you working on your own local machine?
->> You need to add the root path of the folder where the data is available
->> to the `config-user.yml` file as:
->>
->>```yaml
->> rootpath:
->> ...
->> CMIP5: ~/esmvaltool_tutorial/data
->> CMIP6: ~/esmvaltool_tutorial/data
->>```
->>
->> - Are you working on your local machine and have downloaded data using ESMValTool?
->> You need to add the root path of the folder where the data has been downloaded to as
->> specified in the `download_dir`.
->>
->> ```yaml
->> rootpath:
->> ...
->> CMIP5: ~/climate_data
->> CMIP6: ~/climate_data
->>```
->>
->> - Are you working on a computer cluster like Jasmin or DKRZ?
->> Site-specific path to the data for JASMIN/DKRZ/ETH/IPSL
->> are already listed at the end of the
->> `config-user.yml` file. You need to uncomment the related lines.
->> For example, on JASMIN:
->>
->>```yaml
->>auxiliary_data_dir: /gws/nopw/j04/esmeval/aux_data/AUX
->>rootpath:
->> CMIP6: /badc/cmip6/data/CMIP6
->> CMIP5: /badc/cmip5/data/cmip5/output1
->> OBS: /gws/nopw/j04/esmeval/obsdata-v2
->> OBS6: /gws/nopw/j04/esmeval/obsdata-v2
->> obs4MIPs: /gws/nopw/j04/esmeval/obsdata-v2
->> ana4mips: /gws/nopw/j04/esmeval/obsdata-v2
->> default: /gws/nopw/j04/esmeval/obsdata-v2
->>```
->>
->> - For more information about setting the rootpath, see also the ESMValTool
->> [documentation](https://docs.esmvaltool.org/projects/esmvalcore/en/latest/
-quickstart/find_data.html).
-> {: .solution}
-{: .challenge}
-
-## Directory structure for the data from different projects
-
-Input data can be from various models, observations and reanalysis data that
-adhere to the [CF/CMOR standard](https://cmor.llnl.gov/). The ``drs`` setting
-describes the file structure.
-
-The ``drs`` setting describes the file structure for several projects (e.g.
-CMIP6, CMIP5, obs4mips, OBS6, OBS) on several key machines
-(e.g. BADC, CP4CDS, DKRZ, ETHZ, SMHI, BSC). For more
-information about ``drs``, you can visit the ESMValTool documentation on
-[Data Reference Syntax (DRS)](https://docs.esmvaltool.org/projects/esmvalcore/
-en/latest/quickstart/find_data.html#cmor-drs).
-
-> ## Set the correct drs
->
-> In this lesson, we will work with data from
-> [CMIP5](https://esgf-node.llnl.gov/projects/cmip5/)
-> and [CMIP6](https://esgf-node.llnl.gov/projects/cmip6/).
-> How can we set the correct `drs`?
->
->> ## Solution
->>
->> - Are you working on your own local machine?
->> You need to set the `drs` of the data
->> in the `config-user.yml` file as:
->>```yaml
->> drs:
->> CMIP5: default
->> CMIP6: default
->>```
->> - Are you asking ESMValTool to download the data for use with your diagnostics?
->> You need to set the `drs` of the data in the `config-user.yml` file as:
->> ```yaml
->> drs:
->> CMIP5: ESGF
->> CMIP6: ESGF
->> CORDEX: ESGF
->> obs4MIPs: ESGF
->>```
->> - Are you working on a computer cluster like Jasmin or DKRZ?
->> Site-specific `drs` of the data are already listed at the end of the
->> `config-user.yml` file. You need to uncomment the related lines.
->> For example, on Jasmin:
->>```yaml
->> # Site-specific entries: Jasmin
->> # Uncomment the lines below to locate data on JASMIN
->> drs:
->> CMIP6: BADC
->> CMIP5: BADC
->> OBS: default
->> OBS6: default
->> obs4mips: default
->> ana4mips: default
->>```
->>
-> {: .solution}
-{: .challenge}
-
-> ## Explain the default drs (if working on local machine)
->
-> 1. In the previous exercise, we set the `drs` of CMIP5 data to `default`.
-> Can you explain why?
-> 2. Have a look at the directory structure of the `OBS` data.
-> There is a folder called `Tier1`. What does it mean?
->
->> ## Solution
->>
->> 1. `drs: default` is one way to retrieve data from a ROOT directory that has
->> no DRS-like structure. ``default`` indicates that all the files are in a
->> folder without any structure.
->>
->> 2. Observational data are organized in Tiers depending on their level of
->> public availability. Therefore the default directory must be structured
->> accordingly with sub-directories `TierX` e.g. Tier1, Tier2 or Tier3, even
->> when `drs: default`. More details can be found in the
-[documentation](https://docs.esmvaltool.org/projects/esmvalcore/en/latest/
-quickstart/find_data.html#observational-data).
->>
-> {: .solution}
-{: .challenge}
-
-## Other settings
-
-> ## Auxiliary data directory
->
-> The ``auxiliary_data_dir`` setting is the path where any required additional
-auxiliary data files are stored. This location allows us to tell the diagnostic
-script where to find the files if they can not be downloaded at runtime. This
-option should not be used for model or observational datasets, but for data
-files (e.g. shape files) used in plotting such as coastline descriptions and
-if you want to feed some additional data (e.g. shape files) to your recipe.
->
->```yaml
-> auxiliary_data_dir: ~/auxiliary_data
-> ```
-> See more information in ESMValTool
-[document](https://docs.esmvaltool.org/projects/ESMValCore/en/latest/quickstart
-/configure.html?highlight=auxiliary_data#user-configuration-file).
-{: .callout}
-
-> ## Number of parallel tasks
->
-> This option enables you to perform parallel processing. You can choose the
-number of tasks in parallel as 1/2/3/4/... or you can set it to ``null``. That
-tells ESMValTool to use the maximum number of available CPUs. For the purpose of
-the tutorial, please set ESMValTool use only 1 cpu:
->
->```yaml
-> max_parallel_tasks: 1
-> ```
->
-> In general, if you run out of memory, try setting ``max_parallel_tasks`` to 1.
-Then, check the amount of memory you need for that by inspecting the file
-``run/resource_usage.txt`` in the output directory. Using the number there you
-can increase the number of parallel tasks again to a reasonable number for the
-amount of memory available in your system.
-{: .callout}
-
-> ## Make your own configuration file
->
-> It is possible to have several configuration files with different purposes,
-> for example: config-user_formalised_runs.yml, config-user_debugging.yml.
-> In this case, you have to pass the path of your own configuration file
-> as a command-line option when running the ESMValTool.
-> We will learn how to do this in the
-> [next lesson]({{ page.root }}{% link _episodes/04-recipe.md %}).
-{: .callout}
-
-{% include links.md %}
diff --git a/_episodes/07-development-setup.md b/_episodes/07-development-setup.md
deleted file mode 100644
index 33df420f..00000000
--- a/_episodes/07-development-setup.md
+++ /dev/null
@@ -1,517 +0,0 @@
----
-title: "Development and contribution"
-teaching: 10
-exercises: 20
-compatibility: ESMValTool v2.9.0
-
-questions:
-- "What is a development installation?"
-- "How can I test new or improved code?"
-- "How can I incorporate my contributions into ESMValTool?"
-
-objectives:
-- "Execute a successful ESMValTool installation from the source code."
-- "Contribute to ESMValTool development."
-
-keypoints:
-- "A development installation is needed if you want to incorporate your code into ESMValTool."
-- "Contributions include adding a new or improved script or helping with a review process."
-- "There are several tools to help improve the quality of your code."
-- "It is possible to run tests on your machine."
-- "You can preview documentation pages locally."
----
-
-We now know how ESMValTool works, but how do we develop it?
-ESMValTool is an open-source project in ESMValGroup. We can contribute to its development by:
-
-- a new or updated recipe script, see lesson on
-[Writing your own recipe]({{ page.root }}{% link _episodes/06-preprocessor.md %})
-- a new or updated diagnostics script, see lesson on
-[Writing your own diagnostic script]({{ page.root }}{% link _episodes/08-diagnostics.md %})
-- a new or updated cmorizer script, see lesson on
-[CMORization: Using observational datasets]({{ page.root }}{% link _episodes/09-cmorization.md %})
-- helping with reviewing process of pull requests, see ESMValTool documentation on
-[Review of pull requests](https://docs.esmvaltool.org/en/latest/community/review.html)
-
-In this lesson, we first show how to set up a development installation of ESMValTool so you can
-make changes or additions. We then explain how you can contribute these changes to the community.
-
-> ## Git knowledge
->
-> For this episode, you need some knowledge of
-> [Git](https://git-scm.com/). You can refresh your knowledge in the
-> corresponding [Git carpentries course](http://swcarpentry.github.io/git-novice/).
-{: .callout}
-
-## Development installation
-
-We’ll explore how ESMValTool can be installed it in a ``develop`` mode.
-Even if you aren’t collaborating with the community, this installation is needed
-to run your new codes with ESMValTool.
-Let’s get started.
-
-### 1 Source code
-
-The ESMValTool source code is available on a public GitHub repository:
-[https://github.com/ESMValGroup/ESMValTool](https://github.com/ESMValGroup/ESMValTool).
-To obtain the code, there are two options:
-
-1. Download the code from the repository. A ZIP file called
- ``ESMValTool-main.zip`` is downloaded. To continue the installation, unzip
- the file, move to the ``ESMValTool-main`` directory and then follow the
- sequence of steps starting from the section on
- **ESMValTool dependencies** below.
-2. Clone the repository if you want to contribute to the ESMValTool development:
-
-~~~bash
-git clone https://github.com/ESMValGroup/ESMValTool.git
-~~~
-
-This command will ask your GitHub username and a personal **token** as password.
-Please follow instructions on
-[GitHub token authentication requirements][token-authentication-requirements]
-to create a personal access token.
-Alternatively, you could [generate a new SSH key][generate-ssh-key] and
-[add it to your GitHub account][add-ssh-key].
-After the authentication, the output might look like:
-
-~~~
-Cloning into 'ESMValTool'...
-remote: Enumerating objects: 163, done.
-remote: Counting objects: 100% (163/163), done.
-remote: Compressing objects: 100% (125/125), done.
-remote: Total 95049 (delta 84), reused 76 (delta 30), pack-reused 94886
-Receiving objects: 100% (95049/95049), 175.16 MiB | 5.48 MiB/s, done.
-Resolving deltas: 100% (68808/68808), done.
-~~~
-{: .output}
-
-Now, a folder called ``ESMValTool`` has been created in your working directory.
-This folder contains the source code of the tool.
-To continue the installation, we move into the ``ESMValTool`` directory:
-
-~~~bash
-cd ESMValTool
-~~~
-
-Note that the ``main`` branch is checked out by default.
-We can see this if we run:
-
-~~~bash
-git status
-~~~
-
-~~~
-On branch main
-Your branch is up to date with 'origin/main'.
-
-nothing to commit, working tree clean
-~~~
-{: .output}
-
-### 2 ESMValTool dependencies
-
-Please don’t forget if an esmvaltool environment is already created
-following the lesson
-[Installation]({{ page.root }}{% link _episodes/02-installation.md %}),
-we should choose another name for the new environment in this lesson.
-
-ESMValTool now uses `mamba` instead of `conda` for the recommended installation.
-For a minimal mamba installation, see section **Install Mamba** in lesson
-[Installation]({{ page.root }}{% link _episodes/02-installation.md %}).
-
-It is good practice to update the version of mamba and conda on your machine before
-setting up ESMValTool. This can be done as follows:
-
-~~~bash
-mamba update --name base mamba conda
-~~~
-
-To simplify the installation process, an environment file ``environment.yml`` is
-provided in the ESMValTool directory. We create an environment by running:
-
-~~~bash
-mamba env create --name esmvaltool --file environment.yml
-~~~
-
-The environment is called ``esmvaltool`` by default.
-If an ``esmvaltool`` environment is already created following the lesson
-[Installation]({{ page.root }}{% link _episodes/02-installation.md %}),
-we should choose another name for the new environment in this lesson by:
-
-~~~bash
-mamba env create --name a_new_name --file environment.yml
-~~~
-This will create a new conda environment and install ESMValTool (with all
-dependencies that are needed for development purposes) into it with a single command.
-
-For more information see [conda managing environments][manage-environments].
-
-Now, we should activate the environment:
-
-~~~bash
-conda activate esmvaltool
-~~~
-where ``esmvaltool`` is the name of the environment (replace by ``a_new_name``
-in case another environment name was used).
-
-### 3 ESMValTool installation
-
-ESMValTool can be installed in a ``develop`` mode by running:
-
-~~~bash
-pip install --editable '.[develop]'
-~~~
-
-This will add the ``esmvaltool`` directory to the Python path in editable mode and
-install the development dependencies. We should check if the installation
-works properly. To do this, run the tool with:
-
-~~~bash
-esmvaltool --help
-~~~
-
-If the installation is successful, ESMValTool prints a help message to the console.
-
-> ## Checking the development installation
->
-> We can use the command ``mamba list`` to list installed packages in
-> the ``esmvaltool`` environment.
-> Use this command to check that ESMValTool is installed in a ``develop`` mode.
->
-> **Tip**: see the
-> [documentation on conda list](https://docs.conda.io/projects/conda/en/latest/commands/list.html).
->
->> ## Solution
->>
->> Run:
->>
->> ~~~bash
->> mamba list esmvaltool
->>~~~
->>
->> ~~~bash
->> # Name Version Build Channel
->> esmvaltool 2.10.0.dev3+g2dbc2cfcc pypi_0 pypi
->>~~~
->>
-> {: .solution}
-{: .challenge}
-
-### 4 Updating ESMValTool
-
-The ``main`` branch has the latest features of ESMValTool. Please make sure
-that the source code on your machine is up-to-date. If you obtain the source
-code using git clone as explained in step **1 Source code**, you can run ``git pull``
-to update the source code. Then ESMValTool installation will be updated
-with changes from the ``main`` branch.
-
-## Contribution
-
-We have seen how to install ESMValTool in a ``develop`` mode.
-Now, we try to contribute to its development. Let's see how this can be achieved.
-We first discuss our ideas in an
-**[issue](https://github.com/ESMValGroup/ESMValTool/issues)** in ESMValTool repository.
-This can avoid disappointment at a later stage, for example,
-if more people are doing the same thing.
-It also gives other people an early opportunity to provide input and suggestions,
-which results in more valuable contributions.
-
-Then, we create a new ``branch`` locally and start developing new codes.
-To create a new branch:
-~~~bash
-git checkout -b your_branch_name
-~~~
-If needed, a link to a git tutorial can be found in [Setup]({{ page.root }}{% link setup.md %}).
-
-Once our development is finished, we can initiate a ``pull request``.
-To this end, we encourage you to join the ESMValTool development team.
-
-For more extensive documentation on contributing code, including a section on the
-[GitHubWorkflow](https://docs.esmvaltool.org/en/latest/community/repository.html#github-workflow),
-please see the
-[Contributing code and documentation][code-documentation]
-section in the ESMValtool documentation.
-
-### Review process
-
-The pull request will be tested, discussed and merged as part of the "**review process**".
-The process will take some effort and time to learn.
-However, a few (command line) tools can get you a long way,
-and we’ll cover those essentials in the next sections.
-
-**Tip**: we encourage you to keep the pull requests small.
-Reviewing small incremental changes is more efficient.
-
-### Working example
-
-We saw the 'warming stripes' diagnostic in lesson
-[Writing your own recipe]({{ page.root }}{% link _episodes/06-preprocessor.md %}).
-Imagine the following task: you want to contribute warming stripes recipe and diagnostics
-to ESMValTool. You have to add the diagnostics
-[warming_stripes.py](../files/warming_stripes.py) and the recipe
-[recipe_warming_stripes.yml](../files/recipe_warming_stripes.yml)
-to their locations in ESMValTool directory.
-After these changes, you should also check if everything works fine.
-This is where we take advantage of the tools that are introduced later.
-
-Let’s get started. Note that since this is an exercise to get familiar with the
-development and contribution process, we will not create a GitHub issue at this time
-but proceed as though it has been done.
-
-### Check code quality
-
-We aim to adhere to best practices and coding standards. There are
-several tools that check our code against those standards like:
-
-- [flake8](https://flake8.pycqa.org/en/latest/#) for checking against the PEP8 style guide
-- [yapf](https://pypi.org/project/yapf/) to ensure consistent formatting for the whole project
-- [isort](https://pypi.org/project/isort/) to consistently sort the import statements
-- [yamllint](https://yamllint.readthedocs.io/en/stable/#) to ensure there are
-no syntax errors in our recipes and config files
-- [lintr](https://github.com/jimhester/lintr) for diagnostic scripts written in R
-- [codespell](https://pypi.org/project/codespell/) to check grammar
-
-The good news is that ``pre-commit`` has been already installed
-when we chose development installation.
-``pre-commit`` is a command line and runs all of those tools. It also fixes some of those errors.
-To explore other tools, have a look at ESMValTool documentation on
-[Code style](https://docs.esmvaltool.org/en/latest/community/introduction.html#code-style).
-
-> ## Using pre-commit
->
-> Let's checkout our local branch and add the script
-> [warming_stripes.py](../files/warming_stripes.py) to the
-> ``esmvaltool/diag_scripts`` directory.
->
-> ~~~bash
-> cd ESMValTool
-> git checkout your_branch_name
-> cp path_of_warming_stripes.py esmvaltool/diag_scripts/
-> ~~~
->
-> By default, ``pre-commit`` only runs on the files that have been staged in git:
->
-> ~~~bash
-> git status
-> git add esmvaltool/diag_scripts/warming_stripes.py
-> pre-commit run --files esmvaltool/diag_scripts/warming_stripes.py
-> ~~~
->
-> Inspect the output of ``pre-commit`` and fix the remaining errors.
->
->> ## Solution
->>
->> The tail of the output of ``pre-commit``:
->>
->> ~~~ bash
->> Check for added large files..............................................Passed
->> Check python ast.........................................................Passed
->> Check for case conflicts.................................................Passed
->> Check for merge conflicts................................................Passed
->> Debug Statements (Python)................................................Passed
->> Fix End of Files.........................................................Passed
->> Trim Trailing Whitespace.................................................Passed
->> yamllint.............................................(no files to check)Skipped
->> nclcodestyle.........................................(no files to check)Skipped
->> style-files..........................................(no files to check)Skipped
->> lintr................................................(no files to check)Skipped
->> codespell................................................................Passed
->> isort....................................................................Passed
->> yapf.....................................................................Passed
->> docformatter.............................................................Failed
->> - hook id: docformatter
->> - files were modified by this hook
->> flake8...................................................................Failed
->> - hook id: flake8
->> - exit code: 1
->>
->> esmvaltool/diag_scripts/warming_stripes.py:20:5:
->> F841 local variable 'nx' is assigned to but never used
->> ~~~
->>
->> As can be seen above, there are two ``Failed`` check:
->>
->> 1. ``docformatter``: it is mentioned that "files were modified by this hook".
->> We run ``git diff`` to see the modifications.
->> The output includes the following:
->> ~~~bash
->> +in the form of the popular warming stripes figure by Ed Hawkins."""
->> ~~~
->> The syntax ``"""`` at the end of docstring is moved by one line.
->> Shifting it to the next line should fix this error.
->>
->> 2. ``flake8``: the error message is about an unused local variable ``nx``.
->> We should check our codes regarding the usage of ``nx``.
->> For now, let's assume that it is added by mistake and remove it.
->> Note that you have to run `git add` again to re-stage the file.
->> Then rerun pre-commit and check that it passes.
-> {: .solution}
-{: .challenge}
-
-### Run unit tests
-
-Previous section introduced some tools to check code style and quality.
-There is lack of mechanism to determine whether or not our code is getting the right answer.
-To achieve that, we need to write and run tests for widely-used functions.
-ESMValTool comes with a lot of tests that are in the folder ``tests``.
-
-To run tests, first we make sure that the working directory is ``ESMValTool``
-and our local branch is checked out. Then, we can run tests using ``pytest`` locally:
-
-~~~bash
-pytest
-~~~
-
-Tests will also be run automatically by [CircleCI](https://circleci.com/),
-when you submit a pull request.
-
-> ## Running tests
->
-> Make sure our local branch is checked out and add the recipe
-> [recipe_warming_stripes.yml](../files/recipe_warming_stripes.yml)
-> to the ``esmvaltool/recipes`` directory:
->
-> ~~~bash
-> cp path_of_recipe_warming_stripes.yml esmvaltool/recipes/
-> ~~~
->
-> Run ``pytest`` and inspect the results, this might take a few minutes.
-> If a test is failed, try to fix it.
->
->> ## Solution
->>
->> Run:
->>
->> ~~~bash
->> pytest
->> ~~~
->>
->> When ``pytest`` run is complete, you can inspect the test reports
->> that are printed in the console. Have a look at the second section of the report
->> ``FAILURES``:
->>
->> ~~~ bash
->> ================================ FAILURES ==========================================
->> ______________ test_recipe_valid[recipe_warming_stripes.yml] ______________
->> ~~~
->>
->> The test message shows that the recipe ``recipe_warming_stripes.yml`` is not a valid recipe.
->> Look for a line that starts with an ``E`` in the rest of the message:
->>
->> ~~~ bash
->>
->> E esmvalcore._task.DiagnosticError: Cannot execute script
->> '~/esmvaltool_tutorial/warming_stripes.py' (~/esmvaltool_tutorial/warming_stripes.py):
->> file does not exist.
->> ~~~
->>
->> To fix the recipe, we need to edit the path of the diagnostic script
->> as ``warming_stripes.py``:
->>
->> ```yaml
->> scripts:
->> warming_stripes_script:
->> script: warming_stripes.py
->> ```
->>
->> For details, see lesson
->> [Writing your own diagnostic script]({{ page.root }}{% link _episodes/08-diagnostics.md %}).
->>
-> {: .solution}
-{: .challenge}
-
-### Build documentation
-
-When we add or update a code, we also update its corresponding documentation.
-The ESMValTool documentation is available on
-[docs.esmvaltool.org](https://docs.esmvaltool.org/en/latest/index.html).
-The source files are located in ``ESMValTool/doc/sphinx/source/``.
-
-To build documentation locally, first we make sure that the working directory is ``ESMValTool``
-and our local branch is checked out. Then, we run:
-
-~~~bash
-sphinx-build -Ea doc/sphinx/source/ doc/sphinx/build/
-~~~
-
-Similar to code, documentation should be well written and adhere to standards.
-If the documentation is built properly, the previous command prints a message to the console:
-
-~~~
-build succeeded.
-
-The HTML pages are in doc/sphinx/build.
-~~~
-{: .output}
-
-The main page of the documentation has been built into ``index.html``
-in ``doc/sphinx/build/`` directory.
-To preview this page locally, we open the file in a web browser:
-
-~~~bash
-xdg-open doc/sphinx/build/index.html
-~~~
-
-> ## Creating a documentation
->
-> In previous exercises, we added the recipe
-> [recipe_warming_stripes.yml](../files/recipe_warming_stripes.yml) to ESMValTool.
-> Now, we create a documentation file ``recipe_warming_stripes.rst`` for this recipe:
->
-> ~~~bash
-> nano doc/sphinx/source/recipes/recipe_warming_stripes.rst
-> ~~~
->
-> Add a reference i.e. ``.. _recipe_warming_stripes:``, a section title
-> and some text about the recipe like:
->
-> ```
-> .. _recipe_warming_stripes:
->
-> Reproducing Ed Hawkins' warming stripes visualization
-> ======================================================
->
-> This recipe produces warming stripes plots.
-> ```
->
-> Save and close the file. We can think of this file as one page of a book.
-> Examples of documentation pages can be found in the folder
-> ``ESMValTool/doc/sphinx/source/recipes``.
-> Then, we need to decide where this page should be located inside the book.
-> The table of content is defined by ``index.rst``. Let's have a look at the content:
->
-> ~~~bash
-> nano doc/sphinx/source/recipes/index.rst
-> ~~~
->
-> Add the recipe name i.e. ``recipe_warming_stripes`` to the section ``Other`` in this file
-> and preview the recipe documentation page locally.
->
->> ## Solution
->>
->> First, we add the recipe name ``recipe_warming_stripes`` to the section ``Other``:
->>
->> ```
->> Other
->> ^^^^^
->> .. toctree::
->> :maxdepth: 1
->> ...
->> ...
->> recipe_warming_stripes
->> ```
->>
->> Then, we build and preview the documentation page:
->>
->> ~~~bash
->> sphinx-build -Ea doc/sphinx/source/ doc/sphinx/build/
->> xdg-open doc/sphinx/build/recipes/recipe_warming_stripes.html
->> ~~~
->>
-> {: .solution}
-{: .challenge}
-
-Congratulations! You are now ready to make a pull request.
-
-{% include links.md %}
diff --git a/_episodes/09-cmorization.md b/_episodes/09-cmorization.md
deleted file mode 100644
index 92a888c5..00000000
--- a/_episodes/09-cmorization.md
+++ /dev/null
@@ -1,912 +0,0 @@
----
-title: "CMORization: adding new datasets to ESMValTool"
-teaching: 15
-exercises: 45
-compatibility: ESMValTool v2.6.0
-
-questions:
-- "CMORization: what is it and why do we need it?"
-- "How to use the existing CMORizer scripts shipped with ESMValTool?"
-- "How to add support for new (observational) datasets?"
-
-objectives:
-- "Understand what CMORization is and why it is necessary."
-- "Use existing scripts to CMORize your data."
-- "Write a new CMORizer script to support additional data."
-
-keypoints:
-- "CMORizers are dataset-specific scripts that can be run once to generate CMOR-compliant data."
-- "ESMValTool comes with a set of CMORizers readily available, but you can also add your own."
----
-
-![Data flow with ESMValTool](../fig/data_flow.png)
-
-## Introduction
-
-This episode deals with "CMORization". ESMValTool is designed to work with data
-that follow the CMOR standards. Unfortunately, not all datasets follow these
-standards. In order to use such datasets in ESMValTool we first need to reformat
-the data. This process is called "CMORization".
-
-> ## What are the CMOR standards?
->
-> The name "CMOR" originates from a tool: [the Climate Model Output
-> Rewriter](https://cmor.llnl.gov/). This tool is used to create "CF-Compliant
-> netCDF files for use in the CMIP projects". So CMOR extends the
-> [CF-standard](https://cfconventions.org/) with additional requirements for
-> the Coupled Model Intercomparison Projects (see e.g.
-> [here](https://pcmdi.llnl.gov/CMIP6/Guide/modelers.html#5-model-output-requirements)).
->
->
-> Concretely, the CMOR standards dictate e.g. the variable names and units,
-coordinate information, how the data should be structured (e.g. 1 variable per
-file), additional metadata requirements, and file naming conventions a.k.a.
-the data reference syntax
-([DRS](https://docs.esmvaltool.org/projects/esmvalcore/en/latest/quickstart/find_data.html)).
-> All this information is stored in so-called CMOR tables.
-> For example, the CMOR tables for the CMIP6 project can be found
-[here](https://github.com/PCMDI/cmip6-cmor-tables).
-{: .callout}
-
-ESMValTool offers two ways to CMORize data:
-1. A reformatting script can be used to create a CMOR-compliant copy. CMORizer
- scripts for several popular datasets are included in ESMValTool, and
- ESMValTool also provides a convenient way to execute them.
-2. ESMValCore can execute CMOR fixes '[on the
- fly](https://docs.esmvaltool.org/projects/esmvalcore/en/latest/develop/
-fixing_data.html#fixing-data)'.
- The advantage is that you don't need to store an additional, reformatted copy
- of the data. The disadvantage is that these fixes should be implemented
- inside ESMValCore, which is beyond the scope of this tutorial.
-
-In this lesson, we will re-implement a CMORizer script for the FLUXCOM dataset
-that contains observations of the Gross Primary Production (GPP), a variable
-that is important for calculating components of the global carbon cycle.
-See the next section on how to obtain data.
-
-As in the previous episode
-([Development and Contribution episode]({{ page.root }}{% link
- _episodes/07-development-setup.md %})),
-we will be using the development installation of ESMValTool.
-
-
-## Obtaining the data
-
-The data for this episode is available via the [FluxCom Data
-Portal](http://www.bgc-jena.mpg.de/geodb/BGI/Home). First you'll need to
-register. After registration, in the dropdown boxes, select FLUXCOM as the data
-choice and click download. Three files will be displayed. Click the download
-button on the "FLUXCOM (RS+METEO) Global Land Carbon Fluxes using CRUNCEP
-climate data". You'll receive an email with the FTP address to access the
-server. Connect to the server, follow the path in your email, and look for the
-file `raw/monthly/GPP.ANN.CRUNCEPv6.monthly.2000.nc`. Download that file and
-save it in a folder called `~/data/RAWOBS/Tier3/FLUXCOM`.
-
-Note: you'll need a user-friendly ftp client. On Linux, `ncftp` works okay.
-
-> ## What is the deal with those "tiers"?
->
-> Many datasets come with access restrictions. In this way the data providers
-> can keep track of how their data is used. In many cases "restricted access"
-> just means that one has to register with an email address and accept the terms
-> of use, which typically ask that you acknowledge the data providers.
->
-> There are also datasets available that do not need a registration. The
-> "obs4MIPs" or "ana4MIPs" datasets, for example, are specifically produced to
-> facilitate comparisons with model simulations.
->
-> To reflect these different levels of access restriction, the ESMValTool team
-> has created a tier-system. The definition of the different tiers are
-> as follows:
->
-> - **Tier1**: obs4MIPs and ana4MIPS datasets (can be used directly with the ESMValTool)
-> - **Tier2**: other freely available datasets (most of them will need some kind of
-> cmorization)
-> - **Tier3**: datasets with access restrictions (most of these datasets will also
-> need some kind of cmorization)
->
-> These access restrictions are also why the ESMValTool developers
-> cannot distribute copies or automate downloading of all observations and
-> reanalysis data used in the recipes. As a compromise, we provide the
-> CMORization scripts so that each user can CMORize their own copy of the access
-> restricted datasets if needed.
->
-{: .callout}
-
-## Run the existing CMORizer script
-
-Before we develop our own CMORizer script, let's first see what happens when we
-run the existing one. There is a specific command available in the ESMValTool to
-run the CMORizer scripts:
-
-```bash
-esmvaltool data format --config_file
-```
-
-The ``config-user.yml`` is the file in which we define the different data
-paths, see the episode on [Configuration]({{ page.root }}{% link _episodes/03-configuration.md %}).
-In the ``rootpath`` of your ``config-user.yml``, make sure to add the right
-directory for "RAWOBS" data in which you downloaded the FLUXCOM dataset:
-
-```yaml
-rootpath:
- RAWOBS: ~/data/RAWOBS
-```
-
-This enables ESMValTool to find the raw observational datasets stored in the
-"RAWOBS" folder. The ``dataset-name`` needs to be identical to the folder
-name that was created to store the raw observation data files, i.e.
-``RAWOBS/TierX/dataset-name``. In our case this would be "FLUXCOM".
-
-If everything is okay, the output should look something like this:
-
-~~~
-...
-... Starting the CMORization Tool at time: 2022-07-26 14:02:16 UTC
-... ----------------------------------------------------------------------
-... input_dir = /home/peter/data/RAWOBS
-... output_dir = /home/peter/esmvaltool_output/data_formatting_20220726_140216
-... ----------------------------------------------------------------------
-... Running the CMORization scripts.
-... Processing datasets ['FLUXCOM']
-... Input data from: /home/peter/data/RAWOBS/Tier3/FLUXCOM
-... Output will be written to: /home/peter/esmvaltool_output/
- data_formatting_20220726_140216/Tier3/FLUXCOM
-... Reformat script: /home/peter/mambaforge/envs/esmvaltool/lib/python3.9/
- site-packages/esmvaltool/cmorizers/data/formatters/datasets/fluxcom
-... CMORizing dataset FLUXCOM using Python script /home/peter/mambaforge/envs/
- esmvaltool/lib/python3.9/site-packages/esmvaltool/cmorizers/data/formatters/
- datasets/fluxcom.py
-... Found input file '/home/peter/data/RAWOBS/Tier3/FLUXCOM/GPP.ANN.CRUNCEPv6.monthly.*.nc'
-... CMORizing variable 'gpp'
-... Lmon
-... Var is gpp
-... ... UserWarning: Ignoring netCDF variable 'GPP' invalid units 'gC m-2 day-1'
-
-... Fixing time...
-... Fixing latitude...
-... Fixing longitude...
-... Flipping dimensional coordinate latitude...
-... Saving file
-... Saving: /home/peter/esmvaltool_output/data_formatting_20220726_140216/Tier3/
- FLUXCOM/OBS_FLUXCOM_reanaly_ANN-v1_Lmon_gpp_200001-200012.nc
-... Cube has lazy data [lazy is preferred]
-... CMORization of dataset FLUXCOM finished!
-... Formatting successful for dataset FLUXCOM
-~~~
-{: .output}
-
-So you can see that several fixes are applied, and the CMORized file is written
-to the ESMValTool output directory, i.e.
-`~/esmvaltool_output/data_formatting_YYYYMMDD_HHMMSS/TierX/dataset-name/filename.nc`
-In order to use it, we'll have to copy it from the output directory to a folder
-called `~/data/OBS/Tier3/FLUXCOM` and make sure the path to ``OBS`` is set
-correctly in our config-user file:
-
-```yaml
-rootpath:
- OBS: ~/data/OBS
-```
-
-You can also see the path where ESMValTool stores the reformatting script:
-`~/ESMValTool/esmvaltool/data/formatters/datasets/fluxcom.py`. You may
-have a look at this file if you want. The script also uses a configuration file:
-`~/ESMValTool/esmvaltool/cmorizers/data/cmor_config/FLUXCOM.yml`.
-
-## Make a test recipe
-
-To verify that the data is correctly CMORized, we will make a simple test
-recipe. As illustrated in the figure at the top of this episode, one of the
-steps that ESMValTool executes is a CMOR-check. If the data is not correctly
-CMORized, ESMValTool will give a warning or error.
-
-> ## Create a test recipe
->
-> Create a simple recipe called [recipe_check_fluxcom.yml](../files/recipe_check_fluxcom.yml)
-> that loads the FLUXCOM data. It should include a datasets section with a single entry for
-> the "FLUXCOM" dataset with the correct dataset keys, and a diagnostics section
-> with two variables: gpp. We don't need any preprocessors or
-> scripts (set `scripts: null`), but we have to add a documentation section with
-> a description, authors and maintainer, otherwise the recipe will fail.
->
-> Use the following dataset keys:
->
-> - project: OBS
-> - dataset: FLUXCOM
-> - type: reanaly
-> - version: ANN-v1
-> - mip: Lmon
-> - start_year: 2000
-> - end_year: 2000
-> - tier: 3
->
-> Some of these dataset keys are further explained in the callout boxes in this
-> episode.
->
-> > ## Answer
-> >
-> > Here's an example recipe
-> >
-> > ```yaml
-> > documentation:
-> >
-> > description: Test recipe for FLUXCOM data
-> > title: This is a test recipe for the FLUXCOM data.
-> >
-> > authors:
-> > - kalverla_peter
-> >
-> > maintainer:
-> > - kalverla_peter
-> >
-> > datasets:
-> > - {project: OBS, dataset: FLUXCOM, mip: Lmon, tier: 3, start_year: 2000,
-> > end_year: 2000, type: reanaly, version: ANN-v1}
-> >
-> > diagnostics:
-> > check_fluxcom:
-> > description: Check that ESMValTool can load the cmorized fluxnet data without errors.
-> > variables:
-> > gpp:
-> > scripts: null
-> >
-> > ```
-> >
-> > To learn more about writing a recipe, please refer to
-[Writing your own recipe]({{ page.root }}{% link _episodes/06-preprocessor.md %}).
-> >
-> {: .solution}
-{: .challenge}
-
-Try to run the example recipe with
-
-```bash
-esmvaltool run recipe_check_fluxcom.yml --config_file --log_level debug
-```
-
-If everything is okay, the recipe should run without problems.
-
-## Starting from scratch
-
-Now that you've seen how to use an existing CMORizer script, let's think about
-adding a new one. We will remove the existing CMORizer script, and re-implement
-it from scratch. This exercise allows us to point out all the details of what's
-going on. We'll also remove the CMORized data that we've just created, so our
-test recipe will not be able to use it anymore.
-
-```bash
-rm ~/data/OBS/Tier3/FLUXCOM/OBS_FLUXCOM_reanaly_ANN-v1_Lmon_gpp_200001-200012.nc
-rm ~/ESMValTool/esmvaltool/cmorizers/data/formatters/datasets/fluxcom.py
-rm ~/ESMValTool/esmvaltool/cmorizers/data/cmor_config/FLUXCOM.yml
-```
-
-If you now run the test recipe again it should fail, and somewhere in the output
-you should find something like:
-
-~~~
-No input files found for ...
-Looked for files matching: /home/peter/data/OBS/Tier3/
- FLUXCOM/OBS_FLUXCOM_reanaly_ANN-v1_Lmon_gpp[_.]*nc
-~~~
-{: .error}
-
-From this we can see that the first thing our CMORizer should do is to rename
-the file so that it follows the CMOR filename conventions.
-
-## Create a new CMORizer script and a corresponding config file
-
-The first step now is to create a new file in the right folder that will contain
-our new CMORizer instructions. Create a file called ``fluxcom.py``
-
-```bash
-nano ~/ESMValTool/esmvaltool/cmorizers/data/formatters/datasets/fluxcom.py
-```
-
-and fill it with the following boilerplate code:
-
-```python
-"""ESMValTool CMORizer for FLUXCOM GPP data.
-
-
-"""
-import logging
-from esmvaltool.cmorizers.data import utilities as utils
-
-logger = logging.getLogger(__name__)
-
-def cmorization(in_dir, out_dir, cfg, cfg_user, start_date, end_date):
- """Cmorize the dataset."""
-
- # This is where you'll add the cmorization code
- # 1. find the input data
- # 2. apply the necessary fixes
- # 3. store the data with the correct filename
-```
-
-Here, ``in_dir`` corresponds to the input directory of the raw files,
-``out_dir`` to the output directory of final reformatted data set and ``cfg`` to
-a configuration dictionary given by a configuration file that we will get to
-shortly. The last three arguments will not be considered in this script but
-can be used in other cases. ``cfg_user`` corresponds to the user configuration
-file, ``start_date`` to the start of the period to format, and ``end_date`` to
-the end of the period to format. When you type the command ``esmvaltool data format``
-in the terminal, ESMValTool will call this function with the settings found in
-your configuration files.
-
-The ESMValTool CMORizer also needs a dataset configuration file. Create a file
-called `~/ESMValTool/esmvaltool/cmorizers/data/cmor_config/FLUXCOM.yml`
-and fill it with the following boilerplate:
-
-```yaml
----
-# filename: ???
-
-attributes:
- project_id: OBS6
-# dataset_id: ???
-# version: ???
-# tier: ???
-# modeling_realm: ???
-# source: ???
-# reference: ???
-# comment: ???
-
-# variables:
-# ???:
-# mip: ???
-```
-
- **Note**: the name of this file *must* be identical to ``dataset-name``.
-
-As you can see, the configuration file contains information about the original
-filename of the dataset, and some additional metadata that you might recognize
-from the CMOR filename structure. It also contains a list of variables that's
-available for this dataset. We'll add this information step by step in the
-following sections.
-
-> ## RAWOBS, OBS, OBS6!?
->
-> In the configuration above we've already filled in the `project_id`.
-> ESMValTool uses these project IDs to find the data on your hard drive, and
-> also to find more information about the data. The `RAWOBS` and `OBS` projects
-> refer to *external* data before and after CMORization, respectively.
-> Historically, most external data were observations, hence the naming.
->
-> In going from CMIP5 to CMIP6, the CMOR standards changed a bit. For example,
-> some variables were renamed, which posed a dilemma: should CMORization
-> reformat to the CMIP5 or CMIP6 definition? To solve this, the `OBS6` project
-> was created. So `OBS6` data follow the CMIP6 standards, and that's what we'll
-> use for the new CMORizer.
->
-{: .callout}
-
-You can try running the CMORizer at this point, and it should work without
-errors. However, it doesn't produce any output yet:
-
-```bash
-esmvaltool data format --config_file FLUXCOM
-```
-
-### 1. Find the input data
-
-First we'll get the CMORizer script to locate our FLUXCOM data. We can use the
-information from the `in_dir` and `cfg` variables. Add the following snippet to
-your CMORizer script:
-
-```python
-# 1. find the input data
-logger.info("in_dir: '%s'", in_dir)
-logger.info("cfg: '%s'", cfg)
-```
-
-If you run the CMORizer again, it will print out the content of these variables
-and the output should contain something like this:
-
-~~~
-... in_dir: '/home/peter/data/RAWOBS/Tier3/FLUXCOM'
-... cfg: '{'attributes': {'project_id': 'OBS6', 'comment': ''},
- 'cmor_table': }'
-~~~
-{: .output}
-
-> ## Load the data
->
-> Try to locate the input data inside the CMORizer script and load it (we'll use
-> `iris` because ESMValTool includes helper utilities for iris cubes). Confirm
-> that you've loaded the data by logging the correct path and (part of the) file
-> content.
->
-> > ## Solution
-> >
-> > There are many ways to do it. In any case, you should have added the
-> > original filename to the configuration file (and un-commented this line):
-> > `filename: 'GPP.ANN.CRUNCEPv6.monthly.*.nc'`. Note the `*`: this is a useful
-> > shorthand to find multiple files for different years. In a similar way we
-> > can also look for multiple variables, etc.
-> >
-> > Here's an example solution (inserted directly under the original comment):
-> >
-> > ```python
-> > # 1. find the input data
-> > filename_pattern = cfg['filename']
-> > matches = Path(in_dir).glob(filename_pattern)
-> >
-> > for match in matches:
-> > input_file = str(match)
-> > logger.info("found: %s", input_file)
-> > cube = iris.load_cube(input_file)
-> > logger.info("content: %s", cube)
-> > ```
-> >
-> > To make this work we've added `import iris` and `from pathlib import Path`
-> > at the top of the file. Note that we've started a loop, since we may find
-> > multiple files if there's more than one year of data available.
-> >
-> {: .solution}
-{: .challenge}
-
-### 2. Save the data with the correct filename
-
-Before we start adding fixes, we'll first make sure that our CMORizer can also
-write output files with the correct name. This will enable us to use the test
-recipe for the CMOR compatibility check.
-
-We can use the `save` function from the `utils` that we imported at the top. The
-call signature looks like this:
-`utils.save_variables(cube, var, outdir, attrs, **kwargs)`.
-
-We already have the `cube` and the `outdir`. The variable short name (`var`) and
-attributes (`attrs`) are set through the configuration file. So we need to find
- out what the correct short name and attributes are.
-
-The standard attributes for CMIP variables are defined in the [CMIP
-tables](https://github.com/ESMValGroup/ESMValCore/tree/main/esmvalcore/cmor/tables/cmip6/Tables).
-These tables are differentiated according to the "MIP" they belong to. The
-tables are a copy of the [PCMDI](https://github.com/PCMDI) guidelines.
-
-> ## Find the variable "gpp" in a CMOR table
->
-> Check the available CMOR tables to find the variable "gpp" with the following characteristics:
-> - standard_name: ``gross_primary_productivity_of_biomass_expressed_as_carbon``
-> - frequency: ``mon``
-> - modeling_realm: ``land``
->
-> > ## Answers
-> >
-> > The variable "gpp" belongs to the land variables. The temporal resolution that we are looking
-> > for is "monthly". This information points to the "Lmon" CMIP table. And indeed, the variable
-> > "gpp" can be found in the file
-> > [here](https://github.com/ESMValGroup/ESMValCore/blob/main/esmvalcore/
-cmor/tables/cmip6/Tables/CMIP6_Lmon.json).
-> >
-> {: .solution}
-{: .challenge}
-
-If the variable you are interested in is not available in the standard CMOR
-tables, you could write a custom CMOR table entry for the variable. This,
-however, is beyond the scope of this tutorial.
-
-> ## Fill the configuration file
->
-> Uncomment the following entries in your configuration file and fill them with appropriate values:
->
-> - dataset_id
-> - version
-> - tier
-> - modeling_realm
-> - short_name (the ??? immediately under `variables`)
-> - mip
->
-> > ## Answers
-> >
-> > The configuration file now look something like this:
-> >
-> > ```yaml
-> > ---
-> > filename: 'GPP.ANN.CRUNCEPv6.monthly.*.nc'
-> >
-> > attributes:
-> > project_id: OBS6
-> > dataset_id: FLUXCOM
-> > version: 'ANN-v1'
-> > tier: 3
-> > modeling_realm: reanaly
-> > source: ''
-> > reference: ''
-> > comment: ''
-> >
-> > variables:
-> > gpp:
-> > mip: Lmon
-> > ```
-> >
-> {: .solution}
-{: .challenge}
-
-Now that we have set this information correctly in the config file, we can call
-the save function. Add the following python code to your CMORizer script:
-
-```python
-# 3. store the data with the correct filename
-attributes = cfg['attributes']
-variables = cfg['variables']
-
-for short_name, variable_info in variables.items():
- all_attributes = {**attributes, **variable_info} # add the mip to the other attributes
- utils.save_variable(cube=cube, var=short_name, outdir=out_dir, attrs=all_attributes)
-```
-
-Since we only have one variable (gpp), the loop is not strictly necessary.
-However, this makes it possible to add more variables later on.
-
-> ## Was the CMORization successful so far?
->
-> If you run the CMORizer again, you should see that it creates an output file
-> named ``OBS6_FLUXCOM_reanaly_ANN-v1_Lmon_gpp_xxxx01-xxxx12.nc`` stored in your
-> ESMValTool output directory `~/esmvaltool_output/data_formatting_YYYYMMDD_HHMMSS/Tier3/FLUXCOM/`.
-> The "xxxx" and "yyyy" represent the start and end year of the data.
->
-{: .callout}
-
-Great! So we have produced a NetCDF file with the CMORizer that follows the
-naming convention for ESMValTool datasets. Let's have a look at the NetCDF file
-as it was written with the very basic CMORizer from above.
-
-```bash
-ncdump -h OBS6_FLUXCOM_reanaly_ANN-v1_Lmon_gpp_200001-200012.nc
-```
-
-~~~
-netcdf OBS6_FLUXCOM_reanaly_ANN-v1_Lmon_gpp_200001-200012 {
-dimensions:
- time = 12 ;
- lat = 360 ;
- lon = 720 ;
-variables:
- float GPP(time, lat, lon) ;
- GPP:_FillValue = 1.e+20f ;
- GPP:long_name = "GPP" ;
- double time(time) ;
- time:axis = "T" ;
- time:units = "days since 1582-10-15 00:00:00" ;
- time:standard_name = "time" ;
- time:calendar = "gregorian" ;
- double lat(lat) ;
- double lon(lon) ;
-
-// global attributes:
- :_NCProperties = "version=2,netcdf=4.7.4,hdf5=1.10.6" ;
- :created_by = "Fabian Gans [fgans@bgc-jena.mpg.de], Ulrich Weber
- [uweber@bgc-jena.mpg.de]" ;
- :flux = "GPP" ;
- :forcing = "CRUNCEPv6" ;
- :institution = "MPI-BGC-BGI" ;
- :invalid_units = "gC m-2 day-1" ;
- :method = "Artificial Neural Networks" ;
- :provided_by = "Martin Jung [mjung@bgc-jena.mpg.de] on behalf of FLUXCOM team" ;
- :reference = "Jung et al. 2016, Nature; Tramontana et al. 2016, Biogeosciences" ;
- :temporal_resolution = "monthly" ;
- :title = "GPP based on FLUXCOM RS+METEO with CRUNCEPv6 climate " ;
- :version = "v1" ;
- :Conventions = "CF-1.7" ;
-}
-~~~
-{: .output}
-
-The file contains a variable named "GPP" that contains three dimensions: "time",
-"lat", "lon". Notice the strange time units, and the `invalid_units` in the
-global attributes section. Also it seems that there is not information available
-about the lat and lon coordinates. These are just some of the things we'll
-address in the next section.
-
-### 3. Implementing additional fixes
-
-Copy the output of the CMORizer to your folder `~/data/OBS6/Tier3/FLUXCOM/`
-and change the test recipe to look for OBS6 data instead of OBS (note: we're
-upgrading the CMORizer to newer standards here!). Make sure the path to ``OBS6``
-is set correctly in our config-user file:
-
-```yaml
-rootpath:
- OBS6: ~/data/OBS6
-```
-
-If we now run the test recipe on our newly 'CMORized' data,
-
-```bash
-esmvaltool run recipe_check_fluxcom.yml --config_file --log_level debug
-```
-
-it should be able to find the correct file, but it does not succeed yet. The first
-thing that the ESMValTool CMOR checker brings up is:
-
-~~~
-iris.exceptions.UnitConversionError: Cannot convert from unknown units. The
-"units" attribute may be set directly.
-~~~
-{: .error}
-
-If you look closely at the error messages, you can see that this error concerns
-the units of the coordinates. ESMValTool tries to fix them automatically,
-but since no units are defined on the coordinates, this fails.
-
-The cmorizer utilities also include a function called `fix_coords`, but before
-we can use it, we'll also need to make sure the coordinates have the correct
-standard name. Add the following code to your cmorizer:
-
-```python
-# 2. Apply the necessary fixes
-# 2a. Fix/add coordinate information and metadata
-cube.coord('lat').standard_name = 'latitude'
-cube.coord('lon').standard_name = 'longitude'
-utils.fix_coords(cube)
-```
-
-With some additional refactoring, our cmorization function might then look
-something like this:
-
-```python
-def cmorization(in_dir, out_dir, cfg, cfg_user, start_date, end_date):
- """Cmorize the dataset."""
-
- # Get general information from the config file
- attributes = cfg['attributes']
- variables = cfg['variables']
-
- for short_name, variable_info in variables.items():
- logger.info("CMORizing variable: %s", short_name)
-
- # 1a. Find the input data (one file for each year)
- filename_pattern = cfg['filename']
- matches = Path(in_dir).glob(filename_pattern)
-
- for match in matches:
- # 1b. Load the input data
- input_file = str(match)
- logger.info("found: %s", input_file)
- cube = iris.load_cube(input_file)
-
- # 2. Apply the necessary fixes
- # 2a. Fix/add coordinate information and metadata
- cube.coord('lat').standard_name = 'latitude'
- cube.coord('lon').standard_name = 'longitude'
- utils.fix_coords(cube)
-
- # 3. Save the CMORized data
- all_attributes = {**attributes, **variable_info}
- utils.save_variable(cube=cube, var=short_name, outdir=out_dir, attrs=all_attributes)
-```
-
-Run the CMORizer script once more. Have a look at the netCDF file,
-and confirm that the coordinates now have much more metadata added to them.
-Then, run the test recipe again with the latest CMORizer output.
-The next error is:
-
-~~~
-esmvalcore.cmor.check.CMORCheckError: There were errors in variable GPP:
-Variable GPP units unknown can not be converted to kg m-2 s-1 in cube:
-~~~
-{: .error}
-
-Okay, so let's fix the units of the "GPP" variable in the CMORizer. Remember
-that you can find the correct units in the CMOR table. Add the following three
-lines to our CMORizer:
-
-```python
-# 2b. Fix gpp units
-logger.info("Changing units for gpp from gc/m2/day to kg/m2/s")
-cube.data = cube.core_data() / (1000 * 86400)
-cube.units = 'kg m-2 s-1'
-```
-
-If everything is okay, the test recipe should now pass. We're getting there.
-Looking through the output though, there's still a warning.
-
-~~~
-WARNING There were warnings in variable GPP:
-Standard name for GPP changed from None to gross_primary_productivity_of_biomass_expressed_as_carbon
-Long name for GPP changed from GPP to Carbon Mass Flux out of Atmosphere Due to
- Gross Primary Production on Land [kgC m-2 s-1]
-~~~
-{: .output}
-
-ESMValTool is able to apply automatic fixes here, but if we are running a
-CMORizer script anyway, we might as well fix it immediately.
-
-Add the following snippet:
-
-```python
-# 2c. Fix metadata
-cmor_table = cfg['cmor_table']
-cmor_info = cmor_table.get_variable(variable_info['mip'], short_name)
-utils.fix_var_metadata(cube, cmor_info)
-```
-
-You can see that we're using the CMOR table here. This was passed on by
-ESMValTool as part of the `CFG` input variable. So here we're making sure that
-we're updating the cubes metadata to conform to the CMOR table.
-
-Finally, the test recipe should run without errors or warnings.
-
-### 4. Finalizing the CMORizer
-
-Once everything works as expected, there's a couple of things that we can still do.
-
-- **Add download instructions**. The header of the CMORizer contains information about
- where to obtain the data, when it was accessed the last time, which ESMValTool
- "tier" it is associated with, and more detailed information about the
- necessary downloading and processing steps.
-
-> ## Fill out the header for the "FLUXCOM" dataset
->
-> Fill out the header of the new CMORizer. The different parts that need to be
-> present in the header are the following:
->
-> - Caption: the first line of the docstring should summarize what the script does.
-> - Tier
-> - Source
-> - Last access
-> - Download and processing instructions
->
-> > ## Answers
-> >
-> > The header for the "FLUXCOM" dataset could look something like this:
-> >
-> > ```python
-> > """ESMValTool CMORizer for FLUXCOM GPP data.
-> >
-> > Tier
-> > Tier 3: restricted dataset.
-> >
-> > Source
-> > http://www.bgc-jena.mpg.de/geodb/BGI/Home
-> >
-> > Last access
-> > 20190727
-> >
-> > Download and processing instructions
-> > From the website, select FLUXCOM as the data choice and click download.
-> > Two files will be displayed. One for Land Carbon Fluxes and one for
-> > Land Energy fluxes. The Land Carbon Flux file (RS + METEO) using
-> > CRUNCEP data file has several data files for different variables.
-> > The data for GPP generated using the
-> > Artificial Neural Network Method will be in files with name:
-> > GPP.ANN.CRUNCEPv6.monthly.\*.nc
-> > A registration is required for downloading the data.
-> > Users in the UK with a CEDA-JASMIN account may request access to the jules
-> > workspace and access the data.
-> > Note : This data may require rechunking of the netcdf files.
-> > This constraint will not exist once iris is updated to
-> > version 2.3.0 Aug 2019
-> > """
-> > ```
-> {: .solution}
-{: .challenge}
-
-
-- **Fill the dataset information list**. The file
-[datasets.yml](https://github.com/ESMValGroup/ESMValTool/blob/main/esmvaltool/
-cmorizers/data/datasets.yml)
- contains the ESMValTool "tier", the data source, the last access time and
- download instructions for all supported datasets in ESMValTool. You can
- simply reuse the information written in the header of the CMORizer.
-
-> ## Fill out the FLUXCOM entry in ``datasets.yml``
->
-> Fill out the FLUXCOM entry in ``datasets.yml``. The different parts that need to be
-> present in the entry are the following:
->
-> - Dataset-name
-> - Tier
-> - Source
-> - Last access
-> - Download and processing instructions
->
-> > ## Answers
-> >
-> > The entry for the "FLUXCOM" dataset should look like:
-> >
-> > ```yaml
-> > FLUXCOM:
-> > tier: 3
-> > source: http://www.bgc-jena.mpg.de/geodb/BGI/Home
-> > last_access: 2019-07-27
-> > info: |
-> > From the website, select FLUXCOM as the data choice and click download.
-> > Two files will be displayed. One for Land Carbon Fluxes and one for
-> > Land Energy fluxes. The Land Carbon Flux file (RS + METEO) using
-> > CRUNCEP data file has several data files for different variables.
-> > The data for GPP generated using the
-> > Artificial Neural Network Method will be in files with name:
-> > GPP.ANN.CRUNCEPv6.monthly.*.nc
-> > A registration is required for downloading the data.
-> > Users in the UK with a CEDA-JASMIN account may request access to the jules
-> > workspace and access the data.
-> > Note : This data may require rechunking of the netcdf files.
-> > This constraint will not exist once iris is updated to
-> > version 2.3.0 Aug 2019
-> > ```
-> {: .solution}
-{: .challenge}
-
-Once the ``datasets.yml`` file is filled, you can check that ESMValTool can
-display information about the added dataset with:
-
-```bash
-esmvaltool data info FLUXCOM
-```
-
-If everything is okay, the output should look something like this:
-
-~~~
- $ esmvaltool data info FLUXCOM
-FLUXCOM
-
-Tier: 3
-Source: http://www.bgc-jena.mpg.de/geodb/BGI/Home
-Automatic download: No
-
-From the website, select FLUXCOM as the data choice and click download.
-Two files will be displayed. One for Land Carbon Fluxes and one for
-Land Energy fluxes. The Land Carbon Flux file (RS + METEO) using
-CRUNCEP data file has several data files for different variables.
-The data for GPP generated using the
-Artificial Neural Network Method will be in files with name:
-GPP.ANN.CRUNCEPv6.monthly.*.nc
-A registration is required for downloading the data.
-Users in the UK with a CEDA-JASMIN account may request access to the jules
-workspace and access the data.
-Note : This data may require rechunking of the netcdf files.
-This constraint will not exist once iris is updated to
-version 2.3.0 Aug 2019
-~~~
-{: .output}
-
-Note that ``Automatic download: No`` means that no automatic downloading script
-is available in ESMValTool for this dataset. The implementation of such a
-script is beyond the scope of this tutorial. To find out which datasets come
-with an automatic download script, you can run: ``esmvaltool data list`` to
-list all datasets supported in ESMValTool. More information about the usage
-of automatic downloading scripts can be found in the
-[User Guide](https://docs.esmvaltool.org/en/latest/develop/dataset.html#downloader-script-optional).
-
-- **Complete the metadata in the config file**. We have left a few fields empty
- in the configuration file, such as 'source'. By filling out these fields we can
- make sure the relevant metadata is passed on as attributes in the CMORized
- data. To make this work, add the following line to the CMORizer script:
-
-```python
-# 2d. Update the cubes metadata with all info from the config file
-utils.set_global_atts(cube, attributes)
-```
-
-- **Add a reference**. Make sure that there is a reference file available for
- the dataset, see the instruction [here](https://docs.esmvaltool.org/en
-/latest/community/diagnostic.html#adding-references).
-
-- **Make a pull request**. Since you have gone through all the trouble to
- reformat the dataset so that the ESMValTool can work with it, it would be
- great if you could provide the CMORizer, and ultimately with that the dataset,
- to the rest of the community. For more information, see the episode
- on [Development and contribution]({{ page.root }}{% link _episodes/07-development-setup.md %}).
-
-- **Add documentation**. Make sure that you have added the info of your dataset
- to the User Guide so that people know it is available for the ESMValTool
- [Obtaining input
- data](https://github.com/ESMValGroup/ESMValTool/blob/main/doc/sphinx/source/input.rst).
-
-
-## Some final comments
-
-Congratulations! You have just added support for a new dataset to ESMValTool!
-Adding a new CMORizer is definitely already an advanced task when working with
-the ESMValTool. You need to have a basic understanding of how the ESMValTool
-works and how it's internal structure looks like. In addition, you need to have
-a basic understanding of NetCDF files and a programming language. In our example
-we used python for the CMORizing script since we advocate for focusing the code
-development on only a few different programming languages. This helps to
-maintain the code and to ensure the compatibility of the code with possible
-fundamental changes to the structure of the ESMValTool and ESMValCore.
-
-More information about adding observations to the ESMValTool can be found in the
-[documentation](https://docs.esmvaltool.org/en/latest/input.html#observations).
From 66201c1ce7f519631d7346e20e1905eca116c22f Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Wed, 24 Jul 2024 20:52:19 +1000
Subject: [PATCH 04/49] Update action
---
.github/workflows/website.yml | 6 ------
1 file changed, 6 deletions(-)
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
index 0d46e851..8c36fdc5 100644
--- a/.github/workflows/website.yml
+++ b/.github/workflows/website.yml
@@ -97,12 +97,6 @@ jobs:
ref: gh-pages
path: gh-pages
- - name: Validate workshop website
- # https://github.com/carpentries/styles/issues/551 is no longer relevant as styles shouldn't be used for
- # lessons but only workshop templates. So, always run the workshop checks now.
- run: make workshop-check
- if: always()
-
- name: Commit and Push
if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}}
run: |
From 324e4b6c0f628520fdea3bf26a2747a27a529f47 Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Wed, 24 Jul 2024 21:19:53 +1000
Subject: [PATCH 05/49] Remove some files
---
_episodes/01-quickstart.md | 11 ++--------
_episodes/08-diagnostics.md | 10 ++-------
_episodes/10-debugging.md | 10 +++------
_includes/links.md | 2 --
index.md | 43 ++-----------------------------------
setup.md | 7 ------
6 files changed, 9 insertions(+), 74 deletions(-)
diff --git a/_episodes/01-quickstart.md b/_episodes/01-quickstart.md
index a3600906..ea51b1b2 100644
--- a/_episodes/01-quickstart.md
+++ b/_episodes/01-quickstart.md
@@ -23,10 +23,7 @@ keypoints:
- "The purpose of the quickstart guide is to enable a user of ESMValTool
to run ESMValTool as quickly as possible without having to go through the
whole tutorial"
-- "Use the `module load` command to load the ESMValTool environment,
- see the [Installation][lesson-installation]
- episode for more details and use `esmvaltool --help` to check the ESMValTool
- environment"
+- "Use the `module load` command to load the ESMValTool environment"
- "Use `esmvaltool config get_config_user` to create the ESMValTool user
configuration file"
- "Use `esmvaltool run .yml` to run a recipe"
@@ -43,9 +40,7 @@ keypoints:
> ## How do I load and check the ESMValTool environment?
>
> - For this quickstart guide, an assumption is made that ESMValTool has
-> already been installed at the site where ESMValTool will be run. If this is
-> not the case, see the [Installation][lesson-installation] episode in this
-> tutorial.
+> already been installed at the site where ESMValTool will be run.
>
> - Load the ESMValTool environment by following the instructions at
> [ESMValTool: Pre-installed versions on HPC clusters / other
@@ -72,8 +67,6 @@ keypoints:
> - Edit the ESMValTool user configuration file using your favourite text editor
> to uncomment the lines relating to the site where ESMValTool will be run.
>
-> - For more details about the ESMValTool user configuration file see the
-> [Configuration][lesson-configuration] episode in this tutorial.
{: .challenge}
> ## How do I run a recipe?
diff --git a/_episodes/08-diagnostics.md b/_episodes/08-diagnostics.md
index 967df0fe..72e5c6a1 100644
--- a/_episodes/08-diagnostics.md
+++ b/_episodes/08-diagnostics.md
@@ -31,9 +31,7 @@ languages such as Python, R, Julia and NCL but we will focus on understanding
and writing Python diagnostics in this lesson.
In this lesson, we will explain how to find an existing diagnostic and run it
-using ESMValTool installed in editable/development mode. For a development
-installation, see the instructions in the lesson [Development and
-contribution]({{ page.root }}{% link _episodes/07-development-setup.md %}).
+using ESMValTool installed in editable/development mode.
Also, we will work with the recipe [recipe_python.yml][recipe] and the
diagnostic script [diagnostic.py][diagnostic] called by this recipe that we have
seen in the lesson [Running your first recipe]({{ page.root }}{% link
@@ -44,9 +42,7 @@ Let's get started!
## Understanding an existing Python diagnostic
If you clone the ESMValTool repository, a folder called ``ESMValTool`` is
-created in your home/working directory, see the instructions in the lesson
-[Development and contribution]({{ page.root }}{% link
-_episodes/07-development-setup.md %}).
+created in your home/working directory.
The folder ``ESMValTool`` contains the source code of the tool. We can find the
recipe ``recipe_python.yml`` and the python script ``diagnostic.py`` in these
@@ -219,8 +215,6 @@ The ESMValTool documentation page provides an overview of what is in this file,
> ## What information do I need when writing a diagnostic script?
>
-> From the lesson [Configuration]({{ page.root }}{% link _episodes/03-configuration.md %}),
-> we saw how to change the configuration settings before running a recipe.
> First we set the option ``remove_preproc_dir`` to ``false`` in the configuration file,
> then run the recipe ``recipe_python.yml``:
>
diff --git a/_episodes/10-debugging.md b/_episodes/10-debugging.md
index 656a9150..76be4100 100644
--- a/_episodes/10-debugging.md
+++ b/_episodes/10-debugging.md
@@ -25,8 +25,7 @@ Each time we run ESMValTool, it will produce a new output directory. This
directory should contain the ``run`` folder that is automatically generated by
ESMValTool. To examine this, we run a ``recipe_python.yml`` that can be found in
lesson [Running your first recipe]({{ page.root }}{% link _episodes/04-recipe.md
-%}). Check lesson [Configuration]({{ page.root }}{% link
-_episodes/03-configuration.md %}) on how to set paths.
+%}).
In a new terminal, run the recipe:
@@ -51,7 +50,6 @@ conda activate esmvaltool
> ## conda environment
>
> More information about the conda environment can be found at
-> [Installation]({{ page.root }}{% link _episodes/02-installation.md %}).
{: .callout}
Let's list the files in the ``run`` directory:
@@ -330,8 +328,7 @@ What suggestions would you give the researcher for fixing the error?
## Check pre-processed data
The setting ``save_intermediary_cubes`` in the configuration file can be used to
-save the pre-processed data. More information about this setting can be found at
-[Configuration]({{ page.root }}{% link _episodes/03-configuration.md %}).
+save the pre-processed data.
> ## save_intermediary_cubes
>
@@ -354,8 +351,7 @@ scripts:
The diagnostic scripts are located in the folder ``diag_scripts`` in the
ESMValTool installation directory ````. To find
-where ESMValTool is located on your system, see [Installation]({{ page.root }}{% link
-_episodes/02-installation.md %}).
+where ESMValTool is located on your system.
Let's see what happens if we can change the script path as:
diff --git a/_includes/links.md b/_includes/links.md
index 9d788081..8fef1f63 100644
--- a/_includes/links.md
+++ b/_includes/links.md
@@ -38,9 +38,7 @@
[lc-lessons]: https://librarycarpentry.org/lessons/
[lesson-aio]: {{ relative_root_path }}{% link aio.md %}
[lesson-coc]: {{ relative_root_path }}{% link CODE_OF_CONDUCT.md %}
-[lesson-configuration]: {{ relative_root_path }}{% link _episodes/03-configuration.md %}
[lesson-example]: https://carpentries.github.io/lesson-example/
-[lesson-installation]: {{ relative_root_path }}{% link _episodes/02-installation.md %}
[lesson-introduction]: {{ relative_root_path }}{% link _episodes/00-introduction.md %}
[lesson-license]: {{ relative_root_path }}{% link LICENSE.md %}
[lesson-mainpage]: {{ relative_root_path }}{% link index.md %}
diff --git a/index.md b/index.md
index 6294c56d..d2062dcc 100644
--- a/index.md
+++ b/index.md
@@ -11,29 +11,14 @@ software toolkit that aims to facilitate the diagnosis and evaluation of the
causes and effects of model biases and inter-model spread within the CMIP model
ensemble.
-This tutorial is structured into ``basic`` and ``advanced`` topics such that episodes
-starting from the [Introduction][lesson-introduction] up to the episode on
-[Conclusion of the basic tutorial]({{ page.root }}{% link _episodes/05-conclusions.md %})
-all cover basic topics and can be done in one sitting.
-
-The remaining episodes cover the advanced topics and each episode is a
-mini-tutorial covering an advanced aspect of working with ESMValTool. These
-mini-tutorials can be appended to the main tutorial or worked through
-independently.
> ## What will you learn in this course
>
> - What is ESMValTool
-> - How to install ESMValTool
-> - How to configure ESMValTool for your local system
-> - How to run ESMValTool
+> - How to run ESMValTool on NCI-Gadi
> - How to work with ESMValTool's suite of preprocessors
> - How to debug your recipes
-> - How to access and deploy recipes from the ESMValTools gallery (Advanced)
-> - How to develop your own diagnostics and recipes (Advanced)
-> - How to contribute your recipes and diagnostics back into ESMValTool
-> (Advanced)
-> - How to include new observational datasets (Advanced)
+> - How to develop your own diagnostics and recipes
>
{: .checklist}
@@ -44,25 +29,6 @@ independently.
>
{: .prereq}
-### Main things you need to know before starting this course
-
-1. This tutorial can be taken online independently or taught by one of our
- instructors.
-
-2. Don’t be alarmed if you can’t work through the entire tutorial in one
- sitting. It may take some time to get used to working with ESMValTool.
-
-3. If you get stuck, help is always available from the tutors, from ESMValTool
- developers via the [github issues
- page](https://github.com/ESMValGroup/ESMValTool/issues) or via the
- ESMValTool email list. Please see
- [information](https://docs.esmvaltool.org/en/latest/introduction.html#user-mailing-list)
- on how to subscribe to user mailing list.
-
-4. This tutorial includes several advanced lessons after the conclusion. These
- advanced lessons should be treated like “mini-tutorials”, and include aspects
- like “developing your own diagnostic” or “how to include observations”.
-
> ## Additional Resources
>
> - [Documentation](https://docs.esmvaltool.org)
@@ -75,9 +41,4 @@ independently.
>
{: .callout}
-## How to cite the Tutorial
-
-Please use citation information available at
-[https://doi.org/10.5281/zenodo.3974591](https://doi.org/10.5281/zenodo.3974591).
-
{% include links.md %}
diff --git a/setup.md b/setup.md
index 4b27bffe..394c0919 100644
--- a/setup.md
+++ b/setup.md
@@ -237,13 +237,6 @@ that you are able to download CMIP data and that you have a few GB of space
available to install conda and ESMValTool, but also enough to make a copy of some
data (~125MB) needed for this tutorial.
-You can use ESMValTool to automatically download data needed for test recipes.
-Please see the [Configuration][lesson-configuration] episode
-or the [configuration file documentation][config-file] for more information.
-This the recommended option as it has the advantage that data is
-stored in subdirectories, and features such as wildcards and recording
-the version of the data will work automatically.
-
Alternatively, you can run the following command using
[wget](https://en.wikipedia.org/wiki/Wget):
From 2e2cbb3766cd2836856285146c185fc1d5500128 Mon Sep 17 00:00:00 2001
From: rbeucher
Date: Thu, 25 Jul 2024 09:17:16 +1000
Subject: [PATCH 06/49] Restructure a bit
---
_config.yml | 6 +-
_episodes/02-observationdatasets.md | 15 +++
_episodes/{04-recipe.md => 03-runarecipe.md} | 2 +-
...reprocessor.md => 04-writingyourrecipe.md} | 6 +-
_episodes/05-conclusions.md | 107 ------------------
...iagnostics.md => 05-writingdiagnostics.md} | 4 +-
_episodes/06-esmvaltoolworkflow.md | 14 +++
_episodes/07-gadioptimise.md | 14 +++
_episodes/08-accesslivecmoriser.md | 14 +++
_episodes/09-jupyternotebook.md | 14 +++
_episodes/10-esmvalcoreapi.md | 14 +++
_episodes/11-helpandcontribute.md | 14 +++
.../{10-debugging.md => 12-debugging.md} | 2 +-
_includes/links.md | 2 +-
14 files changed, 110 insertions(+), 118 deletions(-)
create mode 100644 _episodes/02-observationdatasets.md
rename _episodes/{04-recipe.md => 03-runarecipe.md} (99%)
rename _episodes/{06-preprocessor.md => 04-writingyourrecipe.md} (99%)
delete mode 100644 _episodes/05-conclusions.md
rename _episodes/{08-diagnostics.md => 05-writingdiagnostics.md} (99%)
create mode 100644 _episodes/06-esmvaltoolworkflow.md
create mode 100644 _episodes/07-gadioptimise.md
create mode 100644 _episodes/08-accesslivecmoriser.md
create mode 100644 _episodes/09-jupyternotebook.md
create mode 100644 _episodes/10-esmvalcoreapi.md
create mode 100644 _episodes/11-helpandcontribute.md
rename _episodes/{10-debugging.md => 12-debugging.md} (99%)
diff --git a/_config.yml b/_config.yml
index a9e5184f..3035426a 100644
--- a/_config.yml
+++ b/_config.yml
@@ -12,11 +12,11 @@
carpentry: "et"
# Overall title for pages.
-title: "ESMValTool Tutorial"
+title: "CMIP7 ACCESS MED Hackathon"
# Life cycle stage of the lesson
# possible values: "pre-alpha", "alpha", "beta", "stable"
-life_cycle: "beta"
+life_cycle: "stable"
#------------------------------------------------------------
# Generic settings (should not need to change).
@@ -31,7 +31,7 @@ kind: "lesson"
repository: /
# Email address, no mailto:
-email: "esmvaltool_user_engagement_team@listserv.dfn.de"
+email: "romain.beucher@anu.edu.au"
# Sites.
amy_site: "https://amy.carpentries.org/workshops"
diff --git a/_episodes/02-observationdatasets.md b/_episodes/02-observationdatasets.md
new file mode 100644
index 00000000..85c47f19
--- /dev/null
+++ b/_episodes/02-observationdatasets.md
@@ -0,0 +1,15 @@
+---
+title: "CMIP data and Observation datasets on NCI GADI"
+teaching: 15
+exercises: 15
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+
+---
+
+{% include links.md %}
\ No newline at end of file
diff --git a/_episodes/04-recipe.md b/_episodes/03-runarecipe.md
similarity index 99%
rename from _episodes/04-recipe.md
rename to _episodes/03-runarecipe.md
index eac6e35f..df88b5d3 100644
--- a/_episodes/04-recipe.md
+++ b/_episodes/03-runarecipe.md
@@ -2,7 +2,7 @@
title: "Running your first recipe"
teaching: 15
exercises: 15
-compatibility: ESMValTool v2.10.0
+compatibility: ESMValTool v2.11.0
questions:
- "How to run a recipe?"
diff --git a/_episodes/06-preprocessor.md b/_episodes/04-writingyourrecipe.md
similarity index 99%
rename from _episodes/06-preprocessor.md
rename to _episodes/04-writingyourrecipe.md
index 0eed72d9..f038247d 100644
--- a/_episodes/06-preprocessor.md
+++ b/_episodes/04-writingyourrecipe.md
@@ -2,7 +2,7 @@
title: "Writing your own recipe"
teaching: 15
exercises: 30
-compatibility: ESMValTool v2.10.0
+compatibility: ESMValTool v2.11.0
questions:
- "How do I create a new recipe?"
@@ -249,7 +249,7 @@ Let us start with the BCC-ESM1 dataset and add a datasets section to the recipe,
listing this single dataset, as shown below. Note that key fields such
as `mip` or `start_year` are included in the `datasets` section here but are part
of the `diagnostic` section in the recipe example seen in
-[Running your first recipe]({{ page.root }}{% link _episodes/04-recipe.md %}).
+[Running your first recipe]({{ page.root }}{% link _episodes/03-runarecipe.md %}).
```yaml
# ESMValTool
@@ -395,7 +395,7 @@ Note: for the purpose of simplicity in this episode, we have not added logging
or provenance tracking in the diagnostic script. Once you start to develop your
own diagnostic scripts and want to add them to the ESMValTool repositories, this
will be required. Writing your own diagnostic script is discussed in a
-[later episode]({{ page.root }}{% link _episodes/08-diagnostics.md %}).
+[later episode]({{ page.root }}{% link _episodes/05-writingdiagnostics.md %}).
## Bonus exercises
diff --git a/_episodes/05-conclusions.md b/_episodes/05-conclusions.md
deleted file mode 100644
index 638017b9..00000000
--- a/_episodes/05-conclusions.md
+++ /dev/null
@@ -1,107 +0,0 @@
----
-title: "Conclusion of the basic tutorial"
-teaching: 10
-exercises: 0
-compatibility: ESMValTool v2.10.0
-
-questions:
-- "What do I do now?"
-- "Where can I get help?"
-- "What if I find a bug?"
-- "Where can I find more information about ESMValtool?"
-- "How can I cite ESMValtool?"
-
-objectives:
-- "Breathe - you're finished now!"
-- "Congratulations & Thanks!"
-- "Find out about the mini-tutorials, and what to do next."
-
-keypoints:
-- "Individual mini-tutorials help work through a specific issue (not developed yet)."
-- "We are constantly improving this tutorial."
----
-
-## Congratulations!
-
-Congratulations on completing the ESMValTool tutorial!
-You should be now ready to go and start using ESMValTool independently.
-
-The rest of this tutorial contains individual mini-tutorials
-to help work through a specific issue (not developed yet).
-
-### What next?
-
-From here, there are lots of ways that you can continue to use ESMValTool.
-
-- You can start from the list of
-[existing recipes](https://docs.esmvaltool.org/en/latest/recipes/index.html)
-and run one of those.
-- You can learn how to
-[write your own diagnostics and recipes](https://docs.esmvaltool.org/en/latest/develop/index.html).
-- You can
-[contribute your recipe and diagnostics](https://docs.esmvaltool.org/en/latest/community/index.html)
-back into ESMValTool.
-- You can learn how to prepare
-[observational datasets](https://docs.esmvaltool.org/en/latest/input.html#observations)
-to be suitable for use by ESMValTool.
-
-> ## `Exercise: What do you want to do next?`
->
-> - Think about what you want to do with ESMValTool.
-> - Decide what datasets and variables you want to use.
-> - Is any observational data available?
-> - How will you preprocess the data?
-> - What will your diagnostic script need to do?
-> - What will your final figure show?
-{: .challenge}
-
-### Where can I get more information on ESMValTool?
-
-> ## Additional resources:
->
-> - [Documenation](https://docs.esmvaltool.org)
-> - [ESMValTool home page](https://www.esmvaltool.org/)
-> - [Papers](https://esmvaltool.org/references/)
-> - [Source code (ESMValTool)](https://github.com/ESMValGroup/ESMValTool)
-> - [Source code (ESMValCore )](https://github.com/ESMValGroup/ESMValCore)
-{: .callout}
-
-
-### Where can I get more help?
-
-There are lots of resources available to assist you in using ESMValTool.
-
-The ESMValTool [Discussions page](https://github.com/ESMValGroup/ESMValTool/discussions)
-is a good place to find information on general issues, or check
- if your question has already been addressed.
-If you have a GitHub account, you can also post your questions there.
-
-If you encounter difficulties, a great starting point is to visit issues page
- [issue page](https://github.com/ESMValGroup/ESMValTool/issues) to check
-whether your issues have already been reported or not. If they have been reported before,
- suggestions provided by developers can help you to solve the issues you encountered.
-Note that you will need a GitHub account for this.
-
-Additionally, there is an ESMValTool email list.
-Please see
- [information](https://docs.esmvaltool.org/en/latest/introduction.html#user-mailing-list)
- on how to subscribe to the user mailing list.
-
-### What if I find a bug?
-
-If you find a bug, please report it to the ESMValTool team.
-This will help us fix issues, ensuring not only your uninterrupted workflow
- but also contributing to the overall stability of ESMValTool for all users.
-
-To report a bug, please create a new issue using the
-[issue page](https://github.com/ESMValGroup/ESMValTool/issues).
-
-In your bug report, please describe the problem as clearly and as completely as possible.
-You may need to include a recipe or the output log as well.
-
-### How do I cite the Tutorial?
-
-Please use citation information available at
-[https://doi.org/10.5281/zenodo.3974591](https://doi.org/10.5281/zenodo.3974591).
-
-{% include links.md %}
diff --git a/_episodes/08-diagnostics.md b/_episodes/05-writingdiagnostics.md
similarity index 99%
rename from _episodes/08-diagnostics.md
rename to _episodes/05-writingdiagnostics.md
index 72e5c6a1..29071552 100644
--- a/_episodes/08-diagnostics.md
+++ b/_episodes/05-writingdiagnostics.md
@@ -2,7 +2,7 @@
title: "Writing your own diagnostic script"
teaching: 20
exercises: 30
-compatibility: ESMValTool v2.9.0
+compatibility: ESMValTool v2.11.0
questions:
- "How do I write a new diagnostic in ESMValTool?"
@@ -35,7 +35,7 @@ using ESMValTool installed in editable/development mode.
Also, we will work with the recipe [recipe_python.yml][recipe] and the
diagnostic script [diagnostic.py][diagnostic] called by this recipe that we have
seen in the lesson [Running your first recipe]({{ page.root }}{% link
-_episodes/04-recipe.md %}).
+_episodes/03-runarecipe.md %}).
Let's get started!
diff --git a/_episodes/06-esmvaltoolworkflow.md b/_episodes/06-esmvaltoolworkflow.md
new file mode 100644
index 00000000..ec28d82b
--- /dev/null
+++ b/_episodes/06-esmvaltoolworkflow.md
@@ -0,0 +1,14 @@
+---
+title: "Running the ACCESS-NRI ESMValTool-workflow"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/07-gadioptimise.md b/_episodes/07-gadioptimise.md
new file mode 100644
index 00000000..027ace70
--- /dev/null
+++ b/_episodes/07-gadioptimise.md
@@ -0,0 +1,14 @@
+---
+title: "Optimize Runs Using Multiple Cores and Dask on Gadi"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/08-accesslivecmoriser.md b/_episodes/08-accesslivecmoriser.md
new file mode 100644
index 00000000..0991fbee
--- /dev/null
+++ b/_episodes/08-accesslivecmoriser.md
@@ -0,0 +1,14 @@
+---
+title: "The ACCESS-ESM Live CMORiser"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/09-jupyternotebook.md b/_episodes/09-jupyternotebook.md
new file mode 100644
index 00000000..a3d227ac
--- /dev/null
+++ b/_episodes/09-jupyternotebook.md
@@ -0,0 +1,14 @@
+---
+title: "Use a Jupyter Notebook to Run a Recipe"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/10-esmvalcoreapi.md b/_episodes/10-esmvalcoreapi.md
new file mode 100644
index 00000000..395c0979
--- /dev/null
+++ b/_episodes/10-esmvalcoreapi.md
@@ -0,0 +1,14 @@
+---
+title: "The ESMValCore API"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/11-helpandcontribute.md b/_episodes/11-helpandcontribute.md
new file mode 100644
index 00000000..b04b1a6b
--- /dev/null
+++ b/_episodes/11-helpandcontribute.md
@@ -0,0 +1,14 @@
+---
+title: "Contribute and Ask for ACCESS-NRI Help"
+teaching: 20
+exercises: 30
+compatibility: ESMValTool v2.11.0
+
+questions:
+
+objectives:
+
+keypoints:
+---
+
+{% include links.md %}
diff --git a/_episodes/10-debugging.md b/_episodes/12-debugging.md
similarity index 99%
rename from _episodes/10-debugging.md
rename to _episodes/12-debugging.md
index 76be4100..2a6f5b3d 100644
--- a/_episodes/10-debugging.md
+++ b/_episodes/12-debugging.md
@@ -24,7 +24,7 @@ types of errors and when you are likely to encounter them.
Each time we run ESMValTool, it will produce a new output directory. This
directory should contain the ``run`` folder that is automatically generated by
ESMValTool. To examine this, we run a ``recipe_python.yml`` that can be found in
-lesson [Running your first recipe]({{ page.root }}{% link _episodes/04-recipe.md
+lesson [Running your first recipe]({{ page.root }}{% link _episodes/03-runarecipe.md
%}).
In a new terminal, run the recipe:
diff --git a/_includes/links.md b/_includes/links.md
index 8fef1f63..e4b21d42 100644
--- a/_includes/links.md
+++ b/_includes/links.md
@@ -42,7 +42,7 @@
[lesson-introduction]: {{ relative_root_path }}{% link _episodes/00-introduction.md %}
[lesson-license]: {{ relative_root_path }}{% link LICENSE.md %}
[lesson-mainpage]: {{ relative_root_path }}{% link index.md %}
-[lesson-recipe]: {{ relative_root_path }}{% link _episodes/04-recipe.md %}
+[lesson-recipe]: {{ relative_root_path }}{% link _episodes/03-runarecipe.md %}
[lesson-reference]: {{ relative_root_path }}{% link reference.md %}
[lesson-setup]: {{ relative_root_path }}{% link setup.md %}
[list-of-authors]: https://docs.esmvaltool.org/en/latest/community/code_documentation.html#list-of-authors
From 39112d73cd7865b9fe493b896cf57a050bb15109 Mon Sep 17 00:00:00 2001
From: flicj191
Date: Thu, 25 Jul 2024 09:53:54 +1000
Subject: [PATCH 07/49] ex2 branch
---
fig/warming_stripes_australia.png | Bin 0 -> 29253 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 fig/warming_stripes_australia.png
diff --git a/fig/warming_stripes_australia.png b/fig/warming_stripes_australia.png
new file mode 100644
index 0000000000000000000000000000000000000000..1aa7cb21b2e35ad288ab17e5aed8b6fea6381c29
GIT binary patch
literal 29253
zcmeI*eM}Q)90%}oZWeXCs2eI1>2$trVtLa#5Go2moPaMZI8@#oAXYh~fEtTM8()}8
zWnqG%kP)XYt{8(IAhXD%Ru|5q%&OS+urLs*KrKp<(ylk3zGQ!xEYV~vze@;rm-Z;1
z`#vwd=jk7>ywP&wHa&hq>SzH>4{iaVC0IxC3ESKn-b|^
z@fn+<@N_n3E5sGK~1_)MdfOw!dId(Fsud^?8Ar&9~yzpp@u}klkP43CA;4?@=
zE_Ix!-9rKm;Voc!imS66WZgr3ZBfalqttS{@z!F2(nHU`AQE%QP7P6L$lRQjCadFD
z@Y(#cc_M=7e|)n>%9J{urY)%Y(bd@3JD(%WGze=2_*BJUzJ}1y1nwoihO~~`8p7S-
zbSd`**;-u4>U*MYaTZ+I?w_5?)z*Xr1c<98SJL$yac^^t>DWTqQ)8p9-8q%p{k?{G
z*iZWSRY`^t4tZ}nbhfIvWRag~GesAjh!?p(s)yMIb_f_kR-#I#zb{3vI&iW>tmD!_fzundCLUJ|R
zStYJhc-LdtLxyHY0dD9BA>BxYmgtf)d4}8PlV~`%<2WUKkrQ^jTyP&n(9-aX}GPdeBl&(|SSFMV^wYj2!Oz#XrK@P1VCWWYM>AR1VH2ryADcYW)9fZ0^7M_@FbK=fB*<68Ylw*0T39p8Ylz+0T38;s89$10w6Hx
zEu#s-b01x6VF2!Mc35}*tK1VCVKsYixnq4NO{(B`5H00clln~O5=?;Ti$?x^
z-?Bi1oWFhwwF*NhNE09c0)|jf1^@yehWl6&I)gBG2q2)FW6l8d_skN|-$N1r0T9sN
zLm2=F6T}?GF;@&5mq2|-0ObNGkPdh^fHLqp2oak`ebWcFS1+VhFFXOaQF~
Date: Thu, 25 Jul 2024 10:51:39 +1000
Subject: [PATCH 08/49] Add some installation guides
---
_config.yml | 2 +-
_episodes/13-vscodesetup.md | 129 ++++++++++++
_episodes/14-aresetup.md | 101 ++++++++++
_episodes/15-vdisetup.md | 102 ++++++++++
assets/assets_ARE/compute.png | Bin 0 -> 27484 bytes
assets/assets_ARE/jupyter_select.png | Bin 0 -> 478381 bytes
assets/assets_ARE/launch.png | Bin 0 -> 109983 bytes
assets/assets_ARE/login.png | Bin 0 -> 108880 bytes
assets/assets_ARE/module_directories.png | Bin 0 -> 62466 bytes
assets/assets_ARE/modules.png | Bin 0 -> 39649 bytes
assets/assets_ARE/project.png | Bin 0 -> 24662 bytes
assets/assets_ARE/queue.png | Bin 0 -> 333292 bytes
assets/assets_ARE/running.png | Bin 0 -> 413592 bytes
assets/assets_ARE/storage.png | Bin 0 -> 26976 bytes
assets/assets_ARE/terminal.png | Bin 0 -> 472970 bytes
assets/assets_ARE/walltime.png | Bin 0 -> 29117 bytes
assets/assets_VDI/compute.png | Bin 0 -> 27484 bytes
assets/assets_VDI/launch.png | Bin 0 -> 109983 bytes
assets/assets_VDI/login.png | Bin 0 -> 108880 bytes
assets/assets_VDI/module_directories.png | Bin 0 -> 62466 bytes
assets/assets_VDI/modules.png | Bin 0 -> 39649 bytes
assets/assets_VDI/pbsflags.png | Bin 0 -> 21515 bytes
assets/assets_VDI/project.png | Bin 0 -> 24662 bytes
assets/assets_VDI/queue.png | Bin 0 -> 96680 bytes
assets/assets_VDI/running.png | Bin 0 -> 154344 bytes
assets/assets_VDI/storage.png | Bin 0 -> 26976 bytes
assets/assets_VDI/terminal.png | Bin 0 -> 484751 bytes
assets/assets_VDI/vdi_select.png | Bin 0 -> 136326 bytes
assets/assets_VDI/walltime.png | Bin 0 -> 29117 bytes
assets/assets_vscode/config.png | Bin 0 -> 234718 bytes
assets/assets_vscode/config_rename.png | Bin 0 -> 63811 bytes
assets/assets_vscode/extensions.png | Bin 0 -> 244162 bytes
assets/assets_vscode/extensions_jupyter.png | Bin 0 -> 825588 bytes
.../assets_vscode/extensions_liveserver.png | Bin 0 -> 1050364 bytes
assets/assets_vscode/extensions_python.png | Bin 0 -> 907234 bytes
assets/assets_vscode/extensions_ssh.png | Bin 0 -> 768120 bytes
assets/assets_vscode/files.png | Bin 0 -> 614422 bytes
assets/assets_vscode/open_remote1.png | Bin 0 -> 246816 bytes
assets/assets_vscode/open_remote2.png | Bin 0 -> 307454 bytes
assets/assets_vscode/open_remote3.png | Bin 0 -> 277610 bytes
assets/assets_vscode/open_remote4.png | Bin 0 -> 252922 bytes
assets/assets_vscode/open_remote5.png | Bin 0 -> 279699 bytes
assets/assets_vscode/terminals.png | Bin 0 -> 335437 bytes
assets/assets_vscode/workspace1.png | Bin 0 -> 273422 bytes
assets/assets_vscode/workspace2.png | Bin 0 -> 309847 bytes
assets/assets_vscode/workspace3.png | Bin 0 -> 309008 bytes
assets/assets_vscode/workspace4.png | Bin 0 -> 425206 bytes
setup.md | 186 +-----------------
48 files changed, 339 insertions(+), 181 deletions(-)
create mode 100644 _episodes/13-vscodesetup.md
create mode 100644 _episodes/14-aresetup.md
create mode 100644 _episodes/15-vdisetup.md
create mode 100644 assets/assets_ARE/compute.png
create mode 100644 assets/assets_ARE/jupyter_select.png
create mode 100644 assets/assets_ARE/launch.png
create mode 100644 assets/assets_ARE/login.png
create mode 100644 assets/assets_ARE/module_directories.png
create mode 100644 assets/assets_ARE/modules.png
create mode 100644 assets/assets_ARE/project.png
create mode 100644 assets/assets_ARE/queue.png
create mode 100644 assets/assets_ARE/running.png
create mode 100644 assets/assets_ARE/storage.png
create mode 100644 assets/assets_ARE/terminal.png
create mode 100644 assets/assets_ARE/walltime.png
create mode 100644 assets/assets_VDI/compute.png
create mode 100644 assets/assets_VDI/launch.png
create mode 100644 assets/assets_VDI/login.png
create mode 100644 assets/assets_VDI/module_directories.png
create mode 100644 assets/assets_VDI/modules.png
create mode 100644 assets/assets_VDI/pbsflags.png
create mode 100644 assets/assets_VDI/project.png
create mode 100644 assets/assets_VDI/queue.png
create mode 100644 assets/assets_VDI/running.png
create mode 100644 assets/assets_VDI/storage.png
create mode 100644 assets/assets_VDI/terminal.png
create mode 100644 assets/assets_VDI/vdi_select.png
create mode 100644 assets/assets_VDI/walltime.png
create mode 100644 assets/assets_vscode/config.png
create mode 100644 assets/assets_vscode/config_rename.png
create mode 100644 assets/assets_vscode/extensions.png
create mode 100644 assets/assets_vscode/extensions_jupyter.png
create mode 100644 assets/assets_vscode/extensions_liveserver.png
create mode 100644 assets/assets_vscode/extensions_python.png
create mode 100644 assets/assets_vscode/extensions_ssh.png
create mode 100644 assets/assets_vscode/files.png
create mode 100644 assets/assets_vscode/open_remote1.png
create mode 100644 assets/assets_vscode/open_remote2.png
create mode 100644 assets/assets_vscode/open_remote3.png
create mode 100644 assets/assets_vscode/open_remote4.png
create mode 100644 assets/assets_vscode/open_remote5.png
create mode 100644 assets/assets_vscode/terminals.png
create mode 100644 assets/assets_vscode/workspace1.png
create mode 100644 assets/assets_vscode/workspace2.png
create mode 100644 assets/assets_vscode/workspace3.png
create mode 100644 assets/assets_vscode/workspace4.png
diff --git a/_config.yml b/_config.yml
index 3035426a..c98fd06c 100644
--- a/_config.yml
+++ b/_config.yml
@@ -62,7 +62,7 @@ instructor_post_survey: "https://www.surveymonkey.com/r/instructor_training_post
# Start time in minutes (0 to be clock-independent, 540 to show a start at 09:00 am).
-start_time: 0
+start_time: 570
# Specify that things in the episodes collection should be output.
collections:
diff --git a/_episodes/13-vscodesetup.md b/_episodes/13-vscodesetup.md
new file mode 100644
index 00000000..9427be32
--- /dev/null
+++ b/_episodes/13-vscodesetup.md
@@ -0,0 +1,129 @@
+---
+title: "Visual Studio Code (VS Code) setup guide"
+teaching: 5
+exercises: 10
+
+keypoints:
+
+---
+
+This is an introductory guide to setting up and using Microsoft Visual Studio Code (often referred to as VS Code) to interact with Gadi and run ESMValTool recipes for the ACCESS-NRI CMIP7-Hackathon.
+
+
+## 0. Pre-workshop preparation
+
+- *0.1* In order to get the most out of the Hackathon, you will require a NCI account. If you do not yet have a NCI account, you can sign up on the [MyNCI website](https://my.nci.org.au).
+- *0.2* To run the exercises, access to specific projects on Gadi is required. To help things run as smoothly as possible on the day, please log in to the [MyNCI website](https://my.nci.org.au) and join the following projects:
+`nf33`, `xp65`, `fs38`, `oi10`, `al33`, `rr3`, `rt52`, `zz93` and `ct11` **prior** to attending the Hackathon. Please note it can take 1-2 days to receive membership approvals.
+- *0.3* Download and install Microsoft Visual Studio Code on your local system. VS Code can be downloaded from [this page](https://code.visualstudio.com/).
+
+
+## 1. Installing VS Code extensions
+Out of the box, VS Code doesn't do everything we need it to - so we must install some software extensions to get the most out of the Hackathon.
+
+- *1.1* When VS Code starts up, you are greeted with a GUI that looks like this. The first thing we need to do is click the extensions icon in the left-hand navigation pane marked below with the red ellipse.
+
+
+
+We have a total of 4 extensions to install. Note that when hovering over a listed extension, a small information pane pops up, and clicking on an extension opens a full extension information page.
+
+- *Extension 1:* **Remote-SSH**
+This extension allows us to securely login to remote servers, in our case NCI Gadi, using *ssh*. Type `remote ssh` into the extensions search bar and select the *Remote-SSH* extension published by Microsoft marked with the red ellipse below. Click `install` to add the extension.
+
+
+
+- *Extension 2:* **Live Server**
+Type `live server` into the extensions search bar and select the *Live Server* extension published by Ritwick Dey marked with the red ellipse below. This extension allows us to preview html files from a browser on our computer, and will update automatically as the html file is updated in VS Code. We will use this extension to preview some of the ESMValTool recipe outputs that come in html format. Click `install` to add the extension.
+
+
+
+- *Extension 3:* **Python** *(Optional)*
+This extension provides full code support and highlighting for the *Python* programming language within VS Code. Type `python` into the extensions search bar and select the *Python* extension published by Microsoft marked with the red ellipse below. This extension will be helpful if you want to edit any Python files associated with ESMValTool recipes. Click `install` to add the extension.
+
+
+
+- *Extension 4:* **Jupyter** *(Optional)*
+This extension allows us to view, edit and run *Jupyter Notebooks* within VS Code. Type `jupyter` into the extensions search bar and select the *Jupyter* extension published by Microsoft marked with the red ellipse below. This extension will be helpful if you prefer to use Jupyter Notebooks when editing code in VS Code. Click `install` to add the extension.
+
+
+
+[\[Back to top\]](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/docs/1_VSCode_setup_guide_RECOMMENDED.md#getting-started-guide-for-visual-studio-code-vs-code)
+
+## 2. Open remote connection to Gadi
+
+To connect to Gadi, follow these steps to establish and open a remote connection using the *Remote-SSH* extension.
+
+- *2.1* To get started, click the blue `Open a Remote Window` button in the bottom left-hand corner.
+
+
+
+- *2.2* Select `Connect Current Window to Host...` to open the connection to Gadi within the current window. Alternatively, you can select `Connect to Host...` to open the connection in a new window.
+
+
+
+- *2.3* Click `+ Add New SSH Host`
+
+
+
+- *2.4* Enter the remote host (Gadi) details which are comprised of your NCI `username` followed by `@gadi.nci.org.au`. You may be prompted to select a _ssh_ `config` file so VS Code can remember your _ssh_ connections in future. VS Code will automatically create a config file for you, so usually selecting the first default option that appears will work fine as VS Code will manage the file.
+
+
+
+N.B. You can have multiple host connections can exist in your config file with the same name (`gadi.nci.org.au` for example). To rename these you must open the config file selected in step 2.4 by first clicking `Configure SSH Hosts...`
+
+
+
+You can then change the text next to the `Host` tag to any unique string that does not contain spaces. In example below, each host name string has been renamed to unique values.
+
+
+
+- *2.5* You will then be prompted to enter your NCI account password. Once connected, the blue button in the bottom left-hand corner will say `SSH: gadi.nci.org.au`. VS Code also automatically opens a live terminal (bottom right) in your `/home` folder. Great news, you are now connected to Gadi!
+
+
+
+[\[Back to top\]](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/docs/1_VSCode_setup_guide_RECOMMENDED.md#getting-started-guide-for-visual-studio-code-vs-code)
+
+## 3. Load ESMValTool modules and set up Hackathon environment
+
+You can now follow the instructions in the [README](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/README.md) for how to setup your environment to run ESMValTool and how to use ESMValTool recipes. To continue to Step 4 below, you must have at least run the steps under the heading [Set up our environment to run ESMValTool](https://github.com/paigem/CMIP7-Hackathon/blob/main/README.md#set-up-our-environment-to-run-esmvaltool), as these steps will create the folders that we will open below.
+
+[\[Back to top\]](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/docs/1_VSCode_setup_guide_RECOMMENDED.md#getting-started-guide-for-visual-studio-code-vs-code)
+
+## 4. Create a workspace / open folders on Gadi
+
+VS Code allows you to create custom workspaces, which is particularly convenient for quick access to multiple directories/folders on Gadi which may be located in different locations.
+
+- *4.1* To add a directory/folder to the current workspace, simply click the `Open Folder` button marked in red below. Alternatively, you can also add folders via `File > Open Folder`.
+
+
+
+- *4.2* You will then be prompted to add a valid path on Gadi to the folder you wish to add. In this example, we are adding the path to your main Hackathon folder `/scratch/nf33/[username]/CMIP7-Hackathon` created by running `check_hackathon` above. Once you have entered the path, press `OK`. N.B. When adding a folder, VS Code may request you re-enter your NCI account password.
+
+
+
+Once this is done, the folder will be visible in the left-hand `EXPLORER` pane (and can be expanded to show all contents), it is also displayed at the top of page in the search bar (allowing quick searches of the selected folder), and the terminal also opens in the selected folder (the `ls` command is shown here to list the folder contents).
+
+
+
+You can add multiple unique folders to the current workspace by right clicking and selecting `Add folder to Workspace` and following the process described above in section 4.2.
+
+
+
+Now that you have a workspace setup, we suggest adding the above mentioned `esmvaltool_outputs` and `logs` folders (replacing [username] with your NCI account username) for quick access.
+
+[\[Back to top\]](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/docs/1_VSCode_setup_guide_RECOMMENDED.md#getting-started-guide-for-visual-studio-code-vs-code)
+
+## 5. VS Code extras
+
+To open any supported file(s), you can double click it in the left-hand `EXPLORER` pane or drag-and-drop it into the main panel. To add a second main panel, right-click any extra files in `EXPLORER` and select `Open to the Side`.
+
+
+
+Along with folders in a workspace, you can also have multiple independent terminal sessions running at the same time. To do this, click the `+` button at the top right of a terminal panel.
+
+
+If you have multiple folders open in your workspace, you will first be prompted to `Select current working directory for new terminal` at the top.
+
+
+
+[\[Back to top\]](https://github.com/ACCESS-NRI/CMIP7-Hackathon/blob/main/docs/1_VSCode_setup_guide_RECOMMENDED.md#getting-started-guide-for-visual-studio-code-vs-code)
diff --git a/_episodes/14-aresetup.md b/_episodes/14-aresetup.md
new file mode 100644
index 00000000..80a7a380
--- /dev/null
+++ b/_episodes/14-aresetup.md
@@ -0,0 +1,101 @@
+---
+title: "ARE JupyterLab setup guide"
+teaching: 5
+exercises: 10
+
+keypoints:
+
+---
+
+Quick-start guide to setting up a JupyterLab session using the Australian Research Environment to run the ACCESS-NRI CMIP7-Hackathon exercises.
+
+## 0. Pre-workshop preparation
+
+- *0.1* In order to get the most out of the Hackathon, you will require a NCI account. If you do not yet have a NCI account, you can sign up on the [MyNCI website](https://my.nci.org.au).
+- *0.2* To run the exercises, access to specific projects on Gadi is required. To help things run as smoothly as possible on the day, please log in to the [MyNCI website](https://my.nci.org.au) and join the following projects:
+`nf33`, `xp65`, `fs38`, `oi10`, `al33`, `rr3`, `rt52`, `zz93` and `ct11` **prior** to attending the Hackathon. Please note it can take 1-2 days to receive membership approvals.
+
+## 1. Open ARE on Gadi
+Go to the [Australian Research Environment](https://are-auth.nci.org.au/) website and login with your **NCI username and password**. If you don't have an NCI account, you can sign up for one at the [MyNCI website](https://my.nci.org.au).
+
+
+
+## 2. Start JupyterLab App
+Click on `JupyterLab` under *Featured Apps* to configure a new JupyterLab instance. This option is also available under the *All Apps* section at the bottom of the page and the *Interactive Apps* dropdown located in the top menu.
+
+
+
+## 3. Configure JupyterLab session
+You will now be presented with the main JupyterLab instance configuration form. Please complete **only** the fields below - leave all other fields blank or to their default values.
+
+- *3.1* **Walltime**: The number of hours the JupyterLab instance will run. For the hackathon, please insert a walltime of `4` hours.
+
+
+
+- *3.2* **Compute Size**: Select `Medium (4 cpus, 18G mem)` from the dropdown menu.
+
+
+
+- *3.3* **Project**: Please enter `nf33`. This will allocate SU usage to the workshop project.
+
+
+
+- *3.4* **Storage**: This is the list of project data storage locations required to complete the hackathon exercises. In ARE, storage locations need to be explicitly defined to access these data from within a JupyterLab instance. Please copy and paste the following string in its entirety into the storage input field:
+```
+scratch/nf33+gdata/nf33+gdata/xp65+gdata/fs38+gdata/oi10+gdata/al33+gdata/rr3+gdata/rt52+gdata/zz93+gdata/ct11
+```
+
+
+
+- *3.5* Click `Advanced options ...`
+ * Optional: You can check the box here to receive an email notification when your JupyterLab instance starts, but as we are running a relatively small instance, it will likely spin up quickly so this probably isn't necessary.
+
+- *3.6* **Module directories**: To load the required environment modules, please copy and paste the following. This is equivalent to using `module use` on the command line.
+```
+/g/data/xp65/public/modules
+```
+
+
+
+- *3.7* **Modules** To load the ESMValTool-workflow environment, please copy and paste the following. This is equivalent to using `module load` on the command line.
+```
+esmvaltool
+```
+
+
+
+- *3.7* Click `Launch` to start your JupyterLab instance.
+
+
+
+
+
+
+## 4. Launch JupyterLab session
+Once you have clicked `Launch` the browser will redirect to the 'interactive sessions' page where you will see your JupyterLab instance details and current status which will look something like this:
+
+
+
+Once the JupyterLab instance has started (this usually takes around 30 seconds), this status window should update and look something like the following, reporting that the instance has started and the time remaining. More detailed information on the instance can be accessed by clicking the `Session ID` link.
+
+
+
+Click `Open JupyterLab`. This opens the instance in a new browser window where you can navigate to the location of the cloned tutorial files.
+
+
+
+## 5. Setup Hackathon ESMValTool environment
+To finalise the system setup, we must run the hackathon setup script. This verifies that your NCI account has access to the required projects on Gadi and that their respective storage locations are mounted, clones the [CMIP7-Hackathon Github repository](https://github.com/ACCESS-NRI/CMIP7-Hackathon), and automatically runs each of the hackathon ESMValTool recipes as PBS jobs on Gadi.
+
+To do this within ARE, from the `Launcher` window we must first open `Terminal`:
+
+
+
+Once the terminal is open, insert the following command and press `ENTER/RETURN`:
+
+```
+check_hackathon
+```
+
+When successful, you will see a range of checks and processes print to the screen, which may take up to 1 minute to complete. Once you see the "YOU ARE ALL SET!!!" message, everything is setup and ready to go.
+
diff --git a/_episodes/15-vdisetup.md b/_episodes/15-vdisetup.md
new file mode 100644
index 00000000..0ae71f19
--- /dev/null
+++ b/_episodes/15-vdisetup.md
@@ -0,0 +1,102 @@
+---
+title: "ARE Virtual Desktop (VDI) setup guide"
+teaching: 5
+exercises: 10
+
+keypoints:
+
+---
+
+Quick-start guide to setting up a virtual desktop (VDI) session using the Australian Research Environment (ARE) to run the ACCESS-NRI CMIP7-Hackathon exercises.
+
+## 0. Pre-workshop preparation
+
+- *0.1* In order to get the most out of the Hackathon, you will require a NCI account. If you do not yet have a NCI account, you can sign up on the [MyNCI website](https://my.nci.org.au).
+- *0.2* To run the exercises, access to specific projects on Gadi is required. To help things run as smoothly as possible on the day, please log in to the [MyNCI website](https://my.nci.org.au) and join the following projects:
+`nf33`, `xp65`, `fs38`, `oi10`, `al33`, `rr3`, `rt52`, `zz93` and `ct11` **prior** to attending the Hackathon. Please note it can take 1-2 days to receive membership approvals.
+
+## 1. Open ARE/VDI on Gadi
+Go to the [Australian Research Environment](https://are-auth.nci.org.au/) website and login with your **NCI username and password**. If you don't have an NCI account, you can sign up for one at the [MyNCI website](https://my.nci.org.au).
+
+
+
+## 2. Start VDI App
+Click on `Virtual Desktop` under *Featured Apps* to configure a new VDI instance. This option is also available under the *All Apps* section at the bottom of the page and the *Interactive Apps* dropdown located in the top menu.
+
+
+
+## 3. Configure VDI session
+You will now be presented with the main VDI instance configuration form. Please complete **only** the fields below - leave all other fields blank or to their default values.
+
+- *3.1* **Walltime**: The number of hours the VDI instance will run. For the hackathon, please insert a walltime of `4` hours.
+
+
+
+- *3.2* **Compute Size**: Select `Medium (4 cpus, 18G mem)` from the dropdown menu.
+
+
+
+- *3.3* **Project**: Please enter `nf33`. This will allocate SU usage to the hackathon project.
+
+
+
+- *3.4* **Storage**: This is the list of project data storage locations required to complete the hackathon exercises. In ARE, storage locations need to be explicitly defined to access these data from within a VDI instance. Please copy and paste the following string in its entirety into the storage input field:
+```
+scratch/nf33+gdata/nf33+gdata/xp65+gdata/fs38+gdata/oi10+gdata/al33+gdata/rr3+gdata/rt52+gdata/zz93+gdata/ct11
+```
+
+
+
+- *3.5* **Click** `Advanced options ...`
+
+- *3.6* **PBS flags**: The `xp65` conda environment is a containerised environment that requires the `SINGULARITY_OVERLAYIMAGE` environment variable to be defined. Please copy and paste the following string in its entirety into the PBS flags input field:
+
+```
+-v SINGULARITY_OVERLAYIMAGE=/g/data/xp65/public/apps/med_conda/envs/access-med-0.3.sqsh
+```
+
+
+
+- *3.5* Click `Launch` to start your VDI instance.
+
+
+
+
+## 4. Launch VDI session
+Once you have clicked `Launch` the browser will redirect to the 'interactive sessions' page where you will see your VDI instance details and current status which will initially look something like this:
+
+
+
+Once the VDI instance has started (this usually takes around 30 seconds), this status window should update and look something like the following, reporting that the instance has started and the time remaining. More detailed information on the instance can be accessed by clicking the `Session ID` link.
+
+Additionally there are extra streaming performance related controls here for both `Compression` and `Image Quality`. Generally the default settings here work fine, but if you are having trouble you can adjust these parameters.
+
+
+
+Click `Launch VDI Desktop`. This opens the VDI instance in a new browser window where you can navigate to the location of the cloned tutorial files.
+
+Depending on which browser you are using, a prompt can appear in the browser at VDI startup stating that ARE is requesting access to your computer clipboard. This is optional, but allowing this access can make transferring copied text and files between your computer and the VDI instance much easier!
+
+## 5. Setup Hackathon ESMValTool environment and run recipes
+To finalise the system setup, we must run the hackathon setup scripts. The setup script loads the required ESMValTool-workflow dependencies, verifies that your NCI account has access to the required projects on Gadi and that their respective storage locations are mounted, clones the [CMIP7-Hackathon Github repository](https://github.com/ACCESS-NRI/CMIP7-Hackathon), and automatically runs each of the hackathon ESMValTool recipes as PBS jobs on Gadi.
+
+To do this within VDI, from the top menu we must first open `Terminal` by clicking on the small computer screen icon shown in red below:
+
+
+
+Enter the following two commands (one after the other). The first command loads some necessary dependencies needed to run ESMValTool, and the second command loads the required [ACCESS-NRI ESMValTool-workflow](https://github.com/ACCESS-NRI/ESMValTool-workflow) module.
+```
+module use /g/data/xp65/public/modules
+```
+```
+module load esmvaltool
+```
+
+then finally:
+
+```
+check_hackathon
+```
+You will see a range of checks and processes print to the screen, which may take up to 1 minute to complete. Once you see the "YOU ARE ALL SET!!!" message, everything is setup and ready to go.
+
+
diff --git a/assets/assets_ARE/compute.png b/assets/assets_ARE/compute.png
new file mode 100644
index 0000000000000000000000000000000000000000..04639a9b62b7e273f3aff82e3c6f81a383f85385
GIT binary patch
literal 27484
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
literal 0
HcmV?d00001
diff --git a/assets/assets_ARE/jupyter_select.png b/assets/assets_ARE/jupyter_select.png
new file mode 100644
index 0000000000000000000000000000000000000000..79f317ff09998624512e1283bde679c82e93a654
GIT binary patch
literal 478381
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