def get_TIModel_clim_model_type(gd, mb_type='mb_monthly', grad_type='cte',
                                pd_geodetic_loc=None,  # pd_geodetic_comp
                                ):
    rho_geodetic = 850

    # get volume estimates
    dV = pd.read_hdf(utils.get_demo_file('rgi62_itmix_df.h5'))

    # for potential restricting total ice melt
    V_gd_m3 = dV.loc[gd.rgi_id]['vol_itmix_m3']  # m3 volume of HEF
    total_mass_gd = V_gd_m3 * rho_geodetic
    # this is the area from 2000, could use another estimate (e.g. mean between 2000 and 2020...)
    gd_area = pd_geodetic_loc.loc[gd.rgi_id]['area']  # in km2
    # convert kg --> kg/km2
    max_allowed_specificMB = - total_mass_gd / 1e6 / gd_area

    h, w = gd.get_inversion_flowline_hw()
    if mb_type != 'mb_real_daily':
        cfg.PARAMS['baseline_climate'] = 'ERA5dr'
        oggm.shop.ecmwf.process_ecmwf_data(gd, dataset='ERA5dr')
    else:
        cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
        process_era5_daily_data(gd)

    ref_df = gd.get_ref_mb_data()

    # at instantiation use prcp_fac = 2.5, change this in def_get_mb later on
    gd_mb = TIModel(gd, 150, mb_type=mb_type, N=100, prcp_fac=2.5,
                    grad_type=grad_type)
    gd_mb.historical_climate_qc_mod(gd)

    return gd_mb, ref_df, h, w, max_allowed_specificMB
예제 #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_hydro_years_HEF(gdir):
    # only very basic test, the other stuff is done in oggm man basis
    # test if it also works for hydro_month ==1, necessary for geodetic mb
    # if hydro_month ==1, and msm start in 1979, then hydro_year should also
    # be 1979, this works only with the newest OGGM dev version...
    cfg.PARAMS['hydro_month_nh'] = 1

    h, w = gdir.get_inversion_flowline_hw()
    cfg.PARAMS['baseline_climate'] = 'ERA5dr'
    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset='ERA5dr')
    f = gdir.get_filepath('climate_historical', filesuffix='')
    test_climate = xr.open_dataset(f)
    assert test_climate.time[0] == np.datetime64('1979-01-01')
    assert test_climate.time[-1] == np.datetime64('2018-12-01')

    # now test it for ERA5_daily
    cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
    process_era5_daily_data(gdir)
    f = gdir.get_filepath('climate_historical', filesuffix='_daily')
    test_climate = xr.open_dataset(f)
    assert test_climate.time[0] == np.datetime64('1979-01-01')
    assert test_climate.time[-1] == np.datetime64('2018-12-31')
    def test_process_era5_daily_data(self, gdir):
        process_era5_daily_data(gdir, y0=1979, y1=2018)

        fs = '_daily_ERA5'
        fpath = gdir.get_filepath('climate_historical', filesuffix=fs)

        # check the climate files of an individual glacier (Hintereisferner)
        xr_nc = xr.open_dataset(fpath)
        assert np.all(xr_nc.prcp) >= 0
        # daily precipitation amount in kg m-2  (not in kg m-2 s-1)
        assert xr_nc.prcp.max() > 1
        # to be sure that there are no erroneaous filling values inside
        assert np.all(xr_nc.prcp) < 10000
        # temperature values are in °C and in the right range
        assert np.all(xr_nc.temp) > -100
        assert np.all(xr_nc.temp) < 100

        # temperature gradient should be in the following range
        assert np.all(xr_nc.gradient > -0.015)
        assert np.all(xr_nc.gradient < -0.002)

        # all lapse rates/ precipitation values in one month should be equal
        # because only temperature is on daily basis
        np.testing.assert_allclose(xr_nc.resample(time='1M').std().prcp,
                                   0, atol=1e-3)
        np.testing.assert_allclose(xr_nc.resample(time='1M').std().gradient,
                                   0, atol=1e-3)

        # summed up monthly precipitation from daily dataset
        xr_nc_prcp_m = xr_nc.prcp.resample(time='1M').sum()

        oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5",
                                           y0=1979, y1=2018)
        filename = 'climate_historical'

        fpath = gdir.get_filepath(filename)
        xr_nc_monthly = xr.open_dataset(fpath)

        # check if summed up monthly precipitation from daily
        # dataset equals approx. to the ERA5 monthly prcp
        np.testing.assert_allclose(xr_nc_prcp_m.values,
                                   xr_nc_monthly.prcp.values, rtol=1e-4)

        xr_nc_temp_m = xr_nc.temp.resample(time='1M').mean()
        # check if mean temperature from daily dataset equals
        # approx. to the ERA5 monthly temp.
        np.testing.assert_allclose(xr_nc_temp_m.values,
                                   xr_nc_monthly.temp.values, atol=0.05)

        with pytest.raises(InvalidParamsError):
            # dataset only goes from 1979--2018
            process_era5_daily_data(gdir, y0=1979, y1=2019)

            # in cfg.PARAMS that is initiated during testing,
            # cfg.PARAMS[hydro_month_nh = 10], this is in conflict with 8
            process_era5_daily_data(gdir, y0=1979, y1=2018, hydro_month_nh=8)
예제 #6
0
            gdirs = workflow.init_glacier_directories(
                pd_geodetic_comp_alps.dropna().index[start_ind:end_ind].values,
                from_prepro_level=2,
                prepro_border=10,
                prepro_base_url=base_url,
                prepro_rgi_version='62')

            if mb_type != 'mb_real_daily':
                cfg.PARAMS['baseline_climate'] = 'ERA5dr'
                workflow.execute_entity_task(tasks.process_ecmwf_data,
                                             gdirs,
                                             dataset='ERA5dr')
            else:
                cfg.PARAMS['baseline_climate'] = 'ERA5_daily'
                for gd in pd_geodetic_comp_alps.index[start_ind:end_ind]:
                    process_era5_daily_data(gd)

        elif compute_missing:
            #raise NotImplementedError('this has to be adapted')
            path_samples = '/home/users/lschuster/bayesian_calibration/WFDE5_ISIMIP/burned_trace_plus200samples/'
            miss_samples = {}
            exist_samples = {}
            typ = '{}_{}'.format(mb_type, grad_type)
            miss_samples[typ] = []
            exist_samples[typ] = []

            geod_ind = pd_geodetic_comp_alps.dropna().index
            path_dir = '/home/users/lschuster/oggm_files/all/per_glacier/RGI60-11/'
            for t in os.listdir(path_dir):
                path_t = path_dir + t + '/'
                for rgi_id in os.listdir(path_t):
    def test_all_at_once(self, gdir):

        # Init
        exps = ['CRU', 'HISTALP', 'ERA5', 'ERA5L', 'CERA',
                'ERA5_daily', 'WFDE5_CRU_daily', 'W5E5_daily',
                'WFDE5_CRU_monthly', 'W5E5_monthly']
        ref_hgts = []
        dft = []
        dfp = []
        for base in exps:
            if base not in ['ERA5_daily', 'WFDE5_CRU_daily',
                            'W5E5_daily',
                            'WFDE5_CRU_monthly', 'W5E5_monthly']:
                cfg.PARAMS['baseline_climate'] = base
                tasks.process_climate_data(gdir, output_filesuffix=base)
            elif base == 'ERA5_daily':
                cfg.PARAMS['baseline_climate'] = base
                process_era5_daily_data(gdir, output_filesuffix=base)
            elif base == 'WFDE5_CRU_daily' or base == 'W5E5_daily':
                process_w5e5_data(gdir, output_filesuffix=base,
                                   temporal_resol='daily')
            elif '_monthly' in base:
                # wfde5_cru and w5e5
                process_w5e5_data(gdir, output_filesuffix=base,
                                  temporal_resol='monthly')
            f = gdir.get_filepath('climate_historical',
                                   filesuffix=base)

            with xr.open_dataset(f) as ds:
                ref_hgts.append(ds.ref_hgt)
                assert ds.ref_pix_dis < 30000
                dft.append(ds.temp.to_series())
                dfp.append(ds.prcp.to_series())
        dft = pd.concat(dft, axis=1, keys=exps)
        dfp = pd.concat(dfp, axis=1, keys=exps)

        # compare daily mean temperatures of ERA5 and WFDE5
        assert dft[['ERA5_daily', 'WFDE5_CRU_daily']].corr().min().min() > 0.95
        assert dft[['W5E5_daily', 'WFDE5_CRU_daily']].corr().min().min() > 0.95

        # want to compare mean monthly temperatures
        # (daily resolution datasets have to be resampled)
        dft = dft.resample('MS').mean()
        print(dft)
        # Common period
        #dft = dft.resample(time='1M').mean()
        dfy = dft.resample('AS').mean().dropna().iloc[1:]
        dfm = dft.groupby(dft.index.month).mean()
        assert dfy.corr().min().min() > 0.44  # ERA5L and CERA do not correlate
        assert dfm.corr().min().min() > 0.97
        dfavg = dfy.describe()

        # Correct for hgt
        ref_h = ref_hgts[0]
        for h, d in zip(ref_hgts, exps):
            dfy[d] = dfy[d] - 0.0065 * (ref_h - h)
            dfm[d] = dfm[d] - 0.0065 * (ref_h - h)
        dfavg_cor = dfy.describe()

        # After correction less spread
        assert dfavg_cor.loc['mean'].std() < 0.8 * dfavg.loc['mean'].std()
        print(dfavg_cor)
        # with ERA5_daily and WFDE5_daily, smaller std (from <2.1 -> <1.7)
        assert dfavg_cor.loc['mean'].std() < 1.7

        # PRECIP
        # want to compare summed up monthly precipitation
        # (daily resolution datasets, so far only wfde5, have to resample)
        dfp = dfp.resample('MS').sum(min_count =1)
        # Common period
        dfy = dfp.resample('AS').mean().dropna().iloc[1:] * 12
        dfm = dfp.groupby(dfp.index.month).mean()
        assert dfy.corr().min().min() > 0.5
        # monthly prcp of WFDE5 is quite different > 0.8 -> > 0.75
        assert dfm.corr().min().min() > 0.73  # 0.8
        dfavg = dfy.describe()
        assert dfavg.loc['mean'].std() / dfavg.loc['mean'].mean() < 0.28  # %
    def test_process_w5e5_data(self, gdir):

        # first with daily resolution
        cfg.PARAMS['hydro_month_nh'] = 1
        process_w5e5_data(gdir, y0=1979, y1=2019, temporal_resol='daily',
                          climate_type='W5E5')
        process_w5e5_data(gdir, y0=1979, y1=2018, temporal_resol='daily',
                          climate_type='WFDE5_CRU')


        filename = 'climate_historical'
        fpath = gdir.get_filepath(filename, filesuffix='_daily_WFDE5_CRU')
        # check the climate files of an individual glacier (Hintereisferner)
        xr_nc = xr.open_dataset(fpath)
        fpath_w5e5 = gdir.get_filepath(filename, filesuffix='_daily_W5E5')
        # check the climate files of an individual glacier (Hintereisferner)
        xr_nc_w5e5 = xr.open_dataset(fpath_w5e5)

        assert np.all(xr_nc.prcp) >= 0
        assert np.all(xr_nc_w5e5.prcp) >= 0

        # daily precipitation amount in kg m-2  (not in kg m-2 s-1)
        assert xr_nc.prcp.max() > 1
        assert xr_nc_w5e5.prcp.max() > 1
        # to be sure that there are no erroneous filling values inside
        assert np.all(xr_nc.prcp) < 10000
        assert np.all(xr_nc_w5e5.prcp) < 10000
        # temperature values are in °C and in the right range
        assert np.all(xr_nc.temp) > -100
        assert np.all(xr_nc.temp) < 100
        assert np.all(xr_nc_w5e5.temp) > -100
        assert np.all(xr_nc_w5e5.temp) < 100
        # temperature gradient should be in the following range
        assert np.all(xr_nc.gradient > -0.015)
        assert np.all(xr_nc.gradient < -0.002)
        assert np.all(xr_nc_w5e5.gradient > -0.015)
        assert np.all(xr_nc_w5e5.gradient < -0.002)

        # all lapse rates values in one month should be equal
        # because only temperature and prcp is on daily basis
        #np.testing.assert_allclose(xr_nc.resample(time='1M').std().prcp,
        #                           0, atol=1e-3)
        np.testing.assert_allclose(xr_nc.resample(time='MS').std().gradient,
                                   0, atol=1e-3)
        np.testing.assert_allclose(xr_nc_w5e5.resample(time='MS').std().gradient,
                                   0, atol=1e-3)

        # summed up monthly precipitation from daily dataset
        xr_nc_prcp_m = xr_nc.prcp.resample(time='MS').sum()
        xr_nc_prcp_m_w5e5 = xr_nc_w5e5.prcp.resample(time='MS').sum()


        oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5",
                                           y0=1979, y1=2018)
        filename = 'climate_historical'
        fpath = gdir.get_filepath(filename)
        xr_nc_monthly_ERA5 = xr.open_dataset(fpath)

        # check if summed up monthly precipitation from daily
        # dataset equals approx to the WFDE5 monthly prcp
        # first with daily resolution
        process_w5e5_data(gdir, y0=1979, y1=2018, temporal_resol='monthly',
                           climate_type='WFDE5_CRU')
        process_w5e5_data(gdir, y0=1979, y1=2019, temporal_resol='monthly',
                          climate_type='W5E5')
        # an output filesuffix is needed, otherwise the
        # ERA5 dataset from above is used as it has the same name ...
        fpath_monthly = gdir.get_filepath(filename,
                                          filesuffix='_monthly_WFDE5_CRU')
        xr_nc_monthly = xr.open_dataset(fpath_monthly)
        fpath_monthly = gdir.get_filepath(filename,
                                          filesuffix='_monthly_W5E5')
        xr_nc_monthly_W5E5 = xr.open_dataset(fpath_monthly)
        assert np.all(xr_nc_monthly.prcp) > 0
        assert np.all(xr_nc_monthly_W5E5.prcp) > 0
        assert xr_nc_monthly.prcp.max() > 1
        assert xr_nc_monthly_W5E5.prcp.max() > 1
        # to be sure that there are no erroneous filling values inside
        assert np.all(xr_nc_monthly.prcp) < 10000
        assert np.all(xr_nc_monthly_W5E5) < 10000
        # temperature values are in °C and in the right range
        assert np.all(xr_nc_monthly.temp) > -100
        assert np.all(xr_nc_monthly.temp) < 100
        assert np.all(xr_nc_monthly_W5E5.temp) > -100
        assert np.all(xr_nc_monthly_W5E5.temp) < 100
        # temperature gradient should be in the following range
        assert np.all(xr_nc_monthly.gradient > -0.015)
        assert np.all(xr_nc_monthly.gradient < -0.002)
        assert np.all(xr_nc_monthly_W5E5.gradient > -0.015)
        assert np.all(xr_nc_monthly_W5E5.gradient < -0.002)
        assert_allclose(xr_nc_prcp_m.values,
                        xr_nc_monthly.prcp.values, rtol=1e-4)
        assert_allclose(xr_nc_prcp_m_w5e5.values,
                        xr_nc_monthly_W5E5.prcp.values,
                        rtol=1e-4)
        # check if summed up monthly precipitation from daily
        # dataset correlate for prpc ...
        assert np.corrcoef(xr_nc_prcp_m.values,
                           xr_nc_monthly_ERA5.prcp.values)[0][1] > 0.75
        xr_nc_prcp_m_w5e5 = xr_nc_prcp_m_w5e5.sel(time=slice('1979', '2018'))
        assert np.corrcoef(xr_nc_prcp_m.values,
                           xr_nc_prcp_m_w5e5)[0][1] > 0.75
        #np.testing.assert_allclose(xr_nc_prcp_m.values,
        #                           xr_nc_monthly.prcp.values, rtol=1e-4)

        xr_nc_temp_m = xr_nc.temp.resample(time='MS').mean()
        xr_nc_temp_m_w5e5 = xr_nc_w5e5.temp.resample(time='MS').mean()

        # check if mean temperature from daily dataset equals
        # approx. the WFDE5 monthly temp.
        assert_allclose(xr_nc_temp_m.values,
                        xr_nc_monthly.temp.values, atol=1e-4)
        assert_allclose(xr_nc_temp_m_w5e5.values,
                        xr_nc_monthly_W5E5.temp.values, atol=1e-4)

        # check if mean temperature from daily dataset equals
        # approx. to the ERA5 monthly temp.
        assert np.corrcoef(xr_nc_monthly_ERA5.temp.values,
                           xr_nc_temp_m.values)[0][1] > 0.75
        xr_nc_temp_m = xr_nc_temp_m.sel(time=slice('1979', '2018'))
        assert np.corrcoef(xr_nc_monthly_ERA5.temp.values,
                           xr_nc_temp_m.values)[0][1] > 0.75
        with pytest.raises(InvalidParamsError):
            # dataset only goes from 1979--2018
            process_era5_daily_data(gdir, y0=1979, y1=2019)

            # in cfg.PARAMS that is initiated during testing,
            # cfg.PARAMS[hydro_month_nh = 1], this is in conflict with 8
            process_era5_daily_data(gdir, y0=1979, y1=2018, hydro_month_nh=8)
예제 #9
0
def test_process_era5_daily_data():

    cfg.initialize()
    test_dir = '/home/lilianschuster/Schreibtisch/PhD/oggm_files/tests'
    if not os.path.exists(test_dir):
        test_dir = utils.gettempdir(dirname='OGGM_era5_daily_test', reset=True)
    cfg.PATHS['working_dir'] = test_dir
    b_url_ = 'https://cluster.klima.uni-bremen.de/~fmaussion'
    base_url = b_url_ + '/gdirs/prepro_l2_202010/elevbands_fl_with_consensus'

    df = utils.get_rgi_glacier_entities(['RGI60-11.00897'])
    gdirs = workflow.init_glacier_directories(df,
                                              from_prepro_level=2,
                                              prepro_border=40,
                                              prepro_base_url=base_url,
                                              prepro_rgi_version='62')
    gdir = gdirs[0]

    process_era5_daily_data(gdir, y0=1979, y1=2018)

    filename = 'climate_historical_daily'
    fpath = gdir.get_filepath(filename)

    # check the climate files of an individual glacier (Hintereisferner)
    xr_nc = xr.open_dataset(fpath)
    assert np.all(xr_nc.prcp) > 0
    # to be sure that there are no erroneaous filling values inside
    assert np.all(xr_nc.prcp) < 10000
    # temperature values are in °C and in the right range
    assert np.all(xr_nc.temp) > -100
    assert np.all(xr_nc.temp) < 100

    # temperature gradient should be in the following range
    assert np.all(xr_nc.gradient > -0.015)
    assert np.all(xr_nc.gradient < -0.002)

    # all lapse rates/ precipitation values in one month should be equal
    # because only temperature is on daily basis
    np.testing.assert_allclose(xr_nc.resample(time='1M').std().prcp,
                               0,
                               atol=1e-3)
    np.testing.assert_allclose(xr_nc.resample(time='1M').std().gradient,
                               0,
                               atol=1e-3)

    # summed up monthly precipitation from daily dataset
    xr_nc_prcp_m = xr_nc.prcp.resample(time='1M').sum()

    oggm.shop.ecmwf.process_ecmwf_data(gdir, dataset="ERA5", y0=1979, y1=2018)
    filename = 'climate_historical'

    fpath = gdir.get_filepath(filename)
    xr_nc_monthly = xr.open_dataset(fpath)

    # check if summed up monthly precipitation from daily
    # dataset equals approx. to the ERA5 monthly prcp
    np.testing.assert_allclose(xr_nc_prcp_m.values,
                               xr_nc_monthly.prcp.values,
                               rtol=1e-4)

    xr_nc_temp_m = xr_nc.temp.resample(time='1M').mean()
    # check if mean temperature from daily dataset equals
    # approx. to the ERA5 monthly temp.
    np.testing.assert_allclose(xr_nc_temp_m.values,
                               xr_nc_monthly.temp.values,
                               atol=0.05)

    with pytest.raises(InvalidParamsError):
        # dataset only goes from 1979--2018
        process_era5_daily_data(gdir, y0=1979, y1=2019)

        # in cfg.PARAMS that is initiated during testing,
        # cfg.PARAMS[hydro_month_nh = 10], this is in conflict with 8
        process_era5_daily_data(gdir, y0=1979, y1=2018, hydro_month_nh=8)
def get_opt_pf_melt_f(gd,
                      mb_type='mb_monthly',
                      grad_type='cte',
                      pd_calib_opt=None,
                      pd_geodetic=None,
                      dataset='ERA5'):
    if type(pd_calib_opt) == pd.core.frame.DataFrame:
        pass
    else:
        pd_calib_opt = pd.DataFrame(columns=[
            'pf_opt',
            'melt_f_opt_pf',
            'mb_geodetic',
            'mb_geodetic_err',
            'mb_glaciological_mean',
            'mb_glaciological_std',
            'stats_calib',  # 'stats_valid',
            'amount_glacmsm',
            # 'glacmsm_after_2000', 'glacmsm_before_2000',
            'temp std',
            'temp for melt std (mean)',
            'tempfmelt_std_quot_hdiff',
            'prcp std',
            'solid prcp std (mean)',
            'prcpsols_std_hstd',
            'prcp std valid',
            'solid prcp std valid',
            'prcp mean',
            'solid prcp mean',
            'temp mean',
            'temp for melt mean',
            'prcp mean nopf',
            'prcp mean nopf weighted',
            'solid prcp mean nopf',
            'solid prcp mean nopf weighted',
            'solid prcp std nopf'
        ])
        pd_calib_opt.loc[gd.rgi_id] = np.NaN
    if mb_type != 'mb_real_daily':
        if dataset == 'ERA5':
            baseline_climate = 'ERA5dr'
            oggm.shop.ecmwf.process_ecmwf_data(gd, dataset='ERA5dr')
            input_fs = ''

        elif dataset == 'WFDE5_CRU_monthly':
            baseline_climate = 'WFDE5_CRU'
            process_w5e5_data(gd,
                              climate_type=baseline_climate,
                              temporal_resol='monthly')
            input_fs = '_monthly_WFDE5_CRU'
    elif mb_type == 'mb_real_daily':
        if dataset == 'ERA5':
            baseline_climate = 'ERA5dr'
            process_era5_daily_data(gd)
            input_fs = ''
        elif dataset == 'WFDE5_CRU_monthly':
            baseline_climate = 'WFDE5_CRU'
            process_w5e5_data(gd,
                              climate_type=baseline_climate,
                              temporal_resol='daily')
            input_fs = '_daily_WFDE5_CRU'

    mbdf = gd.get_ref_mb_data(input_filesuffix=input_fs)
    mb_glaciological = mbdf['ANNUAL_BALANCE']
    ys_glac = mbdf.index.values
    # print(ys_glac)
    gd_mb = TIModel(gd,
                    None,
                    mb_type=mb_type,
                    N=100,
                    prcp_fac=2.5,
                    grad_type=grad_type,
                    baseline_climate=baseline_climate)
    gd_mb.historical_climate_qc_mod(gd)

    h, w = gd.get_inversion_flowline_hw()
    mb_geodetic = pd_geodetic.loc[gd.rgi_id].dmdtda * 1000
    mb_geodetic_err = pd_geodetic.loc[gd.rgi_id].err_dmdtda * 1000

    if len(ys_glac) > 1:
        try:
            pf_opt = scipy.optimize.brentq(optimize_std_quot_brentq_geod,
                                           0.01,
                                           20,
                                           xtol=0.01,
                                           args=(gd_mb, mb_geodetic,
                                                 mb_glaciological, h, w,
                                                 ys_glac),
                                           disp=True)
        except ValueError:  # (' f(a) and f(b) must have different signs'):
            print('{}: try out with 0.1 and 10 as pf boundaries'.format(
                gd.rgi_id))
            try:
                pf_opt = scipy.optimize.brentq(optimize_std_quot_brentq_geod,
                                               0.1,
                                               10,
                                               xtol=0.01,
                                               args=(gd_mb, mb_geodetic,
                                                     mb_glaciological, h, w,
                                                     ys_glac),
                                               disp=True)
            except ValueError:  # (' f(a) and f(b) must have different signs'):
                print('{}: try out with 0.5 and 3 as pf boundaries'.format(
                    gd.rgi_id))
                # try:
                pf_opt = scipy.optimize.brentq(optimize_std_quot_brentq_geod,
                                               0.5,
                                               3,
                                               xtol=0.01,
                                               args=(gd_mb, mb_geodetic,
                                                     mb_glaciological, h, w,
                                                     ys_glac),
                                               disp=True)
                # except:
                #    pf_opt = 2.5

        melt_f_opt_pf = scipy.optimize.brentq(minimize_bias_geodetic,
                                              1,
                                              10000,
                                              xtol=0.01,
                                              args=(gd_mb, mb_geodetic, h, w,
                                                    pf_opt),
                                              disp=True)
        gd_mb.melt_f = melt_f_opt_pf
        gd_mb.prcp_fac = pf_opt
        mb_specific_optstd = gd_mb.get_specific_mb(heights=h,
                                                   widths=w,
                                                   year=ys_glac)

        stats_calib = compute_stat(mb_specific=mb_specific_optstd,
                                   mbdf=mbdf,
                                   return_dict=True)

        cs = [
            'pf_opt',
            'melt_f_opt_pf',
            'mb_geodetic',
            'mb_geodetic_err',
            'mb_glaciological_mean',
            'mb_glaciological_std',
            'stats_calib',  # 'stats_valid',
            'amount_glacmsm'
        ]
        var = [
            pf_opt,
            melt_f_opt_pf,
            mb_geodetic,
            mb_geodetic_err,
            mb_glaciological.mean(),
            mb_glaciological.std(),
            str(stats_calib),  # str(stats_valid),
            len(ys_glac)
        ]
        # len(ys_glac[ys_glac < 2000])]
        for c, v in zip(cs, var):
            # print(c, v)
            pd_calib_opt.loc[gd.rgi_id, c] = v
        pd_calib_opt.loc[gd.rgi_id, 'optimisation_possible'] = True

        ### understand which glaciers need a high pf_opt as
        # they have a high mb_glaciological_std
        gd_mb.prcp_fac = 1
        prcps_nofac = pd.DataFrame()
        prcpsols_nofac = pd.DataFrame()
        # I take only those years where measurements are available!!!!
        for y in ys_glac:
            t, tfmelt, prcp, prcpsol = gd_mb.get_annual_climate(h, year=y)
            prcps_nofac[y] = prcp
            prcpsols_nofac[y] = prcpsol
        prcp_mean_nopf = prcps_nofac.mean(axis=1).mean()
        prcp_mean_nopf_weight = (prcps_nofac.mean(axis=1) *
                                 w).mean() / w.mean()
        solid_prcp_mean_nopf = prcpsols_nofac.mean(axis=1).mean()
        solid_prcp_mean_nopf_weight = (prcpsols_nofac.mean(axis=1) *
                                       w).mean() / w.mean()
        prcpsols_std_nopf = prcpsols_nofac.std(axis=1).mean()

        # back to calibrated value
        gd_mb.prcp_fac = pf_opt

        # other climate data
        ts = pd.DataFrame()
        tfmelts = pd.DataFrame()
        prcps = pd.DataFrame()
        prcpsols = pd.DataFrame()
        # I take only those years where measurements are available!!!!
        for y in ys_glac:
            t, tfmelt, prcp, prcpsol = gd_mb.get_annual_climate(h, year=y)
            ts[y] = t
            tfmelts[y] = tfmelt
            prcps[y] = prcp
            prcpsols[y] = prcpsol
        # ts.index = h
        ts_std = ts.std(
            axis=1).mean()  # this is everywhere the same because of lapse rate
        ts_mean = ts.mean(
            axis=1).mean()  # this is everywhere the same because of lapse rate
        prcp_mean = prcps.mean(axis=1).mean()
        solid_prcp_mean = prcpsols.mean(axis=1).mean()
        tfmelts_std = tfmelts.std(axis=1).mean()
        tfmelts_mean = tfmelts.mean(axis=1).mean()
        tfmelts_std_quot_hdiff = tfmelts.std(axis=1).iloc[0] / \
                                 tfmelts.std(axis=1).iloc[-1]
        # this is everywhere the same because no prcp changes with height!
        prcps_std = prcps.std(axis=1).mean()

        # print(prcp_mean)
        # this changes with height
        prcpsols_std = prcpsols.std(axis=1).mean()
        prcpsols_std_hstd = prcpsols.std(axis=1).std()

        var = [
            ts_std, tfmelts_std, tfmelts_std_quot_hdiff, prcps_std,
            prcpsols_std, prcpsols_std_hstd, prcp_mean, solid_prcp_mean,
            ts_mean, tfmelts_mean, prcp_mean_nopf, prcp_mean_nopf_weight,
            solid_prcp_mean_nopf, solid_prcp_mean_nopf_weight,
            prcpsols_std_nopf
        ]
        cs = [
            'temp std', 'temp for melt std (mean)', 'tempfmelt_std_quot_hdiff',
            'prcp std', 'solid prcp std (mean)', 'prcpsols_std_hstd',
            'prcp mean', 'solid prcp mean', 'temp mean', 'temp for melt mean',
            'prcp mean nopf', 'prcp mean nopf weighted',
            'solid prcp mean nopf', 'solid prcp mean nopf weighted',
            'solid prcp std nopf'
        ]
        for c, v in zip(cs, var):
            pd_calib_opt.loc[gd.rgi_id, c] = v
        ###

        # validation: no validation right no
        pd_calib_opt.loc[gd.rgi_id, 'prcp std valid'] = np.NaN
        pd_calib_opt.loc[gd.rgi_id, 'solid prcp std valid'] = np.NaN

    else:
        pd_calib_opt.loc[gd.rgi_id] = np.NaN
        pd_calib_opt.loc[gd.rgi_id, 'amount_glacmsm'] = len(ys_glac)
        pd_calib_opt.loc[gd.rgi_id,
                         'optimisation_possible'] = 'only 1 or less msm>=1979'

    return pd_calib_opt, gd_mb
예제 #11
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)
예제 #12
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