예제 #1
0
def _get_value(val_in, settings_dict, tracers_dict, dict_prefix=''):
    """ Translate val_in (which may be a variable name) to an integer value
    """

    logger = logging.getLogger(__name__)

    # If val_in is an integer, then it is the dimension size and should be returned
    if isinstance(val_in, int):
        return val_in

    # If val_in is a string, then it is a variable name that should be in
    # settings_dict already
    if isinstance(val_in, type(u'')):
        # If val_in = _tracer_list, that's a special case where we want
        # to find a list of tracers according to current settings
        if val_in == '_tracer_list':
            return len(tracers_dict.keys())

        # Otherwise, val_in must refer to a variable that could be
        # in the dictionary with or without the prefix
        try:
            val_out = settings_dict[dict_prefix + val_in]
        except:
            try:
                val_out = settings_dict[val_in]
            except:
                logger.error('Unknown variable name in _get_value: %s' %
                             val_in)
                MARBL_tools.abort(1)
        return val_out

    # Otherwise this is not a well-defined variable request
    logger.error('_get_value() requires integer or string argument')
    MARBL_tools.abort(1)
예제 #2
0
 def get_settings_dict_variable_names(self, subcategory):
     """ Returns a sorted list of variables in a specific category
         and subcategory, expanding variable names if they are arrays
         or derived types
     """
     varlist = []
     for cat_name in self._settings['_order']:
         for var_name in MARBL_tools.sort(self._settings[cat_name].keys()):
             if isinstance(self._settings[cat_name][var_name]['datatype'],
                           dict):
                 for subvar_name in MARBL_tools.sort(
                         self._settings[cat_name][var_name]
                     ['datatype'].keys()):
                     if subvar_name[0] != '_':
                         this_var = self._settings[cat_name][var_name][
                             'datatype'][subvar_name]
                         if this_var['subcategory'] == subcategory:
                             for settings_name in this_var[
                                     '_list_of_settings_names']:
                                 varlist.append(settings_name)
             else:
                 this_var = self._settings[cat_name][var_name]
                 if this_var['subcategory'] == subcategory:
                     for settings_name in this_var[
                             '_list_of_settings_names']:
                         varlist.append(settings_name)
     return MARBL_tools.sort(varlist, sort_key=MARBL_tools.natural_sort_key)
예제 #3
0
    def get_subcategory_names(self):
        """ Returns a sorted list of subcategories in a specific category.
            For now, the list is sorted naturally (so 10 appears after 9, not after 1).

            Optional: only return variables in a specific subcategory
        """
        subcat_list = []
        for cat_name in self._settings['_order']:
            for var_name in MARBL_tools.sort(self._settings[cat_name].keys()):
                if isinstance(self._settings[cat_name][var_name]['datatype'],
                              dict):
                    for subvar_name in MARBL_tools.sort(
                            self._settings[cat_name][var_name]
                        ['datatype'].keys()):
                        if subvar_name[0] != '_':
                            this_subcat = self._settings[cat_name][var_name][
                                'datatype'][subvar_name]['subcategory']
                            if this_subcat not in subcat_list:
                                subcat_list.append(this_subcat)
                else:
                    this_subcat = self._settings[cat_name][var_name][
                        'subcategory']
                    if this_subcat not in subcat_list:
                        subcat_list.append(this_subcat)
        return MARBL_tools.sort(subcat_list,
                                sort_key=MARBL_tools.natural_sort_key)
def _get_array_info(array_size_in, settings_dict, tracers_dict, dict_prefix=''):
    """ Return a list of the proper indexing for array elements, e.g.
            ['(1)', '(2)'] for 1D array or
            ['(1,1)', '(2,1)'] for 2D array
        If array_size_in is not an integer, check to see if it is in settings_dict
    """

    logger = logging.getLogger(__name__)

    # List to be returned:
    str_index = []

    # How many dimensions?
    if isinstance(array_size_in, list):
        # Error checking:
        # This script only support 2D arrays for now
        # (and assumes array_size_in is not a list for 1D arrays)
        if len(array_size_in) > 2:
            logger.error("_get_array_info() only supports 1D and 2D arrays")
            MARBL_tools.abort(1)

        for i in range(0, _get_value(array_size_in[0], settings_dict, tracers_dict, dict_prefix)):
            for j in range(0, _get_value(array_size_in[1], settings_dict, tracers_dict, dict_prefix)):
                str_index.append("(%d,%d)" % (i+1,j+1))
        return str_index

    # How many elements? May be an integer or an entry in self.settings_dict
    for i in range(0, _get_value(array_size_in, settings_dict, tracers_dict, dict_prefix)):
        str_index.append("(%d)" % (i+1))
    return str_index
    def _get_tracers(self):
        """ Parses self._settings['_tracer_list'] to determine what tracers
            are enabled given other MARBL settings
        """

        import re

        tracer_dict = dict()
        tracers_to_delete = []

        # 1. tracer_dict should be identical to self._settings['_tracer_list'] except
        #    we expand any templated values such as ((autotroph_sname))
        for tracer_name in self._settings['_tracer_list'].keys():
            if re.search('\(\(.*\)\)', tracer_name) == None:
                tracer_dict[tracer_name] = dict(self._settings['_tracer_list'][tracer_name])
            else:
                tracer_dict.update(MARBL_tools.expand_template_value(tracer_name, self, self._settings['_tracer_list'][tracer_name]))

        # 2. Delete tracers where dependencies are not met
        #    (Some tracers have already been removed via expand_template_value())
        for tracer_name in tracer_dict.keys():
            if not MARBL_tools.meet_dependencies(tracer_dict[tracer_name], self):
                tracers_to_delete.append(tracer_name)
                continue

            # 3. Add tend_units and flux_units to dictionary
            tracer_dict[tracer_name][u'tend_units'] = tracer_dict[tracer_name]['units'] + '/s'
            tracer_dict[tracer_name][u'flux_units'] = tracer_dict[tracer_name]['units'] + ' cm/s'

        for tracer_name in tracers_to_delete:
            del tracer_dict[tracer_name]

        return tracer_dict
예제 #6
0
    def __init__(self,
                 default_settings_file,
                 saved_state_vars_source="settings_file",
                 grid=None,
                 input_file=None):
        """ Class constructor: set up a dictionary of config keywords for when multiple
            default values are provided, read the JSON file, and then populate
            self.settings_dict and self.tracers_dict.
        """

        logger = logging.getLogger(__name__)

        # 1. List of configuration keywords to match in JSON if default_default is a dictionary
        self._config_keyword = []
        if grid != None:
            self._config_keyword.append('GRID == "%s"' % grid)
        self._config_keyword.append('SAVED_STATE_VARS_SOURCE == "%s"' %
                                    saved_state_vars_source)

        # 2. Read settings JSON file
        import json
        with open(default_settings_file) as settings_file:
            self._settings = json.load(settings_file)

        # 3 Make sure JSON file adheres to MARBL settings file schema
        if not MARBL_tools.settings_dictionary_is_consistent(self._settings):
            logger.error("%s is not a valid MARBL settings file" %
                         default_settings_file)
            MARBL_tools.abort(1)

        # 4. Read settings input file
        self._input_dict = _parse_input_file(input_file)

        # 5. Use an ordered dictionary for keeping variable, value pairs
        #    Also, tracer information is in its own dictionary (initialized to None)
        from collections import OrderedDict
        self.settings_dict = OrderedDict()
        self.tracers_dict = None
        for cat_name in self.get_category_names():
            for var_name in self.get_variable_names(cat_name):
                self._process_variable_value(cat_name, var_name)
            # 5b. Need tracer count after determining PFT_derived_types, which means
            #     determining which tracers are active
            if cat_name == "PFT_derived_types":
                self.tracers_dict = self._get_tracers()

        # 6. Abort if not all values from input file were processed
        #    (That implies at least one variable from input file was not recognized)
        if (self._input_dict):
            message = "Did not fully parse input file:"
            for varname in self._input_dict.keys():
                message = message + "\n     * Variable %s not found in JSON file" % varname
                message = message + "\n       (this was a case-insensitive lookup)"
            logger.error(message)
            MARBL_tools.abort(1)
def _sort_with_specific_suffix_first(list_in, suffix=None, sort_key=lambda s: s.lower()):
    """ Sort, but make sure entries that end in a specified suffix are listed first
    """

    # 1. initialize empty list
    list_out = []

    # 2. Anything that ends in suffix gets appended to list_out first
    if suffix is not None:
        for list_entry in MARBL_tools.sort(list_in, sort_key):
            if list_entry.endswith(suffix):
                list_out.append(list_entry)

    # 3. Sort everything else
    for list_entry in MARBL_tools.sort(list_in, sort_key):
        if list_entry not in list_out:
            list_out.append(list_entry)
    return list_out
예제 #8
0
def _parse_input_file(input_file):
    """ 1. Read an input file; ignore blank lines and non-quoted Fortran comments.
        2. Turn lines of the form
              variable = value
           Into input_dict['variable'] = value
        3. Return input_dict
    """
    input_dict = dict()
    logger = logging.getLogger(__name__)

    try:
        f = open(input_file, "r")
        for line in f:
            # Ignore comments in input file!
            line_loc = _string_to_substring(line, '!')[0]

            # ignore empty lines
            if len(line_loc.lstrip()) == 0:
                continue

            line_list = line_loc.strip().split('=')
            # keys in input_dict are all lowercase to allow case-insensitive match
            var_name = line_list[0].strip().lower()
            value = line_list[1].strip()
            val_array = _string_to_substring(value, ',')
            if len(val_array) > 1:
                # Treat comma-delimited value as an array
                for n, value in enumerate(val_array):
                    suffix = "(%d)" % (n + 1)
                    input_dict[var_name + suffix] = value.strip()
            else:
                # Single value
                input_dict[var_name] = value
        f.close()
    except TypeError:
        # If inputfile == None then the open will result in TypeError
        pass
    except:
        logger.error("input_file '%s' was not found" % input_file)
        MARBL_tools.abort(1)
    return input_dict
예제 #9
0
    def get_category_names(self):
        """ Returns category names as determined by the '_order' key in JSON file
        """

        # Consistency checks:
        # 1. All keys listed in self._settings["_order"] should also be in self._settings.keys()
        for key in self._settings["_order"]:
            if key not in self._settings.keys():
                msg = "ERROR: can not find '" + key + "' in JSON file"
                MARBL_tools.abort(msg)

        # 2. All keys listed in self._settings.keys() should also be in self._settings["_order"]
        #    (except _order itself)
        for key in self._settings.keys():
            if key not in ["_order", "_tracer_list"
                           ] and key not in self._settings["_order"]:
                msg = "ERROR: '" + key + "' is not listed in '_order' and won't be processed"
                MARBL_tools.abort(msg)

        # 3. No duplicates in _order
        unique_keys = []
        for key in self._settings["_order"]:
            if key in unique_keys:
                msg = "ERROR: '" + key + "' appears in '_order' multiple times"
                MARBL_tools.abort(msg)
            unique_keys.append(key)

        return self._settings["_order"]
예제 #10
0
 def get_variable_names(self, category_name, sort_key=lambda s: s.lower()):
     """ Returns a sorted list of variables in a specific category.
         For now, the list is sorted alphabetically.
     """
     return MARBL_tools.sort(self._settings[category_name].keys(), sort_key)