Filter the glacier length and area time series#

In this short tutorial, we show how to deal with unwanted “spikes” in the length and area time series of individual glaciers. These happen because OGGM currently doesn’t differentiate between snow and ice when computing area and length, i.e. occasional years with large snowfall events can artificially increase the glacier area and length.

There are two ways to address this problem:

  1. Before the run (more robust, recommended if you can afford to re-run): set cfg.PARAMS['min_ice_thick_for_length'] = 1 to exclude thin snow/ice from the length computation.

  2. Postprocessing (always applicable): apply a moving minimum filter to the output time series.

We demonstrate both approaches below.

Set-up#

import matplotlib.pyplot as plt
import xarray as xr
import os
from oggm import cfg, utils, workflow, tasks
cfg.initialize()
2026-04-11 16:16:18: oggm.cfg: Reading default parameters from the OGGM `params.cfg` configuration file.
2026-04-11 16:16:18: oggm.cfg: Multiprocessing switched OFF according to the parameter file.
2026-04-11 16:16:18: oggm.cfg: Multiprocessing: using all available processors (N=4)
cfg.PATHS['working_dir'] = utils.gettempdir(dirname='OGGM-Filter')

Define the glaciers for the run#

We take the Hintereisferner in the Austrian Alps:

rgi_ids = ['RGI60-11.00006']  # Random glacier

Glacier directories#

# in OGGM v1.6 you have to explicitly indicate the url from where you want to start from
# we will use here the elevation band flowlines which are much simpler than the centerlines
base_url = ('https://cluster.klima.uni-bremen.de/~oggm/gdirs/oggm_v1.6/'
            'L3-L5_files/2025.6/elev_bands/W5E5/per_glacier')
gdirs = workflow.init_glacier_directories(rgi_ids, from_prepro_level=5, prepro_border=80,
                                         prepro_base_url=base_url)
2026-04-11 16:16:18: oggm.workflow: init_glacier_directories from prepro level 5 on 1 glaciers.
2026-04-11 16:16:18: oggm.workflow: Execute entity tasks [gdir_from_prepro] on 1 glaciers

Run#

We can step directly to a new experiment! This runs under a random climate representative for the recent climate (1980-2010) and a small warm temperature offset:

workflow.execute_entity_task(tasks.run_random_climate, gdirs,
                             nyears=200, y0=1995, seed=5, temperature_bias=0.5,
                             output_filesuffix='_commitment');
2026-04-11 16:16:18: oggm.workflow: Execute entity tasks [run_random_climate] on 1 glaciers
2026-04-11 16:16:18: oggm.core.flowline: (RGI60-11.00006) run_random_climate_commitment
2026-04-11 16:16:18: oggm.core.flowline: (RGI60-11.00006) flowline_model_run_commitment

The problem#

ds = utils.compile_run_output(gdirs, input_filesuffix='_commitment')
ds = ds.isel(rgi_id=0)  # take just the one glacier
2026-04-11 16:16:19: oggm.utils: Applying global task compile_run_output on 1 glaciers
2026-04-11 16:16:19: oggm.utils: Applying compile_run_output on 1 gdirs.
ds.area.plot();
../../_images/661c756fc3389492f7952424e83050cdf0ae192fdceb205f35edb8852ed1a2e8.png
ds.length.plot();
../../_images/a6ed13f2a638b8d2963c27a207731e0e6ab54fe53bbe99dd6b01f7f77c8f0cf2.png

For small areas, the glacier has the unrealistic “spikes” described above.

Solutions#

Solution 2: Postprocessing (always applicable)#

If you cannot or do not want to re-run, a good postprocessing workaround is to apply a moving minimum filter, which keeps the smallest area or length in a given window size. This works for both area and length:

roll_yrs = 5
# Take the minimum out of 5 years
ts = ds.area.to_series()
ts = ts.rolling(roll_yrs).min()
ts.iloc[0:roll_yrs] = ts.iloc[roll_yrs]
# Plot
ds.area.plot(label='Original')
ts.plot(label='Filtered')
plt.legend();
../../_images/4632b64006ff5c30417a3d360f925e8eb4a60350b639ad0962031c53a8e0b84d.png

It works the same with length:

# Take the minimum out of 5 years
ts = ds.length.to_series()
ts = ts.rolling(roll_yrs).min()
ts.iloc[0:roll_yrs] = ts.iloc[roll_yrs]
# Plot
ds.length.plot(label='Original')
ts.plot(label='Filtered')
plt.legend();
../../_images/1a905a9bfdc598f6d63aaff4cb9a99292502b60fcaeea1bb3ef205820557fb39.png

What’s next?#