The repository is structured into the following directories:
/routetools: Python source code/tests: Python code for testing via pytest
Conveniently, a set of workflows via Github Actions are already installed:
pre-commit: run pre-commit hookspytest: automatically discover and runs tests intests/
Tools:
- uv: manage dependencies, Python versions and virtual environments
- ruff: lint and format Python code
- mypy: check types
- pytest: run unit tests
- pre-commit: manage pre-commit hooks
- prettier: format YAML and Markdown
- codespell: check spelling in source code
- Parametric Performance Model — closed-form RISE model for ship power prediction (hull, wind, wave, and wingsail components).
Install package and pinned dependencies with the uv package manager:
-
Install
uv. See instructions for Windows, Linux or MacOS here. -
Clone repository
-
Install package and dependencies in a virtual environment:
uv sync -
(Optional) Install the SWOPP3 performance model:
uv sync --extra swopp3 --find-links release_package/wheelsIf the pre-built wheels are available locally in
release_package/wheels/,uvwill resolveswopp3-performance-modelfrom that directory. Wheels are available for Python 3.10 – 3.13 on Linux (manylinux) and Windows (win_amd64). -
Run any command or Python script with
uv run, for instance:uv run routetools/cmaes.pyAlternatively, you can also activate the virtual env and run the scripts normally:
source .venv/bin/activate
Install a specific version of the package with pip or uv pip:
pip install git+ssh://git@github.com:Weather-Routing-Research/cmaes_bezier_demo.git
To be able to run the code, you need to download oceanographic data from Google Drive. This data is stored in a zip file (15.5 GB) and should be extracted to a folder (24.0 GB).
You can use the following bash script to download the data:
curl -L -C - \
-o data.zip \
'https://drive.usercontent.google.com/download?id=1E52akVR--yPNUHB12vUl2IZH8S9-RuHA&export=download&confirm=t'
unzip -o data.zip -d .The extracted folder should have the following structure:
data
├── currents
│ ├── 2023-01-01.nc
│ ├── 2023-01-02.nc
│ ├── ...
│ └── 2023-12-31.nc
├── earth-seas-1km-valid.geo.json
└── earth-seas-2km5-valid.geo.json
Note: This data only includes ocean currents. If you want to include wave data, you need to download the full data folder (121 GB, compressed to 43.5 GB) from here instead.
There are several examples in the scripts/ folder. You can run them with uv run, for instance:
uv run scripts/single_run.pyIf your computer does not have a GPU, you can force JAX to use the CPU with JAX_PLATFORMS=cpu before the command. For instance:
JAX_PLATFORMS=cpu uv run scripts/single_run.pyThe routetools.era5 module provides real-world ERA5 wind and wave fields
for weather routing. Two download backends are available:
- GCS (default) — Google Cloud archive, no API key required.
- CDS — Copernicus Climate Data Store (requires
cdsapi+ API key).
1. Download ERA5 data for the Atlantic corridor (USNYC ↔ DEHAM):
uv run scripts/download_era5.py --corridor atlantic --year 2023This creates data/era5/era5_wind_atlantic_2023.nc and
data/era5/era5_waves_atlantic_2023.nc.
2. Run the real-world benchmark (New York → Hamburg, Jan 8 2023):
uv run scripts/era5_benchmark.py --departure 2023-01-08T00:00:00See scripts/download_era5.py --help and scripts/era5_benchmark.py --help
for all available options.
The default SWOPP3 competition pipeline is:
uv run scripts/download_era5.py
uv run scripts/swopp3_run.pyThese two commands line up without extra path flags. The downloader writes the
four default 2024 files that scripts/swopp3_run.py expects:
data/era5/era5_wind_atlantic_2024.nc
data/era5/era5_waves_atlantic_2024.nc
data/era5/era5_wind_pacific_2024.nc
data/era5/era5_waves_pacific_2024.nc
scripts/swopp3_run.py validates these files before running any case. If one
or more inputs are missing, it exits immediately with a precise error message
instead of silently substituting a great-circle route or running without
weather data. This is intentional:
- GC cases still require wind and wave data for SWOPP3 energy evaluation.
- Optimised cases require wind data for the CMA-ES vectorfield and wind/wave data for the final SWOPP3 energy evaluation.
If you download a different year or only one corridor, pass matching
--wind-path* and --wave-path* options to scripts/swopp3_run.py.
scripts/swopp3_run.py supports named experiment profiles stored in
config.toml.
Run a named experiment:
uv run scripts/swopp3_run.py k15_p400_w1000Use another TOML file if needed:
uv run scripts/swopp3_run.py k15_p400_w1000 --config-path path/to/experiments.tomlRelative paths inside a profile are resolved from the directory that contains the TOML file, not from your current working directory.
Each profile can define shared defaults plus one or more runs.
The runner writes a resolved manifest to:
output/<experiment>/experiment_manifest.json
This records the experiment name, config file, source script, and resolved run parameters used for the launch.
To add a new experiment:
- Add a new
[swopp3.experiments.<name>]section toconfig.toml. - Put shared parameters under
[swopp3.experiments.<name>.defaults]. - Add one or more
[[swopp3.experiments.<name>.runs]]entries. - Set
source_scriptto the script or workflow the profile replaces. - Run
uv run scripts/swopp3_run.py <name>.
To reproduce the results from the paper, run the following command:
sh scripts/run_results.sh(Preferably, using nohup to avoid interruption if you close the terminal, and redirecting output to a log file for later review):
This will run BERS across all instance for the synthetic scenarios and output the results to output/ folder.
Next, to generate the plots and tables related to the synthetic scenarios, run:
uv run scripts/synthetic/figures.py
uv run scripts/synthetic/tables.pyIn order to generate the results for the real-world scenarios, make sure you have downloaded the benchmark data as described in the Benchmark data section. Then run:
uv run scripts/realworld/results.pyFinally, to generate the plots and tables for the paper, run:
uv run scripts/realworld/figures.py
uv run scripts/realworld/tables.pySource the activation script to prefer GPU for JAX in your current shell:
source scripts/activate_gpu.shThis sets JAX_PLATFORM_NAME=cuda, CUDA_VISIBLE_DEVICES=0, and XLA_PYTHON_CLIENT_PREALLOCATE=false so JAX will pick the local GPU by default.
The repository includes a .env file with the same defaults; tools that read .env (or your CI) can load it. You can also set the variables per-command:
JAX_PLATFORM_NAME=cuda CUDA_VISIBLE_DEVICES=0 uv run scripts/single_run.pyInstall uv and pre-commit hooks:
make install
uv will automatically create a virtual environment with the specified Python version in .python-version and install the dependencies from uv.lock (both standard and dev dependencies). It will also install the package in editable mode.
Add dependencies with:
uv add <PACKAGE>
Add dev dependencies with:
uv add --dev <PACKAGE>
Remove dependency with:
uv remove <PACKAGE>
In all cases uv will automatically update the uv.lock file and sync the virtual environment. This can also be done manually with:
uv sync
uv run ipython kernel install --user --name=routetools
Hooks are run on modified files before any commit. To run them manually on all files use:
make hooks
make ruff
make test
make mypy
Follow these steps locally before pushing or opening a PR to keep the repository stable and CI-green:
- Parse the lockfile quickly:
python tools/tools_parse_uv_lock.py- Run pre-commit hooks locally (fast feedback):
pre-commit run --all-files- Run linter and type checks (if you have uv environment):
# with uv
uv run ruff check --show-source .
uv run mypy --install-types --non-interactive
# or system-installed tools
ruff check --show-source .
mypy --install-types --non-interactive- Run the test suite:
uv run pytest- If you need to validate reproducible environment creation, run
uv sync --dev --frozenon a Linux environment (CI will run this step).
If you are on Windows and the project requires platform-specific packages (for example CUDA-enabled JAX), use WSL2 or a Linux runner for the uv sync step.
Occasionally you may make a tiny, clearly-safe change (for example: updating a small helper script, fixing a documentation typo, or adding a fallback version file) and want to commit immediately without running the full pre-commit chain locally. In these rare cases you can bypass hooks with:
git commit --no-verify -m "chore: small doc or safe fix"Use this sparingly. Always prefer running pre-commit run --all-files locally or in your CI workflow. Bypassing hooks should be limited to situations where:
- The change is small and low-risk (docs, generated fallback file).
- You have validated the change manually.
- You plan to run the full checks in CI (or immediately afterwards).
If you are unsure whether a change is safe to commit with --no-verify, run the hooks locally first.