Beispiel #1
0
def prepare_for_initializing(gdirs):

    list_tasks = [
        tasks.compute_centerlines,
        tasks.initialize_flowlines,
        tasks.catchment_area,
        tasks.catchment_width_geom,
        tasks.catchment_width_correction,
        tasks.compute_downstream_line,
        tasks.compute_downstream_bedshape
    ]
    for task in list_tasks:
        workflow.execute_entity_task(task, gdirs)

    workflow.climate_tasks(gdirs)
    workflow.execute_entity_task(tasks.prepare_for_inversion, gdirs)
    glen_a = cfg.A

    for gdir in gdirs:
        mass_conservation_inversion(gdir, glen_a=glen_a)

    workflow.execute_entity_task(tasks.optimize_inversion_params,gdirs)
    workflow.execute_entity_task(tasks.volume_inversion, gdirs)
    workflow.execute_entity_task(tasks.filter_inversion_output, gdirs)
    workflow.execute_entity_task(tasks.init_present_time_glacier,gdirs)
def prepare_for_initializing(gdirs):
    '''
    oggm workflow for preparing initializing
    :param gdirs: list of oggm.GlacierDirectories
    :return None, but creates required files
    '''
    list_tasks = [
        tasks.compute_centerlines,
        tasks.initialize_flowlines,
        tasks.catchment_area,
        tasks.catchment_width_geom,
        tasks.catchment_width_correction,
        tasks.compute_downstream_line,
        tasks.compute_downstream_bedshape
    ]
    for task in list_tasks:
        workflow.execute_entity_task(task, gdirs)

    workflow.climate_tasks(gdirs)
    workflow.execute_entity_task(tasks.prepare_for_inversion, gdirs)
    glen_a = cfg.A

    for gdir in gdirs:
        mass_conservation_inversion(gdir, glen_a=glen_a)

    workflow.execute_entity_task(tasks.volume_inversion, gdirs)
    workflow.execute_entity_task(tasks.filter_inversion_output, gdirs)
    workflow.execute_entity_task(tasks.init_present_time_glacier,gdirs)
Beispiel #3
0
def test_coxe():

    testdir = os.path.join(get_test_dir(), 'tmp_coxe')
    utils.mkdir(testdir, reset=True)

    # Init
    cfg.initialize()
    cfg.PARAMS['use_intersects'] = False
    cfg.PATHS['dem_file'] = get_demo_file('dem_RGI50-01.10299.tif')
    cfg.PARAMS['border'] = 40
    cfg.PARAMS['clip_tidewater_border'] = False
    cfg.PARAMS['use_multiple_flowlines'] = False
    cfg.PARAMS['use_kcalving_for_inversion'] = True
    cfg.PARAMS['use_kcalving_for_run'] = True
    cfg.PARAMS['trapezoid_lambdas'] = 1

    hef_file = get_demo_file('rgi_RGI50-01.10299.shp')
    entity = gpd.read_file(hef_file).iloc[0]

    gdir = oggm.GlacierDirectory(entity, base_dir=testdir, reset=True)
    gis.define_glacier_region(gdir)
    gis.glacier_masks(gdir)
    centerlines.compute_centerlines(gdir)
    centerlines.initialize_flowlines(gdir)
    centerlines.compute_downstream_line(gdir)
    centerlines.compute_downstream_bedshape(gdir)
    centerlines.catchment_area(gdir)
    centerlines.catchment_intersections(gdir)
    centerlines.catchment_width_geom(gdir)
    centerlines.catchment_width_correction(gdir)
    climate.apparent_mb_from_linear_mb(gdir)
    inversion.prepare_for_inversion(gdir)
    inversion.mass_conservation_inversion(gdir)
    inversion.filter_inversion_output(gdir)

    flowline.init_present_time_glacier(gdir)

    fls = gdir.read_pickle('model_flowlines')

    p = gdir.read_pickle('linear_mb_params')
    mb_mod = massbalance.LinearMassBalance(ela_h=p['ela_h'], grad=p['grad'])
    mb_mod.temp_bias = -0.3
    model = flowline.FluxBasedModel(fls,
                                    mb_model=mb_mod,
                                    y0=0,
                                    inplace=True,
                                    is_tidewater=True)

    # run
    model.run_until(200)
    assert model.calving_m3_since_y0 > 0

    fig, ax = plt.subplots()
    graphics.plot_modeloutput_map(gdir, ax=ax, model=model)
    fig.tight_layout()
    shutil.rmtree(testdir)
    return fig
Beispiel #4
0
 def to_optimize(x):
     # For backwards compat
     _fd = 1.9e-24 * x[0]
     glen_a = (glen_n + 2) * _fd / 2.
     fs = 5.7e-20 * x[1]
     v = inversion.mass_conservation_inversion(gdir, fs=fs, glen_a=glen_a)
     return (v - ref_v)**2
Beispiel #5
0
 def to_optimize(x):
     # For backwards compat
     _fd = 1.9e-24 * x[0]
     glen_a = (glen_n+2) * _fd / 2.
     fs = 5.7e-20 * x[1]
     v, _ = inversion.mass_conservation_inversion(gdir, fs=fs,
                                                  glen_a=glen_a)
     return (v - ref_v)**2
Beispiel #6
0
 def to_optimize(x):
     tmp_ = np.zeros(len(ref_gdirs))
     glen_a = cfg.A * x[0]
     for i, gdir in enumerate(ref_gdirs):
         v, a = mass_conservation_inversion(gdir,
                                            glen_a=glen_a,
                                            fs=0.,
                                            write=False)
         tmp_[i] = v / a
     return utils.rmsd(tmp_, ref_thickness_m)
Beispiel #7
0
mb = LinearMassBalance(2600.)
model = FluxBasedModel(fls, mb_model=mb, y0=0.)
model.run_until_equilibrium()
fls = []
for fl in model.fls:
    pg = np.where(fl.thick > 0)
    line = shpg.LineString([fl.line.coords[int(p)] for p in pg[0]])
    flo = Centerline(line, dx=fl.dx, surface_h=fl.surface_h[pg])
    flo.widths = fl.widths[pg]
    flo.is_rectangular = np.ones(flo.nx).astype(np.bool)
    fls.append(flo)

gdir.write_pickle(fls, 'inversion_flowlines')
tasks.apparent_mb_from_linear_mb(gdir)
tasks.prepare_for_inversion(gdir)
v, _ = mass_conservation_inversion(gdir)
np.testing.assert_allclose(v, model.volume_m3, rtol=0.05)
inv = gdir.read_pickle('inversion_output')[-1]
# plot
ax = axs[0]
thick1 = inv['thick']
pg = model.fls[-1].thick > 0
bh = model.fls[-1].bed_h[pg]
sh = model.fls[-1].surface_h[pg]
ax.plot(sh, 'k', label='Glacier surface')
ax.plot(bh, 'C0', label='Real bed', linewidth=2)
ax.plot(sh - thick1, 'C3', label='Computed bed')
ax.set_ylabel('Elevation [m]')
ax.set_ylim([1950, 3100])
ax.legend(loc=3)
ax.text(tx, ty, 'a', transform=ax.transAxes, **letkm)
Beispiel #8
0
tasks.prepare_for_inversion(gdir)

facs = np.append((np.arange(9) + 1) * 0.1, (np.arange(19) + 2) * 0.5)
vols1 = facs * 0.
vols2 = facs * 0.
vols3 = facs * 0.
vols4 = facs * 0.
vols5 = facs * 0.
vols6 = facs * 0.
vols7 = facs * 0.
vols8 = facs * 0.

glen_a = cfg.PARAMS['glen_a']
fs = 5.7e-20
for i, f in enumerate(facs):
    v, _ = mass_conservation_inversion(gdir, glen_a=glen_a * f)
    vols1[i] = v * 1e-9
    v, _ = mass_conservation_inversion(gdir, glen_a=glen_a * f, fs=fs * 0.5)
    vols2[i] = v * 1e-9
    v, a = mass_conservation_inversion(gdir, glen_a=glen_a * f, fs=fs)
    vols3[i] = v * 1e-9

cfg.PARAMS['use_shape_factor_for_inversion'] = 'Adhikari'

for i, f in enumerate(facs):
    # Adhikari
    v, _ = mass_conservation_inversion(gdir, glen_a=glen_a * f)
    vols4[i] = v * 1e-9

tasks.prepare_for_inversion(gdir, invert_with_rectangular=False)
for i, f in enumerate(facs):
Beispiel #9
0
def find_inversion_calving_loop(gdir,
                                initial_water_depth=None,
                                max_ite=30,
                                stop_after_convergence=True,
                                fixed_water_depth=False):
    """Iterative search for a calving flux compatible with the bed inversion.

    See Recinos et al 2019 for details.

    Parameters
    ----------
    initial_water_depth : float
        the initial water depth starting the loop (for sensitivity experiments
        or to fix it to an observed value). The default is to use 1/3 of the
        terminus elevation if > 10 m, and 10 m otherwise
    max_ite : int
        the maximal number of iterations allowed before raising an error
    stop_after_convergence : bool
        continue to loop after convergence is reached
        (for sensitivity experiments)
    fixed_water_depth : bool
        fix the water depth and let the frontal altitude vary instead
    """

    # Shortcuts
    from oggm.core import climate, inversion
    from oggm.exceptions import MassBalanceCalibrationError

    # Input
    if initial_water_depth is None:
        fl = gdir.read_pickle('inversion_flowlines')[-1]
        initial_water_depth = utils.clip_min(fl.surface_h[-1] / 3, 10)

    rho = cfg.PARAMS['ice_density']

    # We accept values down to zero before stopping
    cfg.PARAMS['min_mu_star'] = 0

    # Start iteration
    i = 0
    cfg.PARAMS['clip_mu_star'] = False
    odf = pd.DataFrame()
    mu_is_zero = False
    while i < max_ite:

        # Calculates a calving flux from model output
        if i == 0:
            # First call we set to zero (it's just to be sure we start
            # from a non-calving glacier)
            f_calving = 0
        elif i == 1:
            # Second call, we set a small positive calving to start with

            # Default is to get the thickness from free board and
            # initial water depth
            thick = None
            if fixed_water_depth:
                # This leaves the free board open for change
                thick = initial_water_depth + 1
            out = calving_flux_from_depth(gdir,
                                          water_depth=initial_water_depth,
                                          thick=thick,
                                          fixed_water_depth=fixed_water_depth)
            f_calving = out['flux']
        elif cfg.PARAMS['clip_mu_star']:
            # If we had to clip mu, the inversion calving becomes the real
            # flux, i.e. not compatible with calving law but with the
            # inversion
            fl = gdir.read_pickle('inversion_flowlines')[-1]
            f_calving = fl.flux[-1] * (gdir.grid.dx**2) * 1e-9 / rho
            mu_is_zero = True
        else:
            # Otherwise it is parameterized by the calving law
            if fixed_water_depth:
                out = calving_flux_from_depth(gdir,
                                              water_depth=initial_water_depth,
                                              fixed_water_depth=True)
                f_calving = out['flux']
            else:
                f_calving = calving_flux_from_depth(gdir)['flux']

        # Give it back to the inversion and recompute
        gdir.inversion_calving_rate = f_calving

        # At this step we might raise a MassBalanceCalibrationError
        try:
            climate.local_t_star(gdir)
            df = gdir.read_json('local_mustar')
        except MassBalanceCalibrationError as e:
            assert 'mu* out of specified bounds' in str(e)
            # When this happens we clip mu* to zero and store the
            # bad value (just for plotting)
            cfg.PARAMS['clip_mu_star'] = True
            df = gdir.read_json('local_mustar')
            df['mu_star_glacierwide'] = float(str(e).split(':')[-1])
            climate.local_t_star(gdir)

        climate.mu_star_calibration(gdir)

        inversion.prepare_for_inversion(gdir, add_debug_var=True)
        v_inv, _ = inversion.mass_conservation_inversion(gdir)
        if fixed_water_depth:
            out = calving_flux_from_depth(gdir,
                                          water_depth=initial_water_depth,
                                          fixed_water_depth=True)
        else:
            out = calving_flux_from_depth(gdir)

        # Store the data
        odf.loc[i, 'calving_flux'] = f_calving
        odf.loc[i, 'mu_star'] = df['mu_star_glacierwide']
        odf.loc[i, 'calving_law_flux'] = out['flux']
        odf.loc[i, 'width'] = out['width']
        odf.loc[i, 'thick'] = out['thick']
        odf.loc[i, 'water_depth'] = out['water_depth']
        odf.loc[i, 'free_board'] = out['free_board']

        # Do we have to do another_loop? Start testing at 5th iteration
        calving_flux = odf.calving_flux.values
        if stop_after_convergence and i > 4:
            # We want to make sure that we don't converge by chance
            # so we test on last two iterations
            conv = (np.allclose(calving_flux[[-1, -2]],
                                [out['flux'], out['flux']],
                                rtol=0.01))
            if mu_is_zero or conv:
                break
        i += 1

    # Write output
    odf.index.name = 'iterations'
    odf.to_csv(gdir.get_filepath('calving_loop'))

    # Restore defaults
    cfg.PARAMS['min_mu_star'] = 1.
    cfg.PARAMS['clip_mu_star'] = False

    return odf
Beispiel #10
0
def init_hef(reset=False,
             border=40,
             invert_with_sliding=True,
             invert_with_rectangular=True):

    # test directory
    testdir = os.path.join(get_test_dir(), 'tmp_border{}'.format(border))
    if not invert_with_sliding:
        testdir += '_withoutslide'
    if not invert_with_rectangular:
        testdir += '_withoutrectangular'
    if not os.path.exists(testdir):
        os.makedirs(testdir)
        reset = True

    # Init
    cfg.initialize()
    cfg.set_intersects_db(get_demo_file('rgi_intersect_oetztal.shp'))
    cfg.PATHS['dem_file'] = get_demo_file('hef_srtm.tif')
    cfg.PATHS['climate_file'] = get_demo_file('histalp_merged_hef.nc')
    cfg.PARAMS['border'] = border
    cfg.PARAMS['use_optimized_inversion_params'] = True

    hef_file = get_demo_file('Hintereisferner_RGI5.shp')
    entity = gpd.read_file(hef_file).iloc[0]

    gdir = oggm.GlacierDirectory(entity, base_dir=testdir, reset=reset)
    if not gdir.has_file('inversion_params'):
        reset = True
        gdir = oggm.GlacierDirectory(entity, base_dir=testdir, reset=reset)

    if not reset:
        return gdir

    gis.define_glacier_region(gdir, entity=entity)
    execute_entity_task(gis.glacier_masks, [gdir])
    execute_entity_task(centerlines.compute_centerlines, [gdir])
    centerlines.initialize_flowlines(gdir)
    centerlines.compute_downstream_line(gdir)
    centerlines.compute_downstream_bedshape(gdir)
    centerlines.catchment_area(gdir)
    centerlines.catchment_intersections(gdir)
    centerlines.catchment_width_geom(gdir)
    centerlines.catchment_width_correction(gdir)
    climate.process_custom_climate_data(gdir)
    climate.mu_candidates(gdir)
    mbdf = gdir.get_ref_mb_data()['ANNUAL_BALANCE']
    res = climate.t_star_from_refmb(gdir, mbdf)
    climate.local_mustar(gdir,
                         tstar=res['t_star'][-1],
                         bias=res['bias'][-1],
                         prcp_fac=res['prcp_fac'])
    climate.apparent_mb(gdir)

    inversion.prepare_for_inversion(
        gdir,
        add_debug_var=True,
        invert_with_rectangular=invert_with_rectangular)
    ref_v = 0.573 * 1e9

    if invert_with_sliding:

        def to_optimize(x):
            # For backwards compat
            _fd = 1.9e-24 * x[0]
            glen_a = (cfg.N + 2) * _fd / 2.
            fs = 5.7e-20 * x[1]
            v, _ = inversion.mass_conservation_inversion(gdir,
                                                         fs=fs,
                                                         glen_a=glen_a)
            return (v - ref_v)**2

        out = optimization.minimize(to_optimize, [1, 1],
                                    bounds=((0.01, 10), (0.01, 10)),
                                    tol=1e-4)['x']
        _fd = 1.9e-24 * out[0]
        glen_a = (cfg.N + 2) * _fd / 2.
        fs = 5.7e-20 * out[1]
        v, _ = inversion.mass_conservation_inversion(gdir,
                                                     fs=fs,
                                                     glen_a=glen_a,
                                                     write=True)
    else:

        def to_optimize(x):
            glen_a = cfg.A * x[0]
            v, _ = inversion.mass_conservation_inversion(gdir,
                                                         fs=0.,
                                                         glen_a=glen_a)
            return (v - ref_v)**2

        out = optimization.minimize(to_optimize, [1],
                                    bounds=((0.01, 10), ),
                                    tol=1e-4)['x']
        glen_a = cfg.A * out[0]
        fs = 0.
        v, _ = inversion.mass_conservation_inversion(gdir,
                                                     fs=fs,
                                                     glen_a=glen_a,
                                                     write=True)
    d = dict(fs=fs, glen_a=glen_a)
    d['factor_glen_a'] = out[0]
    try:
        d['factor_fs'] = out[1]
    except IndexError:
        d['factor_fs'] = 0.
    gdir.write_pickle(d, 'inversion_params')

    # filter
    inversion.filter_inversion_output(gdir)

    inversion.distribute_thickness_interp(gdir, varname_suffix='_interp')
    inversion.distribute_thickness_per_altitude(gdir, varname_suffix='_alt')

    flowline.init_present_time_glacier(gdir)

    return gdir
Beispiel #11
0
def find_inversion_calving(gdir,
                           water_depth=1,
                           max_ite=30,
                           stop_after_convergence=True):
    """Iterative search for a calving flux compatible with the bed inversion.

    See Recinos et al 2019 for details.

    Parameters
    ----------
    water_depth : float
        the initial water depth starting the loop (for sensitivity experiments)
    """

    # Shortcuts
    from oggm.core import climate, inversion
    from oggm.exceptions import MassBalanceCalibrationError

    rho = cfg.PARAMS['ice_density']

    # We accept values down to zero before stopping
    cfg.PARAMS['min_mu_star'] = 0

    # Start iteration
    i = 0
    cfg.PARAMS['clip_mu_star'] = False
    odf = pd.DataFrame()
    mu_is_zero = False
    while i < max_ite:

        # Calculates a calving flux from model output
        if i == 0:
            # First call we set to zero (it's just to be sure we start
            # from a non-calving glacier)
            f_calving = 0
        elif i == 1:
            # Second call we set a small positive calving to start with
            out = calving_flux_from_depth(gdir, water_depth=water_depth)
            f_calving = out['flux']
        elif cfg.PARAMS['clip_mu_star']:
            # If we had to clip mu, the inversion calving becomes the real
            # flux, i.e. not compatible with calving law but with the
            # inversion
            fl = gdir.read_pickle('inversion_flowlines')[-1]
            f_calving = fl.flux[-1] * (gdir.grid.dx**2) * 1e-9 / rho
            mu_is_zero = True
        else:
            # Otherwise it is parameterized by the calving law
            f_calving = calving_flux_from_depth(gdir)['flux']

        # Give it back to the inversion and recompute
        gdir.inversion_calving_rate = f_calving

        # At this step we might raise a MassBalanceCalibrationError
        try:
            climate.local_t_star(gdir)
            df = gdir.read_json('local_mustar')
        except MassBalanceCalibrationError as e:
            assert 'mu* out of specified bounds' in str(e)
            # When this happens we clip mu* to zero and store the
            # bad value (just for plotting)
            cfg.PARAMS['clip_mu_star'] = True
            df = gdir.read_json('local_mustar')
            df['mu_star_glacierwide'] = float(str(e).split(':')[-1])
            climate.local_t_star(gdir)

        climate.mu_star_calibration(gdir)
        inversion.prepare_for_inversion(gdir, add_debug_var=True)
        v_inv, _ = inversion.mass_conservation_inversion(gdir)
        out = calving_flux_from_depth(gdir)

        # Store the data
        odf.loc[i, 'calving_flux'] = f_calving
        odf.loc[i, 'mu_star'] = df['mu_star_glacierwide']
        odf.loc[i, 'calving_law_flux'] = out['flux']
        odf.loc[i, 'width'] = out['width']
        odf.loc[i, 'thick'] = out['thick']
        odf.loc[i, 'water_depth'] = out['water_depth']
        odf.loc[i, 'free_board'] = out['free_board']

        # Do we have to do another_loop?
        calving_flux = odf.calving_flux.values
        if stop_after_convergence and i > 0:
            conv = np.allclose(calving_flux[-1], out['flux'], rtol=0.001)
            if mu_is_zero or conv:
                break
        i += 1

    odf.index.name = 'iterations'
    return odf
Beispiel #12
0
def init_hef(reset=False, border=40):

    # test directory
    testdir = os.path.join(get_test_dir(), 'tmp_border{}'.format(border))
    if not os.path.exists(testdir):
        os.makedirs(testdir)
        reset = True

    # Init
    cfg.initialize()
    cfg.set_intersects_db(get_demo_file('rgi_intersect_oetztal.shp'))
    cfg.PATHS['dem_file'] = get_demo_file('hef_srtm.tif')
    cfg.PATHS['climate_file'] = get_demo_file('histalp_merged_hef.nc')
    cfg.PARAMS['baseline_climate'] = ''
    cfg.PATHS['working_dir'] = testdir
    cfg.PARAMS['border'] = border

    hef_file = get_demo_file('Hintereisferner_RGI5.shp')
    entity = gpd.read_file(hef_file).iloc[0]

    gdir = oggm.GlacierDirectory(entity, reset=reset)
    if not gdir.has_file('inversion_params'):
        reset = True
        gdir = oggm.GlacierDirectory(entity, reset=reset)

    if not reset:
        return gdir

    gis.define_glacier_region(gdir, entity=entity)
    execute_entity_task(gis.glacier_masks, [gdir])
    execute_entity_task(centerlines.compute_centerlines, [gdir])
    centerlines.initialize_flowlines(gdir)
    centerlines.compute_downstream_line(gdir)
    centerlines.compute_downstream_bedshape(gdir)
    centerlines.catchment_area(gdir)
    centerlines.catchment_intersections(gdir)
    centerlines.catchment_width_geom(gdir)
    centerlines.catchment_width_correction(gdir)
    climate.process_custom_climate_data(gdir)
    mbdf = gdir.get_ref_mb_data()['ANNUAL_BALANCE']
    res = climate.t_star_from_refmb(gdir, mbdf=mbdf)
    climate.local_t_star(gdir, tstar=res['t_star'], bias=res['bias'])
    climate.mu_star_calibration(gdir)

    inversion.prepare_for_inversion(gdir, add_debug_var=True)

    ref_v = 0.573 * 1e9

    glen_n = cfg.PARAMS['glen_n']

    def to_optimize(x):
        # For backwards compat
        _fd = 1.9e-24 * x[0]
        glen_a = (glen_n+2) * _fd / 2.
        fs = 5.7e-20 * x[1]
        v, _ = inversion.mass_conservation_inversion(gdir, fs=fs,
                                                     glen_a=glen_a)
        return (v - ref_v)**2

    out = optimization.minimize(to_optimize, [1, 1],
                                bounds=((0.01, 10), (0.01, 10)),
                                tol=1e-4)['x']
    _fd = 1.9e-24 * out[0]
    glen_a = (glen_n+2) * _fd / 2.
    fs = 5.7e-20 * out[1]
    v, _ = inversion.mass_conservation_inversion(gdir, fs=fs,
                                                 glen_a=glen_a,
                                                 write=True)

    d = dict(fs=fs, glen_a=glen_a)
    d['factor_glen_a'] = out[0]
    d['factor_fs'] = out[1]
    gdir.write_pickle(d, 'inversion_params')

    # filter
    inversion.filter_inversion_output(gdir)

    inversion.distribute_thickness_interp(gdir, varname_suffix='_interp')
    inversion.distribute_thickness_per_altitude(gdir, varname_suffix='_alt')

    flowline.init_present_time_glacier(gdir)

    return gdir
Beispiel #13
0
local_mustar(gdir, tstar=res['t_star'][-1], bias=res['bias'][-1],
             prcp_fac=res['prcp_fac'], reset=True)
apparent_mb(gdir, reset=True)

tasks.prepare_for_inversion(gdir, reset=True)


f, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharey=True)

facs = np.append((np.arange(9)+1)*0.1, (np.arange(19)+2) * 0.5)
vols1 = facs * 0.
vols2 = facs * 0.
vols3 = facs * 0.

for i, f in enumerate(facs):
    v, _ = mass_conservation_inversion(gdir, glen_a=cfg.A*f)
    vols1[i] = v * 1e-9
    v, _ = mass_conservation_inversion(gdir, glen_a=cfg.A*f,
                                       fs=cfg.FS*0.5)
    vols2[i] = v * 1e-9
    v, a = mass_conservation_inversion(gdir, glen_a=cfg.A*f,
                                       fs=cfg.FS)
    vols3[i] = v * 1e-9

v_vas = 0.034*((a*1e-6)**1.375)
v_fischer = 0.573

tx, ty = 0.0175, .983
letkm = dict(color='black', ha='left', va='top', fontsize=16,
             bbox=dict(facecolor='white', edgecolor='black'))
Beispiel #14
0
         tasks.catchment_width_geom,
         tasks.catchment_width_correction,
         tasks.compute_downstream_bedshape
         ]

for task in list_talks:
    workflow.execute_entity_task(task, gdirs)

workflow.climate_tasks(gdirs)
workflow.execute_entity_task(tasks.prepare_for_inversion, gdirs)
from oggm.core.inversion import mass_conservation_inversion

# Select HEF out of all glaciers

glen_a = cfg.A
vol_m3, area_m3 = mass_conservation_inversion(gdir_hef, glen_a=glen_a)
print('With A={}, the mean thickness of HEF is {:.1f} m'.format(glen_a, vol_m3/area_m3))
optim_resuls = tasks.optimize_inversion_params(gdirs)

workflow.execute_entity_task(tasks.volume_inversion, gdirs)
workflow.execute_entity_task(tasks.filter_inversion_output, gdirs)
tasks.init_present_time_glacier(gdir_hef)
fls = gdir_hef.read_pickle('model_flowlines')

model = FluxBasedModel(fls)
surface_before=model.fls[-1].surface_h

today_model = ConstantMassBalance(gdir_hef, y0=1985)

commit_model = FluxBasedModel(fls, mb_model=today_model, glen_a=cfg.A)
pickle.dump(gdir_hef,open('gdir_hef.pkl','wb'))
Beispiel #15
0
t_star, bias = res['t_star'], res['bias']

# compute local t* and the corresponding mu*
climate.local_t_star(gdir, tstar=t_star, bias=bias)
climate.mu_star_calibration(gdir)

from oggm.core import massbalance
# instance the mass balance models
mb_mod = massbalance.PastMassBalance(gdir)

# -----------
#  INVERSION
# -----------
from oggm.core import inversion
inversion.prepare_for_inversion(gdir)
inversion.mass_conservation_inversion(gdir)
inversion.filter_inversion_output(gdir)

# ----------------
#  DYNAMICAL PART
# ----------------

from oggm.core import flowline
# initialize present time glacier
flowline.init_present_time_glacier(gdir)

# instance flowline model
fls = gdir.read_pickle('model_flowlines')
y0 = gdir.read_pickle('climate_info')['baseline_hydro_yr_0']
fl_mod = flowline.FluxBasedModel(flowlines=fls, mb_model=mb_mod, y0=y0)
Beispiel #16
0
 def to_optimize(x):
     glen_a = cfg.A * x[0]
     v, _ = inversion.mass_conservation_inversion(gdir,
                                                  fs=0.,
                                                  glen_a=glen_a)
     return (v - ref_v)**2
Beispiel #17
0
def find_inversion_calving(gdir, fixed_water_depth=None):
    """Optimized search for a calving flux compatible with the bed inversion.

    See Recinos et al 2019 for details.

    Parameters
    ----------
    fixed_water_depth : float
        fix the water depth to an observed value and let the free board vary
        instead.
    """
    from oggm.core import climate, inversion
    from oggm.exceptions import MassBalanceCalibrationError

    # Let's start from a fresh state
    gdir.inversion_calving_rate = 0
    climate.local_t_star(gdir)
    climate.mu_star_calibration(gdir)
    inversion.prepare_for_inversion(gdir, add_debug_var=True)
    inversion.mass_conservation_inversion(gdir)

    # Get the relevant variables
    cls = gdir.read_pickle('inversion_input')[-1]
    slope = cls['slope_angle'][-1]
    width = cls['width'][-1]

    # The functions all have the same shape: they decrease, then increase
    # We seek the absolute minimum first
    def to_minimize(h):
        if fixed_water_depth is not None:
            fl = calving_flux_from_depth(gdir,
                                         thick=h,
                                         water_depth=fixed_water_depth,
                                         fixed_water_depth=True)
        else:
            fl = calving_flux_from_depth(gdir, water_depth=h)

        flux = fl['flux'] * 1e9 / cfg.SEC_IN_YEAR
        sia_thick = sia_thickness(slope, width, flux)
        return fl['thick'] - sia_thick

    abs_min = optimize.minimize(to_minimize, [1],
                                bounds=((1e-4, 1e4), ),
                                tol=1e-1)
    if not abs_min['success']:
        raise RuntimeError('Could not find the absolute minimum in calving '
                           'flux optimization: {}'.format(abs_min))
    if abs_min['fun'] > 0:
        # This happens, and means that this glacier simply can't calve
        # See e.g. RGI60-01.23642
        df = gdir.read_json('local_mustar')
        out = calving_flux_from_depth(gdir)

        odf = dict()
        odf['calving_flux'] = 0
        odf['calving_mu_star'] = df['mu_star_glacierwide']
        odf['calving_law_flux'] = out['flux']
        odf['calving_slope'] = slope
        odf['calving_thick'] = out['thick']
        odf['calving_water_depth'] = out['water_depth']
        odf['calving_free_board'] = out['free_board']
        odf['calving_front_width'] = out['width']
        for k, v in odf.items():
            gdir.add_to_diagnostics(k, v)
        return

    # OK, we now find the zero between abs min and an arbitrary high front
    abs_min = abs_min['x'][0]
    opt = optimize.brentq(to_minimize, abs_min, 1e4)

    # This is the thick guaranteeing OGGM Flux = Calving Law Flux
    # Let's see if it results in a meaningful mu_star

    # Give the flux to the inversion and recompute
    if fixed_water_depth is not None:
        out = calving_flux_from_depth(gdir,
                                      thick=opt,
                                      water_depth=fixed_water_depth,
                                      fixed_water_depth=True)
        f_calving = out['flux']
    else:
        out = calving_flux_from_depth(gdir, water_depth=opt)
        f_calving = out['flux']

    gdir.inversion_calving_rate = f_calving

    # We accept values down to zero before stopping
    cfg.PARAMS['min_mu_star'] = 0
    cfg.PARAMS['clip_mu_star'] = False

    # At this step we might raise a MassBalanceCalibrationError
    try:
        climate.local_t_star(gdir)
        df = gdir.read_json('local_mustar')
    except MassBalanceCalibrationError as e:
        assert 'mu* out of specified bounds' in str(e)
        # When this happens we clip mu* to zero
        cfg.PARAMS['clip_mu_star'] = True
        climate.local_t_star(gdir)
        df = gdir.read_json('local_mustar')

    climate.mu_star_calibration(gdir)
    inversion.prepare_for_inversion(gdir, add_debug_var=True)
    inversion.mass_conservation_inversion(gdir)

    if fixed_water_depth is not None:
        out = calving_flux_from_depth(gdir,
                                      water_depth=fixed_water_depth,
                                      fixed_water_depth=True)
    else:
        out = calving_flux_from_depth(gdir)

    fl = gdir.read_pickle('inversion_flowlines')[-1]
    f_calving = (fl.flux[-1] * (gdir.grid.dx**2) * 1e-9 /
                 cfg.PARAMS['ice_density'])

    # Store results
    odf = dict()
    odf['calving_flux'] = f_calving
    odf['calving_mu_star'] = df['mu_star_glacierwide']
    odf['calving_law_flux'] = out['flux']
    odf['calving_slope'] = slope
    odf['calving_thick'] = out['thick']
    odf['calving_water_depth'] = out['water_depth']
    odf['calving_free_board'] = out['free_board']
    odf['calving_front_width'] = out['width']
    for k, v in odf.items():
        gdir.add_to_diagnostics(k, v)

    # Restore defaults
    cfg.PARAMS['min_mu_star'] = 1.
    cfg.PARAMS['clip_mu_star'] = False

    return odf
Beispiel #18
0
def find_inversion_calving(gdir, initial_water_depth=None, max_ite=30,
                           stop_after_convergence=True,
                           fixed_water_depth=False):
    """Iterative search for a calving flux compatible with the bed inversion.

    See Recinos et al 2019 for details.

    Parameters
    ----------
    initial_water_depth : float
        the initial water depth starting the loop (for sensitivity experiments
        or to fix it to an observed value). The default is to use 1/3 of the
        terminus elevation if > 10 m, and 10 m otherwise
    max_ite : int
        the maximal number of iterations allowed before raising an error
    stop_after_convergence : bool
        continue to loop after convergence is reached
        (for sensitivity experiments)
    fixed_water_depth : bool
        fix the water depth and let the frontal altitude vary instead
    """

    # Shortcuts
    from oggm.core import climate, inversion
    from oggm.exceptions import MassBalanceCalibrationError

    # Input
    if initial_water_depth is None:
        fl = gdir.read_pickle('inversion_flowlines')[-1]
        initial_water_depth = np.clip(fl.surface_h[-1] / 3, 10, None)

    rho = cfg.PARAMS['ice_density']

    # We accept values down to zero before stopping
    cfg.PARAMS['min_mu_star'] = 0

    # Start iteration
    i = 0
    cfg.PARAMS['clip_mu_star'] = False
    odf = pd.DataFrame()
    mu_is_zero = False
    while i < max_ite:

        # Calculates a calving flux from model output
        if i == 0:
            # First call we set to zero (it's just to be sure we start
            # from a non-calving glacier)
            f_calving = 0
        elif i == 1:
            # Second call, we set a small positive calving to start with

            # Default is to get the thickness from free board and
            # initial water depth
            thick = None
            if fixed_water_depth:
                # This leaves the free board open for change
                thick = initial_water_depth + 1
            out = calving_flux_from_depth(gdir,
                                          water_depth=initial_water_depth,
                                          thick=thick,
                                          fixed_water_depth=fixed_water_depth)
            f_calving = out['flux']
        elif cfg.PARAMS['clip_mu_star']:
            # If we had to clip mu, the inversion calving becomes the real
            # flux, i.e. not compatible with calving law but with the
            # inversion
            fl = gdir.read_pickle('inversion_flowlines')[-1]
            f_calving = fl.flux[-1] * (gdir.grid.dx ** 2) * 1e-9 / rho
            mu_is_zero = True
        else:
            # Otherwise it is parameterized by the calving law
            if fixed_water_depth:
                out = calving_flux_from_depth(gdir,
                                              water_depth=initial_water_depth,
                                              fixed_water_depth=True)
                f_calving = out['flux']
            else:
                f_calving = calving_flux_from_depth(gdir)['flux']

        # Give it back to the inversion and recompute
        gdir.inversion_calving_rate = f_calving

        # At this step we might raise a MassBalanceCalibrationError
        try:
            climate.local_t_star(gdir)
            df = gdir.read_json('local_mustar')
        except MassBalanceCalibrationError as e:
            assert 'mu* out of specified bounds' in str(e)
            # When this happens we clip mu* to zero and store the
            # bad value (just for plotting)
            cfg.PARAMS['clip_mu_star'] = True
            df = gdir.read_json('local_mustar')
            df['mu_star_glacierwide'] = float(str(e).split(':')[-1])
            climate.local_t_star(gdir)

        climate.mu_star_calibration(gdir)

        inversion.prepare_for_inversion(gdir, add_debug_var=True)
        v_inv, _ = inversion.mass_conservation_inversion(gdir)
        if fixed_water_depth:
            out = calving_flux_from_depth(gdir,
                                          water_depth=initial_water_depth,
                                          fixed_water_depth=True)
        else:
            out = calving_flux_from_depth(gdir)

        # Store the data
        odf.loc[i, 'calving_flux'] = f_calving
        odf.loc[i, 'mu_star'] = df['mu_star_glacierwide']
        odf.loc[i, 'calving_law_flux'] = out['flux']
        odf.loc[i, 'width'] = out['width']
        odf.loc[i, 'thick'] = out['thick']
        odf.loc[i, 'water_depth'] = out['water_depth']
        odf.loc[i, 'free_board'] = out['free_board']

        # Do we have to do another_loop? Start testing at 5th iteration
        calving_flux = odf.calving_flux.values
        if stop_after_convergence and i > 4:
            # We want to make sure that we don't converge by chance
            # so we test on last two iterations
            conv = (np.allclose(calving_flux[[-1, -2]],
                                [out['flux'], out['flux']],
                                rtol=0.01))
            if mu_is_zero or conv:
                break
        i += 1

    # Write output
    odf.index.name = 'iterations'
    odf.to_csv(gdir.get_filepath('calving_loop'))

    # Restore defaults
    cfg.PARAMS['min_mu_star'] = 1.
    cfg.PARAMS['clip_mu_star'] = False

    return odf
Beispiel #19
0
    def test_run_until_and_store(self):
        """Test the volume/area scaling model against the oggm.FluxBasedModel.

        Both models run the Hintereisferner over the entire HistAlp climate
        period, initialized with the 2003 RGI outline without spin up.

        The following two parameters for length, area and volume are tested:
            - correlation coefficient
            - relative RMSE, i.e. RMSE/mean(OGGM). Whereby the results from the
                VAS model are offset with the average differences to the OGGM
                results.
       """

        # read the Hintereisferner DEM
        hef_file = get_demo_file('Hintereisferner_RGI5.shp')
        entity = gpd.read_file(hef_file).iloc[0]

        # initialize the GlacierDirectory
        gdir = oggm.GlacierDirectory(entity, base_dir=self.testdir)
        # define the local grid and glacier mask
        gis.define_glacier_region(gdir, entity=entity)
        gis.glacier_masks(gdir)

        # process the given climate file
        climate.process_custom_climate_data(gdir)

        # run center line preprocessing tasks
        centerlines.compute_centerlines(gdir)
        centerlines.initialize_flowlines(gdir)
        centerlines.compute_downstream_line(gdir)
        centerlines.compute_downstream_bedshape(gdir)
        centerlines.catchment_area(gdir)
        centerlines.catchment_intersections(gdir)
        centerlines.catchment_width_geom(gdir)
        centerlines.catchment_width_correction(gdir)

        # read reference glacier mass balance data
        mbdf = gdir.get_ref_mb_data()
        # compute the reference t* for the glacier
        # given the reference of mass balance measurements
        res = climate.t_star_from_refmb(gdir, mbdf=mbdf['ANNUAL_BALANCE'])
        t_star, bias = res['t_star'], res['bias']

        # --------------------
        #  SCALING MODEL
        # --------------------

        # compute local t* and the corresponding mu*
        vascaling.local_t_star(gdir, tstar=t_star, bias=bias)

        # instance the mass balance models
        vas_mbmod = vascaling.VAScalingMassBalance(gdir)

        # get reference area
        a0 = gdir.rgi_area_m2
        # get reference year
        y0 = gdir.read_json('climate_info')['baseline_hydro_yr_0']
        # get min and max glacier surface elevation
        h0, h1 = vascaling.get_min_max_elevation(gdir)

        vas_model = vascaling.VAScalingModel(year_0=y0, area_m2_0=a0,
                                             min_hgt=h0, max_hgt=h1,
                                             mb_model=vas_mbmod)

        # let model run over entire HistAlp climate period
        vas_ds = vas_model.run_until_and_store(2003)

        # ------
        #  OGGM
        # ------

        # compute local t* and the corresponding mu*
        climate.local_t_star(gdir, tstar=t_star, bias=bias)
        climate.mu_star_calibration(gdir)

        # instance the mass balance models
        mb_mod = massbalance.PastMassBalance(gdir)

        # perform ice thickness inversion
        inversion.prepare_for_inversion(gdir)
        inversion.mass_conservation_inversion(gdir)
        inversion.filter_inversion_output(gdir)

        # initialize present time glacier
        flowline.init_present_time_glacier(gdir)

        # instance flowline model
        fls = gdir.read_pickle('model_flowlines')
        y0 = gdir.read_json('climate_info')['baseline_hydro_yr_0']
        fl_mod = flowline.FluxBasedModel(flowlines=fls, mb_model=mb_mod, y0=y0)

        # run model and store output as xarray data set
        _, oggm_ds = fl_mod.run_until_and_store(2003)

        # temporal indices must be equal
        assert (vas_ds.time == oggm_ds.time).all()

        # specify which parameters to compare and their respective correlation
        # coefficients and rmsd values
        params = ['length_m', 'area_m2', 'volume_m3']
        corr_coeffs = np.array([0.96, 0.90, 0.93])
        rmsds = np.array([0.43e3, 0.14e6, 0.03e9])

        # compare given parameters
        for param, cc, rmsd in zip(params, corr_coeffs, rmsds):
            # correlation coefficient
            assert corrcoef(oggm_ds[param].values, vas_ds[param].values) >= cc
            # root mean squared deviation
            rmsd_an = rmsd_bc(oggm_ds[param].values, vas_ds[param].values)
            assert rmsd_an <= rmsd
Beispiel #20
0
def optimize_thick(gdirs):
    """Optimizes fd based on GlaThiDa thicknesses.

    We use the glacier averaged thicknesses provided by GlaThiDa and correct
    them for differences in area with RGI, using a glacier specific volume-area
    scaling formula.

    Parameters
    ----------
    gdirs: list of oggm.GlacierDirectory objects
    """

    gtd_df = _prepare_inv(gdirs)
    ref_gdirs = gtd_df['ref_gdirs']
    ref_volume_km3 = gtd_df['ref_volume_km3']
    ref_area_km2 = gtd_df['ref_area_km2']
    ref_thickness_m = gtd_df['ref_thickness_m']

    # Optimize without sliding
    log.info('Compute the inversion parameter.')

    def to_optimize(x):
        tmp_ = np.zeros(len(ref_gdirs))
        glen_a = cfg.A * x[0]
        for i, gdir in enumerate(ref_gdirs):
            v, a = mass_conservation_inversion(gdir,
                                               glen_a=glen_a,
                                               fs=0.,
                                               write=False)
            tmp_[i] = v / a
        return utils.rmsd(tmp_, ref_thickness_m)

    opti = optimization.minimize(to_optimize, [1.],
                                 bounds=((0.01, 10), ),
                                 tol=1.e-4)
    # Check results and save.
    glen_a = cfg.A * opti['x'][0]
    fs = 0.

    # This is for the stats
    oggm_volume_m3 = np.zeros(len(ref_gdirs))
    rgi_area_m2 = np.zeros(len(ref_gdirs))
    for i, gdir in enumerate(ref_gdirs):
        v, a = mass_conservation_inversion(gdir,
                                           glen_a=glen_a,
                                           fs=fs,
                                           write=False)
        oggm_volume_m3[i] = v
        rgi_area_m2[i] = a
    assert np.allclose(rgi_area_m2 * 1e-6, ref_area_km2)

    # This is for each glacier
    out = dict()
    out['glen_a'] = glen_a
    out['fs'] = fs
    out['factor_glen_a'] = opti['x'][0]
    try:
        out['factor_fs'] = opti['x'][1]
    except IndexError:
        out['factor_fs'] = 0.
    for gdir in gdirs:
        gdir.write_pickle(out, 'inversion_params')

    # This is for the working dir
    # Simple stats
    out['vol_rmsd'] = utils.rmsd(oggm_volume_m3 * 1e-9, ref_volume_km3)
    out['thick_rmsd'] = utils.rmsd(oggm_volume_m3 / (ref_area_km2 * 1e6),
                                   ref_thickness_m)
    log.info(
        'Optimized glen_a and fs with a factor {factor_glen_a:.2f} and '
        '{factor_fs:.2f} for a thick RMSD of {thick_rmsd:.3f}'.format(**out))

    df = pd.DataFrame(out, index=[0])
    fpath = os.path.join(cfg.PATHS['working_dir'],
                         'inversion_optim_params.csv')
    df.to_csv(fpath)

    # All results
    df = utils.glacier_characteristics(ref_gdirs)
    df['ref_area_km2'] = ref_area_km2
    df['ref_volume_km3'] = ref_volume_km3
    df['ref_thickness_m'] = ref_thickness_m
    df['oggm_volume_km3'] = oggm_volume_m3 * 1e-9
    df['oggm_thickness_m'] = oggm_volume_m3 / (ref_area_km2 * 1e6)
    df['vas_volume_km3'] = 0.034 * (df['ref_area_km2']**1.375)
    df['vas_thickness_m'] = df['vas_volume_km3'] / ref_area_km2 * 1000

    rgi_id = [gdir.rgi_id for gdir in ref_gdirs]
    df = pd.DataFrame(df, index=rgi_id)
    fpath = os.path.join(cfg.PATHS['working_dir'],
                         'inversion_optim_results.csv')
    df.to_csv(fpath)

    # return value for tests
    return out
Beispiel #21
0
def init_hef(reset=False, border=40, logging_level='INFO'):

    from oggm.core import gis, inversion, climate, centerlines, flowline
    import geopandas as gpd

    # test directory
    testdir = os.path.join(get_test_dir(), 'tmp_border{}'.format(border))
    if not os.path.exists(testdir):
        os.makedirs(testdir)
        reset = True

    # Init
    cfg.initialize(logging_level=logging_level)
    cfg.set_intersects_db(get_demo_file('rgi_intersect_oetztal.shp'))
    cfg.PATHS['dem_file'] = get_demo_file('hef_srtm.tif')
    cfg.PATHS['climate_file'] = get_demo_file('histalp_merged_hef.nc')
    cfg.PARAMS['baseline_climate'] = ''
    cfg.PATHS['working_dir'] = testdir
    cfg.PARAMS['border'] = border

    hef_file = get_demo_file('Hintereisferner_RGI5.shp')
    entity = gpd.read_file(hef_file).iloc[0]

    gdir = oggm.GlacierDirectory(entity, reset=reset)
    if not gdir.has_file('inversion_params'):
        reset = True
        gdir = oggm.GlacierDirectory(entity, reset=reset)

    if not reset:
        return gdir

    gis.define_glacier_region(gdir)
    execute_entity_task(gis.glacier_masks, [gdir])
    execute_entity_task(centerlines.compute_centerlines, [gdir])
    centerlines.initialize_flowlines(gdir)
    centerlines.compute_downstream_line(gdir)
    centerlines.compute_downstream_bedshape(gdir)
    centerlines.catchment_area(gdir)
    centerlines.catchment_intersections(gdir)
    centerlines.catchment_width_geom(gdir)
    centerlines.catchment_width_correction(gdir)
    climate.process_custom_climate_data(gdir)
    mbdf = gdir.get_ref_mb_data()['ANNUAL_BALANCE']
    res = climate.t_star_from_refmb(gdir, mbdf=mbdf)
    climate.local_t_star(gdir, tstar=res['t_star'], bias=res['bias'])
    climate.mu_star_calibration(gdir)

    inversion.prepare_for_inversion(gdir, add_debug_var=True)

    ref_v = 0.573 * 1e9

    glen_n = cfg.PARAMS['glen_n']

    def to_optimize(x):
        # For backwards compat
        _fd = 1.9e-24 * x[0]
        glen_a = (glen_n + 2) * _fd / 2.
        fs = 5.7e-20 * x[1]
        v, _ = inversion.mass_conservation_inversion(gdir,
                                                     fs=fs,
                                                     glen_a=glen_a)
        return (v - ref_v)**2

    out = optimization.minimize(to_optimize, [1, 1],
                                bounds=((0.01, 10), (0.01, 10)),
                                tol=1e-4)['x']
    _fd = 1.9e-24 * out[0]
    glen_a = (glen_n + 2) * _fd / 2.
    fs = 5.7e-20 * out[1]
    v, _ = inversion.mass_conservation_inversion(gdir,
                                                 fs=fs,
                                                 glen_a=glen_a,
                                                 write=True)

    d = dict(fs=fs, glen_a=glen_a)
    d['factor_glen_a'] = out[0]
    d['factor_fs'] = out[1]
    gdir.write_pickle(d, 'inversion_params')

    # filter
    inversion.filter_inversion_output(gdir)

    inversion.distribute_thickness_interp(gdir, varname_suffix='_interp')
    inversion.distribute_thickness_per_altitude(gdir, varname_suffix='_alt')

    flowline.init_present_time_glacier(gdir)

    return gdir
def compare(rgi_id, glacier_name):
    """

    :param rgi_id:
    :param glacier_name:
    :return:
    """

    # ---------------------
    #  PREPROCESSING TASKS
    # ---------------------
    # create test directory
    wdir = os.path.join(os.path.abspath('.'), 'comparison_wdir')
    if not os.path.exists(wdir):
        os.makedirs(wdir)
    shutil.rmtree(wdir)
    os.makedirs(wdir)

    # load default parameter file
    cfg.initialize()

    # RGI entity
    # get/downlaod the rgi entity including the outline shapefile
    rgi_df = utils.get_rgi_glacier_entities([rgi_id])
    # set name, since not delivered with RGI
    if rgi_df.loc[int(rgi_id[-5:])-1, 'Name'] is None:
        rgi_df.loc[int(rgi_id[-5:])-1, 'Name'] = glacier_name

    # select single entry
    rgi_entity = rgi_df.iloc[0]

    # GlacierDirectory
    # specify the working directory and define the glacier directory
    cfg.PATHS['working_dir'] = wdir
    gdir = oggm.GlacierDirectory(rgi_entity)

    # DEM and GIS tasks
    # get the path to the DEM file (will download if necessary)
    dem = utils.get_topo_file(gdir.cenlon, gdir.cenlat)
    # set path in config file
    cfg.PATHS['dem_file'] = dem[0][0]
    cfg.PARAMS['border'] = 10
    cfg.PARAMS['use_intersects'] = False
    # run GIS tasks
    gis.define_glacier_region(gdir, entity=rgi_entity)
    gis.glacier_masks(gdir)

    # Climate data
    # using HistAlp
    cfg.PARAMS['baseline_climate'] = 'HISTALP'
    # climate records before 1850 are hardly reliable, which is not so drastic for
    # qualitative experiments (could be driven with random climate anyway)
    # cfg.PARAMS['baseline_y0'] = 1850
    # change hyper parameters for HistAlp
    cfg.PARAMS['prcp_scaling_factor'] = 1.75
    cfg.PARAMS['temp_melt'] = -1.75
    # run climate task
    climate.process_histalp_data(gdir)

    # run center line preprocessing tasks
    centerlines.compute_centerlines(gdir)
    centerlines.initialize_flowlines(gdir)
    centerlines.compute_downstream_line(gdir)
    centerlines.compute_downstream_bedshape(gdir)
    centerlines.catchment_area(gdir)
    centerlines.catchment_intersections(gdir)
    centerlines.catchment_width_geom(gdir)
    centerlines.catchment_width_correction(gdir)

    # --------------------
    #  SCALING MODEL
    # --------------------

    # compute local t* and the corresponding mu*
    vascaling.local_t_star(gdir)

    # instance the mass balance models
    vas_mb_mod = vascaling.VAScalingMassBalance(gdir)

    # get reference area
    a0 = gdir.rgi_area_m2
    # get reference year
    y0 = gdir.read_pickle('climate_info')['baseline_hydro_yr_0']
    y1 = gdir.read_pickle('climate_info')['baseline_hydro_yr_1']
    # get min and max glacier surface elevation
    h0, h1 = vascaling.get_min_max_elevation(gdir)

    # instance VAS model
    vas_model = vascaling.VAScalingModel(year_0=y0, area_m2_0=a0,
                                         min_hgt=h0, max_hgt=h1,
                                         mb_model=vas_mb_mod)
    # run model over all HistAlp climate period
    vas_df = vas_model.run_and_store(y1, reset=True)
    # get relevant parameters
    years_vas = vas_df.index.values
    length_m_vas = vas_df.length_m.values
    area_m2_vas = vas_df.area_m2.values
    volume_m3_vas = vas_df.volume_m3.values

    # ------
    #  OGGM
    # ------

    # compute local t* and the corresponding mu*
    climate.local_t_star(gdir)
    climate.mu_star_calibration(gdir)

    # instance the mass balance models
    mb_mod = massbalance.PastMassBalance(gdir)

    # run inversion tasks
    inversion.prepare_for_inversion(gdir)
    inversion.mass_conservation_inversion(gdir)
    inversion.filter_inversion_output(gdir)

    # initialize present time glacier
    flowline.init_present_time_glacier(gdir)

    # instance flowline model
    fls = gdir.read_pickle('model_flowlines')
    y0 = gdir.read_pickle('climate_info')['baseline_hydro_yr_0']
    y1 = gdir.read_pickle('climate_info')['baseline_hydro_yr_1']
    fl_mod = flowline.FluxBasedModel(flowlines=fls, mb_model=mb_mod, y0=y0)

    # run model and store output as xarray data set
    _, oggm_ds = fl_mod.run_until_and_store(y1)

    years_oggm = oggm_ds.hydro_year.values
    # annual index must be equal
    np.testing.assert_array_equal(years_oggm, years_vas)
    length_m_oggm = oggm_ds.length_m.values
    area_m2_oggm = oggm_ds.area_m2.values
    volume_m3_oggm = oggm_ds.volume_m3.values

    # define column names for DataFrame
    names = ['length_vas', 'length_oggm',
             'area_vas', 'area_oggm',
             'volume_vas', 'volume_oggm']
    # combine glacier geometries into DataFrame
    df = pd.DataFrame(np.array([length_m_vas, length_m_oggm,
                                area_m2_vas, area_m2_oggm,
                                volume_m3_vas, volume_m3_oggm]).T,
                      index=years_vas, columns=names)
    # save to file
    store = True
    if store:
        # define path and file names
        folder = '/Users/oberrauch/work/master/data/'
        df.to_csv(folder+'run_comparison.csv')

    def plot_both(vas_df, oggm_df, ref=None, correct_bias=False,
                  title='', ylabel='', file_path='', exp=0):
        """ Plot geometric parameters of both models.
        If a `file_path` is given, the figure will be saved.

        :param vas_df: (pandas.Series) geometric glacier parameter of the VAS model
        :param oggm_df: (pandas.Series) geometric glacier parameter of the OGGM
        :param ref: (pandas.Series) measured glacier parameter, optional
        :param title: (string) figure title, optional
        :param ylabel: (string) label for y-axis, optional
        :param file_path: (string) where to store the figure, optional
        :param exp: (int) exponent for labels in scientific notation, optional
        """
        beamer = True
        if beamer:
            mpl.rc('axes', titlesize=18)
            mpl.rc('axes', labelsize=14)
            mpl.rc('xtick', labelsize=14)
            mpl.rc('ytick', labelsize=14)
            mpl.rc('legend', fontsize=10)
        # create figure and first axes
        fig = plt.figure(figsize=[6, 4])
        ax = fig.add_axes([0.15, 0.1, 0.8, 0.8])

        # define colors
        c1 = 'C0'
        c2 = 'C1'
        c3 = 'C3'
        # plot vas and OGGM parameters
        ax.plot(oggm_df.index, oggm_df.values, c=c2, label='OGGM')
        ax.plot(vas_df.index, vas_df.values, c=c1, label='VAS')
        if ref:
            # plot reference parameter if given
            ax.plot(ref.index, ref.values, c=c3, label='measurements')
        if correct_bias:
            # plot bias corrected vas
            df_ = pd.DataFrame([oggm_df, vas_df]).T
            bias = vas_df.values - df_.mean().diff().iloc[1]
            ax.plot(vas_df.index, bias, c=c1, ls='--',
                    label='VAS, bias corrected')
            # add RMSD as text
            ax.text(0.05, 0.05,
                    'RMSD: {:.1e}'.format(utils.rmsd(oggm_df, bias)),
                    transform=plt.gca().transAxes)

        # add correlation coefficient as text
        ax.text(0.05, 0.11, 'Corr. Coef.: {:.2f}'.format(
            utils.corrcoef(oggm_df, vas_df)),
                    transform=plt.gca().transAxes)

        # add title, labels, legend
        ax.set_title(title)
        ax.set_ylabel(ylabel)
        ax.legend()

        import matplotlib.ticker

        class OOMFormatter(matplotlib.ticker.ScalarFormatter):
            def __init__(self, order=0, fformat="%1.1f", offset=False, mathText=False):
                self.oom = order
                self.fformat = fformat
                matplotlib.ticker.ScalarFormatter.__init__(self, useOffset=offset, useMathText=mathText)

            def _set_orderOfMagnitude(self, nothing):
                self.orderOfMagnitude = self.oom

            def _set_format(self, vmin, vmax):
                self.format = self.fformat
                if self._useMathText:
                    self.format = '$%s$' % matplotlib.ticker._mathdefault(self.format)

        # use scientific notation with fixed exponent according
        ax.yaxis.set_major_formatter(OOMFormatter(exp, "%1.2f"))

        # store to file
        if file_path:
            plt.savefig(file_path, bbox_inches='tight',
                        format=file_path.split('.')[-1])

    # specify plot directory
    folder = '/Users/oberrauch/work/master/plots/'

    # plot length
    plot_both(df.length_vas, df.length_oggm, correct_bias=True,
              title='Glacier length - {}'.format(glacier_name),
              ylabel=r'Length [m]',
              file_path=os.path.join(folder, '{}_length.pdf'.format(rgi_id)),
              exp=3)
    # plot area
    plot_both(df.area_vas, df.area_oggm, correct_bias=True,
              title='Surface area - {}'.format(glacier_name),
              ylabel=r'Area [m$^2$]',
              file_path=os.path.join(folder, '{}_area.pdf'.format(rgi_id)),
              exp=6)
    # plot volume
    plot_both(df.volume_vas, df.volume_oggm, correct_bias=True,
              title='Glacier volume - {}'.format(glacier_name),
              ylabel=r'Volume [m$^3$]',
              file_path=os.path.join(folder, '{}_volume.pdf'.format(rgi_id)),
              exp=9)