예제 #1
0
def test_mb_modules_monthly(gdir):
    # check if massbalance.PastMassBalance equal to mb_modules with cte
    # gradient and mb_monthly as options for lapse rate mb_type

    mu_star_opt_cte_var = 195.5484547754791
    # if I use ERA5dr in PastMassBalance, it applies automatically the
    # gradient that changes with time and location
    mu_opts = [mu_star_opt_cte['mb_monthly'], mu_star_opt_cte_var]
    grads = ['cte', 'var']
    for k, clim in zip([0, 1], ['ERA5', 'ERA5dr']):
        mu_opt = mu_opts[k]
        grad_type = grads[k]
        cfg.PARAMS['baseline_climate'] = clim
        oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset=clim)

        mb_mod = mb_modules(gdir,
                            mu_opt,
                            mb_type='mb_monthly',
                            prcp_fac=2.5,
                            t_solid=0,
                            t_liq=2,
                            t_melt=0,
                            default_grad=-0.0065,
                            bias=0,
                            grad_type=grad_type)

        hgts, widths = gdir.get_inversion_flowline_hw()
        mbdf = gdir.get_ref_mb_data()
        tot_mb = mb_mod.get_specific_mb(heights=hgts,
                                        widths=widths,
                                        year=mbdf.index.values)

        cfg.PARAMS['temp_default_gradient'] = -0.0065
        cfg.PARAMS['prcp_scaling_factor'] = 2.5
        cfg.PARAMS['temp_all_solid'] = 0
        cfg.PARAMS['temp_all_liq'] = 2
        cfg.PARAMS['temp_melt'] = 0

        # check if the default OGGM monthly mass balance with cte gradient
        # gives the same result as the new mb_modules with the options
        # mb_monthly and constant lapse rate gradient!
        mb_mod_default = massbalance.PastMassBalance(gdir,
                                                     mu_star=mu_opt,
                                                     bias=0,
                                                     check_calib_params=False)

        tot_mb_default = mb_mod_default.get_specific_mb(heights=hgts,
                                                        widths=widths,
                                                        year=mbdf.index.values)

        assert_allclose(tot_mb, tot_mb_default, rtol=1e-4)
예제 #2
0
def test_optimize_std_quot_brentq(gdir):
    # check if double optimisation of bias and std_quotient works

    grad_type = 'cte'
    N = 2000
    loop = False
    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset='ERA5dr')
    for mb_type in ['mb_monthly', 'mb_daily', 'mb_real_daily']:
        if mb_type != 'mb_real_daily':
            cfg.PARAMS['baseline_climate'] = 'ERA5dr'
            oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset='ERA5dr')
        else:
            cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
            process_era5_daily_data(gdir)

        hgts, widths = gdir.get_inversion_flowline_hw()
        mbdf = gdir.get_ref_mb_data()
        pf_opt = scipy.optimize.brentq(optimize_std_quot_brentq,
                                       0.01,
                                       20,
                                       args=(mb_type, grad_type, gdir, N,
                                             loop),
                                       xtol=0.01)

        DDF_opt_pf = scipy.optimize.brentq(minimize_bias,
                                           1,
                                           10000,
                                           args=(mb_type, grad_type, gdir, N,
                                                 pf_opt, loop, False),
                                           disp=True,
                                           xtol=0.1)
        gd_mb = mb_modules(gdir,
                           DDF_opt_pf,
                           prcp_fac=pf_opt,
                           mb_type=mb_type,
                           grad_type=grad_type)
        mb_specific = gd_mb.get_specific_mb(heights=hgts,
                                            widths=widths,
                                            year=mbdf.index.values)

        RMSD, bias, rcor, quot_std = compute_stat(mb_specific=mb_specific,
                                                  mbdf=mbdf)

        # check if the bias is optimised
        assert bias.round() == 0
        # check if the std_quotient is optimised
        assert quot_std.round(1) == 1
예제 #3
0
def test_minimize_bias(gdir):

    # important to initialize again, otherwise hydro_month_nh=1
    # from test_hydro_years_HEF...
    # just checks if minimisation gives always same results
    grad_type = 'cte'
    N = 2000
    loop = False
    for mb_type in ['mb_real_daily', 'mb_monthly', 'mb_daily']:
        if mb_type != 'mb_real_daily':
            cfg.PARAMS['baseline_climate'] = 'ERA5dr'
            oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset='ERA5dr')
        else:
            cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
            process_era5_daily_data(gdir)

        DDF_opt = scipy.optimize.brentq(minimize_bias,
                                        1,
                                        10000,
                                        disp=True,
                                        xtol=0.1,
                                        args=(mb_type, grad_type, gdir, N, pf,
                                              loop, False))
        hgts, widths = gdir.get_inversion_flowline_hw()
        mbdf = gdir.get_ref_mb_data()
        # check if they give the same optimal DDF
        # print(mu_star_opt_cte[mb_type], DDF_opt)
        assert np.round(mu_star_opt_cte[mb_type] / DDF_opt, 3) == 1

        gd_mb = mb_modules(gdir, DDF_opt, mb_type=mb_type, grad_type=grad_type)
        mb_specific = gd_mb.get_specific_mb(heights=hgts,
                                            widths=widths,
                                            year=mbdf.index.values)

        RMSD, bias, rcor, quot_std = compute_stat(mb_specific=mb_specific,
                                                  mbdf=mbdf)

        # check if the bias is optimised
        assert bias.round() == 0
예제 #4
0
def test_N(gdir):
    # tests whether modelled mb_daily massbalances of different values of N
    # is similar to observed mass balances

    # this could be optimised and included in the above tests
    climate = 'ERA5dr'
    mb_type = 'mb_daily'
    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5dr")
    for grad_type in ['cte', 'var_an_cycle']:
        if grad_type == 'var_an_cycle':
            fail_err_4 = (mb_type == 'mb_monthly') and (climate == 'CRU')
            mu_star_opt = mu_star_opt_var
        else:
            fail_err_4 = False
            mu_star_opt = mu_star_opt_cte

        if fail_err_4:
            with pytest.raises(InvalidParamsError):
                mb_mod = mb_modules(gdir,
                                    mu_star_opt[mb_type],
                                    mb_type=mb_type,
                                    prcp_fac=pf,
                                    t_solid=0,
                                    t_liq=2,
                                    t_melt=0,
                                    default_grad=-0.0065,
                                    bias=0,
                                    grad_type=grad_type)
        else:
            mbdf = gdir.get_ref_mb_data()
            hgts, widths = gdir.get_inversion_flowline_hw()

            tot_mb_N = {}
            for N in [10000, 5000, 1000, 500, 100]:
                mb_mod = mb_modules(gdir,
                                    mu_star_opt[mb_type],
                                    mb_type=mb_type,
                                    prcp_fac=pf,
                                    N=N,
                                    t_solid=0,
                                    t_liq=2,
                                    t_melt=0,
                                    default_grad=-0.0065,
                                    bias=0,
                                    grad_type=grad_type)

                tot_mb_N[N] = mb_mod.get_specific_mb(heights=hgts,
                                                     widths=widths,
                                                     year=mbdf.index.values)

                assert np.abs(utils.md(tot_mb_N[N],
                                       mbdf['ANNUAL_BALANCE'])) < 10


# %%
# something like that could also be included later on
# bbut only if I somehow get the data from the climate files ....
# or can I use these things with the ELA... without the climate files...
# in the moment oggm.core.climate works only with default OGGM mass balance

# def test_mb_modules(self, hef_gdir):

#     rho = cfg.PARAMS['ice_density']

#     F = SEC_IN_YEAR * rho

#     gdir = hef_gdir
#     init_present_time_glacier(gdir)

#     df = gdir.read_json('local_mustar')
#     mu_star = df['mu_star_glacierwide']
#     bias = df['bias']

#     # Climate period
#     yrp = [1851, 2000]

#     # Flowlines height
#     h, w = gdir.get_inversion_flowline_hw()

#     mb_mod = massbalance.PastMassBalance(gdir, bias=0)
#     for i, yr in enumerate(np.arange(yrp[0], yrp[1]+1)):
#         ref_mb_on_h = p[:, i] - mu_star * t[:, i]
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * F
#         np.testing.assert_allclose(ref_mb_on_h, my_mb_on_h,
#                                    atol=1e-2)
#         ela_z = mb_mod.get_ela(year=yr)
#         totest = mb_mod.get_annual_mb([ela_z], year=yr) * F
#         assert_allclose(totest[0], 0, atol=1)

#     mb_mod = massbalance.PastMassBalance(gdir)
#     for i, yr in enumerate(np.arange(yrp[0], yrp[1]+1)):
#         ref_mb_on_h = p[:, i] - mu_star * t[:, i]
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * F
#         np.testing.assert_allclose(ref_mb_on_h, my_mb_on_h + bias,
#                                    atol=1e-2)
#         ela_z = mb_mod.get_ela(year=yr)
#         totest = mb_mod.get_annual_mb([ela_z], year=yr) * F
#         assert_allclose(totest[0], 0, atol=1)

#     for i, yr in enumerate(np.arange(yrp[0], yrp[1]+1)):

#         ref_mb_on_h = p[:, i] - mu_star * t[:, i]
#         my_mb_on_h = ref_mb_on_h*0.
#         for m in np.arange(12):
#             yrm = utils.date_to_floatyear(yr, m + 1)
#             tmp = mb_mod.get_monthly_mb(h, yrm) * SEC_IN_MONTH * rho
#             my_mb_on_h += tmp

#         np.testing.assert_allclose(ref_mb_on_h,
#                                    my_mb_on_h + bias,
#                                    atol=1e-2)

#     # real data
#     h, w = gdir.get_inversion_flowline_hw()
#     mbdf = gdir.get_ref_mb_data()
#     mbdf.loc[yr, 'MY_MB'] = np.NaN
#     mb_mod = massbalance.PastMassBalance(gdir)
#     for yr in mbdf.index.values:
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * SEC_IN_YEAR * rho
#         mbdf.loc[yr, 'MY_MB'] = np.average(my_mb_on_h, weights=w)

#     np.testing.assert_allclose(mbdf['ANNUAL_BALANCE'].mean(),
#                                mbdf['MY_MB'].mean(),
#                                atol=1e-2)
#     mbdf['MY_ELA'] = mb_mod.get_ela(year=mbdf.index.values)
#     assert mbdf[['MY_ELA', 'MY_MB']].corr().values[0, 1] < -0.9
#     assert mbdf[['MY_ELA', 'ANNUAL_BALANCE']].corr().values[0, 1] < -0.7

#     mb_mod = massbalance.PastMassBalance(gdir, bias=0)
#     for yr in mbdf.index.values:
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * SEC_IN_YEAR * rho
#         mbdf.loc[yr, 'MY_MB'] = np.average(my_mb_on_h, weights=w)

#     np.testing.assert_allclose(mbdf['ANNUAL_BALANCE'].mean() + bias,
#                                mbdf['MY_MB'].mean(),
#                                atol=1e-2)

#     mb_mod = massbalance.PastMassBalance(gdir)
#     for yr in mbdf.index.values:
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * SEC_IN_YEAR * rho
#         mbdf.loc[yr, 'MY_MB'] = np.average(my_mb_on_h, weights=w)
#         mb_mod.temp_bias = 1
#         my_mb_on_h = mb_mod.get_annual_mb(h, yr) * SEC_IN_YEAR * rho
#         mbdf.loc[yr, 'BIASED_MB'] = np.average(my_mb_on_h, weights=w)
#         mb_mod.temp_bias = 0

#     np.testing.assert_allclose(mbdf['ANNUAL_BALANCE'].mean(),
#                                mbdf['MY_MB'].mean(),
#                                atol=1e-2)
#     assert mbdf.ANNUAL_BALANCE.mean() > mbdf.BIASED_MB.mean()

#     # Repeat
#     mb_mod = massbalance.PastMassBalance(gdir, repeat=True,
#                                          ys=1901, ye=1950)
#     yrs = np.arange(100) + 1901
#     mb = mb_mod.get_specific_mb(h, w, year=yrs)
#     assert_allclose(mb[50], mb[-50])
예제 #5
0
def test_loop(gdir):
    # tests whether ERA5dr works better with or without the loop in mb_daily
    # tests that both option give same results and in case that default option
    # (no loop) is 30% slower, it raises an error

    # this could be optimised and included in the above tests
    cfg.initialize()

    climate = 'ERA5dr'
    mb_type = 'mb_daily'
    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5dr")

    for grad_type in ['cte', 'var_an_cycle']:
        if grad_type == 'var_an_cycle':
            fail_err_4 = (mb_type == 'mb_monthly') and (climate == 'CRU')
            mu_star_opt = mu_star_opt_var
        else:
            fail_err_4 = False
            mu_star_opt = mu_star_opt_cte

        if fail_err_4:
            with pytest.raises(InvalidParamsError):
                mb_modules(gdir,
                           mu_star_opt[mb_type],
                           mb_type=mb_type,
                           prcp_fac=pf,
                           t_solid=0,
                           t_liq=2,
                           t_melt=0,
                           default_grad=-0.0065,
                           bias=0,
                           grad_type=grad_type)
        else:
            mbdf = gdir.get_ref_mb_data()
            ys = mbdf.index.values

            hgts, widths = gdir.get_inversion_flowline_hw()

            ex_t = time.time()
            for t in np.arange(10):
                mb_mod_noloop = mb_modules(gdir,
                                           mu_star_opt[mb_type],
                                           mb_type=mb_type,
                                           prcp_fac=pf,
                                           loop=False,
                                           t_solid=0,
                                           t_liq=2,
                                           t_melt=0,
                                           default_grad=-0.0065,
                                           bias=0,
                                           grad_type=grad_type)
                tot_mb_noloop = mb_mod_noloop.get_specific_mb(heights=hgts,
                                                              widths=widths,
                                                              year=ys)
            ex_noloop = time.time() - ex_t

            ex_t = time.time()
            for t in np.arange(10):
                mb_mod_loop = mb_modules(gdir,
                                         mu_star_opt[mb_type],
                                         mb_type=mb_type,
                                         prcp_fac=pf,
                                         loop=True,
                                         t_solid=0,
                                         t_liq=2,
                                         t_melt=0,
                                         default_grad=-0.0065,
                                         bias=0,
                                         grad_type=grad_type)
                tot_mb_loop = mb_mod_loop.get_specific_mb(heights=hgts,
                                                          widths=widths,
                                                          year=ys)
            ex_loop = time.time() - ex_t

            # both should give the same results!!!
            assert_allclose(tot_mb_loop, tot_mb_noloop, atol=1e-2)

            # if the loop would be at least 30% faster than not using the loop
            # raise an error
            assert (ex_loop - ex_noloop) / ex_noloop > -0.3
예제 #6
0
def test_monthly_glacier_massbalance(gdir):
    # TODO: problem with that, monthly and annual MB not exactly the same!!!
    # I think there is a problem with SEC_IN_MONTH/SEC_IN_YEAR ...

    # do this for all model types
    # ONLY TEST it for ERA5dr or ERA5_daily!!!
    for climate in ['ERA5dr', 'ERA5_daily']:
        for mb_type in ['mb_monthly', 'mb_daily', 'mb_real_daily']:
            for grad_type in ['cte', 'var_an_cycle']:
                if grad_type == 'var_an_cycle':
                    fail_err_4 = ((mb_type == 'mb_monthly')
                                  and (climate == 'CRU'))
                    mu_star_opt = mu_star_opt_var
                else:
                    fail_err_4 = False
                    mu_star_opt = mu_star_opt_cte
                if climate == 'ERA5dr':
                    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
                    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5dr")
                elif climate == 'ERA5_daily':
                    process_era5_daily_data(gdir)
                    cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
                else:
                    tasks.process_climate_data(gdir)
                    pass
                # mb_type ='mb_daily'
                fail_err_1 = (mb_type == 'mb_daily') and (climate != 'ERA5dr')
                fail_err_2 = ((mb_type == 'mb_monthly')
                              and (climate == 'ERA5_daily'))
                fail_err_3 = ((mb_type == 'mb_real_daily')
                              and (climate != 'ERA5_daily'))

                if fail_err_1 or fail_err_2 or fail_err_3 or fail_err_4:
                    with pytest.raises(InvalidParamsError):
                        mb_mod = mb_modules(gdir,
                                            mu_star_opt[mb_type],
                                            mb_type=mb_type,
                                            prcp_fac=pf,
                                            t_solid=0,
                                            t_liq=2,
                                            t_melt=0,
                                            default_grad=-0.0065,
                                            bias=0,
                                            grad_type=grad_type)
                else:
                    # but this is just a test for reproducibility!
                    mb_mod = mb_modules(gdir,
                                        mu_star_opt[mb_type],
                                        mb_type=mb_type,
                                        prcp_fac=pf,
                                        t_solid=0,
                                        t_liq=2,
                                        t_melt=0,
                                        default_grad=-0.0065,
                                        bias=0,
                                        grad_type=grad_type)
                    hgts, widths = gdir.get_inversion_flowline_hw()

                    rho = 900  # ice density
                    yrp = [1980, 2018]
                    for i, yr in enumerate(np.arange(yrp[0], yrp[1] + 1)):
                        my_mon_mb_on_h = 0.
                        dayofyear = 0
                        for m in np.arange(12):
                            yrm = utils.date_to_floatyear(yr, m + 1)
                            _, dayofmonth = monthrange(yr, m + 1)
                            dayofyear += dayofmonth
                            tmp = (mb_mod.get_monthly_mb(hgts, yrm) *
                                   dayofmonth * SEC_IN_DAY * rho)
                            my_mon_mb_on_h += tmp
                        my_an_mb_on_h = (mb_mod.get_annual_mb(hgts, yr) *
                                         dayofyear * SEC_IN_DAY * rho)

                        # these large errors might come from the problematic of
                        # different amount of days in a year?
                        # or maybe it just does not fit ...
                        assert_allclose(np.mean(my_an_mb_on_h -
                                                my_mon_mb_on_h),
                                        0,
                                        atol=100)
예제 #7
0
def test_present_time_glacier_massbalance(gdir):

    # check if area of  HUSS flowlines corresponds to the rgi area
    h, w = gdir.get_inversion_flowline_hw()
    fls = gdir.read_pickle('inversion_flowlines')
    assert_allclose(gdir.rgi_area_m2, np.sum(w * gdir.grid.dx * fls[0].dx))

    # do this for all model types
    # ONLY TEST it for ERA5dr or ERA5_daily!!!
    for climate in ['ERA5dr', 'ERA5_daily']:
        for mb_type in ['mb_monthly', 'mb_daily', 'mb_real_daily']:
            for grad_type in ['cte', 'var_an_cycle']:
                if grad_type == 'var_an_cycle':
                    fail_err_4 = ((mb_type == 'mb_monthly')
                                  and (climate == 'CRU'))
                    mu_star_opt = mu_star_opt_var
                else:
                    fail_err_4 = False
                    mu_star_opt = mu_star_opt_cte
                if climate == 'ERA5dr':
                    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
                    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5dr")
                elif climate == 'ERA5_daily':
                    cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
                    process_era5_daily_data(gdir)
                else:
                    tasks.process_climate_data(gdir)
                    pass
                fail_err_1 = (mb_type == 'mb_daily') and (climate != 'ERA5dr')
                fail_err_2 = ((mb_type == 'mb_monthly')
                              and (climate == 'ERA5_daily'))
                fail_err_3 = ((mb_type == 'mb_real_daily')
                              and (climate != 'ERA5_daily'))

                if fail_err_1 or fail_err_2 or fail_err_3 or fail_err_4:
                    with pytest.raises(InvalidParamsError):
                        mb_mod = mb_modules(gdir,
                                            mu_star_opt[mb_type],
                                            mb_type=mb_type,
                                            prcp_fac=pf,
                                            t_solid=0,
                                            t_liq=2,
                                            t_melt=0,
                                            default_grad=-0.0065,
                                            bias=0,
                                            grad_type=grad_type)
                else:
                    # this is just a test for reproducibility!
                    mb_mod = mb_modules(gdir,
                                        mu_star_opt[mb_type],
                                        mb_type=mb_type,
                                        prcp_fac=pf,
                                        t_solid=0,
                                        t_liq=2,
                                        t_melt=0,
                                        default_grad=-0.0065,
                                        bias=0,
                                        grad_type=grad_type)

                    mbdf = gdir.get_ref_mb_data()
                    hgts, widths = gdir.get_inversion_flowline_hw()

                    tot_mb = []
                    refmb = []
                    grads = hgts * 0
                    for yr, mb in mbdf.iterrows():
                        refmb.append(mb['ANNUAL_BALANCE'])
                        mbh = (mb_mod.get_annual_mb(hgts, yr) * SEC_IN_YEAR *
                               cfg.PARAMS['ice_density'])
                        grads += mbh
                        tot_mb.append(np.average(mbh, weights=widths))
                    grads /= len(tot_mb)

                    # check if calibrated total mass balance similar
                    # to observe mass balance time series
                    assert np.abs(utils.md(tot_mb, refmb)) < 50