def compute_ref_t_stars(gdirs): """ Detects the best t* for the reference glaciers and writes them to disk This task will be needed for mass balance calibration of custom climate data. For CRU and HISTALP baseline climate a precalibrated list is available and should be used instead. Parameters ---------- gdirs : list of :py:class:`oggm.GlacierDirectory` objects will be filtered for reference glaciers """ if not cfg.PARAMS['run_mb_calibration']: raise InvalidParamsError('Are you sure you want to calibrate the ' 'reference t*? There is a pre-calibrated ' 'version available. If you know what you are ' 'doing and still want to calibrate, set the ' '`run_mb_calibration` parameter to `True`.') log.info('Compute the reference t* and mu* for WGMS glaciers') # Reference glaciers only if in the list and period is good ref_gdirs = utils.get_ref_mb_glaciers(gdirs) # Run from oggm.workflow import execute_entity_task out = execute_entity_task(t_star_from_refmb, ref_gdirs) # Loop write df = pd.DataFrame() for gdir, res in zip(ref_gdirs, out): # list of mus compatibles with refmb rid = gdir.rgi_id df.loc[rid, 'lon'] = gdir.cenlon df.loc[rid, 'lat'] = gdir.cenlat df.loc[rid, 'n_mb_years'] = len(gdir.get_ref_mb_data()) df.loc[rid, 'tstar'] = res['t_star'] df.loc[rid, 'bias'] = res['bias'] # Write out df['tstar'] = df['tstar'].astype(int) df['n_mb_years'] = df['n_mb_years'].astype(int) file = os.path.join(cfg.PATHS['working_dir'], 'ref_tstars.csv') df.sort_index().to_csv(file)
def crossval_t_stars(gdirs): """Cross-validate the interpolation of tstar to each individual glacier. This is a thorough check (redoes many calculations) because it recomputes the chosen tstars at each time. You should use quick_crossval_t_stars instead. Parameters ---------- gdirs: list of oggm.GlacierDirectory objects """ log.info('Cross-validate the t* and mu* determination') full_ref_df = pd.read_csv(os.path.join(cfg.PATHS['working_dir'], 'ref_tstars.csv'), index_col=0) rgdirs = utils.get_ref_mb_glaciers(gdirs) n = len(full_ref_df) for i, rid in enumerate(full_ref_df.index): log.info('Cross-validation iteration {} of {}'.format(i + 1, n)) # the glacier to look at gdir = [g for g in rgdirs if g.rgi_id == rid][0] # the reference glaciers ref_gdirs = [g for g in rgdirs if g.rgi_id != rid] # redo the computations with utils.DisableLogger(): compute_ref_t_stars(ref_gdirs) distribute_t_stars([gdir]) # store rdf = pd.read_csv(gdir.get_filepath('local_mustar')) full_ref_df.loc[rid, 'cv_tstar'] = int(rdf['t_star'].values[0]) full_ref_df.loc[rid, 'cv_mustar'] = rdf['mu_star'].values[0] full_ref_df.loc[rid, 'cv_prcp_fac'] = rdf['prcp_fac'].values[0] full_ref_df.loc[rid, 'cv_bias'] = rdf['bias'].values[0] # write file = os.path.join(cfg.PATHS['working_dir'], 'crossval_tstars.csv') full_ref_df.to_csv(file)
def compute_ref_t_stars(gdirs): """ Detects the best t* for the reference glaciers. Parameters ---------- gdirs: list of oggm.GlacierDirectory objects """ if not cfg.PARAMS['run_mb_calibration']: raise RuntimeError('Are you sure you want to calibrate the reference ' 't*? There is a pre-calibrated version available. ' 'If you know what you are doing and still want to ' 'calibrate, set the `run_mb_calibration` parameter ' 'to `True`.') log.info('Compute the reference t* and mu* for WGMS glaciers') # Reference glaciers only if in the list and period is good ref_gdirs = utils.get_ref_mb_glaciers(gdirs) # Loop df = pd.DataFrame() for gdir in ref_gdirs: # all possible mus mu_candidates(gdir, reset=True) # list of mus compatibles with refmb res = t_star_from_refmb(gdir) rid = gdir.rgi_id df.loc[rid, 'lon'] = gdir.cenlon df.loc[rid, 'lat'] = gdir.cenlat df.loc[rid, 'n_mb_years'] = len(gdir.get_ref_mb_data()) df.loc[rid, 'tstar'] = res['t_star'] df.loc[rid, 'bias'] = res['bias'] # Write out df['tstar'] = df['tstar'].astype(int) df['n_mb_years'] = df['n_mb_years'].astype(int) file = os.path.join(cfg.PATHS['working_dir'], 'ref_tstars.csv') df.sort_index().to_csv(file)
'glaciers.'.format(rgi_version, len(rgidf))) # We have to check which of them actually have enough mb data. # Let OGGM do it: gdirs = workflow.init_glacier_regions(rgidf) # We need to know which period we have data for log.info('Process the climate data...') if baseline == 'CRU': execute_entity_task(tasks.process_cru_data, gdirs, print_log=False) elif baseline == 'HISTALP': cfg.PARAMS['continue_on_error'] = True # Some glaciers are not in Alps execute_entity_task(tasks.process_histalp_data, gdirs, print_log=False) cfg.PARAMS['continue_on_error'] = False gdirs = utils.get_ref_mb_glaciers(gdirs) # Keep only these rgidf = rgidf.loc[rgidf.RGIId.isin([g.rgi_id for g in gdirs])] # Save log.info('For RGIV{} and {} we have {} reference glaciers.'.format( rgi_version, baseline, len(rgidf))) rgidf.to_file(os.path.join(WORKING_DIR, 'mb_ref_glaciers.shp')) # Sort for more efficient parallel computing rgidf = rgidf.sort_values('Area', ascending=False) # Go - initialize glacier directories gdirs = workflow.init_glacier_regions(rgidf)
def quick_crossval_t_stars(gdirs): """Cross-validate the interpolation of tstar to each individual glacier. This version does NOT recompute the precipitation scaling factor at each round (this quite OK to do so) Parameters ---------- gdirs: list of oggm.GlacierDirectory objects """ log.info('Cross-validate the t* and mu* determination') rgdirs = utils.get_ref_mb_glaciers(gdirs) # This might be redundant but we redo the calc here with utils.DisableLogger(): compute_ref_t_stars(rgdirs) full_ref_df = pd.read_csv(os.path.join(cfg.PATHS['working_dir'], 'ref_tstars.csv'), index_col=0) with utils.DisableLogger(): distribute_t_stars(rgdirs) n = len(full_ref_df) for i, rid in enumerate(full_ref_df.index): # log.info('Cross-validation iteration {} of {}'.format(i+1, n)) # the glacier to look at gdir = [g for g in rgdirs if g.rgi_id == rid][0] # the reference glaciers tmp_ref_df = full_ref_df.loc[full_ref_df.index != rid] # before the cross-val we can get the info about "real" mustar rdf = pd.read_csv(gdir.get_filepath('local_mustar')) full_ref_df.loc[rid, 'mustar'] = rdf['mu_star'].values[0] # redo the computations with utils.DisableLogger(): distribute_t_stars([gdir], ref_df=tmp_ref_df) # store rdf = pd.read_csv(gdir.get_filepath('local_mustar')) full_ref_df.loc[rid, 'cv_tstar'] = int(rdf['t_star'].values[0]) full_ref_df.loc[rid, 'cv_mustar'] = rdf['mu_star'].values[0] full_ref_df.loc[rid, 'cv_prcp_fac'] = rdf['prcp_fac'].values[0] full_ref_df.loc[rid, 'cv_bias'] = rdf['bias'].values[0] # Reproduce Ben's figure for i, rid in enumerate(full_ref_df.index): # the glacier to look at gdir = full_ref_df.loc[full_ref_df.index == rid] # the reference glaciers tmp_ref_df = full_ref_df.loc[full_ref_df.index != rid] # Compute the distance distances = utils.haversine(gdir.lon.values[0], gdir.lat.values[0], tmp_ref_df.lon, tmp_ref_df.lat) # Take the 10 closests aso = np.argsort(distances)[0:9] amin = tmp_ref_df.iloc[aso] distances = distances[aso]**2 interp = np.average(amin.mustar, weights=1. / distances) full_ref_df.loc[rid, 'interp_mustar'] = interp # write file = os.path.join(cfg.PATHS['working_dir'], 'crossval_tstars.csv') full_ref_df.to_csv(file)
def compute_ref_t_stars(gdirs): """ Detects the best t* for the reference glaciers. Parameters ---------- gdirs: list of oggm.GlacierDirectory objects """ if not cfg.PARAMS['run_mb_calibration']: raise RuntimeError('Are you sure you want to calibrate the reference ' 't*? There is a pre-calibrated version available. ' 'If you know what you are doing and still want to ' 'calibrate, set the `run_mb_calibration` parameter ' 'to `True`.') log.info('Compute the reference t* and mu* for WGMS glaciers') # Reference glaciers only if in the list and period is good ref_gdirs = utils.get_ref_mb_glaciers(gdirs) prcp_sf = None if cfg.PARAMS['prcp_scaling_factor'] == 'stddev': prcp_sf = _get_optimal_scaling_factor(ref_gdirs) # Loop only_one = [] # start to store the glaciers with just one t* per_glacier = dict() for gdir in ref_gdirs: # all possible mus mu_candidates(gdir, prcp_sf=prcp_sf, reset=True) # list of mus compatibles with refmb mbdf = gdir.get_ref_mb_data()['ANNUAL_BALANCE'] res = t_star_from_refmb(gdir, mbdf) # if we have just one candidate this is good if len(res['t_star']) == 1: only_one.append(gdir.rgi_id) # this might be more than one, we'll have to select them later per_glacier[gdir.rgi_id] = (gdir, res['t_star'], res['bias'], res['prcp_fac']) # At least one of the glaciers should have a single t*, otherwise we don't # know how to start if len(only_one) == 0: # TODO: hardcoded stuff here, for the test workflow for v in ['4', '5', '6']: rid = 'RGI{}0-11.00897'.format(v) if rid in per_glacier: only_one.append(rid) gdir, t_star, res_bias, prcp_fac = per_glacier[rid] per_glacier[rid] = (gdir, [t_star[-1]], [res_bias[-1]], prcp_fac) if len(only_one) == 0: raise RuntimeError('We need at least one glacier with one ' 'tstar only.') log.info('%d out of %d have only one possible t*. Start from here', len(only_one), len(ref_gdirs)) # Ok. now loop over the nearest glaciers until all have a unique t* while True: ids_left = [id for id in per_glacier.keys() if id not in only_one] if len(ids_left) == 0: break # Compute the summed distance to all glaciers with one t* distances = [] for id in ids_left: gdir = per_glacier[id][0] lon, lat = gdir.cenlon, gdir.cenlat ldis = 0. for id_o in only_one: ogdir = per_glacier[id_o][0] ldis += utils.haversine(lon, lat, ogdir.cenlon, ogdir.cenlat) distances.append(ldis) # Take the shortest and choose the best t* pg = per_glacier[ids_left[np.argmin(distances)]] gdir, t_star, res_bias, prcp_fac = pg distances = [] for tt in t_star: ldis = 0. for id_o in only_one: _, ot_star, _, _ = per_glacier[id_o] ldis += np.abs(tt - ot_star) distances.append(ldis) amin = np.argmin(distances) per_glacier[gdir.rgi_id] = (gdir, [t_star[amin]], [res_bias[amin]], prcp_fac) only_one.append(gdir.rgi_id) # Write out the data rgis_ids, t_stars, prcp_facs, biases, lons, lats, n_mb = ([], [], [], [], [], [], []) for id, (gdir, t_star, res_bias, prcp_fac) in per_glacier.items(): rgis_ids.append(id) t_stars.append(t_star[0]) prcp_facs.append(prcp_fac) biases.append(res_bias[0]) lats.append(gdir.cenlat) lons.append(gdir.cenlon) n_mb.append(len(gdir.get_ref_mb_data())) df = pd.DataFrame(index=rgis_ids) df['lon'] = lons df['lat'] = lats df['n_mb_years'] = n_mb df['tstar'] = t_stars df['prcp_fac'] = prcp_facs df['bias'] = biases file = os.path.join(cfg.PATHS['working_dir'], 'ref_tstars.csv') df.sort_index().to_csv(file)
def mb_calibration(rgi_version, baseline): """Run the mass balance calibration for the VAS model. RGI version and baseline climate must be given. Parameters ---------- rgi_version : str Version (and subversion) of the RGI, e.g., '62' baseline : str 'HISTALP' or 'CRU', name of the baseline climate """ # initialize OGGM and set up the run parameters vascaling.initialize(logging_level='WORKFLOW') # LOCAL paths (where to write the OGGM run output) # dirname = 'VAS_ref_mb_{}_RGIV{}'.format(baseline, rgi_version) # wdir = utils.gettempdir(dirname, home=True, reset=True) # utils.mkdir(wdir, reset=True) # cfg.PATHS['working_dir'] = wdir # CLUSTER paths wdir = os.environ.get('WORKDIR', '') cfg.PATHS['working_dir'] = wdir # we are running the calibration ourselves cfg.PARAMS['run_mb_calibration'] = True # we are using which baseline data? cfg.PARAMS['baseline_climate'] = baseline # no need for intersects since this has an effect on the inversion only cfg.PARAMS['use_intersects'] = False # use multiprocessing? cfg.PARAMS['use_multiprocessing'] = True # set to True for operational runs cfg.PARAMS['continue_on_error'] = True # 10 is only for OGGM-VAS, OGGM needs 80 to run cfg.PARAMS['border'] = 80 if baseline == 'HISTALP': # OGGM HISTALP PARAMETERS from Matthias Dusch # see https://oggm.org/2018/08/10/histalp-parameters/ # cfg.PARAMS['prcp_scaling_factor'] = 1.75 # cfg.PARAMS['temp_melt'] = -1.75 # cfg.PARAMS['temp_all_solid'] = 0 # cfg.PARAMS['prcp_default_gradient'] = 0 # VAS HISTALP PARAMETERS from x-validation cfg.PARAMS['prcp_scaling_factor'] = 2.5 cfg.PARAMS['temp_melt'] = -0.5 cfg.PARAMS['temp_all_solid'] = 0 cfg.PARAMS['prcp_default_gradient'] = 0 elif baseline == 'CRU': # using the parameters from Marzeion et al. (2012) # cfg.PARAMS['prcp_scaling_factor'] = 2.5 # cfg.PARAMS['temp_melt'] = 1 # cfg.PARAMS['temp_all_solid'] = 3 # cfg.PARAMS['prcp_default_gradient'] = 3e-4 # using the parameters from Malles and Marzeion 2020 cfg.PARAMS['prcp_scaling_factor'] = 3 cfg.PARAMS['temp_melt'] = 0 cfg.PARAMS['temp_all_solid'] = 4 cfg.PARAMS['prcp_default_gradient'] = 4e-4 # the next step is to get all the reference glaciers, # i.e. glaciers with mass balance measurements. # get the reference glacier ids (they are different for each RGI version) df, _ = utils.get_wgms_files() rids = df['RGI{}0_ID'.format(rgi_version[0])] # we can't do Antarctica rids = [rid for rid in rids if not ('-19.' in rid)] # For HISTALP only RGI reg 11.01 (ALPS) if baseline == 'HISTALP': rids = [rid for rid in rids if '-11' in rid] # initialize the glacier regions base_url = "https://cluster.klima.uni-bremen.de/~oggm/gdirs/oggm_v1.4/" \ "L3-L5_files/CRU/elev_bands/qc3/pcp2.5/match_geod" # Go - get the pre-processed glacier directories gdirs = workflow.init_glacier_directories(rids, from_prepro_level=3, prepro_base_url=base_url, prepro_rgi_version=rgi_version) # Some glaciers in RGI Region 11 are not inside the HISTALP domain if baseline == 'HISTALP': gdirs = [gdir for gdir in gdirs if gdir.rgi_subregion == '11-01'] # get reference glaciers with mass balance measurements gdirs = utils.get_ref_mb_glaciers(gdirs) # make a new dataframe with those (this takes a while) print('For RGIV{} we have {} candidate reference ' 'glaciers.'.format(rgi_version, len(gdirs))) # run climate tasks vascaling.compute_ref_t_stars(gdirs) # execute_entity_task(vascaling.local_t_star, gdirs) # we store the associated params mb_calib = gdirs[0].read_pickle('climate_info')['mb_calib_params'] with open(os.path.join(wdir, 'mb_calib_params.json'), 'w') as fp: json.dump(mb_calib, fp)
def initialization_selection(): # ------------- # Initialization # ------------- cfg.initialize() # working directories cfg.PATHS['working_dir'] = mbcfg.PATHS['working_dir'] cfg.PATHS['rgi_version'] = mbcfg.PARAMS['rgi_version'] # We are running the calibration ourselves cfg.PARAMS['run_mb_calibration'] = True # No need for intersects since this has an effect on the inversion only cfg.PARAMS['use_intersects'] = False # Use multiprocessing? cfg.PARAMS['use_multiprocessing'] = True # Set to True for operational runs # maybe also here? cfg.PARAMS['continue_on_error'] = False # set negative flux filtering to false. should be standard soon cfg.PARAMS['filter_for_neg_flux'] = False # Pre-download other files which will be needed later _ = utils.get_cru_file(var='tmp') _ = utils.get_cru_file(var='pre') rgi_dir = utils.get_rgi_dir(version=cfg.PATHS['rgi_version']) # Get the reference glacier ids (they are different for each RGI version) df, _ = utils.get_wgms_files() rids = df['RGI{}0_ID'.format(cfg.PATHS['rgi_version'])] # Make a new dataframe with those (this takes a while) rgidf = [] for reg in df['RGI_REG'].unique(): if reg == '19': continue # we have no climate data in Antarctica if mbcfg.PARAMS['region'] is not None\ and reg != mbcfg.PARAMS['region']: continue fn = '*' + reg + '_rgi{}0_*.shp'.format(cfg.PATHS['rgi_version']) fs = list(sorted(glob(os.path.join(rgi_dir, '*', fn))))[0] sh = gpd.read_file(fs) rgidf.append(sh.loc[sh.RGIId.isin(rids)]) rgidf = pd.concat(rgidf) rgidf.crs = sh.crs # for geolocalisation # reduce Europe to Histalp area (exclude Pyrenees, etc...) if mbcfg.PARAMS['histalp']: rgidf = rgidf.loc[(rgidf.CenLon >= 4) & (rgidf.CenLon < 20) & (rgidf.CenLat >= 43) & (rgidf.CenLat < 47)] # We have to check which of them actually have enough mb data. # Let OGGM do it: gdirs = workflow.init_glacier_regions(rgidf) # We need to know which period we have data for if mbcfg.PARAMS['histalp']: cfg.PATHS['climate_file'] = mbcfg.PATHS['histalpfile'] execute_entity_task(tasks.process_custom_climate_data, gdirs) else: execute_entity_task(tasks.process_cru_data, gdirs, print_log=False) gdirs = utils.get_ref_mb_glaciers(gdirs) # Keep only these rgidf = rgidf.loc[rgidf.RGIId.isin([g.rgi_id for g in gdirs])] # Save rgidf.to_file(os.path.join(cfg.PATHS['working_dir'], 'mb_ref_glaciers.shp')) # Sort for more efficient parallel computing rgidf = rgidf.sort_values('Area', ascending=False) # Go - initialize working directories gdirs = workflow.init_glacier_regions(rgidf, reset=True, force=True) return gdirs
'glaciers.'.format(rgi_version, len(rgidf))) # We have to check which of them actually have enough mb data. # Let OGGM do it: gdirs = workflow.init_glacier_regions(rgidf) # We need to know which period we have data for log.info('Process the climate data...') if baseline == 'CRU': execute_entity_task(tasks.process_cru_data, gdirs, print_log=False) elif baseline == 'HISTALP': cfg.PARAMS['continue_on_error'] = True # Some glaciers are not in Alps execute_entity_task(tasks.process_histalp_data, gdirs, print_log=False) cfg.PARAMS['continue_on_error'] = False gdirs = utils.get_ref_mb_glaciers(gdirs) # Keep only these rgidf = rgidf.loc[rgidf.RGIId.isin([g.rgi_id for g in gdirs])] # Save log.info('For RGIV{} and {} we have {} reference glaciers.'.format(rgi_version, baseline, len(rgidf))) rgidf.to_file(os.path.join(WORKING_DIR, 'mb_ref_glaciers.shp')) # Sort for more efficient parallel computing rgidf = rgidf.sort_values('Area', ascending=False) # Go - initialize glacier directories gdirs = workflow.init_glacier_regions(rgidf)
def mb_calibration(rgi_version, baseline): """ Run the mass balance calibration for the VAS model. RGI version and baseline cliamte must be given. :param rgi_version: int, RGI version :param baseline: str, baseline climate 'HISTALP' or 'CRU' """ # initialize OGGM and set up the run parameters vascaling.initialize(logging_level='WORKFLOW') # LOCAL paths (where to write the OGGM run output) # dirname = 'VAS_ref_mb_{}_RGIV{}'.format(baseline, rgi_version) # wdir = utils.gettempdir(dirname, home=True, reset=True) # utils.mkdir(wdir, reset=True) # cfg.PATHS['working_dir'] = wdir # CLUSTER paths wdir = os.environ.get('WORKDIR', '') cfg.PATHS['working_dir'] = wdir # we are running the calibration ourselves cfg.PARAMS['run_mb_calibration'] = True # we are using which baseline data? cfg.PARAMS['baseline_climate'] = baseline # no need for intersects since this has an effect on the inversion only cfg.PARAMS['use_intersects'] = False # use multiprocessing? cfg.PARAMS['use_multiprocessing'] = True # set to True for operational runs cfg.PARAMS['continue_on_error'] = True # 10 is only for OGGM-VAS, OGGM needs 80 to run cfg.PARAMS['border'] = 80 if baseline == 'HISTALP': # other params: see https://oggm.org/2018/08/10/histalp-parameters/ # cfg.PARAMS['prcp_scaling_factor'] = 1.75 # cfg.PARAMS['temp_melt'] = -1.75 cfg.PARAMS['prcp_scaling_factor'] = 2.5 cfg.PARAMS['temp_melt'] = -0.5 elif baseline == 'CRU': # using the parameters from Marzeion et al. (2012) # cfg.PARAMS['prcp_scaling_factor'] = 2.5 # cfg.PARAMS['temp_melt'] = 1 # cfg.PARAMS['temp_all_solid'] = 3 # using the parameters from Malles and Marzeion 2020 cfg.PARAMS['prcp_scaling_factor'] = 3 cfg.PARAMS['temp_melt'] = 0 cfg.PARAMS['temp_all_solid'] = 4 # cfg.PARAMS['prcp_gradient'] = 4 # the next step is to get all the reference glaciers, # i.e. glaciers with mass balance measurements. # get the reference glacier ids (they are different for each RGI version) df, _ = utils.get_wgms_files() rids = df['RGI{}0_ID'.format(rgi_version[0])] # we can't do Antarctica rids = [rid for rid in rids if not ('-19.' in rid)] # For HISTALP only RGI reg 11.01 (ALPS) if baseline == 'HISTALP': rids = [rid for rid in rids if '-11' in rid] # make a new dataframe with those (this takes a while) print('Reading the RGI shapefiles...') rgidf = utils.get_rgi_glacier_entities(rids, version=rgi_version) print('For RGIV{} we have {} candidate reference ' 'glaciers.'.format(rgi_version, len(rgidf))) # initialize the glacier regions base_url = 'https://cluster.klima.uni-bremen.de/~oggm/gdirs/oggm_v1.4/' \ 'L3-L5_files/RGIV62_fleb_qc3_CRU_pcp2.5' # Go - get the pre-processed glacier directories gdirs = workflow.init_glacier_directories(rids, from_prepro_level=3, prepro_base_url=base_url, prepro_rgi_version=rgi_version) # Some glaciers in RGI Region 11 are not inside the HISTALP domain if baseline == 'HISTALP': gdirs = [gdir for gdir in gdirs if gdir.rgi_subregion == '11-01'] # get reference glaciers with mass balance measurements gdirs = utils.get_ref_mb_glaciers(gdirs) # keep only these glaciers rgidf = rgidf.loc[rgidf.RGIId.isin([g.rgi_id for g in gdirs])] # save to file rgidf.to_file(os.path.join(wdir, 'mb_ref_glaciers.shp')) print('For RGIV{} and {} we have {} reference glaciers'.format( rgi_version, baseline, len(rgidf))) # sort for more efficient parallel computing rgidf = rgidf.sort_values('Area', ascending=False) # newly initialize glacier directories gdirs = workflow.init_glacier_directories(rgidf, reset=False, force=True) workflow.execute_entity_task(gis.define_glacier_region, gdirs) workflow.execute_entity_task(gis.glacier_masks, gdirs) # run climate tasks vascaling.compute_ref_t_stars(gdirs) execute_entity_task(vascaling.local_t_star, gdirs) # we store the associated params mb_calib = gdirs[0].read_pickle('climate_info')['mb_calib_params'] with open(os.path.join(wdir, 'mb_calib_params.json'), 'w') as fp: json.dump(mb_calib, fp)
def mb_calibration(rgi_version, baseline): """ Run the mass balance calibration for the VAS model. RGI version and baseline cliamte must be given. :param rgi_version: int, RGI version :param baseline: str, baseline climate 'HISTALP' or 'CRU' """ # initialize OGGM and set up the run parameters vascaling.initialize(logging_level='WORKFLOW') # local paths (where to write the OGGM run output) # dirname = 'VAS_ref_mb_{}_RGIV{}'.format(baseline, rgi_version) # wdir = utils.gettempdir(dirname, home=True, reset=True) # utils.mkdir(wdir, reset=True) wdir = os.environ['WORKDIR'] cfg.PATHS['working_dir'] = wdir # we are running the calibration ourselves cfg.PARAMS['run_mb_calibration'] = True # we are using which baseline data? cfg.PARAMS['baseline_climate'] = baseline # no need for intersects since this has an effect on the inversion only cfg.PARAMS['use_intersects'] = False # use multiprocessing? cfg.PARAMS['use_multiprocessing'] = True # set to True for operational runs cfg.PARAMS['continue_on_error'] = True if baseline == 'HISTALP': # other params: see https://oggm.org/2018/08/10/histalp-parameters/ # cfg.PARAMS['prcp_scaling_factor'] = 1.75 # cfg.PARAMS['temp_melt'] = -1.75 cfg.PARAMS['prcp_scaling_factor'] = 2.5 cfg.PARAMS['temp_melt'] = -0.5 elif baseline == 'CRU': # using the parameters from Marzeion et al. (2012) cfg.PARAMS['prcp_scaling_factor'] = 2.5 cfg.PARAMS['temp_melt'] = 1 cfg.PARAMS['temp_all_solid'] = 3 # the next step is to get all the reference glaciers, # i.e. glaciers with mass balance measurements. # get the reference glacier ids (they are different for each RGI version) rgi_dir = utils.get_rgi_dir(version=rgi_version) df, _ = utils.get_wgms_files() rids = df['RGI{}0_ID'.format(rgi_version[0])] # we can't do Antarctica rids = [rid for rid in rids if not ('-19.' in rid)] # For HISTALP only RGI reg 11.01 (ALPS) if baseline == 'HISTALP' or True: rids = [rid for rid in rids if '-11' in rid] debug = False if debug: print("==================================\n" + "DEBUG MODE: only RGI60-11.00897\n" + "==================================") rids = [rid for rid in rids if '-11.00897' in rid] cfg.PARAMS['use_multiprocessing'] = False # make a new dataframe with those (this takes a while) print('Reading the RGI shapefiles...') rgidf = utils.get_rgi_glacier_entities(rids, version=rgi_version) print('For RGIV{} we have {} candidate reference ' 'glaciers.'.format(rgi_version, len(rgidf))) # initialize the glacier regions gdirs = workflow.init_glacier_directories(rgidf, reset=False, force=True) workflow.execute_entity_task(gis.define_glacier_region, gdirs) workflow.execute_entity_task(gis.glacier_masks, gdirs) # we need to know which period we have data for print('Process the climate data...') if baseline == 'CRU': execute_entity_task(tasks.process_cru_data, gdirs, print_log=False) elif baseline == 'HISTALP': # Some glaciers are not in Alps gdirs = [gdir for gdir in gdirs if gdir.rgi_subregion == '11-01'] # cfg.PARAMS['continue_on_error'] = True execute_entity_task(tasks.process_histalp_data, gdirs, print_log=False, y0=1850) # cfg.PARAMS['continue_on_error'] = False else: execute_entity_task(tasks.process_custom_climate_data, gdirs, print_log=False) # get reference glaciers with mass balance measurements gdirs = utils.get_ref_mb_glaciers(gdirs) # keep only these glaciers rgidf = rgidf.loc[rgidf.RGIId.isin([g.rgi_id for g in gdirs])] # save to file rgidf.to_file(os.path.join(wdir, 'mb_ref_glaciers.shp')) print('For RGIV{} and {} we have {} reference glaciers'.format(rgi_version, baseline, len(rgidf))) # sort for more efficient parallel computing rgidf = rgidf.sort_values('Area', ascending=False) # newly initialize glacier directories gdirs = workflow.init_glacier_directories(rgidf, reset=False, force=True) workflow.execute_entity_task(gis.define_glacier_region, gdirs) workflow.execute_entity_task(gis.glacier_masks, gdirs) # run climate tasks vascaling.compute_ref_t_stars(gdirs) execute_entity_task(vascaling.local_t_star, gdirs) # we store the associated params mb_calib = gdirs[0].read_pickle('climate_info')['mb_calib_params'] with open(os.path.join(wdir, 'mb_calib_params.json'), 'w') as fp: json.dump(mb_calib, fp)