Skip to content

Commit cba9166

Browse files
Fix the syntax for adding multiple ensemble members from the same dataset (#678)
* fix the syntax for multiple ensembles, add a note, fix some typo * Fix multiple expansion * update the doc about multiple ensembles * Update doc/recipe/overview.rst Co-authored-by: Bouwe Andela <b.andela@esciencecenter.nl> Co-authored-by: Bouwe Andela <b.andela@esciencecenter.nl>
1 parent 950cf40 commit cba9166

File tree

3 files changed

+73
-18
lines changed

3 files changed

+73
-18
lines changed

doc/recipe/overview.rst

+9-7
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ the following:
3838
documentation:
3939
description: |
4040
Recipe to produce time series figures of the derived variable, the
41-
Atlantic meriodinal overturning circulation (AMOC).
41+
Atlantic meridional overturning circulation (AMOC).
4242
This recipe also produces transect figures of the stream functions for
4343
the years 2001-2004.
4444
@@ -102,8 +102,8 @@ Here it is an example concatenating the `historical` experiment with `rcp85`
102102
datasets:
103103
- {dataset: CanESM2, project: CMIP5, exp: [historical, rcp85], ensemble: r1i1p1, start_year: 2001, end_year: 2004}
104104
105-
It is also possible to define the ensemble as a list, although it is useful only
106-
case the two experiments have different ensemble names
105+
It is also possible to define the ensemble as a list when the two experiments have different ensemble names.
106+
In this case, the specified datasets are concatenated into a single cube:
107107

108108
.. code-block:: yaml
109109
@@ -113,22 +113,24 @@ case the two experiments have different ensemble names
113113
ESMValTool also supports a simplified syntax to add multiple ensemble members from the same dataset.
114114
In the ensemble key, any element in the form `(x:y)` will be replaced with all numbers from x to y (both inclusive),
115115
adding a dataset entry for each replacement. For example, to add ensemble members r1i1p1 to r10i1p1
116-
you can use the following abreviatted syntax:
116+
you can use the following abbreviated syntax:
117117

118118
.. code-block:: yaml
119119
120120
datasets:
121-
- {dataset: CanESM2, project: CMIP5, exp: historical, ensemble: r(1:10)i1p1, start_year: 2001, end_year: 2004}
121+
- {dataset: CanESM2, project: CMIP5, exp: historical, ensemble: "r(1:10)i1p1", start_year: 2001, end_year: 2004}
122122
123123
It can be included multiple times in one definition. For example, to generate the datasets definitions
124124
for the ensemble members r1i1p1 to r5i1p1 and from r1i2p1 to r5i1p1 you can use:
125125

126126
.. code-block:: yaml
127127
128128
datasets:
129-
- {dataset: CanESM2, project: CMIP5, exp: historical, ensemble: r(1:5)i(1:2)p1, start_year: 2001, end_year: 2004}
129+
- {dataset: CanESM2, project: CMIP5, exp: historical, ensemble: "r(1:5)i(1:2)p1", start_year: 2001, end_year: 2004}
130130
131131
Please, bear in mind that this syntax can only be used in the ensemble tag.
132+
Also, note that the combination of multiple experiments and ensembles, like
133+
exp: [historical, rcp85], ensemble: [r1i1p1, "r(2:3)i1p1"] is not supported and will raise an error.
132134

133135
Note that this section is not required, as datasets can also be provided in the
134136
Diagnostics_ section.
@@ -140,7 +142,7 @@ Diagnostics_ section.
140142
Recipe section: ``preprocessors``
141143
=================================
142144

143-
The preprocessor section of the recipe includes one or more preprocesors, each
145+
The preprocessor section of the recipe includes one or more preprocessors, each
144146
of which may call the execution of one or several preprocessor functions.
145147

146148
Each preprocessor section includes:

esmvalcore/_recipe.py

+22-11
Original file line numberDiff line numberDiff line change
@@ -1015,20 +1015,31 @@ def _expand_ensemble(variables):
10151015
"""
10161016
expanded = []
10171017
regex = re.compile(r'\(\d+:\d+\)')
1018+
1019+
def expand_ensemble(variable):
1020+
ens = variable.get('ensemble', "")
1021+
match = regex.search(ens)
1022+
if match:
1023+
start, end = match.group(0)[1:-1].split(':')
1024+
for i in range(int(start), int(end) + 1):
1025+
expand = deepcopy(variable)
1026+
expand['ensemble'] = regex.sub(str(i), ens, 1)
1027+
expand_ensemble(expand)
1028+
else:
1029+
expanded.append(variable)
1030+
10181031
for variable in variables:
10191032
ensemble = variable.get('ensemble', "")
1020-
if not isinstance(ensemble, str):
1033+
if isinstance(ensemble, (list, tuple)):
1034+
for elem in ensemble:
1035+
if regex.search(elem):
1036+
raise RecipeError(
1037+
f"In variable {variable}: ensemble expansion "
1038+
"cannot be combined with ensemble lists")
10211039
expanded.append(variable)
1022-
continue
1023-
match = regex.search(ensemble)
1024-
if not match:
1025-
expanded.append(variable)
1026-
continue
1027-
start, end = match.group(0)[1:-1].split(':')
1028-
for i in range(int(start), int(end) + 1):
1029-
expand = deepcopy(variable)
1030-
expand['ensemble'] = regex.sub(str(i), ensemble, 1)
1031-
expanded.append(expand)
1040+
else:
1041+
expand_ensemble(variable)
1042+
10321043
return expanded
10331044

10341045
def _initialize_variables(self, raw_variable, raw_datasets):

tests/unit/test_recipe.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from esmvalcore._recipe import Recipe
4+
from esmvalcore._recipe_checks import RecipeError
5+
6+
7+
class TestRecipe:
8+
def test_expand_ensemble(self):
9+
10+
datasets = [
11+
{
12+
'dataset': 'XYZ',
13+
'ensemble': 'r(1:2)i(2:3)p(3:4)',
14+
},
15+
]
16+
17+
expanded = Recipe._expand_ensemble(datasets)
18+
19+
ensembles = [
20+
'r1i2p3',
21+
'r1i2p4',
22+
'r1i3p3',
23+
'r1i3p4',
24+
'r2i2p3',
25+
'r2i2p4',
26+
'r2i3p3',
27+
'r2i3p4',
28+
]
29+
for i, ensemble in enumerate(ensembles):
30+
assert expanded[i] == {'dataset': 'XYZ', 'ensemble': ensemble}
31+
32+
def test_expand_ensemble_nolist(self):
33+
34+
datasets = [
35+
{
36+
'dataset': 'XYZ',
37+
'ensemble': ['r1i1p1', 'r(1:2)i1p1']
38+
},
39+
]
40+
41+
with pytest.raises(RecipeError):
42+
Recipe._expand_ensemble(datasets)

0 commit comments

Comments
 (0)