Skip to content

Commit a86c92b

Browse files
bouweandelaRémi Kazeroni
andauthored
Fix issue where data was not loaded and saved (#1963)
Co-authored-by: Rémi Kazeroni <remi.kazeroni@dlr.de>
1 parent 576a5bb commit a86c92b

File tree

2 files changed

+113
-7
lines changed

2 files changed

+113
-7
lines changed

esmvalcore/preprocessor/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -654,12 +654,8 @@ def _run(self, _):
654654
for product in self.products for step in product.settings
655655
}
656656
blocks = get_step_blocks(steps, self.order)
657-
if not blocks:
658-
# If no preprocessing is configured, just load the data and save.
659-
for product in self.products:
660-
product.cubes # pylint: disable=pointless-statement
661-
product.close()
662657

658+
saved = set()
663659
for block in blocks:
664660
logger.debug("Running block %s", block)
665661
if block[0] in MULTI_MODEL_FUNCTIONS:
@@ -675,9 +671,13 @@ def _run(self, _):
675671
if block == blocks[-1]:
676672
product.cubes # pylint: disable=pointless-statement
677673
product.close()
674+
saved.add(product.filename)
678675

679676
for product in self.products:
680-
product.close()
677+
if product.filename not in saved:
678+
product.cubes # pylint: disable=pointless-statement
679+
product.close()
680+
681681
metadata_files = write_metadata(self.products,
682682
self.write_ncl_interface)
683683
return metadata_files

tests/integration/preprocessor/test_preprocessing_task.py

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import iris.cube
44
from prov.model import ProvDocument
55

6+
import esmvalcore.preprocessor
67
from esmvalcore.dataset import Dataset
78
from esmvalcore.preprocessor import PreprocessingTask, PreprocessorFile
89

@@ -15,7 +16,7 @@ def test_load_save_task(tmp_path):
1516
iris.save(cube, in_file)
1617
dataset = Dataset(short_name='tas')
1718
dataset.files = [in_file]
18-
dataset._load_with_callback = lambda _: cube
19+
dataset._load_with_callback = lambda _: cube.copy()
1920

2021
# Create task
2122
task = PreprocessingTask([
@@ -40,3 +41,108 @@ def test_load_save_task(tmp_path):
4041

4142
result.attributes.clear()
4243
assert result == cube
44+
45+
46+
def test_load_save_and_other_task(tmp_path, monkeypatch):
47+
"""Test that a task just copies one file and preprocesses another file."""
48+
# Prepare test datasets
49+
in_cube = iris.cube.Cube(data=[0.], var_name='tas', units='degrees_C')
50+
(tmp_path / 'climate_data').mkdir()
51+
file1 = tmp_path / 'climate_data' / 'tas_dataset1.nc'
52+
file2 = tmp_path / 'climate_data' / 'tas_dataset2.nc'
53+
54+
# Save cubes for reading global attributes into provenance
55+
iris.save(in_cube, target=file1)
56+
iris.save(in_cube, target=file2)
57+
58+
dataset1 = Dataset(short_name='tas', dataset='dataset1')
59+
dataset1.files = [file1]
60+
dataset1._load_with_callback = lambda _: in_cube.copy()
61+
62+
dataset2 = Dataset(short_name='tas', dataset='dataset1')
63+
dataset2.files = [file2]
64+
dataset2._load_with_callback = lambda _: in_cube.copy()
65+
66+
# Create some mock preprocessor functions and patch
67+
# `esmvalcore.preprocessor` so it uses them.
68+
def single_preproc_func(cube):
69+
cube.data = cube.core_data() + 1.
70+
return cube
71+
72+
def multi_preproc_func(products):
73+
for product in products:
74+
cube = product.cubes[0]
75+
cube.data = cube.core_data() + 1.
76+
product.cubes = [cube]
77+
return products
78+
79+
monkeypatch.setattr(
80+
esmvalcore.preprocessor,
81+
'single_preproc_func',
82+
single_preproc_func,
83+
raising=False,
84+
)
85+
monkeypatch.setattr(
86+
esmvalcore.preprocessor,
87+
'multi_preproc_func',
88+
multi_preproc_func,
89+
raising=False,
90+
)
91+
monkeypatch.setattr(
92+
esmvalcore.preprocessor,
93+
'MULTI_MODEL_FUNCTIONS',
94+
{'multi_preproc_func'},
95+
)
96+
default_order = (esmvalcore.preprocessor.INITIAL_STEPS +
97+
('single_preproc_func', 'multi_preproc_func') +
98+
esmvalcore.preprocessor.FINAL_STEPS)
99+
monkeypatch.setattr(
100+
esmvalcore.preprocessor,
101+
'DEFAULT_ORDER',
102+
default_order,
103+
)
104+
105+
# Create task
106+
task = PreprocessingTask(
107+
[
108+
PreprocessorFile(
109+
filename=tmp_path / 'tas_dataset1.nc',
110+
settings={},
111+
datasets=[dataset1],
112+
attributes={'dataset': 'dataset1'},
113+
),
114+
PreprocessorFile(
115+
filename=tmp_path / 'tas_dataset2.nc',
116+
settings={
117+
'single_preproc_func': {},
118+
'multi_preproc_func': {},
119+
},
120+
datasets=[dataset2],
121+
attributes={'dataset': 'dataset2'},
122+
),
123+
],
124+
order=default_order,
125+
)
126+
127+
# Create an 'activity' representing a run of the tool
128+
provenance = ProvDocument()
129+
provenance.add_namespace('software', uri='https://example.com/software')
130+
activity = provenance.activity('software:esmvalcore')
131+
task.initialize_provenance(activity)
132+
133+
task.run()
134+
135+
# Check that two files were saved and the preprocessor functions were
136+
# only applied to the second one.
137+
assert len(task.products) == 2
138+
for product in task.products:
139+
print(product.filename)
140+
assert product.filename.exists()
141+
out_cube = iris.load_cube(product.filename)
142+
print(out_cube.data)
143+
if product.attributes['dataset'] == 'dataset1':
144+
assert out_cube.data.tolist() == [0.]
145+
elif product.attributes['dataset'] == 'dataset2':
146+
assert out_cube.data.tolist() == [2.]
147+
else:
148+
assert False, "unexpected product"

0 commit comments

Comments
 (0)