Example #1
0
 def register_from_cfg(self, cfg):
     """"Register new elements from a :class:`ConfigObj` instance
     or a config file"""
     if isinstance(cfg, dict) and self.category not in cfg.keys():
         cfg = {self.category:cfg}
     local_cfg = CF_CFGM.load(cfg)[self.category]
     self._dict = dict_merge(self._dict, local_cfg,
         cls=OrderedDict, **CF_DICT_MERGE_KWARGS)
     self._post_process_()
Example #2
0
    def load_formula_terms(self, formula_terms=None, at=None, mode='noerr'):
        """Read formula terms at T and W points and store them in
        the dictionary attribute :attr:`formula_terms` whose keys are 't' and 'w'
        """

        # String from file
        formula_terms_from_file = {}
        for at_, levelvar in list(self.levelvars.items()):
            if at and at!=at_:
                continue
            formula_terms_from_file[at_] = getattr(levelvar, "formula_terms", {})

        # Specified
        if not formula_terms:
           formula_terms = {}
        elif (isinstance(formula_terms, (str, list, tuple)) or
                (isinstance(formula_terms, dict) and
                    't' not in formula_terms and 'w' not in formula_terms)):
            formula_terms = {'t':formula_terms}

        # Scan formulas
        self.formula_terms = {}
        for at_ in 'wt':

            # Check position
            if at and at!=at_:
                continue

            # To dicts
            file_formula_terms = self._ft_to_dict_(formula_terms.get(at_, {}))
            spec_formula_terms = self._ft_to_dict_(formula_terms_from_file.get(at_, {}))

            # Merge
            self.formula_terms[at_] = dict_merge(spec_formula_terms, file_formula_terms)

            # Check if empty when required
            if at and not self.formula_terms[at_]:
                vcwarn('No formula term for {} position'.format(at_))

            # Patch names for eta and depth into self.names
            for name in self.horiz_terms:
                if name in self.formula_terms[at_]:
                    self.names[name] = self.formula_terms[at_][name]

        # Final check
        if (not self.formula_terms or
                not any([bool(ct) for ct in list(self.formula_terms.values())])):
            vcwarn('No formula term currently loaded')
Example #3
0
def dupl_loc_specs(all_specs, fromname, toloc):
    """Duplicate the specification for a variable or an axis to another or several locations

    The following rules apply:

        - If the original specifications are from a name without a specific location
          (generic), new specs (located) are appended (merged) with original specs.
        - If the specifications at target location already exist,
          it merges new specs with old specs.
        - Generic specification are systematically created or updated by merging of
          specialized ones.

    :Example:

        >>> dupl_loc_specs(CF_VAR_SPECS, 'corio', 'u') # Create the 'corio_u' entry in CF_VAR_SPECS and update 'corio'
        >>> dupl_loc_specs(CF_VAR_SPECS, 'corio_t', 'u') # Create 'corio_u' and 'corio_t'

    """
    if not fromname in all_specs:
        raise KeyError('No such entry in specifications: ' + fromname)
    single = not isinstance(toloc, (list, tuple))
    if single:
        toloc = [toloc]
    tonames = []
    tomerge = []
    fromnoloc = no_loc_single(fromname, 'id') == fromname
    for loc in toloc:

        # New name (id)
        toname = change_loc_single(fromname, 'id', loc)
        tonames.append(toname)

        # New specs
        tospecs = change_loc_specs(loc, **all_specs[fromname])

        # Add a version of standard_name and long_name for T loc without location spec
        if loc == 't':  # 'toto_at_t_location' -> ['toto_at_t_location','toto']
            for spname in 'standard_name', 'long_name':
                if spname not in tospecs: continue
                addspecs = change_loc_specs(None, **{spname: tospecs[spname]})
                for dd in tospecs, addspecs:  # to lists
                    if not isinstance(dd[spname], list):
                        dd[spname] = [dd[spname]]
                tospecs[spname].extend(addspecs[spname])

        # For merging specs back with old specs if old has no location
#        if fromnoloc: # generic
        tomerge.append(tospecs)

        # Merge with old spec if existing
        if toname in all_specs:
            tospecs = dict_merge(
                tospecs,
                all_specs[toname],
                mergelists=True,
                cls=dict,
                mergedicts=True,
            )

#        # Default location -> add its generic version ('_t' -> + '')
#        if loc==DEFAULT_LOCATION:
#            genspecs = change_loc_specs(None, **tospecs)
#            tospecs = dict_merge(tospecs, genspecs, mergelists=True)

# Remove atlocs attribute
        if 'atlocs' in tospecs:
            tospecs.pop('atlocs')

        # Store it
        all_specs[toname] = tospecs

    # Make a generic entry that merges all specialized ones
    if fromnoloc:
        genspecs = all_specs[fromname]  # existing generic specs
    else:
        genspecs = change_loc_specs(
            None, **all_specs[fromname])  # remove location info
    tomerge.insert(0, genspecs)
    genname = genspecs['id'][0]
    all_specs[genname] = dict_merge(*tomerge, **CF_DICT_MERGE_KWARGS)

    if single: return tonames[0]
    return tonames
Example #4
0
    def _check_entry_(self, name):
        """Validate an entry

        - Makes sure to have lists, except for 'axis' and 'inherit'
        - Check geo axes
        - Check inheritance
        - Makes sure that axes specs have no 'axes' key
        - Makes sure that specs key is the first entry of 'names'
        - add standard_name to list of names
        - Check duplication to other locations ('toto' -> 'toto_u')

        """
        # Wrong entry!
        if name not in self:
            return

        # Entry already generated with the atlocs key
        if name in self._from_atlocs:
            return

        # Get the specs
        if hasattr(self._dict[name], 'dict'):
            self._dict[name] = self._dict[name].dict()
        specs = self._dict[name]

        # Ids
        if name in specs['id']:
            specs['id'].remove(name)
        specs['id'].insert(0, name)
        if name == 'mld':
            pass

        # Long name
        if not specs['long_name']:
            specs['long_name'].append(name.title().replace('_', ' '))

        # Physloc must be the first atlocs
        if 'physloc' in specs and 'atlocs' in specs:
            p = specs['physloc']
            if p:
                if p in specs['atlocs']:
                    specs['atlocs'].remove(p)
                specs['atlocs'].insert(0, p)

        # Geo axes (variables only)
        if 'axes' in specs:
            specs['axes'].setdefault('t', ['time'])
            suffixes = [('_' + s) for s in 'rftuv']
            specs['axes'].setdefault(
                'y', [cp_suffix(name, 'lat', suffixes=suffixes)])
            specs['axes'].setdefault(
                'x', [cp_suffix(name, 'lon', suffixes=suffixes)])
            for l, n in ('t', 'time'), ('y', 'lat'), ('x', 'lon'):
                if isinstance(specs['axes'][l],
                              list) and n not in specs['axes'][l]:
                    specs['axes'][l].append(n)

        # Inherits from other specs (merge specs with dict_merge)
        if name == 'mld':
            pass
        if specs['inherit']:
            from_name = specs['inherit']
            from_specs = None
            to_scan = []
            if self._inherit:
                to_scan.append(self._inherit)
            to_scan.append(self)
            for from_specs in to_scan:
                if from_name in from_specs:

                    # Merge
                    self._dict[name] = specs = dict_merge(
                        specs,
                        from_specs[from_name],
                        cls=dict,
                        **CF_DICT_MERGE_KWARGS)

                    # Validate
                    #                    if from_specs is not self:
                    for key in specs.keys():
                        if key not in self._cfgspec:
                            del specs[key]


#                    break

# Standard_names in ids
        if name == 'mld':
            pass
        if specs['standard_name']:
            for standard_name in specs['standard_name']:
                if standard_name not in specs['id']:
                    specs['id'].append(standard_name)

        # Duplicate at other locations
        if specs['atlocs']:
            tonames = dupl_loc_specs(self._dict, name, specs['atlocs'])
            self._from_atlocs.extend(tonames)
            specs = self._dict[name]
Example #5
0
def dupl_loc_specs(all_specs, fromname, toloc):
    """Duplicate the specification for a variable or an axis to another or several locations

    The following rules apply:

        - If the original specifications are from a name without a specific location
          (generic), new specs (located) are appended (merged) with original specs.
        - If the specifications at target location already exist,
          it merges new specs with old specs.
        - Generic specification are systematically created or updated by merging of
          specialized ones.

    :Example:

        >>> dupl_loc_specs(VAR_SPECS, 'corio', 'u') # Create the 'corio_u' entry in VAR_SPECS and update 'corio'
        >>> dupl_loc_specs(VAR_SPECS, 'corio_t', 'u') # Create 'corio_u' and 'corio_t'

    """
    if not fromname in all_specs:
        raise KeyError('No such entry in specifications: '+fromname)
    single = not isinstance(toloc, (list, tuple))
    if single:
        toloc = [toloc]
    tonames = []
    tomerge = []
    fromnoloc = no_loc_single(fromname, 'name')==fromname
    for loc in toloc:

        # New name (id)
        toname = change_loc_single(fromname, 'name', loc)
        tonames.append(toname)

        # New specs
        tospecs = change_loc_specs(loc, **all_specs[fromname])

        # Add a version of standard_name and long_name for T loc without location spec
        if loc=='t': # 'toto_at_t_location' -> ['toto_at_t_location','toto']
            for spname in 'standard_names', 'long_names':
                if spname not in tospecs: continue
                addspecs = change_loc_specs(None, **{spname:tospecs[spname]})
                for dd in tospecs, addspecs: # to lists
                    if not isinstance(dd[spname], list):
                        dd[spname] = [dd[spname]]
                tospecs[spname].extend(addspecs[spname])

        # For merging specs back with old specs if old has no location
#        if fromnoloc: # generic
        tomerge.append(tospecs)

        # Merge with old spec if existing
        if toname in all_specs:
            tospecs = dict_merge(tospecs, all_specs[toname], mergelists=True)

#        # Default location -> add its generic version ('_t' -> + '')
#        if loc==DEFAULT_LOCATION:
#            genspecs = change_loc_specs(None, **tospecs)
#            tospecs = dict_merge(tospecs, genspecs, mergelists=True)

        # Remove atlocs attribute
        if 'atlocs' in tospecs:
            tospecs.pop('atlocs')

        # Store it
        all_specs[toname] = tospecs

    # Make a generic entry that merges all specialized ones
    if fromnoloc:
        genspecs = all_specs[fromname] # existing generic specs
    else:
        genspecs = change_loc_specs(None, **all_specs[fromname]) # remove location info
    tomerge.insert(0, genspecs)
    kw = dict(mergelists=True)
    genname = genspecs['names'][0]
    all_specs[genname] = dict_merge(*tomerge, **kw)

    if single: return tonames[0]
    return tonames
Example #6
0
        # Inherits from other specs (merge specs with dict_merge)
        if 'inherit' in specs:
            objname = specs['inherit']
            obj_specs = None
            if name==objname: # same name
                if all_specs is VAR_SPECS and objname in AXIS_SPECS:
                    obj_specs = AXIS_SPECS
                elif all_specs is AXIS_SPECS and objname in VAR_SPECS:
                    obj_specs = VAR_SPECS
            elif objname in VAR_SPECS: # check in VAR_SPECS first
                obj_specs = VAR_SPECS
            elif objname in AXIS_SPECS: # then in AXIS_SPECS
                obj_specs = AXIS_SPECS
            if obj_specs is not None:
                all_specs[name] = specs = dict_merge(specs, obj_specs[objname])

        # No geo axes for axes!
        if all_specs is AXIS_SPECS and 'axes' in specs:
            del specs['axes']

        # Key = first name (id)
        if name in specs['names']:
            specs['names'].remove(name)
        specs['names'].insert(0, name)

        # Standard_names in names
        if ('standard_names' in specs and specs['standard_names']):
            for standard_name in specs['standard_names']:
                if standard_name not in specs['names']:
                    specs['names'].append(standard_name)