def _cleanup_our_var(var_): if hasattr(var_, attr_name): # cleanup placeholder attr if our var was altered var_.value, new_units = getattr(var_, attr_name) var_.units = units.to_cfunits(new_units) _log.debug("Updated (value, units) of '%s' to (%s, %s).", var_.name, var_.value, var_.units) delattr(var_, attr_name)
def edit_request(self, v, pod, data_mgr): """Edit *pod*\'s Varlist prior to query. If the :class:`~src.diagnostic.VarlistEntry` *v* has a ``standard_name`` in the recognized list, insert an alternate VarlistEntry whose translation requests the complementary type of variable (i.e., if given rate, add an entry for flux; if given flux, add an entry for rate.) The signature of this method is altered by the :func:`edit_request_wrapper` decorator. """ std_name = getattr(v, 'standard_name', "") if std_name not in self._rate_d and std_name not in self._flux_d: # logic not applicable to this VE; do nothing return None # construct dummy var to translate (rather than modifying std_name & units) # on v's translation) because v may not have a translation if std_name in self._rate_d: # requested rate, so add alternate for flux v_to_translate = copy_as_alternate( v, data_mgr, standard_name=self._rate_d[std_name], units=units.to_cfunits(v.units) * self._liquid_water_density) elif std_name in self._flux_d: # requested flux, so add alternate for rate v_to_translate = copy_as_alternate( v, data_mgr, standard_name=self._flux_d[std_name], units=units.to_cfunits(v.units) / self._liquid_water_density) translate = core.VariableTranslator() try: new_tv = translate.translate(data_mgr.attrs.convention, v_to_translate) except KeyError as exc: pod.log.debug(("%s edit_request on %s: caught %r when trying to " "translate '%s'; varlist unaltered."), self.__class__.__name__, v.full_name, exc, v_to_translate.standard_name) return None new_v = copy_as_alternate(v, data_mgr) new_v.translation = new_tv return new_v
def edit_request(self, v, pod, data_mgr): """Edit the POD's Varlist prior to query. If v has a standard_name in the list above, insert an alternate varlist entry whose translation requests the complementary type of variable (ie, if given rate, add an entry for flux; if given flux, add an entry for rate.) """ std_name = getattr(v, 'standard_name', "") if std_name not in self._rate_d and std_name not in self._flux_d: # logic not applicable to this VE; do nothing return None # construct dummy var to translate (rather than modifying std_name & units) # on v's translation) because v may not have a translation if std_name in self._rate_d: # requested rate, so add alternate for flux v_to_translate = copy_as_alternate( v, data_mgr, standard_name = self._rate_d[std_name], units = units.to_cfunits(v.units) / self._liquid_water_density ) elif std_name in self._flux_d: # requested flux, so add alternate for rate v_to_translate = copy_as_alternate( v, data_mgr, standard_name = self._flux_d[std_name], units = units.to_cfunits(v.units) * self._liquid_water_density ) translate = core.VariableTranslator() try: new_tv = translate.translate(data_mgr.convention, v_to_translate) except KeyError as exc: _log.debug(("%s edit_request on %s: caught %r when trying to translate " "'%s'; varlist unaltered."), self.__class__.__name__, v.full_name, exc, v_to_translate.standard_name) return None new_v = copy_as_alternate(v, data_mgr) new_v.translation = new_tv return new_v
def check_names_and_units(self, our_var, ds, ds_var_name, update_name=False): """Reconcile the standard_name and units attributes between the 'ground truth' of the dataset we downloaded (*ds_var*) and our expectations based on the model's convention (*our_var*). """ # check name if ds_var_name not in ds: raise ValueError( f"Variable name '{ds_var_name}' not found in dataset: " f"({list(ds.variables)}).") # attempt to match on standard_name? self.check_name(our_var, ds_var_name, update_name=update_name) ds_var = ds[ds_var_name] # abbreviate # check CF standard_name # see if standard_name has been stored in a nonstandard attribute # check_attr will set missing attr on ds _ = self.normalize_attr('standard_name', 'standard', ds_var.attrs) self.check_attr(our_var, ds_var, 'standard_name', update_our_var=True, update_ds=True) # check units (and scalar coord value, if set) is_scalar = hasattr(our_var, 'is_scalar') and our_var.is_scalar # see if units has been stored in a nonstandard attribute # check_attr will set missing attr on ds _ = self.normalize_attr('units', 'unit', ds_var.attrs, "") # if units inequivalent, raise TypeError if is_scalar: self.check_scalar_coord_value(our_var, ds_var, equivalent=True) else: self.check_attr(our_var, ds_var, 'units', comparison_func=units.units_equivalent, update_our_var=True, update_ds=True) # now check equality of units - not an error, since we can convert try: if is_scalar: # test equality of quantities+units self.check_scalar_coord_value(our_var, ds_var, equivalent=False) else: # test units only, not quantities+units self.check_attr(our_var, ds_var, 'units', comparison_func=units.units_equal, update_our_var=True, update_ds=True) except TypeError as exc: _log.warning(exc) our_var.units = units.to_cfunits(our_var.units)