示例#1
0
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)
示例#2
0
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)
示例#3
0
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)
示例#4
0
         '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)
示例#5
0
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)
示例#6
0
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)
示例#7
0
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)
示例#8
0
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)
示例#10
0
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)
示例#11
0
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)