Skip to content

Commit

Permalink
Test conversions (#372)
Browse files Browse the repository at this point in the history
<!-- Please ensure the PR fulfills the following requirements! -->
<!-- If this is your first PR, make sure to add your details to the
AUTHORS.rst! -->
### Pull Request Checklist:
- [x] This PR addresses an already opened issue (for bug fixes /
features)
    - This PR fixes #xyz
- [x] (If applicable) Documentation has been added / updated (for bug
fixes / features).
- [x] (If applicable) Tests have been added.
- [x] This PR does not seem to break the templates.
- [x] CHANGES.rst has been updated (with summary of main changes).
- [x] Link to issue (:issue:`number`) and pull request (:pull:`number`)
has been added.

### What kind of change does this PR introduce?

* Tests for `xclim_modules/conversions.py`
* Added `context="hydro"` to the precipitation conversion.
* Fixed a bug in `tasmin/max_from_dtr` when `dtr` was in different units
than `tasmin/max`.

### Does this PR introduce a breaking change?

* I changed `dtr` (the function) to `dtr_from_minmax` to avoid conflicts
with `dtr` (the variable). This is only breaking if people directly used
the Python file, which should be no one.


### Other information:
  • Loading branch information
RondeauG authored Mar 21, 2024
2 parents c7308ab + 5c6c8fe commit 0bae81b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 8 deletions.
4 changes: 3 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ Breaking changes
^^^^^^^^^^^^^^^^
* Removed support for the old instances of the `region` argument in ``spatial_mean``, ``extract_dataset``, and ``subset``. (:pull:`367`).
* Removed ``xscen.extract.clisops_subset``. (:pull:`367`).
* ``dtr`` (the function) was renamed to ``dtr_from_minmax`` to avoid confusion with the `dtr` variable. (:pull:`372`).

Internal changes
^^^^^^^^^^^^^^^^
* Updated the `cookiecutter` template to the latest version. (:pull:`358`):
* Addresses a handful of misconfigurations in the GitHub Workflows.
* Added a few free `grep`-based hooks for finding unwanted artifacts in the code base.
* Updated `ruff` to v0.2.0 and `black` to v24.2.0.
* Added more tests. (:pull:`366`, :pull:`367`).
* Added more tests. (:pull:`366`, :pull:`367`, :pull:`372`).
* Refactored ``xs.spatial.subset`` into smaller functions. (:pull:`367`).
* An `encoding` argument was added to ``xs.config.load_config``. (:pull:`370`).

Expand All @@ -29,6 +30,7 @@ Bug fixes
* Fixed bug for adding the preprocessing attributes inside the `adjust` function. (:pull:`366`).
* Fixed a bug to accept `group = False` in `adjust` function. (:pull:`366`).
* `creep_weights` now correctly handles the case where the grid is small, `n` is large, and `mode=wrap`. (:issue:`367`).
* Fixed a bug in ``tasmin_from_dtr`` and ``tasmax_from_dtr``, when `dtr` units differed from tasmin/max. (:pull:`372`).

v0.8.3 (2024-02-28)
-------------------
Expand Down
61 changes: 61 additions & 0 deletions tests/test_xclimmod_conversions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import numpy as np
from xclim.testing.helpers import test_timeseries as timeseries

import xscen.xclim_modules.conversions as conv


def test_precipitation():
prsn = timeseries(np.ones(3), variable="prsn", start="2001-01-01", freq="D")
prlp = timeseries(
np.ones(3) * 10, variable="pr", start="2001-01-01", freq="D", units="mm d-1"
)
prlp.attrs["standard_name"] = "liquid_precipitation_flux"

pr = conv.precipitation(prsn, prlp)
assert pr.attrs["units"] == prsn.attrs["units"]
np.testing.assert_array_equal(pr, prsn + prlp / 86400)


def test_tasmin_from_dtr():
dtr = timeseries(
np.ones(3) * 10, variable="tas", start="2001-01-01", freq="D", units="C"
)
dtr.attrs["standard_name"] = "daily_temperature_range"
tasmax = timeseries(
np.ones(3) * 20, variable="tasmax", start="2001-01-01", freq="D"
)

tasmin = conv.tasmin_from_dtr(dtr, tasmax)
assert tasmin.attrs["units"] == tasmax.attrs["units"]
np.testing.assert_array_equal(
tasmin, tasmax - dtr
) # DTR in Celsius should not matter in the result, for a tasmax in Kelvin


def test_tasmax_from_dtr():
dtr = timeseries(
np.ones(3) * 10, variable="tas", start="2001-01-01", freq="D", units="C"
)
dtr.attrs["standard_name"] = "daily_temperature_range"
tasmin = timeseries(
np.ones(3) * 10, variable="tasmin", start="2001-01-01", freq="D"
)

tasmax = conv.tasmax_from_dtr(dtr, tasmin)
assert tasmax.attrs["units"] == tasmin.attrs["units"]
np.testing.assert_array_equal(
tasmax, tasmin + dtr
) # DTR in Celsius should not matter in the result, for a tasmin in Kelvin


def test_dtr():
tasmax = timeseries(
np.ones(3) * 20, variable="tasmax", start="2001-01-01", freq="D", units="C"
)
tasmin = timeseries(
np.ones(3) * 10, variable="tasmin", start="2001-01-01", freq="D"
)

dtr = conv.dtr_from_minmax(tasmin, tasmax)
assert dtr.attrs["units"] == "K"
np.testing.assert_array_equal(dtr, (tasmax + 273.15) - tasmin)
18 changes: 12 additions & 6 deletions xscen/xclim_modules/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def precipitation(prsn: xr.DataArray, prlp: xr.DataArray) -> xr.DataArray:
xr.DataArray, [same as prsn]
Surface precipitation flux (all phases)
"""
prlp = convert_units_to(prlp, prsn)
prlp = convert_units_to(prlp, prsn, context="hydro")
pr = prsn + prlp
pr.attrs["units"] = prsn.attrs["units"]
return pr
Expand All @@ -48,9 +48,12 @@ def tasmin_from_dtr(dtr: xr.DataArray, tasmax: xr.DataArray) -> xr.DataArray:
xr.DataArray, [same as tasmax]
Daily minimum temperature
"""
dtr = convert_units_to(dtr, tasmax)
out_units = tasmax.units
# To prevent strange behaviors that could arise from changing DTR units, we change the units of tasmax to match DTR
tasmax = convert_units_to(tasmax, dtr)
tasmin = tasmax - dtr
tasmin.attrs["units"] = tasmax.units
tasmin.attrs["units"] = dtr.units
tasmin = convert_units_to(tasmin, out_units)
return tasmin


Expand All @@ -72,14 +75,17 @@ def tasmax_from_dtr(dtr: xr.DataArray, tasmin: xr.DataArray) -> xr.DataArray:
xr.DataArray, [same as tasmin]
Daily maximum temperature
"""
dtr = convert_units_to(dtr, tasmin)
out_units = tasmin.attrs["units"]
# To prevent strange behaviors that could arise from changing DTR units, we change the units of tasmin to match DTR
tasmin = convert_units_to(tasmin, dtr)
tasmax = tasmin + dtr
tasmax.attrs["units"] = tasmin.units
tasmax.attrs["units"] = dtr.attrs["units"]
tasmax = convert_units_to(tasmax, out_units)
return tasmax


@declare_units(tasmin="[temperature]", tasmax="[temperature]")
def dtr(tasmin: xr.DataArray, tasmax: xr.DataArray) -> xr.DataArray:
def dtr_from_minmax(tasmin: xr.DataArray, tasmax: xr.DataArray) -> xr.DataArray:
"""DTR computed from tasmin and tasmax.
Dtr as tasmin subtracted from tasmax.
Expand Down
2 changes: 1 addition & 1 deletion xscen/xclim_modules/conversions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ indicators:
- var_name: evspsblpot
dtr:
src_freq: D
compute: dtr
compute: dtr_from_minmax
cf_attrs:
units: K
description: Daily temperature range.
Expand Down

0 comments on commit 0bae81b

Please sign in to comment.