def test_wrapped_indicator(tas_series): def indice(tas, tas2=None, thresh=0, freq="YS"): if tas2 is None: out = tas < thresh else: out = tas < tas2 out = out.resample(time="YS").sum() out.attrs["units"] = "days" return out ind1 = Daily( realm="atmos", identifier="test_ind1", nvar=1, units="days", compute=wrapped_partial(indice, tas2=None), ) ind2 = Daily( realm="atmos", identifier="test_ind2", nvar=2, units="days", compute=wrapped_partial(indice, thresh=None), ) tas = tas_series(np.arange(366), start="2000-01-01") tas2 = tas_series(1 + np.arange(366), start="2000-01-01") assert ind2(tas, tas2) == 366 assert ind1(tas, thresh=1111) == 366
def test_resamplingIndicator_new_error(): with pytest.raises(ValueError, match="ResamplingIndicator require a 'freq'"): Daily( realm="atmos", identifier="multiopt", cf_attrs=[dict(units="K")], module="test", compute=multioptvar_compute, )
def test_indicator_from_dict(): d = dict( realm="atmos", output=dict( var_name="tmean{thresh}", units="K", long_name="{freq} mean surface temperature", standard_name="{freq} mean temperature", cell_methods=[{ "time": "mean within days" }], ), index_function=dict( name="thresholded_statistics", parameters=dict( threshold={ "data": { "thresh": None }, "description": "A threshold temp" }, condition={"data": "`<"}, reducer={"data": "mean"}, ), ), input={"data": "tas"}, ) ind = Daily.from_dict(d, identifier="tmean", module="test") assert ind.realm == "atmos" # Parameters metadata modification assert ind.parameters["threshold"]["description"] == "A threshold temp" # Injection of paramters assert "condition" in ind.compute._injected # Placeholders were translated to name in signature assert ind.cf_attrs[0]["var_name"] == "tmean{threshold}" # Default value for input variable injected and meta injected assert ind._sig.parameters["data"].default == "tas" assert ind.parameters["data"]["units"] == "[temperature]" # Cf checks were generated assert ind.cfcheck is not Daily.cfcheck
def test_indicator_from_dict(): d = dict( realm="atmos", cf_attrs=dict( var_name="tmean{threshold}", units="K", long_name="{freq} mean surface temperature", standard_name="{freq} mean temperature", cell_methods=[{ "time": "mean within days" }], ), compute="thresholded_statistics", parameters=dict( threshold={"description": "A threshold temp"}, condition="<", reducer="mean", ), input={"data": "tas"}, ) ind = Daily.from_dict(d, identifier="tmean", module="test") assert ind.realm == "atmos" # Parameters metadata modification assert ind.parameters["threshold"].description == "A threshold temp" # Injection of paramters assert ind.injected_parameters["condition"] == "<" # Default value for input variable injected and meta injected assert ind._variable_mapping["data"] == "tas" assert signature(ind).parameters["tas"].default == "tas" assert ind.parameters["tas"].units == "K" # Wrap a multi-output ind d = dict(base="wind_speed_from_vector") ind = Indicator.from_dict(d, identifier="wsfv", module="test")
fire_weather_indexes = Daily( _nvar=4, identifier="fwi", realm="atmos", var_name=["dc", "dmc", "ffmc", "isi", "bui", "fwi"], standard_name=[ "drought_code", "duff_moisture_code", "fine_fuel_moisture_code", "initial_spread_index", "buildup_index", "fire_weather_index", ], long_name=[ "Drought Code", "Duff Moisture Code", "Fine Fuel Moisture Code", "Initial Spread Index", "Buildup Index", "Fire Weather Index", ], description=[ "Numeric rating of the average moisture content of deep, compact organic layers. Computed with start up method {start_up_mode}", "Numeric rating of the average moisture content of loosely compacted organic layers of moderate depth. Computed with start up method {start_up_mode}", "Numeric rating of the average moisture content of litter and other cured fine fuels. Computed with start up method {start_up_mode}", "Numeric rating of the expected rate of fire spread.", "Numeric rating of the total amount of fuel available for combustion.", "Numeric rating of fire intensity.", ], units="", compute=indices.fire_weather_indexes, missing="skip", )
def test_indicator_errors(): def func(data: xr.DataArray, thresh: str = "0 degC", freq: str = "YS"): return data doc = [ "The title", "", " The abstract", "", " Parameters", " ----------", " data : xr.DataArray", " A variable.", " thresh : str", " A threshold", " freq : str", " The resampling frequency.", "", " Returns", " -------", " xr.DataArray, [K]", " An output", ] func.__doc__ = "\n".join(doc) d = dict( realm="atmos", cf_attrs=dict( var_name="tmean{threshold}", units="K", long_name="{freq} mean surface temperature", standard_name="{freq} mean temperature", cell_methods=[{ "time": "mean within days" }], ), compute=func, input={"data": "tas"}, ) ind = Daily(identifier="indi", module="test", **d) with pytest.raises(AttributeError, match="`identifier` has not been set"): Daily(**d) d["identifier"] = "bad_indi" d["module"] = "test" bad_doc = doc[:12] + [" extra: bool", " Woupsi"] + doc[12:] func.__doc__ = "\n".join(bad_doc) with pytest.raises(ValueError, match="Malformed docstring"): Daily(**d) func.__doc__ = "\n".join(doc) d["parameters"] = {} d["parameters"]["thresh"] = "1 degK" d["parameters"]["extra"] = "woopsi again" with pytest.raises(ValueError, match="Parameter 'extra' was passed but it does"): Daily(**d) del d["parameters"]["extra"] d["input"]["data"] = "3nsd6sk72" with pytest.raises(ValueError, match="Compute argument data was mapped to"): Daily(**d) d2 = dict(input={"tas": "sfcWind"}) with pytest.raises(ValueError, match="When changing the name of a variable by"): ind.__class__(**d2) del d["input"] with pytest.raises(ValueError, match="variable data is missing expected units"): Daily(**d) d["parameters"]["thresh"] = {"units": "K"} d["realm"] = "mercury" d["input"] = {"data": "tasmin"} with pytest.raises(AttributeError, match="Indicator's realm must be given as one"): Daily(**d) def func(data: xr.DataArray, thresh: str = "0 degC"): return data func.__doc__ = "\n".join(doc[:10] + doc[12:]) d = dict( realm="atmos", cf_attrs=dict( var_name="tmean{threshold}", units="K", long_name="{freq} mean surface temperature", standard_name="{freq} mean temperature", cell_methods=[{ "time": "mean within days" }], ), compute=func, input={"data": "tas"}, ) with pytest.raises(ValueError, match="ResamplingIndicator require a 'freq'"): ind = Daily(identifier="indi", module="test", **d)
def test_multiindicator(tas_series): tas = tas_series(np.arange(366), start="2000-01-01") tmin, tmax = multiTemp(tas, freq="YS") assert tmin[0] == tas.min() assert tmax[0] == tas.max() assert tmin.attrs["standard_name"] == "Min temp" assert tmin.attrs["description"] == "Grouped computation of tmax and tmin" assert tmax.attrs["description"] == "Grouped computation of tmax and tmin" assert multiTemp.units == ["K", "K"] # Attrs passed as keywords - together ind = Daily( realm="atmos", identifier="minmaxtemp2", cf_attrs=[ dict( var_name="tmin", units="K", standard_name="Min temp", description="Grouped computation of tmax and tmin", ), dict( var_name="tmax", units="K", description="Grouped computation of tmax and tmin", ), ], compute=multitemp_compute, ) tmin, tmax = ind(tas, freq="YS") assert tmin[0] == tas.min() assert tmax[0] == tas.max() assert tmin.attrs["standard_name"] == "Min temp" assert tmin.attrs["description"] == "Grouped computation of tmax and tmin" assert tmax.attrs["description"] == "Grouped computation of tmax and tmin" with pytest.raises(ValueError, match="Output #2 is missing a var_name!"): ind = Daily( realm="atmos", identifier="minmaxtemp2", cf_attrs=[ dict( var_name="tmin", units="K", ), dict(units="K", ), ], compute=multitemp_compute, ) # Attrs passed as keywords - individually ind = Daily( realm="atmos", identifier="minmaxtemp3", var_name=["tmin", "tmax"], units="K", standard_name=["Min temp", ""], description="Grouped computation of tmax and tmin", compute=multitemp_compute, ) tmin, tmax = ind(tas, freq="YS") assert tmin[0] == tas.min() assert tmax[0] == tas.max() assert tmin.attrs["standard_name"] == "Min temp" assert tmin.attrs["description"] == "Grouped computation of tmax and tmin" assert tmax.attrs["description"] == "Grouped computation of tmax and tmin" assert ind.units == ["K", "K"] # All must be the same length with pytest.raises(ValueError, match="Attribute var_name has 2 elements"): ind = Daily( realm="atmos", identifier="minmaxtemp3", var_name=["tmin", "tmax"], units="K", standard_name=["Min temp"], description="Grouped computation of tmax and tmin", compute=uniindpr_compute, ) ind = Daily( realm="atmos", identifier="minmaxtemp4", var_name=["tmin", "tmax"], units="K", standard_name=["Min temp", ""], description="Grouped computation of tmax and tmin", compute=uniindtemp_compute, ) with pytest.raises(ValueError, match="Indicator minmaxtemp4 was wrongly defined"): tmin, tmax = ind(tas, freq="YS")
freq: str = "YS"): """Docstring""" out = da - convert_units_to(thresh, da) out = out.resample(time=freq).mean() out.attrs["units"] = da.units return out uniIndTemp = Daily( realm="atmos", identifier="tmin", module="test", cf_attrs=[ dict( var_name="tmin{thresh}", units="K", long_name="{freq} mean surface temperature", standard_name="{freq} mean temperature", cell_methods="time: mean within {freq:noun}", another_attr="With a value.", ) ], compute=uniindtemp_compute, ) @declare_units(da="[precipitation]") def uniindpr_compute(da: xr.DataArray, freq: str): """Docstring""" return da.resample(time=freq).mean(keep_attrs=True)