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)
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)
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)
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
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
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
def time_get_ela(): mb_mod = massbalance.PastMassBalance(gdir, bias=0) mb_mod.get_ela(year=years)
def time_PastMassBalance(): mb_mod = massbalance.PastMassBalance(gdir, bias=0) for yr in years: mb_mod.get_annual_mb(heights, year=yr)
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)
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
# -------------------- # 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
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)
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()
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)