Module gdess.data_source.models.cmip.cmip_name_utils
Expand source code
from gdess import load_config_file
from gdess.formatters.args import nullable_str
import os, re, shlex
# -- Define valid model choices --
# Get the default model choices from the config file. Split (on commas) the retrieved string into a list.
config = load_config_file()
config_model_values = config.get('CMIP', 'model_choices', vars=os.environ)
my_splitter = shlex.shlex(config_model_values, posix=True)
my_splitter.whitespace += ','
my_splitter.whitespace_split = True
cmip_model_choices = list(my_splitter)
full_model_name_pattern = re.compile(
r'(?P<activityid>[a-zA-Z\d\-]+)\.(?P<institutionid>[a-zA-Z\d\-]+)\.'
r'(?P<sourceid>[a-zA-Z\d\-]+)\.(?P<experimentid>[a-zA-Z\d\-]+)\.'
r'(?P<tableid>[a-zA-Z\d\-]+)\.(?P<gridlabel>[a-zA-Z\d\-]+)')
def model_name_dict_from_valid_form(s: str) -> dict:
"""Transform model_name into a dictionary with the parts
Parameters
----------
s : str
Raises
------
ValueError, if the form of the input string does not match either form (1) or (2)
"""
# The supplied string is expected to be either in a shortened form <source>.<experiment> or a full name.
short_pattern = re.compile(
r'(?P<sourceid>[a-zA-Z\d\-]+)\.(?P<experimentid>[a-zA-Z\d\-]+)')
if match := full_model_name_pattern.search(s):
return match.groupdict()
elif match := short_pattern.search(s):
return match.groupdict()
else:
raise ValueError("Expected at least a source_id with an experiment_id, in the form "
"<source_id>.<experiment_id>, e.g. 'BCC.esm-hist'. Got <%s>" % s)
def matched_model_and_experiment(s: str) -> str:
"""Function used to allow specification of model names by only supplying a partial string match
This function first checks whether the input is a string and of the form:
(1) source_id.experiment_id
or
(2) activity_id.institution_id.source_id.experiment_id.table_id.grid_label
A full name (i.e., in form (2)) will be returned, if the input matches one of the defined model choices.
If the input does not match a defined model choice, then the input string will be returned unchanged.
Example
-------
>>> matched_model_and_experiment('BCC.esm-hist')
returns 'CMIP.BCC.BCC-CSM2-MR.esm-hist.Amon.gn'
"""
# Transform the full names of the model choices into a dictionary of source and experiment ids.
valid = [full_model_name_pattern.search(m).groupdict() for m in cmip_model_choices]
valid_source_names = [v['sourceid'] for v in valid]
# The supplied string is expected to be either in a shortened form <source>.<experiment> or a full name.
if nullable_str(s):
supplied = model_name_dict_from_valid_form(s)
else:
return s
# match the substring to one of the full model names
options = [(i, c) for i, c in enumerate(valid_source_names)
if supplied['sourceid'] in c]
if len(options) == 1:
if valid[options[0][0]]['experimentid'] == supplied['experimentid']:
return cmip_model_choices[options[0][0]]
return s
Functions
def matched_model_and_experiment(s: str) -> str-
Function used to allow specification of model names by only supplying a partial string match
This function first checks whether the input is a string and of the form: (1) source_id.experiment_id or (2) activity_id.institution_id.source_id.experiment_id.table_id.grid_label A full name (i.e., in form (2)) will be returned, if the input matches one of the defined model choices. If the input does not match a defined model choice, then the input string will be returned unchanged.
Example
>>> matched_model_and_experiment('BCC.esm-hist') returns 'CMIP.BCC.BCC-CSM2-MR.esm-hist.Amon.gn'Expand source code
def matched_model_and_experiment(s: str) -> str: """Function used to allow specification of model names by only supplying a partial string match This function first checks whether the input is a string and of the form: (1) source_id.experiment_id or (2) activity_id.institution_id.source_id.experiment_id.table_id.grid_label A full name (i.e., in form (2)) will be returned, if the input matches one of the defined model choices. If the input does not match a defined model choice, then the input string will be returned unchanged. Example ------- >>> matched_model_and_experiment('BCC.esm-hist') returns 'CMIP.BCC.BCC-CSM2-MR.esm-hist.Amon.gn' """ # Transform the full names of the model choices into a dictionary of source and experiment ids. valid = [full_model_name_pattern.search(m).groupdict() for m in cmip_model_choices] valid_source_names = [v['sourceid'] for v in valid] # The supplied string is expected to be either in a shortened form <source>.<experiment> or a full name. if nullable_str(s): supplied = model_name_dict_from_valid_form(s) else: return s # match the substring to one of the full model names options = [(i, c) for i, c in enumerate(valid_source_names) if supplied['sourceid'] in c] if len(options) == 1: if valid[options[0][0]]['experimentid'] == supplied['experimentid']: return cmip_model_choices[options[0][0]] return s def model_name_dict_from_valid_form(s: str) -> dict-
Transform model_name into a dictionary with the parts
Parameters
s:str
Raises
ValueError, if the formofthe input string does not match either form (1)or(2)
Expand source code
def model_name_dict_from_valid_form(s: str) -> dict: """Transform model_name into a dictionary with the parts Parameters ---------- s : str Raises ------ ValueError, if the form of the input string does not match either form (1) or (2) """ # The supplied string is expected to be either in a shortened form <source>.<experiment> or a full name. short_pattern = re.compile( r'(?P<sourceid>[a-zA-Z\d\-]+)\.(?P<experimentid>[a-zA-Z\d\-]+)') if match := full_model_name_pattern.search(s): return match.groupdict() elif match := short_pattern.search(s): return match.groupdict() else: raise ValueError("Expected at least a source_id with an experiment_id, in the form " "<source_id>.<experiment_id>, e.g. 'BCC.esm-hist'. Got <%s>" % s)