10 minutes to… a glacier change projection with GCM data#

In this example, we illustrate how to do a typical “projection run”, i.e. using GCM data. Here we will first use already bias-corrected CMIP6 data from ISIMIP3b and then show how alternatives like the original CMIP5 and CMIP6 data can be used.

There are three important steps:

  • download the OGGM pre-processed directories containing a pre-calibrated and spun-up glacier model

  • download the climate projections (and bias correct them in the case of CMIP5 or CMIP6)

  • simulate the future glacier evolution from the present day state to the end of the century (2020-2100)

Tags: beginner, projections, CMIP, workflow

# Libs
import matplotlib.pyplot as plt

# Locals
import oggm.cfg as cfg
from oggm import utils, workflow, tasks, DEFAULT_BASE_URL
from oggm.shop import gcm_climate

Pre-processed directories#

Let’s do a run for two Himalayan glaciers: Ngojumba and Khumbu.

# Initialize OGGM and set up the default run parameters
cfg.initialize(logging_level='WARNING')  # print less log messages than the default

# Local working directory (where OGGM will write its output)
cfg.PATHS['working_dir'] = utils.gettempdir('OGGM_gcm_run', reset=True)

# RGI glaciers: Ngojumba and Khumbu
rgi_ids = ['RGI60-15.03473', 'RGI60-15.03733']

# Go - get the pre-processed glacier directories
# You have to explicitly indicate the url from where you want to start from
gdirs = workflow.init_glacier_directories(rgi_ids, from_prepro_level=5, prepro_base_url=DEFAULT_BASE_URL)
2026-07-20 12:55:44: oggm.cfg: Reading default parameters from the OGGM `params.cfg` configuration file.
2026-07-20 12:55:44: oggm.cfg: Multiprocessing switched OFF according to the parameter file.
2026-07-20 12:55:44: oggm.cfg: Multiprocessing: using all available processors (N=4)
2026-07-20 12:55:45: oggm.workflow: init_glacier_directories from prepro level 5 on 2 glaciers.
2026-07-20 12:55:45: oggm.workflow: Execute entity tasks [gdir_from_prepro] on 2 glaciers

The _spinup_historical runs#

The level 5 files now come with a pre-computed model run from the RGI outline date to the last possible date given by the historical climate data. In case of the new default climate dataset GSWP3_W5E5, this is until the end of 2019, so the volume is computed until January 1st, 2020. These files are stored in the directory with a _spinup_historical suffix (see the “10 minutes to… a dynamical spinup” tutorial for context).

Let’s compile them into a single file for our two glaciers:

ds = utils.compile_run_output(gdirs, input_filesuffix='_spinup_historical')
vol_ref2000 = ds.volume / ds.volume.sel(time=2000) * 100
vol_ref2000.plot(hue='rgi_id')
plt.ylabel('Volume (%, reference 2000)');
2026-07-20 12:55:57: oggm.utils: Applying global task compile_run_output on 2 glaciers
2026-07-20 12:55:57: oggm.utils: Applying compile_run_output on 2 gdirs.
---------------------------------------------------------------------------
InvalidParamsError                        Traceback (most recent call last)
Cell In[3], line 1
----> 1 ds = utils.compile_run_output(gdirs, input_filesuffix='_spinup_historical')
      2 vol_ref2000 = ds.volume / ds.volume.sel(time=2000) * 100
      3 vol_ref2000.plot(hue='rgi_id')
      4 plt.ylabel('Volume (%, reference 2000)');

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:584, in global_task.__call__.<locals>._global_task(gdirs, **kwargs)
    580 self.log.workflow('Applying global task %s on %s glaciers',
    581                   task_func.__name__, len(gdirs))
    583 # Run the task
--> 584 return task_func(gdirs, **kwargs)

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:1014, in compile_to_netcdf.__call__.<locals>._compile_to_netcdf(gdirs, input_filesuffix, output_filesuffix, path, tmp_file_size, **kwargs)
   1011 # Run the task
   1012 # If small gdir size, no need for temporary files
   1013 if len(gdirs) < tmp_file_size or not path:
-> 1014     return task_func(gdirs, input_filesuffix=input_filesuffix,
   1015                      path=path, **kwargs)
   1017 # Otherwise, divide and conquer
   1018 sub_gdirs = [gdirs[i: i + tmp_file_size] for i in
   1019              range(0, len(gdirs), tmp_file_size)]

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:1266, in compile_run_output(gdirs, path, input_filesuffix, use_compression)
   1256                         data_vars[vn]['attrs'][attr] = getattr(
   1257                             ds.variables[vn], attr)
   1258         elif vn not in ['time'] + time_keys:
   1259             # This check has future developments in mind.
   1260             # If you end here it means the current data variable is
   (...)   1264             # test_compile_run_output). If it is a new dimension
   1265             # handle it in the if/elif statements.
-> 1266             raise InvalidParamsError(f'The data variable "{vn}" '
   1267                                      'is not known. Is it new or '
   1268                                      'is it a new dimension? '
   1269                                      'Check comment above this '
   1270                                      'raise for more info!')
   1272 # If this worked, keep it as template
   1273 ppath = fp

InvalidParamsError: The data variable "area_m2_min_h" is not known. Is it new or is it a new dimension? Check comment above this raise for more info!

Each RGI glacier has an “inventory date”, the time at which the outline is valid:

gdirs[0].rgi_date, gdirs[1].rgi_date
(2000, 2002)

The glacier volume and area estimates before that date are highly uncertain and serve the purpose of spinup only! In the “10 minutes to… a dynamical spinup” tutorial, we talk about why. For now, these files are perfect for our purpose, since we plan to start our simulation in 2020.

Download and process GCM data from ISIMIP3b (bias-corrected CMIP6)#

A typical use case for OGGM will be to use climate model output (here bias-corrected CMIP6 GCMs from ISIMIP3b). We use the files we mirrored in Bremen here, but you can use whichever you want. From ISIMIP3b, we have 14 GCMs with at least three SSPs per GCM on the cluster (check out https://cluster.klima.uni-bremen.de/~oggm/cmip6/isimip3b/flat/2025.11.25/monthly/ to see the names of the GCMs). You can find more information on the ISIMIP3b Zenodo. Let’s download the data:

# you can choose from in total 14 different climate models (GCMs).
# Here are for example the 5 primary GCMs:
# 'gfdl-esm4_r1i1p1f1', 'mpi-esm1-2-hr_r1i1p1f1', 'mri-esm2-0_r1i1p1f1' ("low sensitivity" models, within typical ranges from AR6)
# 'ipsl-cm6a-lr_r1i1p1f1', 'ukesm1-0-ll_r1i1p1f2' ("hotter" models, especially ukesm1-0-ll)
member = 'mri-esm2-0_r1i1p1f1'

for ssp in ['ssp126', 'ssp370','ssp585']:
    # bias correct them
    workflow.execute_entity_task(gcm_climate.process_monthly_isimip_data, gdirs,
                                 ssp = ssp,
                                 # gcm member -> you can choose another one
                                 member=member,
                                 # recognize the climate file for later
                                 output_filesuffix=f'_ISIMIP3b_{member}_{ssp}'
                                 )
2026-07-20 12:55:58: oggm.workflow: Execute entity tasks [process_monthly_isimip_data] on 2 glaciers
2026-07-20 12:56:16: oggm.workflow: Execute entity tasks [process_monthly_isimip_data] on 2 glaciers
2026-07-20 12:56:25: oggm.workflow: Execute entity tasks [process_monthly_isimip_data] on 2 glaciers

The advantage of using ISIMIP3b data is that they have been bias-corrected by the ISIMIP consortium. Since we are using the W5E5 dataset as the baseline climate in OGGM v1.6, there is no need for us to bias correct any further. If you want to bias-correct the projections yourself or want to have a larger variety of GCMs, you can also use the original CMIP5 or CMIP6 GCMs.

If you want to know which historical data you are using, you can ask OGGM:

gdirs[0].get_climate_info()
{'baseline_climate_source': 'GSWP3_W5E5',
 'baseline_yr_0': np.int64(1901),
 'baseline_yr_1': np.int64(2019),
 'baseline_climate_ref_hgt': np.float32(5376.0),
 'baseline_climate_ref_pix_lon': np.float64(86.75),
 'baseline_climate_ref_pix_lat': np.float64(28.25)}

Projection runs#

We now run OGGM under various scenarios starting from the end year of the historical spin-up run:

for ssp in ['ssp126', 'ssp370', 'ssp585']:
    rid = f'_ISIMIP3b_{member}_{ssp}'
    workflow.execute_entity_task(tasks.run_from_climate_data, gdirs,
                                 climate_filename='gcm_data',  # use gcm_data, not climate_historical
                                 climate_input_filesuffix=rid,  # use the chosen scenario
                                 init_model_filesuffix='_spinup_historical',  # this is important! Start from 2020 glacier
                                 output_filesuffix=rid,  # recognize the run for later
                                )
2026-07-20 12:56:34: oggm.workflow: Execute entity tasks [run_from_climate_data] on 2 glaciers
2026-07-20 12:56:34: oggm.core.flowline: InvalidWorkflowError occurred during task run_from_climate_data_ISIMIP3b_mri-esm2-0_r1i1p1f1_ssp126 on RGI60-15.03473: You seem to have calibrated with the GSWP3_W5E5 climate data while this gdir was calibrated with _ISIMIP3b_mri-esm2-0_r1i1p1f1_ssp126_no_OGGM_bias_correction. Set `check_calib_params=False` to ignore this warning.
---------------------------------------------------------------------------
InvalidWorkflowError                      Traceback (most recent call last)
Cell In[7], line 3
      1 for ssp in ['ssp126', 'ssp370', 'ssp585']:
      2     rid = f'_ISIMIP3b_{member}_{ssp}'
----> 3     workflow.execute_entity_task(tasks.run_from_climate_data, gdirs,
      4                                  climate_filename='gcm_data',  # use gcm_data, not climate_historical
      5                                  climate_input_filesuffix=rid,  # use the chosen scenario
      6                                  init_model_filesuffix='_spinup_historical',  # this is important! Start from 2020 glacier

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/workflow.py:208, in execute_entity_task(task, gdirs, **kwargs)
    204     if ng > 3:
    205         log.workflow('WARNING: you are trying to run an entity task on '
    206                      '%d glaciers with multiprocessing turned off. OGGM '
    207                      'will run faster with multiprocessing turned on.', ng)
--> 208     out = [pc(gdir) for gdir in gdirs]
    210 return out

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/workflow.py:125, in _pickle_copier.__call__(self, arg)
    123 for func in self.call_func:
    124     func, kwargs = func
--> 125     res = self._call_internal(func, arg, kwargs)
    126 return res

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/workflow.py:119, in _pickle_copier._call_internal(self, call_func, gdir, kwargs)
    116     gdir, gdir_kwargs = gdir
    117     kwargs.update(gdir_kwargs)
--> 119 return call_func(gdir, **kwargs)

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:522, in entity_task.__call__.<locals>._entity_task(gdir, reset, print_log, return_value, continue_on_error, add_to_log_file, **kwargs)
    520     signal.alarm(gdir.settings['task_timeout'])
    521 ex_t = time.time()
--> 522 out = task_func(gdir, **kwargs)
    523 ex_t = time.time() - ex_t
    524 if gdir.settings['task_timeout'] > 0:

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/core/flowline.py:4480, in run_from_climate_data(gdir, settings_filesuffix, ys, ye, min_ys, max_ys, fixed_geometry_spinup_yr, store_monthly_step, store_model_geometry, store_fl_diagnostics, climate_filename, mb_model, mb_model_class, climate_input_filesuffix, output_filesuffix, init_model_filesuffix, init_model_yr, init_model_fls, zero_initial_glacier, bias, temperature_bias, precipitation_factor, mb_diagnostics_filesuffix, save_mb_diagnostics_filesuffix, **kwargs)
   4473         mb_model = MultipleFlowlineMassBalance.load_from_file(
   4474             gdir,
   4475             filesuffix=mb_diagnostics_filesuffix,
   4476             climate_filename=_branch_fn,
   4477             climate_input_filesuffix=_branch_isuf,
   4478         )
   4479     else:
-> 4480         mb_model = MultipleFlowlineMassBalance(
   4481             gdir,
   4482             mb_model_class=mb_model_class,
   4483             filename=climate_filename,
   4484             bias=bias,
   4485             input_filesuffix=climate_input_filesuffix,
   4486             settings_filesuffix=settings_filesuffix,
   4487         )
   4489 if temperature_bias is not None:
   4490     mb_model.temp_bias += temperature_bias

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/core/massbalance.py:3494, in MultipleFlowlineMassBalance.__init__(self, gdir, settings_filesuffix, fls, mb_model_class, use_inversion_flowlines, flowlines_filesuffix, input_filesuffix, **kwargs)
   3490     if rgi_filesuffix is not None:
   3491         kwargs['input_filesuffix'] = rgi_filesuffix
   3493     self.flowline_mb_models.append(
-> 3494         mb_model_class(
   3495             gdir=gdir,
   3496             settings_filesuffix=settings_filesuffix,
   3497             **kwargs,
   3498         )
   3499     )
   3501 self.valid_bounds = self.flowline_mb_models[-1].valid_bounds
   3502 self.hemisphere = gdir.hemisphere

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/core/massbalance.py:594, in MonthlyTIModel.__init__(self, gdir, filename, input_filesuffix, settings_filesuffix, fl_id, melt_f, temp_bias, prcp_fac, bias, temp_melt, ys, ye, repeat, check_calib_params, check_climate_data, use_leap_years)
    589     if src != src_calib:
    590         msg = (f'You seem to have calibrated with the {src} '
    591                f"climate data while this gdir was calibrated with "
    592                f"{src_calib}. Set `check_calib_params=False` to "
    593                f"ignore this warning.")
--> 594         raise InvalidWorkflowError(msg)
    596 self.melt_f = melt_f
    597 self.bias = bias

InvalidWorkflowError: You seem to have calibrated with the GSWP3_W5E5 climate data while this gdir was calibrated with _ISIMIP3b_mri-esm2-0_r1i1p1f1_ssp126_no_OGGM_bias_correction. Set `check_calib_params=False` to ignore this warning.

Plot model output#

f, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))
# Pick some colors for the lines
color_dict={'ssp126':'blue', 'ssp370':'orange', 'ssp585':'red'}
for ssp in ['ssp126','ssp370', 'ssp585']:
    rid = f'_ISIMIP3b_{member}_{ssp}'
    # Compile the output into one file
    ds = utils.compile_run_output(gdirs, input_filesuffix=rid)
    # Plot it
    ds.isel(rgi_id=0).volume.plot(ax=ax1, label=ssp, c=color_dict[ssp])
    ds.isel(rgi_id=1).volume.plot(ax=ax2, label=ssp, c=color_dict[ssp])
plt.legend();
2026-07-20 12:56:34: oggm.utils: Applying global task compile_run_output on 2 glaciers
2026-07-20 12:56:34: oggm.utils: Applying compile_run_output on 2 gdirs.
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[8], line 7
      3 color_dict={'ssp126':'blue', 'ssp370':'orange', 'ssp585':'red'}
      4 for ssp in ['ssp126','ssp370', 'ssp585']:
      5     rid = f'_ISIMIP3b_{member}_{ssp}'
      6     # Compile the output into one file
----> 7     ds = utils.compile_run_output(gdirs, input_filesuffix=rid)
      8     # Plot it
      9     ds.isel(rgi_id=0).volume.plot(ax=ax1, label=ssp, c=color_dict[ssp])
     10     ds.isel(rgi_id=1).volume.plot(ax=ax2, label=ssp, c=color_dict[ssp])

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:584, in global_task.__call__.<locals>._global_task(gdirs, **kwargs)
    580 self.log.workflow('Applying global task %s on %s glaciers',
    581                   task_func.__name__, len(gdirs))
    583 # Run the task
--> 584 return task_func(gdirs, **kwargs)

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:1014, in compile_to_netcdf.__call__.<locals>._compile_to_netcdf(gdirs, input_filesuffix, output_filesuffix, path, tmp_file_size, **kwargs)
   1011 # Run the task
   1012 # If small gdir size, no need for temporary files
   1013 if len(gdirs) < tmp_file_size or not path:
-> 1014     return task_func(gdirs, input_filesuffix=input_filesuffix,
   1015                      path=path, **kwargs)
   1017 # Otherwise, divide and conquer
   1018 sub_gdirs = [gdirs[i: i + tmp_file_size] for i in
   1019              range(0, len(gdirs), tmp_file_size)]

File /usr/local/pyenv/versions/3.13.13/lib/python3.13/site-packages/oggm/utils/_workflow.py:1278, in compile_run_output(gdirs, path, input_filesuffix, use_compression)
   1275         pass
   1277 if 'time' not in time_info:
-> 1278     raise RuntimeError('Found no valid glaciers!')
   1280 # OK found it, open it and prepare the output
   1281 with xr.open_dataset(ppath) as ds_diag:
   1282 
   1283     # Prepare output

RuntimeError: Found no valid glaciers!
../../_images/4492345bdf5ff18bcc032b6bf957365944d311fe6b5035b3e3558cc2d46f703c.png

That’s it! Your OGGM projection in 10 minutes.

Have 5 minutes more? Download and process GCM data from CMIP5 or CMIP6#

ISIMIP data is very useful because it is bias corrected. Furthermore, it offers daily data, which we will soon use in OGGM.

But you may want a higher diversity of models or scenarios: for this, you may also use the CMIP5 or CMIP6 GCMs directly. These need to be bias-corrected first to the applied baseline climate (see process_gcm_data). This relatively simple bias-correction is automatically done by process_cmip_data and is very important, as the model is very sensitive to temperature variability (see the following blogpost for more details).

  • CMIP5 has 4 different RCP scenarios and a variety of GCMs, online you can find them here. The above-mentioned storage contains information about the data, how to cite them and tabular summaries of the available GCMs.

  • CMIP6 has up to 8 different SSP scenarios, see this table for a summary of available GCMs. There are even some CMIP6 runs that go until 2300.

Note, that the CMIP5 and CMIP6 files are much larger than the ISIMIP3b files. This is because we use a simple processing trick for the ISIMIP3b GCM files as we only save the glacier gridpoints, instead of the entire globe for CMIP5 and CMIP6.0

Therefore: run the following code only if it is ok to download a few gigabytes of data. Set the variable below to true to run it. (Attention! This may take some time …)

download_cmip5_data = False  # set to True to run the code below
if download_cmip5_data:

    bp = 'https://cluster.klima.uni-bremen.de/~oggm/cmip5-ng/pr/pr_mon_CCSM4_{}_r1i1p1_g025.nc'
    bt = 'https://cluster.klima.uni-bremen.de/~oggm/cmip5-ng/tas/tas_mon_CCSM4_{}_r1i1p1_g025.nc'

    color_dict_rcp={'rcp26':'blue', 'rcp45':'violet', 'rcp85':'red'}

    # Download and bias correct the data
    for rcp in ['rcp26', 'rcp45', 'rcp85']: # 'rcp60' would also be available
        # Download the files
        ft = utils.file_downloader(bt.format(rcp))
        fp = utils.file_downloader(bp.format(rcp))
        # bias correct them
        workflow.execute_entity_task(gcm_climate.process_cmip_data, gdirs,
                                     filesuffix='_CMIP5_CCSM4_{}'.format(rcp),  # recognize the climate file for later
                                     fpath_temp=ft,  # temperature projections
                                     fpath_precip=fp,  # precip projections
                                     )

    # Run OGGM
    for rcp in ['rcp26', 'rcp45',  'rcp85']: #'rcp60',
        rid = '_CMIP5_CCSM4_{}'.format(rcp)
        workflow.execute_entity_task(tasks.run_from_climate_data, gdirs, ys=2020,
                                     climate_filename='gcm_data',  # use gcm_data, not climate_historical
                                     climate_input_filesuffix=rid,  # use the chosen scenario
                                     init_model_filesuffix='_historical',  # this is important! Start from 2020 glacier
                                     output_filesuffix=rid,  # recognize the run for later
                                    )

    # Plot
    f, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))
    for rcp in ['rcp26', 'rcp45', 'rcp85']: #'rcp60',
        rid = '_CMIP5_CCSM4_{}'.format(rcp)
        ds = utils.compile_run_output(gdirs, input_filesuffix=rid)
        ds.isel(rgi_id=0).volume.plot(ax=ax1, label=rcp, c=color_dict_rcp[rcp])
        ds.isel(rgi_id=1).volume.plot(ax=ax2, label=rcp, c=color_dict_rcp[rcp])
    plt.legend()

Now, the same for CMIP6 but instead of RCPs, now SSPs and again with another GCM:

Set the variable below to true to run it.

download_cmip6_data = False  # set to True to run the code below
if download_cmip6_data:
    bp = 'https://cluster.klima.uni-bremen.de/~oggm/cmip6/GCM/CESM2/CESM2_{}_r1i1p1f1_pr.nc'
    bt = 'https://cluster.klima.uni-bremen.de/~oggm/cmip6/GCM/CESM2/CESM2_{}_r1i1p1f1_tas.nc'

    # Download and bias correct the data
    for ssp in ['ssp126', 'ssp585']:  # Removed 'ssp245', 'ssp370' because the files are large!
        # Download the files
        ft = utils.file_downloader(bt.format(ssp))
        fp = utils.file_downloader(bp.format(ssp))
        # bias correct them
        workflow.execute_entity_task(gcm_climate.process_cmip_data, gdirs,
                                     #year_range=('1979', '2014'),
                                     filesuffix='_CMIP6_CESM2_{}'.format(ssp),  # recognize the climate file for later
                                     fpath_temp=ft,  # temperature projections
                                     fpath_precip=fp,  # precip projections
                                     )

    # Run OGGM
    for ssp in ['ssp126', 'ssp585']:
        rid = '_CMIP6_CESM2_{}'.format(ssp)
        workflow.execute_entity_task(tasks.run_from_climate_data, gdirs, ys=2020,
                                     climate_filename='gcm_data',  # use gcm_data, not climate_historical
                                     climate_input_filesuffix=rid,  # use the chosen scenario
                                     init_model_filesuffix='_historical',  # this is important! Start from 2020 glacier
                                     output_filesuffix=rid,  # recognize the run for later
                                    )

    # Plot
    f, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))
    for ssp in ['ssp126', 'ssp585']:
        rid = '_CMIP6_CESM2_{}'.format(ssp)
        ds = utils.compile_run_output(gdirs, input_filesuffix=rid)
        ds.isel(rgi_id=0).volume.plot(ax=ax1, label=ssp, c=color_dict[ssp])
        ds.isel(rgi_id=1).volume.plot(ax=ax2, label=ssp, c=color_dict[ssp])

    plt.legend()

Have 5 minutes more? Do projections with another preprocessed glacier directory#

If you use the default preprocessed glacier directory (DEFAULT_BASE_URL), you do the same as in the OGGM standard projections. Per-glacier, regional, or global projections with this standard option are available directly at the OGGM/oggm-standard-projections-csv-files repository.

You can also do projections with another preprocessed glacier directory! We have several options of preprocessed glacier directories available. If you want to e.g. use ERA5 instead of W5E5, you just have to update one of the lines above to

new_url = 'https://cluster.klima.uni-bremen.de/~oggm/gdirs/oggm_v1.6/L3-L5_files/2025.6/elev_bands/ERA5/per_glacier_spinup/'
gdirs = workflow.init_glacier_directories(rgi_ids, from_prepro_level=5, prepro_base_url=new_url)

And then you can rerun all the cells below that line! Note that our processed ERA5 data (and thus, the historical runs) go until the end of 2025, and not just until the end of 2019.

What’s next?#