Ejemplo n.º 1
0
 def track_mb_1980_avg(self, gdir):
     self.cfg_init()
     mb = massbalance.PastMassBalance(gdir)
     h, w = gdir.get_inversion_flowline_hw()
     mb_ts = mb.get_specific_mb(heights=h, widths=w,
                                year=np.arange(31)+1970)
     return np.mean(mb_ts)
Ejemplo n.º 2
0
def iterative_initial_glacier_search(gdir, y0=None, init_bias=0., rtol=0.005,
                                     write_steps=True):
    """Iterative search for the glacier in year y0.

    this is outdated and doesn't really work.
    """

    fs = cfg.PARAMS['fs']
    glen_a = cfg.PARAMS['glen_a']

    if y0 is None:
        y0 = cfg.PARAMS['y0']
    y1 = gdir.rgi_date.year
    mb = mbmods.PastMassBalance(gdir)
    fls = gdir.read_pickle('model_flowlines')

    model = FluxBasedModel(fls, mb_model=mb, y0=0., fs=fs, glen_a=glen_a)
    assert np.isclose(model.area_km2, gdir.rgi_area_km2, rtol=0.05)

    mb = mbmods.BackwardsMassBalanceModel(gdir)
    ref_area = gdir.rgi_area_m2
    ite, bias, past_model = _find_inital_glacier(model, mb, y0, y1,
                                                 rtol=rtol,
                                                 init_bias=init_bias,
                                                 ref_area=ref_area)

    path = gdir.get_filepath('model_run', delete=True)
    if write_steps:
        past_model.run_until_and_store(y1, path=path)
    else:
        past_model.to_netcdf(path)
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    def test_specific_mb(self):
        """Compare the specific mass balance to the one computed
        using the OGGM function of the PastMassBalance model.
        """

        # run all needed prepro tasks
        gdir = self._setup_mb_test()

        # instance mb models
        vas_mbmod = vascaling.VAScalingMassBalance(gdir)
        past_mbmod = massbalance.PastMassBalance(gdir)

        # get relevant glacier surface elevation
        min_hgt, max_hgt = vascaling.get_min_max_elevation(gdir)

        # define temporal range
        ys = 1802
        ye = 2003
        years = np.arange(ys, ye + 1)

        # get flow lines
        fls = gdir.read_pickle('inversion_flowlines')

        # create empty container
        past_mb = np.empty(years.size)
        vas_mb = np.empty(years.size)
        # get specific mass balance for all years
        for i, year in enumerate(years):
            past_mb[i] = past_mbmod.get_specific_mb(fls=fls, year=year)
            vas_mb[i] = vas_mbmod.get_specific_mb(min_hgt, max_hgt, year)

        # compute and check correlation
        assert corrcoef(past_mb, vas_mb) >= 0.94

        # relative error of average spec mb
        # TODO: does this even make any sense?!
        assert np.abs(rel_err(past_mb.mean(), vas_mb.mean())) <= 0.36

        # check correlation of positive and negative mb years
        assert corrcoef(np.sign(past_mb), np.sign(vas_mb)) >= 0.72

        # compare to reference mb measurements
        mbs = gdir.get_ref_mb_data()['ANNUAL_BALANCE']
        assert corrcoef(vas_mb[np.in1d(years, mbs.index)], mbs) >= 0.79
Ejemplo n.º 5
0
    def test_annual_climate(self):
        """Test my routine against the corresponding OGGM routine from
        the `PastMassBalance()` model.
        """

        # run all needed prepro tasks
        gdir = self._setup_mb_test()

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

        # get relevant glacier surface elevation
        min_hgt, max_hgt = vascaling.get_min_max_elevation(gdir)
        heights = np.array([min_hgt, (min_hgt + max_hgt) / 2, max_hgt])

        # specify an (arbitray) year
        year = 1975
        # get mass balance relevant climate information
        temp_for_melt_vas, prcp_solid_vas = \
            vas_mbmod.get_annual_climate(min_hgt, max_hgt, year)
        _, temp_for_melt_oggm, _, prcp_solid_oggm = \
            past_mbmod.get_annual_climate(heights, year)

        # prepare my (monthly) values for comparison
        temp_for_melt_vas = temp_for_melt_vas.sum()
        prcp_solid_vas = prcp_solid_vas.sum()

        # computed positive terminus melting temperature must be equal for both
        # used methods, i.e. temp_VAS == temp_OGGM
        np.testing.assert_allclose(temp_for_melt_vas,
                                   temp_for_melt_oggm[0],
                                   rtol=1e-3)

        # glacier averaged solid precipitation amount must be greater than (or
        # equal to) solid precipitation amount at glacier terminus elevation
        assert md(prcp_solid_oggm[0], prcp_solid_vas) >= 0
        # glacier averaged solid precipitation amount must be comparable to the
        # solid precipitation amount at average glacier surface elevation
        assert rel_err(prcp_solid_oggm[1], prcp_solid_vas) <= 0.15
        # glacier averaged solid precipitation amount must be less than (or
        # equal to) solid precipitation amount at maximum glacier elevation
        assert md(prcp_solid_oggm[2], prcp_solid_vas) <= 0
Ejemplo n.º 6
0
    def test_hydro_month_changes(self, hef_gdir):
        # test for HEF if applying different hydro_months does the right thing
        # check if mb of neighbouring hydro_months correlate
        # do this for different climate scenarios

        # maybe there is already somewhere an overview or a better way to get
        # these dates, but I did not find it
        base_data_time = {
            'CRU': {
                'start_year': 1901,
                'end_year': 2014
            },
            'ERA5': {
                'start_year': 1979,
                'end_year': 2018
            },
            'ERA5dr': {
                'start_year': 1979,
                'end_year': 2019
            },
            'HISTALP': {
                'start_year': 1850,
                'end_year': 2014
            },
            'CERA': {
                'start_year': 1901,
                'end_year': 2010
            },
            'ERA5L': {
                'start_year': 1981,
                'end_year': 2018
            }
        }

        gdir = hef_gdir
        oggm.core.flowline.init_present_time_glacier(gdir)
        mb_mod = oggm.core.massbalance.PastMassBalance(gdir)
        h, w = gdir.get_inversion_flowline_hw()

        exps = ['ERA5dr', 'CRU', 'HISTALP', 'ERA5', 'ERA5L', 'CERA']
        for base in exps:
            # this does not need to be the best one,
            # just for comparison between different hydro months
            mu_opt = 213.54

            files = []
            ref_hgts = []
            dft = []
            dfp = []
            tot_mbs = []
            cfg.PARAMS['baseline_climate'] = base

            for m in np.arange(1, 13):
                cfg.PARAMS['hydro_month_nh'] = m
                fsuff = '_{}_{}'.format(base, m)
                tasks.process_climate_data(gdir, output_filesuffix=fsuff)
                files.append(
                    gdir.get_filepath('climate_historical', filesuffix=fsuff))

                with xr.open_dataset(files[-1]) as ds:
                    ref_hgts.append(ds.ref_hgt)
                    dft.append(ds.temp.to_series())
                    dfp.append(ds.prcp.to_series())

                    ci = gdir.get_climate_info(input_filesuffix=fsuff)

                    # check if the right climate source is used
                    assert base in ci['baseline_climate_source']
                    mm = str(m) if m > 9 else str(0) + str(m)
                    mm_e = str(m - 1) if (m - 1) > 9 else str(0) + str(m - 1)
                    b_s_y = base_data_time[base]['start_year']
                    b_e_y = base_data_time[base]['end_year']

                    stime = '{}-{}-01'.format(b_s_y, mm)
                    assert ds.time[0] == np.datetime64(stime)
                    if m == 1:
                        assert ci['baseline_hydro_yr_0'] == b_s_y
                        if base == 'ERA5dr':
                            # do not have full 2019
                            assert ci['baseline_hydro_yr_1'] == b_e_y - 1
                        else:
                            assert ci['baseline_hydro_yr_1'] == b_e_y

                    elif m < 7 and base == 'ERA5dr':
                        # have data till 2019-05 for ERA5dr
                        stime = '{}-{}-01'.format(b_e_y, mm_e)
                        assert ds.time[-1] == np.datetime64(stime)
                        assert ci['baseline_hydro_yr_0'] == b_s_y + 1
                        assert ci['baseline_hydro_yr_1'] == b_e_y

                    else:
                        assert ci['baseline_hydro_yr_0'] == b_s_y + 1
                        if base == 'ERA5dr':
                            # do not have full 2019
                            stime = '{}-{}-01'.format(b_e_y - 1, mm_e)
                            assert ds.time[-1] == np.datetime64(stime)
                            assert ci['baseline_hydro_yr_1'] == b_e_y - 1
                        else:
                            assert ci['baseline_hydro_yr_1'] == b_e_y
                            stime = '{}-{}-01'.format(b_e_y, mm_e)
                            assert ds.time[-1] == np.datetime64(stime)

                    mb_mod = massbalance.PastMassBalance(
                        gdir,
                        mu_star=mu_opt,
                        input_filesuffix=fsuff,
                        bias=0,
                        check_calib_params=False)

                    years = np.arange(ds.hydro_yr_0, ds.hydro_yr_1 + 1)
                    mb_ts = mb_mod.get_specific_mb(heights=h,
                                                   widths=w,
                                                   year=years)
                    tot_mbs.append(pd.Series(mb_ts))

            # check if all ref_hgts are equal
            # means that we likely compare same glacier and climate dataset
            assert len(np.unique(ref_hgts)) == 1
            # concatenate temperature and prcp from different hydromonths
            dft = pd.concat(dft, axis=1, keys=np.arange(1, 13))
            dfp = pd.concat(dfp, axis=1, keys=np.arange(1, 13))
            # Common period
            dft_na = dft.dropna().iloc[1:]
            dfp_na = dfp.dropna().iloc[1:]

            # check if the common period of temperature prcp
            # series is equal for all starting hydromonth dates
            assert np.all(dft_na.eq(dft_na.iloc[:, 0], axis=0).all(1))
            assert np.all(dfp_na.eq(dfp_na.iloc[:, 0], axis=0).all(1))

            # mass balance of different years
            pd_tot_mbs = pd.concat(tot_mbs, axis=1, keys=np.arange(1, 13))
            pd_tot_mbs = pd_tot_mbs.dropna()

            # compute correlations
            corrs = []
            for m in np.arange(1, 12):
                # check if correlation between time series of hydro_month =1,
                # is high to hydro_month = 2 and so on
                corrs.append(pd_tot_mbs.corr().loc[m, m + 1])
                # would be better if for hydro_month=12,
                # correlation is tested to next year
            assert np.mean(corrs) > 0.9
Ejemplo n.º 7
0
def time_get_ela():

    mb_mod = massbalance.PastMassBalance(gdir, bias=0)
    mb_mod.get_ela(year=years)
Ejemplo n.º 8
0
def time_PastMassBalance():

    mb_mod = massbalance.PastMassBalance(gdir, bias=0)
    for yr in years:
        mb_mod.get_annual_mb(heights, year=yr)
Ejemplo n.º 9
0
 def track_mb_1870_sigma(self, gdir):
     self.cfg_init()
     mb = massbalance.PastMassBalance(gdir)
     h, w = gdir.get_inversion_flowline_hw()
     mb_ts = mb.get_specific_mb(h, w, year=np.arange(31) + 1860)
     return np.std(mb_ts)
Ejemplo n.º 10
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
Ejemplo n.º 11
0
# --------------------

# 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']

# 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
Ejemplo n.º 12
0
def run_uncertain_random_climate(gdir,
                                 nyears=700,
                                 output_filesuffix='',
                                 sigma_t=None,
                                 sigma_p=None,
                                 sigma_smb=None,
                                 rdn_temp_bias_seed=None,
                                 rdn_prcp_bias_seed=None,
                                 rdn_bias_seed=None,
                                 orig_mb_tbias=0,
                                 orig_mb_pbias=1,
                                 orig_mb_sbias=0,
                                 **kwargs):
    """Test stuff

    Parameters
    ----------
    gdir
    nyears
    output_filesuffix
    rdn_temp_bias_seed
    rdn_prcp_bias_seed
    rdn_bias_seed
    kwargs

    Returns
    -------
    """

    # Find the optimal bias for a balanced MB
    mbref = mbmods.PastMassBalance(gdir)
    h, w = gdir.get_inversion_flowline_hw()
    cyrs = np.unique(mbref.years)

    def to_minimize(x):
        mbref.bias = x
        return np.mean(mbref.get_specific_mb(h, w, cyrs))

    opti_bias = optimization.brentq(to_minimize, -10000, 10000, xtol=0.01)
    mbref.bias = opti_bias
    assert np.allclose(np.mean(mbref.get_specific_mb(h, w, cyrs)),
                       0,
                       atol=0.01)

    rdf = pd.DataFrame(index=cyrs)
    for y in cyrs:
        rdf.loc[y, 'SMB'] = mbref.get_specific_mb(h, w, year=y)
        t, _, p, _ = mbref.get_annual_climate([np.mean(h)], year=y)
        rdf.loc[y, 'TEMP'] = t
        rdf.loc[y, 'PRCP'] = p

    if sigma_smb is None:
        sigma_smb = rdf.std()['SMB'] / 2
    if sigma_t is None:
        sigma_t = rdf.std()['TEMP'] / 2
    if sigma_p is None:
        sigma_p = (rdf.std() / rdf.mean())['PRCP'] / 2

    mb = mbmods.RandomMassBalance(gdir, all_years=True, seed=0)
    mb.mbmod.temp_bias = orig_mb_tbias
    mb.mbmod.prcp_bias = orig_mb_pbias
    mb.mbmod.bias = orig_mb_sbias + opti_bias

    rmb = mbmods.UncertainMassBalance(mb,
                                      rdn_temp_bias_seed=rdn_temp_bias_seed,
                                      rdn_temp_bias_sigma=sigma_t,
                                      rdn_prcp_bias_seed=rdn_prcp_bias_seed,
                                      rdn_prcp_bias_sigma=sigma_p,
                                      rdn_bias_seed=rdn_bias_seed,
                                      rdn_bias_sigma=sigma_smb)

    return robust_model_run(gdir,
                            output_filesuffix=output_filesuffix,
                            mb_model=rmb,
                            ys=0,
                            ye=nyears,
                            **kwargs)
Ejemplo n.º 13
0
    def test_varying_bias_mb_model(self, case_dir):

        cfg.initialize()
        cfg.PARAMS['prcp_scaling_factor'] = 1.6
        cfg.PATHS['working_dir'] = case_dir
        cfg.PARAMS['use_multiprocessing'] = True

        # Go - get the pre-processed glacier directories
        for rid in ['RGI60-03.04384', 'RGI60-11.00897', 'RGI60-16.02207']:
            gdirs = workflow.init_glacier_directories(
                [rid],
                from_prepro_level=5,
                prepro_base_url=prepro_base_url,
                prepro_border=80,
                prepro_rgi_version='62')
            workflow.execute_entity_task(parse_dt_per_dt, gdirs)

            gdir = gdirs[0]

            exp = 'netzero_py2020_fac1.0_decr0.3'
            magicc_file = magicc_dir + exp + '.nc'
            with xr.open_dataset(utils.file_downloader(magicc_file),
                                 decode_times=False) as ds:
                ds = ds.load()
            df = ds['ens_avg'].to_dataframe()
            dt_per_dt = gdir.get_diagnostics()['magicc_dt_per_dt']
            dp_per_dt = gdir.get_diagnostics()['magicc_dp_per_dt']

            fls = gdir.read_pickle('model_flowlines')

            y0 = 2014
            hs = 5

            mbc = massbalance.ConstantMassBalance(gdir, y0=y0, halfsize=hs)
            mb_ref = massbalance.PastMassBalance(gdir)
            years = np.arange(1980, 2020, dtype=np.float64)
            df['mb_ref'] = pd.Series(index=years,
                                     data=mb_ref.get_specific_mb(fls=fls,
                                                                 year=years))

            mb = MagiccMassBalance(gdir,
                                   y0=y0,
                                   halfsize=hs,
                                   magicc_ts=df['ens_avg'],
                                   dt_per_dt=dt_per_dt)
            df['mb'] = mb.get_specific_mb(fls=fls, year=df.index)

            mb = MagiccMassBalance(gdir,
                                   y0=y0,
                                   halfsize=hs,
                                   magicc_ts=df['ens_avg'],
                                   dt_per_dt=dt_per_dt,
                                   dp_per_dt=dp_per_dt)
            df['mb_wp'] = mb.get_specific_mb(fls=fls, year=df.index)

            mb = MagiccMassBalance(gdir,
                                   y0=y0,
                                   halfsize=hs,
                                   magicc_ts=df['ens_avg'])
            df['mb_nodt'] = mb.get_specific_mb(fls=fls, year=df.index)

            assert_allclose(df.loc[y0 - hs:y0 + hs]['mb'].mean(),
                            mbc.get_specific_mb(fls=fls),
                            rtol=5e-3)
            assert_allclose(df.loc[y0 - hs:y0 + hs]['mb_ref'].mean(),
                            df.loc[y0 - hs:y0 + hs]['mb'].mean(),
                            atol=1e-2)
            assert_allclose(df.loc[y0 - hs:y0 + hs]['mb_ref'].mean(),
                            df.loc[y0 - hs:y0 + hs]['mb_wp'].mean(),
                            atol=1e-2)
            assert_allclose(df.loc[y0 - hs:y0 + hs]['mb_ref'].mean(),
                            df.loc[y0 - hs:y0 + hs]['mb_nodt'].mean(),
                            atol=1e-2)
            assert_allclose(df[['ens_avg', 'mb']].corr().min().min(),
                            -1,
                            rtol=1e-2)
            assert_allclose(df[['ens_avg', 'mb_nodt']].corr().min().min(),
                            -1,
                            rtol=1e-2)
            assert_allclose(df[['mb_wp', 'mb']].corr().min().min(),
                            1,
                            rtol=1e-2)
            assert_allclose(df['mb'], df['mb_wp'], atol=115)

            if DO_PLOT:
                plt.figure()
                df[['mb_ref', 'mb', 'mb_wp',
                    'mb_nodt']].loc[2000:2025].plot(title=rid)
                plt.figure()
                df[['mb_ref', 'mb', 'mb_wp',
                    'mb_nodt']].loc[2000:].plot(title=rid)
                plt.show()
Ejemplo n.º 14
0
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)