def calculate(self, values, threshold=15): """ Return the number of freeze-thaw transitions. A value of 2 corresponds to a complete cycle (frozen-thawed-frozen). :param threshold: The number of degree-days above or below the freezing point after which the ground is considered frozen or thawed. """ assert (len(values.shape) == 3) # Check temporal resolution t = self.field['time'].get_value()[:2] step = t[1] - t[0] if type(step) == dt.timedelta: assert step == dt.timedelta(days=1) else: if self.field['time'].units.startswith('days'): assert step == 1 else: raise NotImplementedError # Unit conversion units = self.field.data_variables[0].units if get_are_units_equal_by_string_or_cfunits(units, 'C', try_cfunits=env.USE_CFUNITS): tas = values elif get_are_units_equal_by_string_or_cfunits(units, 'K', try_cfunits=env.USE_CFUNITS): tas = values - 273.15 out = np.apply_along_axis(freezethaw1d, 0, tas, threshold=threshold) return np.ma.masked_invalid(out)
def calculate(self, values, threshold=15): """ Return the number of freeze-thaw transitions. A value of 2 corresponds to a complete cycle (frozen-thawed-frozen). :param threshold: The number of degree-days above or below the freezing point after which the ground is considered frozen or thawed. """ assert (len(values.shape) == 3) # Check temporal resolution t = self.field['time'].get_value()[:2] step = t[1] - t[0] if type(step) == dt.timedelta: assert step == dt.timedelta(days=1) else: if self.field['time'].units.startswith('days'): assert step == 1 else: raise NotImplementedError # Unit conversion units = self.field.data_variables[0].units if get_are_units_equal_by_string_or_cfunits( units, 'C', try_cfunits=env.USE_CFUNITS): tas = values elif get_are_units_equal_by_string_or_cfunits( units, 'K', try_cfunits=env.USE_CFUNITS): tas = values - 273.15 out = np.apply_along_axis(freezethaw1d, 0, tas, threshold=threshold) return np.ma.masked_invalid(out)
def validate_units(self, variable): if self.required_units is not None: matches = [get_are_units_equal_by_string_or_cfunits(variable.units, target, try_cfunits=env.USE_CFUNITS) \ for target in self.required_units] if not any(matches): raise UnitsValidationError(variable, self.required_units, self.key)
def validate_units(self, variable): if self.required_units is not None: matches = [ get_are_units_equal_by_string_or_cfunits(variable.units, target, try_cfunits=True) for target in self.required_units ] if not any(matches): raise (UnitsValidationError(variable, self.required_units, self.key))
def test_get_are_units_equal_by_string_or_cfunits(self): _try_cfunits = [True, False] source = 'K' target = 'K' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=try_cfunits) self.assertTrue(match) source = 'K' target = 'Kelvin' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=try_cfunits) # cfunits.Units will allow comparison of abbreviated and full name form while string comparison will not if try_cfunits: self.assertTrue(match) else: self.assertFalse(match)
def test_get_are_units_equal_by_string_or_cfunits(self): _try_cfunits = [True, False] source = 'K' target = 'K' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=try_cfunits) self.assertTrue(match) source = 'K' target = 'Kelvin' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=try_cfunits) # CF units packages will allow comparison of abbreviations. if try_cfunits: self.assertTrue(match) else: self.assertFalse(match)
def validate_units(self): if self.required_units is not None: for required_variable in self.required_variables: alias_variable = self.parms[required_variable] variable = self.field[alias_variable] source = variable.units target = self.required_units[required_variable] match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=env.USE_CFUNITS) if not match: raise UnitsValidationError(variable, target, self.key)
def validate_units(self): if self.required_units is not None: for required_variable in self.required_variables: alias_variable = self.parms[required_variable] variable = self.field.variables[alias_variable] source = variable.units target = self.required_units[required_variable] match = get_are_units_equal_by_string_or_cfunits(source, target, try_cfunits=True) if match == False: raise UnitsValidationError(variable, target, self.key)
def test_get_are_units_equal_by_string_or_cfunits(self): _try_cfunits = [True, False] source = 'K' target = 'K' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits( source, target, try_cfunits=try_cfunits) self.assertTrue(match) source = 'K' target = 'Kelvin' for try_cfunits in _try_cfunits: match = get_are_units_equal_by_string_or_cfunits( source, target, try_cfunits=try_cfunits) # CF units packages will allow comparison of abbreviations. if try_cfunits: self.assertTrue(match) else: self.assertFalse(match)
def calculate(self, values, threshold=15): """ Return the number of freeze-thaw transitions. A value of 2 corresponds to a complete cycle (frozen-thawed-frozen). :param threshold: The number of degree-days above or below the freezing point after which the ground is considered frozen or thawed. """ assert (len(values.shape) == 3) # Check temporal resolution t = self.field['time'].get_value()[:2] step = t[1] - t[0] assert step == dt.timedelta(days=1) # Unit conversion units = self.field.data_variables[0].units if get_are_units_equal_by_string_or_cfunits( units, 'C', try_cfunits=env.USE_CFUNITS): tas = values elif get_are_units_equal_by_string_or_cfunits( units, 'K', try_cfunits=env.USE_CFUNITS): tas = values - 273.15 # Storage array for count shp_out = values.shape[-2:] out = np.zeros(shp_out, dtype=int).flatten() # Actual computations, grid cell by grid cell. for ii, (rowidx, colidx) in enumerate( iter_array(values[0, :, :], use_mask=True)): x = tas[:, rowidx, colidx].reshape(-1) out[ii] = freezethaw1d(x, threshold) out.resize(shp_out) # update the output mask. this only applies to geometries so pick the # first masked time field out = np.ma.array(out, mask=values.mask[0, :, :]) return out