Tip

For an interactive online version click here: Binder badge

Example: Working with models from CLI#

HydroMT has the following high-level functionality from the Command Line Interface (CLI) for setting up models from raw data or adjusting models:

  • building a model: building a model from scratch.

  • updating a model: adding or changing model components of an existing model.

Here we show how to build and update a hypothetical gridded model that contains a grid and a config from the command line interface (CLI) based on the generic HydroMT example_model.

Lets first check which models are available in our environment:

[1]:
!hydromt --models
Model plugins:
        - model (hydromt 1.2.0.dev0)
        - example_model (hydromt 1.2.0.dev0)

Build a model from CLI#

To build a model you always follow the next four steps.

  1. Prepare or use a pre-defined data catalog with all the required data sources

  2. Define your model region, see the overview of model region options.

  3. Prepare a model workflow file which describes the complete pipeline to build your model.

  4. Build you model using the CLI or Python interface

Here we focus on steps 2-4 and use data from the predefined artifact_data catalog.

Using the hydromt build method we can setup a complete model from scratch. Let’s get an overview of the method and its arguments.

Note the required MODEL (i.e. name of the model) and MODEL_ROOT (i.e. folder where to save the model) arguments.

[2]:
!hydromt build --help
Usage: hydromt build [OPTIONS] MODEL MODEL_ROOT

  Build models from scratch.

  Example usage: --------------

  To build a wflow model: hydromt build wflow_sbm /path/to/model_root -i
  /path/to/wflow_config.yml -d deltares_data -d /path/to/data_catalog.yml -v

  To build a sfincs model: hydromt build sfincs /path/to/model_root  -i
  /path/to/sfincs_config.yml -d /path/to/data_catalog.yml -v

Options:
  -i, --config PATH        Path to hydroMT configuration file, for the model
                           specific implementation.  [required]
  -d, --data TEXT          Path to local yaml data catalog file OR name of
                           predefined data catalog.
  --dd, --deltares-data    Flag: Shortcut to add the "deltares_data" catalog
  --fo, --force-overwrite  Flag: If provided overwrite existing model files
  --cache                  Flag: If provided cache tiled rasterdatasets
  -v, --verbose            Increase verbosity.
  -q, --quiet              Decrease verbosity.
  --help                   Show this message and exit.

As a first step, we want to create a grid for our example model. We will do this by calling the example_model.grid.create_from_region method. We will based our grid from a bounding box with a resolution of 0.05 degree in EPSG 4326.

For this we will create the following workflow file below, where we define the region for our grid.

The %%writefile magic saves the content below to a file. The content of the .yaml file start from the second line.

[3]:
%%writefile tmp_build_example_model_min.yml

steps:
  - grid.create_from_region:
      region:
        bbox: [11.70, 45.35, 12.95, 46.70]
      res: 0.05
      crs: 4326
Writing tmp_build_example_model_min.yml

Now let’s call the HydroMT build command with our newly created build_example_model.yml workflow file and using the artifact_data catalog:

[4]:
!hydromt build example_model ./tmp_example_model_min -i tmp_build_example_model_min.yml -d artifact_data --fo -v
2025-11-13 11:57:20,368 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:20,395 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Reading data catalog artifact_data latest
2025-11-13 11:57:20,395 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Parsing data catalog from /home/runner/.hydromt/artifact_data/v1.0.0/data_catalog.yml
2025-11-13 11:57:21,070 - hydromt.model.model - model - INFO - Initializing example_model model from hydromt (v1.2.0.dev0).
2025-11-13 11:57:21,071 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - build: grid.create_from_region
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.res=0.05
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.crs=4326
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.region_crs=4326
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.rotated=False
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.hydrography_path=None
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.basin_index_path=None
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.add_mask=True
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.align=True
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.dec_origin=0
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.dec_rotation=3
2025-11-13 11:57:21,071 - hydromt.model.model - model - INFO - grid.create_from_region.region={'bbox': [11.7, 45.35, 12.95, 46.7]}
2025-11-13 11:57:21,071 - hydromt.hydromt.model.example.example_grid_component - example_grid_component - INFO - Preparing 2D grid.
2025-11-13 11:57:21,085 - hydromt.model.components.config - config - INFO - example_model.config: No config data found, skip writing.
2025-11-13 11:57:21,085 - hydromt.model.components.grid - grid - INFO - example_model.grid: Writing grid data to /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model_min/grid.nc.

The example above means the following: run hydromt build with:

  • example_model: i.e. build a generic GridModel instance

  • ./tmp_example_model_min: output model folder

  • -i tmp_build example_model_min.yml: path to the model build workflow file

  • -d artifact_data: data catalog to use

  • -vv : give some extra verbosity (1 * v) to display feedback on screen. Now INFO messages are provided.

Let’s see which files where created for our model:

[5]:
# print MODEL_ROOT folder
import os


def print_dir(root):
    for path, _, files in os.walk(root):
        print(path)
        for name in files:
            if name.endswith(".xml"):
                continue
            print(f" - {name}")


print_dir("tmp_example_model_min")
tmp_example_model_min
 - hydromt.log
 - grid.nc

We can see that in this case, not many files were created, only the grid and the hydromt log file.

So now let’s add more steps to our workflow file to also add a configuration file with some settings, re-create our grid and populate it with some data (e.g. elevation and landuse). We will use the following workflow file:

[6]:
%%writefile tmp_build_example_model.yml

steps:
  - config.update:
      data:
        header.settings: value
        timers.end: "2010-02-15"
        timers.start: "2010-02-05"
  - grid.create_from_region:
      region:
        bbox: [11.70, 45.35, 12.95, 46.70]
      res: 0.05
      crs: 4326
  - grid.add_data_from_rasterdataset:
      raster_data: merit_hydro_ihu
      variables:
        - elevtn
        - basins
      reproject_method:
        - average
        - mode
  - grid.add_data_from_rasterdataset:
      raster_data: vito_2015
      fill_method: nearest
      reproject_method: mode
      rename:
        vito: landuse
  - write:
      components:
        - grid
        - config
Writing tmp_build_example_model.yml

In this configuration, you see that we will prepare quite a lot of data for our grid model using some of the generic model methods for grid. We will prepare:

Let’s now build this model:

[7]:
!hydromt build example_model ./tmp_example_model -i tmp_build_example_model.yml -d artifact_data --fo -v
2025-11-13 11:57:25,481 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:25,510 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Reading data catalog artifact_data latest
2025-11-13 11:57:25,510 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Parsing data catalog from /home/runner/.hydromt/artifact_data/v1.0.0/data_catalog.yml
2025-11-13 11:57:26,190 - hydromt.model.model - model - INFO - Initializing example_model model from hydromt (v1.2.0.dev0).
2025-11-13 11:57:26,190 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:26,190 - hydromt.model.model - model - INFO - build: config.update
2025-11-13 11:57:26,190 - hydromt.model.model - model - INFO - config.update.data={'header.settings': 'value', 'timers.end': '2010-02-15', 'timers.start': '2010-02-05'}
2025-11-13 11:57:26,190 - hydromt.model.model - model - INFO - build: grid.create_from_region
2025-11-13 11:57:26,190 - hydromt.model.model - model - INFO - grid.create_from_region.res=0.05
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.crs=4326
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.region_crs=4326
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.rotated=False
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.hydrography_path=None
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.basin_index_path=None
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.add_mask=True
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.align=True
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.dec_origin=0
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.dec_rotation=3
2025-11-13 11:57:26,191 - hydromt.model.model - model - INFO - grid.create_from_region.region={'bbox': [11.7, 45.35, 12.95, 46.7]}
2025-11-13 11:57:26,191 - hydromt.hydromt.model.example.example_grid_component - example_grid_component - INFO - Preparing 2D grid.
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - build: grid.add_data_from_rasterdataset
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.variables=['elevtn', 'basins']
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.fill_method=None
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.reproject_method=['average', 'mode']
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.mask_name=mask
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.rename=None
2025-11-13 11:57:26,204 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.raster_data=merit_hydro_ihu
2025-11-13 11:57:26,204 - hydromt.hydromt.model.example.example_grid_component - example_grid_component - INFO - Preparing grid data from raster source merit_hydro_ihu
2025-11-13 11:57:26,207 - hydromt.data_catalog.sources.data_source - data_source - INFO - Reading merit_hydro_ihu RasterDataset data from /home/runner/.hydromt/artifact_data/latest/merit_hydro_1k/{variable}.tif
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - build: grid.add_data_from_rasterdataset
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.variables=None
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.fill_method=nearest
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.reproject_method=mode
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.mask_name=mask
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.rename={'vito': 'landuse'}
2025-11-13 11:57:26,341 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.raster_data=vito_2015
2025-11-13 11:57:26,341 - hydromt.hydromt.model.example.example_grid_component - example_grid_component - INFO - Preparing grid data from raster source vito_2015
2025-11-13 11:57:26,343 - hydromt.data_catalog.sources.data_source - data_source - INFO - Reading vito_2015 RasterDataset data from /home/runner/.hydromt/artifact_data/latest/vito.tif
2025-11-13 11:57:26,397 - hydromt.model.model - model - INFO - build: write
2025-11-13 11:57:26,397 - hydromt.model.model - model - INFO - write.components=['grid', 'config']
2025-11-13 11:57:26,397 - hydromt.model.components.grid - grid - INFO - example_model.grid: Writing grid data to /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model/grid.nc.
2025-11-13 11:57:26,441 - hydromt.model.components.config - config - INFO - example_model.config: Writing model config to /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model/settings.toml.

The example above means the following: run hydromt build with:

  • example_model: i.e. build a generic GridModel instance

  • ./tmp_example_model: output model folder

  • -i tmp_build_example_model.yaml: use this .yaml file to configure the model build

  • -d artifact_data: parse the pre-defined artifact_data

  • -vv: give some extra verbosity (1 * v) to display feedback on screen. Now INFO messages are provided.

Let’s check some of the outputs that were produced:

[8]:
# Files created
print_dir("tmp_example_model")
tmp_example_model
 - settings.toml
 - hydromt.log
 - grid.nc
[9]:
# checkout the content of the hypothetical model simulation configuration
fn_yaml = "tmp_example_model/settings.toml"
with open(fn_yaml, "r") as f:
    txt = f.read()
print(txt)
[header]
settings = "value"

[timers]
end = "2010-02-15"
start = "2010-02-05"

[10]:
# List of variables in grid.nc
from hydromt.model import ExampleModel

model = ExampleModel(root="./tmp_example_model", mode="r")
ds = model.grid.data

print(f"Variables available in grid.nc: {list(ds.data_vars)}")
2025-11-13 11:57:30,706 - hydromt.model.model - model - INFO - Initializing example_model model from hydromt (v1.2.0.dev0).
Variables available in grid.nc: ['mask', 'elevtn', 'basins', 'landuse']
[11]:
# Plot one of the variable (change the name below to plot a different variable)
var = "elevtn"
ds[var].plot()
[11]:
<matplotlib.collections.QuadMesh at 0x7f69eb277190>
../_images/_examples_working_with_models_basics_21_1.png

Update a model from CLI#

Using the hydromt update method we can update an existing model with new components or modify existing components. Let’s get an overview of the method and its arguments.

Note that the MODEL (i.e. name of the model), and MODEL_ROOT (i.e. folder of existing model) are still required. There is an optional -o --model-out option to save the updated model in a different directory.

[12]:
!hydromt update --help
Usage: hydromt update [OPTIONS] MODEL MODEL_ROOT

  Update a specific component of a model.

  Set an output directory to copy the edited model to a new folder, otherwise
  maps are overwritten.

  Example usage: --------------

  Update Wflow model components outlined in an .yml configuration file and
  write the model to a directory: hydromt update wflow_sbm /path/to/model_root
  -o /path/to/model_out  -i /path/to/wflow_config.yml  -d
  /path/to/data_catalog.yml -v

Options:
  -o, --model-out DIRECTORY  Output model folder. Maps in MODEL_ROOT are
                             overwritten if left empty.
  -i, --config PATH          Path to hydroMT configuration file, for the model
                             specific implementation.  [required]
  -d, --data TEXT            Path to local yaml data catalog file OR name of
                             predefined data catalog.
  --dd, --deltares-data      Flag: Shortcut to add the "deltares_data" catalog
  --fo, --force-overwrite    Flag: If provided overwrite existing model files
  --cache                    Flag: If provided cache tiled rasterdatasets
  -q, --quiet                Decrease verbosity.
  -v, --verbose              Increase verbosity.
  --help                     Show this message and exit.

In this basic example we use the hydromt update method to update the ExampleModel instance with an upstream area raster map. Then we write only the updated model map component to file.

[13]:
%%writefile tmp_update_example_model.yml

steps:
  - grid.add_data_from_rasterdataset:
      raster_data: merit_hydro_ihu
      variables:
        - uparea
      reproject_method:
        - max
  - grid.write:
Writing tmp_update_example_model.yml
[14]:
!hydromt update example_model ./tmp_example_model -o ./tmp_example_model_update -i tmp_update_example_model.yml -d artifact_data --fo -v
2025-11-13 11:57:39,423 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:39,450 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Reading data catalog artifact_data latest
2025-11-13 11:57:39,450 - hydromt.data_catalog.data_catalog - data_catalog - INFO - Parsing data catalog from /home/runner/.hydromt/artifact_data/v1.0.0/data_catalog.yml
2025-11-13 11:57:40,130 - hydromt.model.model - model - INFO - Initializing example_model model from hydromt (v1.2.0.dev0).
2025-11-13 11:57:40,130 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:40,131 - hydromt.model.model - model - INFO - Reading model data from /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model
2025-11-13 11:57:40,131 - hydromt.model.components.config - config - INFO - Reading model config file from /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model/settings.toml.
2025-11-13 11:57:40,158 - hydromt - log - INFO - HydroMT version: 1.2.0.dev0
2025-11-13 11:57:40,162 - hydromt.model.model - model - INFO - update: grid.add_data_from_rasterdataset
2025-11-13 11:57:40,162 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.variables=['uparea']
2025-11-13 11:57:40,162 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.fill_method=None
2025-11-13 11:57:40,162 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.reproject_method=['max']
2025-11-13 11:57:40,163 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.mask_name=mask
2025-11-13 11:57:40,163 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.rename=None
2025-11-13 11:57:40,163 - hydromt.model.model - model - INFO - grid.add_data_from_rasterdataset.raster_data=merit_hydro_ihu
2025-11-13 11:57:40,163 - hydromt.hydromt.model.example.example_grid_component - example_grid_component - INFO - Preparing grid data from raster source merit_hydro_ihu
2025-11-13 11:57:40,165 - hydromt.data_catalog.sources.data_source - data_source - INFO - Reading merit_hydro_ihu RasterDataset data from /home/runner/.hydromt/artifact_data/latest/merit_hydro_1k/{variable}.tif
2025-11-13 11:57:40,245 - hydromt.model.model - model - INFO - update: grid.write
2025-11-13 11:57:40,245 - hydromt.model.model - model - INFO - grid.write.filename=None
2025-11-13 11:57:40,246 - hydromt.model.model - model - INFO - grid.write.gdal_compliant=False
2025-11-13 11:57:40,246 - hydromt.model.model - model - INFO - grid.write.rename_dims=False
2025-11-13 11:57:40,246 - hydromt.model.model - model - INFO - grid.write.force_sn=False
2025-11-13 11:57:40,246 - hydromt.model.model - model - INFO - grid.write.to_netcdf_kwargs=None
2025-11-13 11:57:40,246 - hydromt.model.components.grid - grid - INFO - example_model.grid: Writing grid data to /home/runner/work/hydromt/hydromt/docs/_examples/tmp_example_model_update/grid.nc.

The example above means the following: run hydromt update with:

  • example_model: i.e. update a ExampleModel instance

  • ./tmp_example_model: the folder of the to-be updated model

  • -o ./tmp_example_model_update: the folder of the updated model

  • -i tmp_update_example_model.yml: the hydromt workflow file listing the methods to be executed

  • -d artifact_data: use the pre-defined artifact_data catalog

  • -v: give some extra verbosity (2 * v) to display feedback on screen. Now debug messages are provided.

Let’s check the content of the updated model and that we should now have an uparea variable available in the updated model grid:

[15]:
# note the difference with the original model
print_dir("tmp_example_model_update")
tmp_example_model_update
 - hydromt.log
 - grid.nc
[16]:
# List of variables in grid.nc
from hydromt.model import ExampleModel

model = ExampleModel(root="./tmp_example_model_update", mode="r")
ds = model.grid.data

print(f"Variables available in grid.nc: {list(ds.data_vars)}")
2025-11-13 11:57:41,002 - hydromt.model.model - model - INFO - Initializing example_model model from hydromt (v1.2.0.dev0).
Variables available in grid.nc: ['mask', 'elevtn', 'basins', 'landuse', 'uparea']