Skip to content

Commit 7c4fcc1

Browse files
authored
Merge branch 'main' into 244-active-mask
2 parents 0239c17 + 07a2382 commit 7c4fcc1

37 files changed

Lines changed: 778 additions & 214 deletions

.github/workflows/build_docs.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
name: Build documentation
3+
4+
# Run workflow on pushes to matching branches
5+
on: # yamllint disable-line rule:truthy
6+
push:
7+
branches: [main]
8+
pull_request:
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
concurrency:
16+
group: pages-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Install uv
29+
uses: astral-sh/setup-uv@v5
30+
31+
- name: Set up Python
32+
uses: actions/setup-python@v5
33+
with:
34+
python-version: "3.11"
35+
36+
- name: Generate reference config
37+
run: uv run --group docs python docs/scripts/generate_config.py
38+
39+
- name: Build docs
40+
run: uv run --group docs zensical build
41+
42+
- name: Upload Pages artifact
43+
if: github.ref == 'refs/heads/main'
44+
uses: actions/upload-pages-artifact@v3
45+
with:
46+
path: docs/_build
47+
48+
deploy:
49+
if: github.ref == 'refs/heads/main'
50+
needs: build
51+
runs-on: ubuntu-latest
52+
environment:
53+
name: github-pages
54+
url: ${{ steps.deployment.outputs.page_url }}
55+
steps:
56+
- name: Deploy to GitHub Pages
57+
id: deployment
58+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ __pycache__
77
.vscode
88
*local.yaml
99
dist
10+
docs/_build
11+
docs/src/api/config.md
1012
outputs
1113
wandb
1214
notebooks/data

README.md

Lines changed: 24 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -1,247 +1,57 @@
11
# IceNet Multimodal Pipeline
22

3-
IceNet-MP is a multimodal pipeline for predicting sea ice.
3+
[![Tests](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/test_code.yaml/badge.svg)](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/test_code.yaml)
4+
[![Docs](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/build_docs.yml/badge.svg)](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/build_docs.yml)
5+
[![Code style](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/code_style.yaml/badge.svg)](https://github.com/alan-turing-institute/icenet-mp/actions/workflows/code_style.yaml)
6+
[![Licence: MIT](https://img.shields.io/badge/licence-MIT-green)](LICENSE)
47

5-
## Setting up your environment
8+
IceNet-MP fuses satellite observations, Argo float sensor data, and ERA5 reanalysis fields to produce short-term sea ice concentration forecasts. It uses an encode-process-decode architecture that projects each input dataset into a shared latent space, allowing new data sources to be added without changing the core model.
69

7-
### Tools
8-
9-
You will need to install the following tools if you want to develop this project:
10-
11-
- [`uv`](https://docs.astral.sh/uv/getting-started/installation/)
12-
13-
On an HPC system, this will install to `~/.local/bin`, so make sure that your home directory has enough free space.
14-
15-
### Installing IceNet-MP
16-
17-
:warning: Isambard-AI uses ARM processors, and there is currently no `aarch64` wheel for `cf-units`.
18-
Before installing on Isambard-AI you will need to set the following environment variables:
19-
20-
```bash
21-
export UDUNITS2_XML_PATH=/projects/u5gf/seaice/udunits/share/udunits/udunits2.xml
22-
export UDUNITS2_INCDIR=/projects/u5gf/seaice/udunits/include/
23-
export UDUNITS2_LIBDIR=/projects/u5gf/seaice/udunits/lib/
24-
```
25-
26-
You can then install the project as follows (for DAWN / Baskerville, you can ignore the previous step):
10+
## Quick start
2711

2812
```bash
2913
git clone git@github.com:alan-turing-institute/icenet-mp.git
30-
cd icenet_mp
14+
cd icenet-mp
3115
uv sync --managed-python
3216
```
3317

34-
### Creating your own configuration file
35-
36-
Create a file in the folder `icenet_mp/config` that is called `<your chosen name here>.local.yaml`.
37-
You will typically want this to inherit from `base.yaml`, and then you can apply your own changes on top.
38-
For example, the following config will override the `base_path` option in `base.yaml`:
18+
Create a local config in `icenet_mp/config/` (see [Configuration](https://alan-turing-institute.github.io/icenet-mp/user-guide/configuration/) for details):
3919

4020
```yaml
21+
# icenet_mp/config/my.local.yaml
4122
defaults:
4223
- base
4324
- _self_
4425

45-
base_path: /local/path/to/my/data
26+
base_path: /path/to/my/data
4627
```
4728
48-
You can then run this with, e.g.:
29+
Then download datasets and train:
4930
5031
```bash
51-
uv run imp <command> --config-name <your local config>.yaml
32+
uv run imp datasets create --config-name my.local
33+
uv run imp train --config-name my.local
5234
```
5335

54-
This will run using the default model setup (rescaling encoder, small UNet, rescaling decoder) that is sufficient for quick tests, but not appropriate for larger training runs.
55-
56-
You can also use this config to override other options in the `base.yaml` file, as shown below:
57-
58-
```yaml
59-
defaults:
60-
- base
61-
- override /model: cnn_unet_cnn # Use this format if you want to use a different config
62-
- _self_
63-
64-
# Override specific model parameters
65-
model:
66-
processor:
67-
start_out_channels: 37 # Use this format to override specific model parameters in the named configs
68-
69-
base_path: /local/path/to/my/data
70-
```
71-
72-
Alternatively, you can apply overrides to specific options at the command line like this:
36+
Evaluate a checkpoint:
7337

7438
```bash
75-
uv run imp <command> ++base_path=/local/path/to/my/data
76-
```
77-
78-
:warning: Note that `base_persistence.yaml` overrides the specific options in `base.yaml` needed to run the `Persistence` model.
79-
80-
### HPC-specific configurations
81-
82-
For running on a shared HPC systems (Baskerville, DAWN or Isambard-AI), you will want to use the pre-downloaded data and the right GPU accelerator.
83-
This is handled for you by including the appropriate config file:
84-
85-
```yaml
86-
defaults:
87-
- base_baskerville OR base_dawn OR base_isambardai
88-
- override /data: full # if you want to run over the full dataset instead of the sample dataset
89-
- _self_
90-
```
91-
92-
### Generating Argo float missing dates
93-
94-
Some dates do not have any Argo float data.
95-
In order to generate a list of missing dates for a particular Argo float dataset, you can do the following:
96-
97-
Add `ignore_missing_dates: true` to the relevant dataset file.
98-
Delete any previously downloaded version of the dataset.
99-
100-
```
101-
uv run imp datasets create --config-name <a config file that requires this dataset>
39+
uv run imp evaluate --checkpoint /path/to/checkpoint.ckpt --config-name my.local
10240
```
10341

104-
This will then attempt to download the full dataset, ignoring any exceptions that would usually be raised by missing dates.
105-
It will also print a list of missing dates at the end of each data group.
106-
107-
### Running with different datasets
42+
## Documentation
10843

109-
The default set of datasets to run over is defined by the `data` key which is set to `sample` in `base.yaml`.
110-
This means that the default set of datasets are the ones defined in `config/data/sample.yaml`.
111-
To understand how dataset properties are encoded in its name, read `config/data/datasets/naming_convention.txt`.
112-
To define a custom set of datasets, for example for comparison testing, you can do the following.
44+
- [Installation](https://alan-turing-institute.github.io/icenet-mp/user-guide/installation/) — prerequisites, `uv` setup, HPC-specific steps
45+
- [Configuration](https://alan-turing-institute.github.io/icenet-mp/user-guide/configuration/) — local config files, model overrides, custom datasets
46+
- [Commands](https://alan-turing-institute.github.io/icenet-mp/user-guide/commands/)`datasets create`, `datasets inspect`, `train`, `evaluate`
47+
- [Add a model](https://alan-turing-institute.github.io/icenet-mp/how-to/add-a-model/) — tensor format, standalone vs. processor model architectures
11348

114-
- create a custom dataset list in `config/data/my_datasets.local.yaml` that might look like this:
115-
116-
```
117-
defaults:
118-
- datasets:
119-
- samp_sicsouth_osisaf_25p0km_2017_2019_24h_v2
120-
- samp_weathersouth_era5_0p5_2017_2019_24h_v2
121-
- split: sample_dataset
122-
- _self_
123-
```
124-
125-
- in this example we have excluded the Argo float data and used ERA5 on the native 0.5 degree grid, instead of the reprojected datasets
126-
- now create a custom main config file, for example `config/my_datasets.local.yaml` that might look like this:
127-
128-
```
129-
defaults:
130-
- <the base config file you are using>
131-
- override /data: my_datasets.local
132-
- _self_
133-
```
134-
135-
- now run with `uv run imp train --config-name my_datasets.local`
136-
137-
## Running IceNet-MP commands
138-
139-
:information_source: Note that if you are running the below commands locally, specify the base path in your local config, then add the argument `--config-name <your local YAML config>`.
140-
141-
### Create
142-
143-
You will need a [CDS account](https://cds.climate.copernicus.eu/how-to-api) to download data with `anemoi` (e.g. the ERA5 data).
144-
145-
Run `uv run imp datasets create` to download datasets.
146-
147-
We make use of the fact that Anemoi datasets keep track of which groups of dates have been loaded to ensure that an interrupted download can be resumed simply by rerunning the `datasets create` command.
148-
149-
### Inspect
150-
151-
Run `uv run imp datasets inspect` to inspect datasets (i.e. to get dataset properties and statistical summaries of the variables).
152-
153-
### Train
154-
155-
You will need a [Weights & Biases account](https://docs.wandb.ai/models/quickstart) to run a training run.
156-
[Generate an API key](https://docs.wandb.ai/models/quickstart) then run the following to allow automatic authentication.
157-
158-
```
159-
export WANDB_API_KEY=<your_api_key>
160-
wandb login
161-
```
162-
163-
Run `uv run imp train` to train using the datasets specified in the config.
164-
165-
:information_source: This will save checkpoints to `${BASE_DIR}/training/wandb/run-${DATE}$-${RANDOM_STRING}/checkpoints/${CHECKPOINT_NAME}$.ckpt`. Where the `BASE_DIR` is the base path to the data defined in your config file.
49+
## Jupyter notebooks
16650

167-
:warning: If you are running on macOS, you may need to prepend your `uv` run command with `PYTORCH_ENABLE_MPS_FALLBACK=1`. For example:
51+
The `notebooks/` folder contains demonstrator notebooks. Run them with:
16852

16953
```bash
170-
PYTORCH_ENABLE_MPS_FALLBACK=1 uv run imp train
171-
```
172-
173-
### Evaluate
174-
175-
Run `uv run imp evaluate --checkpoint PATH_TO_A_CHECKPOINT` to evaluate using a checkpoint from a training run.
176-
177-
### Visualisations
178-
179-
You can plot static images or animations of the raw data by adding the following option to your local config:
180-
```
181-
evaluate:
182-
callbacks:
183-
plotting:
184-
make_input_plots: true
54+
uv run --group notebooks jupyter notebook
18555
```
18656

187-
Settings (output directories, styling, animation parameters) are read from `config.evaluate.callbacks.raw_inputs` in your YAML config files. Command-line options can override config values if needed.
188-
189-
## Adding a new model
190-
191-
### Background
192-
193-
An IceNet-MP model needs to be able to run over multiple different datasets with different dimensions.
194-
These are structured in `NTCHW` format, where:
195-
- `N` is the batch size,
196-
- `T` is the number of history (forecast) steps for inputs (outputs)
197-
- `C` is the number of channels or variables
198-
- `H` is a height dimension
199-
- `W` is a width dimension
200-
201-
`N` and `T` will be the same for all inputs, but `C`, `H` and `W` might vary.
202-
203-
Taking as an example, a batch size (`N=2`), 3 history steps and 4 forecast steps, we will have `k` inputs of shape `(2, 3, C_k, H_k, W_k)` and one output of shape `(2, 4, C_out, H_out, W_out)`.
204-
205-
### Standalone models
206-
207-
A standalone model will need to accept a `dict[str, TensorNTCHW]` which maps dataset names to an `NTCHW` Tensor of values.
208-
The model might want to use one or more of these for training, and will need to produce an output with shape `N, T, C_out, H_out, W_out`.
209-
210-
As can be seen in the example below, a separate instance of the model is likely to be needed for each output to be predicted.
211-
212-
![image](docs/assets/pipeline-standalone.png)
213-
214-
Pros:
215-
- all input variables are available without transformation
216-
217-
Cons:
218-
- hard to add new inputs
219-
- hard to add new outputs
220-
221-
### Processor models
222-
223-
A processor model is part of a larger encode-process-decode step.
224-
Start by defining a latent space as `(C_latent, H_latent, W_latent)` - in the example below, this has been set to `(10, 64, 64)`.
225-
The encode-process-decode model automatically creates one encoder for each input and one decoder for each output.
226-
The dataset-specific encoder takes the input data and converts it to shape `(N, T, C_latent, H_latent, W_latent)`.
227-
The `k` encoded datasets can then be combined in latent space to give a single dataset of shape `(N, T, k * C_latent, H_latent, W_latent)`.
228-
229-
This is then passed to the processor, which must accept input of shape `(N, T, k * C_latent, H_latent, W_latent)` and produce output of the same shape.
230-
231-
This output is then passed to one or more output-specific decoders which take input of shape `(N, T, k * C_latent, H_latent, W_latent)` and produce output of shape `(N, T, C_out, H_out, W_out)`.
232-
233-
![image](docs/assets/pipeline-encode-process-decode.png)
234-
235-
Pros:
236-
- easy to add new inputs
237-
- easy to add new outputs
238-
239-
Cons:
240-
- input variables have been transformed into latent space
241-
242-
## Jupyter notebooks
243-
244-
There are various demonstrator Jupyter notebooks in the `notebooks` folder.
245-
You can run these with `uv run --group notebooks jupyter notebook`.
246-
247-
A good one to start with is `notebooks/demo_pipeline.ipynb` which gives a more detailed overview of the pipeline.
57+
Start with `notebooks/demo_pipeline.ipynb` for a worked example of the full pipeline.

docs/scripts/generate_config.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Generate the full reference configuration documentation page.
2+
3+
Run from the project root:
4+
5+
uv run --group docs python docs/scripts/generate_config.py
6+
"""
7+
8+
from pathlib import Path
9+
10+
from hydra import compose, initialize_config_dir
11+
from omegaconf import OmegaConf
12+
13+
DOCS_DIR = Path(__file__).parent.parent
14+
CONFIG_DIR = str(DOCS_DIR.parent / "icenet_mp" / "config")
15+
OUTPUT_PATH = DOCS_DIR / "src" / "api" / "config.md"
16+
17+
HEADER = """\
18+
# Reference configuration
19+
20+
<!-- This file is auto-generated by `docs/generate_config.py` — do not edit by hand. -->
21+
22+
The full default configuration composed from [`icenet_mp/config/base.yaml`](https://github.com/alan-turing-institute/icenet-mp/blob/main/icenet_mp/config/base.yaml) and all its sub-configs.
23+
This is the configuration used when you run any command without overrides.
24+
25+
!!! note
26+
Interpolation markers such as `${base_path}` are left unresolved so you can see exactly which keys reference shared values.
27+
Set `base_path` in your local config file to point to your data directory.
28+
29+
## Named model configs
30+
31+
The `model` section below shows the default (`naive-unet-naive`).
32+
Alternative model configs live in `icenet_mp/config/model/` and can be selected with:
33+
34+
```bash
35+
uv run imp <command> --config-name my_config # where my_config inherits base and overrides /model
36+
```
37+
38+
## Full config
39+
40+
"""
41+
42+
43+
def main() -> None:
44+
"""Compose the base Hydra config and write the API docs page."""
45+
with initialize_config_dir(config_dir=CONFIG_DIR, version_base=None):
46+
cfg = compose(config_name="base")
47+
48+
OUTPUT_PATH.write_text(f"{HEADER}```yaml\n{OmegaConf.to_yaml(cfg)}```\n")
49+
print(f"Wrote reference config to {OUTPUT_PATH.relative_to(DOCS_DIR.parent)}")
50+
51+
52+
if __name__ == "__main__":
53+
main()

docs/src/api/callbacks.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Callbacks
2+
3+
::: icenet_mp.callbacks

0 commit comments

Comments
 (0)