Skip to content

Commit

Permalink
Merge branch 'climatological_op' into select_indicators_for_available…
Browse files Browse the repository at this point in the history
…_vars
  • Loading branch information
vindelico committed Dec 2, 2023
2 parents d74adcc + af032a8 commit c81817c
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 121 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Announcements
New features and enhancements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* New function ``xscen.indicators.select_inds_for_avail_vars`` to filter the indicators that can be calculated with the variables available in a ``xarray.Dataset``. (:pull:`291`).
* Replaced aggregation function ``climatological_mean()`` with ``climatological_op()`` offering more types of operations to aggregate over climate periods. (:pull:`290`)
* Replaced aggregation function ``climatological_mean()`` with ``climatological_op()`` offering more types of operations to aggregate over climatological periods. (:pull:`290`)
* Added the ability to search for simulations that reach a given warming level. (:pull:`251`).
* ``xs.spatial_mean`` now accepts the ``region="global"`` keyword to perform a global average (:issue:`94`, :pull:`260`).
* ``xs.spatial_mean`` with ``method='xESMF'`` will also automatically segmentize polygons (down to a 1° resolution) to ensure a correct average (:pull:`260`).
Expand Down
12 changes: 5 additions & 7 deletions docs/notebooks/2_getting_started.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1020,20 +1020,18 @@
"\n",
"**NOTE:** The aggregation is over *year*, __*not* over *time*__. For example, if given monthly data, the climatological operation will be computed separately for January, February, etc. This means that the data should already be aggregated at the required frequency, for example using `xs.compute_indicators` to compute yearly, seasonal, or monthly indicators.\n",
"\n",
"The function requires the following arguments:\n",
"- `ds` is the *xr.Dataset* containing the data.\n",
"- `op` is the operation to perform. It can be any of the following: ['max', 'mean', 'median', 'min', 'std', 'sum', 'var', 'linregress']\n",
"\n",
"In the following example, we will use `op='mean'`.\n",
"The function call requires a `xr.Dataset` and argument `op` specifies the operation to perform. It can be any of the following:\n",
"`['max', 'mean', 'median', 'min', 'std', 'sum', 'var', 'linregress']`.\n",
"\n",
"The optional arguments are as follow:\n",
"\n",
"- `window` indicates how many year to use for the average. Uses all available years by default.\n",
"- `min_period` minimum number of years required for a value to be computed durring the `rolling` operation.\n",
"- `stride` indicates the stride (in years) at which to provide an output.\n",
"- `periods` is a list of [start, end] of continuous periods to be considered.\n",
"\n",
"Additional arguments allow to control the output of the function by automatically renaming variables to reflect the operation performed, restructuring the output dataset and setting the `to_level` attribute."
"Additional arguments allow to control the output of the function by automatically renaming variables to reflect the operation performed, restructuring the output dataset and setting the `to_level` attribute.\n",
"\n",
"In the following example, we will use `op='mean'`."
]
},
{
Expand Down
17 changes: 11 additions & 6 deletions docs/notebooks/6_config.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
"xs.load_config(\n",
" str(\n",
" Path().absolute().parent.parent\n",
" / \"home\"\n",
" / \"braun\"\n",
" / \"python\"\n",
" / \"github\"\n",
" / \"xscen\"\n",
" / \"templates\"\n",
" / \"1-basic_workflow_with_config\"\n",
" / \"config1.yml\"\n",
Expand Down Expand Up @@ -248,7 +253,7 @@
"id": "85b36803-29b8-4993-add3-3c69e4e4a750",
"metadata": {},
"source": [
"Let's test that it is working, using `climatological_mean`:"
"Let's test that it is working, using `climatological_op`:"
]
},
{
Expand All @@ -261,7 +266,7 @@
"outputs": [],
"source": [
"# We should obtain 30-year means separated in 10-year intervals.\n",
"CONFIG[\"aggregate\"][\"climatological_mean\"]"
"CONFIG[\"aggregate\"][\"climatological_op\"]"
]
},
{
Expand All @@ -282,8 +287,8 @@
"da.name = \"test\"\n",
"ds = da.to_dataset()\n",
"\n",
"# Call climatological_mean using no argument other than what's in CONFIG\n",
"print(xs.climatological_mean(ds))"
"# Call climatological_op using no argument other than what's in CONFIG\n",
"print(xs.climatological_op(ds))"
]
},
{
Expand Down Expand Up @@ -369,9 +374,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "obsflow",
"language": "python",
"name": "python3"
"name": "obsflow"
},
"language_info": {
"codemirror_mode": {
Expand Down
4 changes: 3 additions & 1 deletion templates/1-basic_workflow_with_config/config1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,13 @@ aggregate:
processing_level: indicators
delta:
processing_level: climatology
climatological_mean: # automatically passed to the function
climatological_op: # automatically passed to the function
op: mean
window: 30
interval: 10
periods: [['1951', '2100']]
to_level: climatology
#periods_as_dim: True
#min_periods:
compute_deltas: # automatically passed to the function
kind: "+"
Expand Down
27 changes: 14 additions & 13 deletions tests/test_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ def test_all_default(self, xrfreq):
# Test metadata
assert (
out.tas.attrs["description"]
== f"Climatological 30-year average of {ds.tas.attrs['description']}"
== f"30-year climatological average of {ds.tas.attrs['description']}"
)
assert (
"Climatological 30-year average over window (non-centered) with a minimum of 30 years of data"
"30-year climatological average over window (non-centered), with a minimum of 30 years of data"
in out.tas.attrs["history"]
)
assert out.attrs["cat:processing_level"] == "climatology"
Expand Down Expand Up @@ -84,10 +84,10 @@ def test_options(self, xrfreq):
# Test metadata
assert (
out.tas.attrs["description"]
== f"Climatological 15-year average of {ds.tas.attrs['description']}"
== f"15-year climatological average of {ds.tas.attrs['description']}"
)
assert (
"Climatological 15-year average over window (non-centered) with a minimum of 15 years of data"
"15-year climatological average over window (non-centered), with a minimum of 15 years of data"
in out.tas.attrs["history"]
)
assert out.attrs["cat:processing_level"] == "for_testing"
Expand Down Expand Up @@ -264,7 +264,7 @@ def test_fx(self):
ds["horizon"] = xr.DataArray(
["1981-2010", "2011-2040", "2041-2070", "2071-2100"], dims=["time"]
)
ds = ds.swap_dims({"time": "horizon"}).drop("time")
ds = ds.swap_dims({"time": "horizon"}).drop_vars("time")

out = xs.compute_deltas(
ds, reference_horizon="1981-2010", rename_variables=False
Expand Down Expand Up @@ -365,14 +365,14 @@ def test_options(self, periods, to_level):
assert all(v in out for v in ["tg_min", "growing_degree_days"])
assert (
# f"{30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}-year mean of"
f"Climatological {30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}-year average of"
f"{30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}-year climatological average of"
in out.tg_min.attrs["description"]
)
assert (
out.tg_min.attrs["description"].split(
# f"{30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}-year mean of "
f"Climatological {30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}"
f"-year average of "
f"{30 if periods is None else int(periods[0][1]) - int(periods[0][0]) + 1}"
f"-year climatological average of "
)[1]
!= self.ds.tas.attrs["description"]
)
Expand Down Expand Up @@ -562,7 +562,8 @@ def test_global(self, lonstart, method, exp):


class TestClimatologicalOp:
def _format(self, s):
@staticmethod
def _format(s):
import xclim

op_format = dict.fromkeys(("mean", "std", "var", "sum"), "adj") | dict.fromkeys(
Expand Down Expand Up @@ -625,10 +626,10 @@ def test_all_default(self, xrfreq, op):
operation = self._format(op) if op not in ["median", "linregress"] else op
assert (
out[f"tas_clim_{op}"].attrs["description"]
== f"Climatological 30-year {operation} of {ds.tas.attrs['description']}"
== f"30-year climatological {operation} of {ds.tas.attrs['description']}"
)
assert (
f"Climatological 30-year {operation} over window (non-centered) with a minimum of 30 years of data"
f"30-year climatological {operation} over window (non-centered), with a minimum of 30 years of data"
in out[f"tas_clim_{op}"].attrs["history"]
)
assert out.attrs["cat:processing_level"] == "climatology"
Expand Down Expand Up @@ -697,10 +698,10 @@ def test_options(self, xrfreq, op):
operation = self._format(op) if op not in ["median", "linregress"] else op
assert (
out[f"tas_clim_{op}"].attrs["description"]
== f"Climatological 15-year {operation} of {ds.tas.attrs['description']}"
== f"15-year climatological {operation} of {ds.tas.attrs['description']}"
)
assert (
f"Climatological 15-year {operation} over window (non-centered) with a minimum of 15 years of data"
f"15-year climatological {operation} over window (non-centered), with a minimum of 15 years of data"
in out[f"tas_clim_{op}"].attrs["history"]
)
assert out.attrs["cat:processing_level"] == "for_testing"
Expand Down
Loading

0 comments on commit c81817c

Please sign in to comment.