scriptengine-tasks-ecearth 0.6.2__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/PKG-INFO +14 -6
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/cubes.py +43 -1
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/map_type_handling.py +3 -3
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/nemo.py +33 -2
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/presentation_objects.py +17 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/linear_combination.py +0 -1
- scriptengine_tasks_ecearth-0.7.0/monitoring/nemo_timeseries.py +157 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_all_mean_map.py +2 -4
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_global_mean_year_mean_timeseries.py +1 -4
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_year_mean_temporalmap.py +1 -4
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_sum_month_mean_timeseries.py +3 -15
- scriptengine_tasks_ecearth-0.7.0/pyproject.toml +57 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/PKG-INFO +14 -6
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/SOURCES.txt +2 -3
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/entry_points.txt +3 -1
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/requires.txt +1 -1
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/top_level.txt +0 -1
- scriptengine_tasks_ecearth-0.7.0/setup.py +5 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_cubes.py +14 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_file_handling.py +4 -2
- scriptengine_tasks_ecearth-0.7.0/tests/test_nemo_timeseries.py +99 -0
- scriptengine-tasks-ecearth-0.6.2/monitoring/nemo_global_mean_year_mean_timeseries.py +0 -89
- scriptengine-tasks-ecearth-0.6.2/pyproject.toml +0 -6
- scriptengine-tasks-ecearth-0.6.2/setup.py +0 -77
- scriptengine-tasks-ecearth-0.6.2/tests/__init__.py +0 -0
- scriptengine-tasks-ecearth-0.6.2/tests/test_nemo_global_mean_year_mean_timeseries.py +0 -40
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/LICENSE +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/README.md +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/__init__.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/dates.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/exceptions.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/files.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/diskusage_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/markdown.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/nemo_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/nemo_time_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/redmine.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_point_month_mean_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_point_month_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/simulatedyears_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/timeseries.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/dependency_links.txt +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/setup.cfg +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_dates.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_diskusage_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_linear_combination.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_map_type_handling.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_markdown.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_nemo_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_nemo_time_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_global_mean_year_mean_timeseries.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_year_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_presentation_objects.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_redmine.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_si3_hemis_point_month_mean_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_si3_hemis_point_month_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_si3_hemis_sum_month_mean_timeseries.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_simulatedyears_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_timeseries.py +0 -0
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: scriptengine-tasks-ecearth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: ScriptEngine tasks for use with the EC-Earth climate model
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: Valentina Schueller <valentina.schueller@gmail.com>, Uwe Fladrich <uwe.fladrich@protonmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/uwefladrich/scriptengine-tasks-ecearth
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/uwefladrich/scriptengine-tasks-ecearth/issues
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: scriptengine>=0.8.1
|
|
15
|
+
Requires-Dist: pyYAML>=5.1
|
|
16
|
+
Requires-Dist: matplotlib>=3.1
|
|
17
|
+
Requires-Dist: numpy>=1.18
|
|
18
|
+
Requires-Dist: imageio>=2.18
|
|
19
|
+
Requires-Dist: scitools-iris>=3.5
|
|
20
|
+
Requires-Dist: cartopy>=0.20
|
|
21
|
+
Requires-Dist: python-redmine
|
|
14
22
|
|
|
15
23
|
[](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
|
|
16
24
|
[](https://coveralls.io/github/uwefladrich/scriptengine-tasks-ecearth)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
5
|
import iris
|
|
6
|
+
import iris.cube
|
|
6
7
|
import numpy as np
|
|
7
8
|
from iris.util import equalise_attributes
|
|
8
9
|
from scriptengine.exceptions import ScriptEngineTaskArgumentInvalidError
|
|
@@ -35,6 +36,34 @@ def load_input_cube(src, varname):
|
|
|
35
36
|
return leg_cube
|
|
36
37
|
|
|
37
38
|
|
|
39
|
+
DEFAULT_UNIT_CONVERSIONS = {
|
|
40
|
+
"kelvin": "degC",
|
|
41
|
+
"meter^-2-kilogram-second^-1": "meter^-2-kilogram-day^-1",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def convert_units(cube: iris.cube.Cube, conversions=None) -> iris.cube.Cube:
|
|
46
|
+
"""Converts units of an Iris cube
|
|
47
|
+
|
|
48
|
+
Converts units if the current unit is present in the 'conversions' dict.
|
|
49
|
+
Does nothing otherwise.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
cube: An Iris cube
|
|
53
|
+
conversions: A mapping (dict) with 'unit': 'converted_unit' strings.
|
|
54
|
+
If None (default), then DEFAULT_UNIT_CONVERSIONS (defined above) is used.
|
|
55
|
+
Returns:
|
|
56
|
+
An Iris cube with modified units.
|
|
57
|
+
"""
|
|
58
|
+
if conversions is None:
|
|
59
|
+
conversions = DEFAULT_UNIT_CONVERSIONS
|
|
60
|
+
try:
|
|
61
|
+
cube.convert_units(conversions[cube.units.name])
|
|
62
|
+
except KeyError:
|
|
63
|
+
pass
|
|
64
|
+
return cube
|
|
65
|
+
|
|
66
|
+
|
|
38
67
|
def set_metadata(cube, **kwargs):
|
|
39
68
|
"""Set metadata for diagnostic."""
|
|
40
69
|
defaults = {
|
|
@@ -66,6 +95,20 @@ def compute_time_weights(monthly_data_cube, cube_shape=None):
|
|
|
66
95
|
return month_weights
|
|
67
96
|
|
|
68
97
|
|
|
98
|
+
def compute_annual_mean(cube):
|
|
99
|
+
# Remove auxiliary time coordinate before collapsing cube
|
|
100
|
+
cube.remove_coord(cube.coord("time", dim_coords=False))
|
|
101
|
+
|
|
102
|
+
annual_mean = cube.collapsed(
|
|
103
|
+
"time",
|
|
104
|
+
iris.analysis.MEAN,
|
|
105
|
+
weights=compute_time_weights(cube),
|
|
106
|
+
)
|
|
107
|
+
# Promote time from scalar to dimension coordinate
|
|
108
|
+
annual_mean = iris.util.new_axis(annual_mean, "time")
|
|
109
|
+
return annual_mean
|
|
110
|
+
|
|
111
|
+
|
|
69
112
|
def extract_month(cube, month):
|
|
70
113
|
return cube.extract(
|
|
71
114
|
iris.Constraint(time=lambda cell: cell.point.month == month_number(month))
|
|
@@ -83,7 +126,6 @@ def remove_aux_time(cube):
|
|
|
83
126
|
|
|
84
127
|
|
|
85
128
|
def annual_time_bounds(cube):
|
|
86
|
-
|
|
87
129
|
t_coord = cube.coord("time")
|
|
88
130
|
cube.remove_coord("time")
|
|
89
131
|
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/map_type_handling.py
RENAMED
|
@@ -24,7 +24,7 @@ def global_ocean_plot(
|
|
|
24
24
|
units=None,
|
|
25
25
|
value_range=[None, None],
|
|
26
26
|
colormap="RdBu_r",
|
|
27
|
-
**kwargs
|
|
27
|
+
**kwargs,
|
|
28
28
|
):
|
|
29
29
|
"""Map Type Handling for Global Ocean Maps"""
|
|
30
30
|
fig = plt.figure(figsize=(6, 4), dpi=150)
|
|
@@ -74,7 +74,7 @@ def global_atmosphere_plot(
|
|
|
74
74
|
units=None,
|
|
75
75
|
value_range=[None, None],
|
|
76
76
|
colormap="RdBu_r",
|
|
77
|
-
**kwargs
|
|
77
|
+
**kwargs,
|
|
78
78
|
):
|
|
79
79
|
"""Map Type Handling for Global Atmosphere Maps"""
|
|
80
80
|
fig = plt.figure(figsize=(6, 4), dpi=150)
|
|
@@ -114,7 +114,7 @@ def polar_ice_sheet_plot(
|
|
|
114
114
|
units=None,
|
|
115
115
|
value_range=[None, None],
|
|
116
116
|
colormap="RdBu_r",
|
|
117
|
-
**kwargs
|
|
117
|
+
**kwargs,
|
|
118
118
|
):
|
|
119
119
|
fig = plt.figure(figsize=(6, 4), dpi=150)
|
|
120
120
|
fig.suptitle(title)
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"""Helper module for NEMO data."""
|
|
2
2
|
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
3
5
|
import iris
|
|
4
6
|
import numpy as np
|
|
7
|
+
from iris.analysis import WeightedAggregator
|
|
8
|
+
from iris.coords import CellMeasure
|
|
5
9
|
from iris.exceptions import CoordinateNotFoundError
|
|
6
10
|
|
|
7
11
|
_nemo_horizontal_coords = (
|
|
@@ -55,7 +59,7 @@ def has_depth(cube):
|
|
|
55
59
|
return len(tuple(depth_coords(cube))) > 0
|
|
56
60
|
|
|
57
61
|
|
|
58
|
-
def
|
|
62
|
+
def _add_cell_size(cube, domain_file, grid):
|
|
59
63
|
"""Compute cell weights for spatial averaging in 2d and 3d"""
|
|
60
64
|
domain = iris.load(domain_file)
|
|
61
65
|
e1, e2 = ( # NEMO grid scale factors in horizontal directions
|
|
@@ -66,7 +70,17 @@ def spatial_weights(cube, domain_file, grid):
|
|
|
66
70
|
if is_3d:
|
|
67
71
|
e3 = domain.extract(f"e3{grid.lower()}_0")[0][0]
|
|
68
72
|
weights = e1 * e2 * e3 if is_3d else e1 * e2
|
|
69
|
-
|
|
73
|
+
weights = np.broadcast_to(weights.data, cube.shape)
|
|
74
|
+
if is_3d:
|
|
75
|
+
cell_size = CellMeasure(
|
|
76
|
+
weights, var_name="cell_size", units="m3", measure="volume"
|
|
77
|
+
)
|
|
78
|
+
else:
|
|
79
|
+
cell_size = CellMeasure(
|
|
80
|
+
weights, var_name="cell_size", units="m2", measure="area"
|
|
81
|
+
)
|
|
82
|
+
dims = tuple(range(len(weights.shape)))
|
|
83
|
+
cube.add_cell_measure(cell_size, dims)
|
|
70
84
|
|
|
71
85
|
|
|
72
86
|
def remove_unique_attributes(cube):
|
|
@@ -74,3 +88,20 @@ def remove_unique_attributes(cube):
|
|
|
74
88
|
for attribute in drop:
|
|
75
89
|
cube.attributes.pop(attribute, None)
|
|
76
90
|
return cube
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def compute_global_aggregate(cube, domain, grid, operation: WeightedAggregator):
|
|
94
|
+
_add_cell_size(cube, domain, grid)
|
|
95
|
+
with warnings.catch_warnings():
|
|
96
|
+
# Suppress warning about insufficient metadata.
|
|
97
|
+
warnings.filterwarnings(
|
|
98
|
+
"ignore",
|
|
99
|
+
"Collapsing a multi-dimensional coordinate.",
|
|
100
|
+
UserWarning,
|
|
101
|
+
)
|
|
102
|
+
global_aggregate = cube.collapsed(
|
|
103
|
+
spatial_coords(cube),
|
|
104
|
+
operation,
|
|
105
|
+
weights="cell_size",
|
|
106
|
+
)
|
|
107
|
+
return global_aggregate
|
|
@@ -98,6 +98,23 @@ class TimeseriesLoader(PresentationObjectLoader):
|
|
|
98
98
|
|
|
99
99
|
fig = plt.figure(figsize=(6, 4), dpi=150)
|
|
100
100
|
ax = fig.add_subplot(1, 1, 1)
|
|
101
|
+
|
|
102
|
+
# plot (constant) reference value if defined
|
|
103
|
+
ref = kwargs.get("reference", None)
|
|
104
|
+
if isinstance(ref, dict):
|
|
105
|
+
ref_value = ref.get("value", None)
|
|
106
|
+
if ref_value:
|
|
107
|
+
ref_label = ref.get("label", "Reference value")
|
|
108
|
+
ax.axhline(
|
|
109
|
+
y=ref_value,
|
|
110
|
+
xmin=0.05,
|
|
111
|
+
xmax=0.95,
|
|
112
|
+
color="r",
|
|
113
|
+
linestyle=":",
|
|
114
|
+
label=ref_label,
|
|
115
|
+
)
|
|
116
|
+
ax.legend()
|
|
117
|
+
|
|
101
118
|
ax.plot(coord_points, self.cube.data, color="k")
|
|
102
119
|
plt.setp(ax.spines.values(), color="grey")
|
|
103
120
|
ax.grid()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Processing Tasks for computing Timeseries from NEMO output."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import iris
|
|
6
|
+
from scriptengine.exceptions import ScriptEngineTaskArgumentInvalidError
|
|
7
|
+
from scriptengine.tasks.core import timed_runner
|
|
8
|
+
|
|
9
|
+
import helpers.cubes
|
|
10
|
+
import helpers.nemo
|
|
11
|
+
|
|
12
|
+
from .timeseries import Timeseries
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NemoTimeseries(Timeseries):
|
|
16
|
+
"""NemoTimeseries Processing Task"""
|
|
17
|
+
|
|
18
|
+
_required_arguments = (
|
|
19
|
+
"src",
|
|
20
|
+
"varname",
|
|
21
|
+
"dst",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def __init__(self, arguments):
|
|
25
|
+
NemoTimeseries.check_arguments(arguments)
|
|
26
|
+
super().__init__(
|
|
27
|
+
{**arguments, "title": None, "coord_value": None, "data_value": None}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def _load_input(self, context):
|
|
31
|
+
src = self.getarg("src", context)
|
|
32
|
+
var_name = self.getarg("varname", context)
|
|
33
|
+
self.log_info(f"Create time series for ocean variable {var_name}.")
|
|
34
|
+
|
|
35
|
+
var_data = helpers.cubes.load_input_cube(src, var_name)
|
|
36
|
+
return var_data
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class NemoGlobalSumYearMeanTimeseries(NemoTimeseries):
|
|
40
|
+
_required_arguments = ("domain",)
|
|
41
|
+
|
|
42
|
+
def __init__(self, arguments):
|
|
43
|
+
NemoGlobalSumYearMeanTimeseries.check_arguments(arguments)
|
|
44
|
+
super().__init__(arguments)
|
|
45
|
+
|
|
46
|
+
@timed_runner
|
|
47
|
+
def run(self, context):
|
|
48
|
+
var_data = self._load_input(context)
|
|
49
|
+
|
|
50
|
+
domain = self.getarg("domain", context)
|
|
51
|
+
grid = self.getarg("grid", context, default="T")
|
|
52
|
+
global_sum = helpers.nemo.compute_global_aggregate(
|
|
53
|
+
var_data, domain, grid, iris.analysis.SUM
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
annual_mean = helpers.cubes.compute_annual_mean(global_sum)
|
|
57
|
+
|
|
58
|
+
annual_mean.cell_methods = (
|
|
59
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
60
|
+
iris.coords.CellMethod(
|
|
61
|
+
"sum",
|
|
62
|
+
coords=(
|
|
63
|
+
("area", helpers.nemo.depth_coord(annual_mean).name())
|
|
64
|
+
if helpers.nemo.has_depth(annual_mean)
|
|
65
|
+
else "area"
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
long_name = annual_mean.long_name
|
|
71
|
+
var_name = annual_mean.standard_name
|
|
72
|
+
comment = f"Product of {long_name} / **{var_name}** and grid-cell area, summed over all grid cells."
|
|
73
|
+
annual_mean = helpers.cubes.set_metadata(
|
|
74
|
+
annual_mean,
|
|
75
|
+
title=f"{long_name} (annual mean)",
|
|
76
|
+
comment=comment,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
dst = Path(self.getarg("dst", context))
|
|
80
|
+
self.check_file_extension(dst)
|
|
81
|
+
self.save(annual_mean, dst)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class NemoGlobalMeanYearMeanTimeseries(NemoTimeseries):
|
|
85
|
+
_required_arguments = ("domain",)
|
|
86
|
+
|
|
87
|
+
def __init__(self, arguments):
|
|
88
|
+
NemoGlobalMeanYearMeanTimeseries.check_arguments(arguments)
|
|
89
|
+
super().__init__(arguments)
|
|
90
|
+
|
|
91
|
+
@timed_runner
|
|
92
|
+
def run(self, context):
|
|
93
|
+
var_data = self._load_input(context)
|
|
94
|
+
|
|
95
|
+
domain = self.getarg("domain", context)
|
|
96
|
+
grid = self.getarg("grid", context, default="T")
|
|
97
|
+
global_mean = helpers.nemo.compute_global_aggregate(
|
|
98
|
+
var_data, domain, grid, iris.analysis.MEAN
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
annual_mean = helpers.cubes.compute_annual_mean(global_mean)
|
|
102
|
+
|
|
103
|
+
annual_mean.cell_methods = (
|
|
104
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
105
|
+
iris.coords.CellMethod(
|
|
106
|
+
"mean",
|
|
107
|
+
coords=(
|
|
108
|
+
("area", helpers.nemo.depth_coord(annual_mean).name())
|
|
109
|
+
if helpers.nemo.has_depth(annual_mean)
|
|
110
|
+
else "area"
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
long_name = annual_mean.long_name
|
|
116
|
+
var_name = annual_mean.standard_name
|
|
117
|
+
comment = f"Global mean of {long_name} / **{var_name}**."
|
|
118
|
+
|
|
119
|
+
annual_mean = helpers.cubes.set_metadata(
|
|
120
|
+
annual_mean,
|
|
121
|
+
title=f"{long_name} (annual mean)",
|
|
122
|
+
comment=comment,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
dst = Path(self.getarg("dst", context))
|
|
126
|
+
self.check_file_extension(dst)
|
|
127
|
+
self.save(annual_mean, dst)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class NemoYearMeanTimeseries(NemoTimeseries):
|
|
131
|
+
@timed_runner
|
|
132
|
+
def run(self, context):
|
|
133
|
+
var_data = self._load_input(context)
|
|
134
|
+
|
|
135
|
+
if not var_data.ndim == 1:
|
|
136
|
+
self.log_error(f"Input data is not one-dimensional.")
|
|
137
|
+
raise ScriptEngineTaskArgumentInvalidError
|
|
138
|
+
|
|
139
|
+
annual_mean = helpers.cubes.compute_annual_mean(var_data)
|
|
140
|
+
|
|
141
|
+
annual_mean.cell_methods = (
|
|
142
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
long_name = annual_mean.long_name
|
|
146
|
+
var_name = annual_mean.standard_name
|
|
147
|
+
comment = f"Annual mean of {long_name} / **{var_name}**."
|
|
148
|
+
|
|
149
|
+
annual_mean = helpers.cubes.set_metadata(
|
|
150
|
+
annual_mean,
|
|
151
|
+
title=f"{long_name} (annual mean)",
|
|
152
|
+
comment=comment,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
dst = Path(self.getarg("dst", context))
|
|
156
|
+
self.check_file_extension(dst)
|
|
157
|
+
self.save(annual_mean, dst)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Processing Task that creates a 2D map of a given extensive atmosphere quantity."""
|
|
2
|
+
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
import iris
|
|
@@ -82,7 +83,4 @@ class OifsAllMeanMap(Map):
|
|
|
82
83
|
comment=f"Simulation average of **{varname}**.",
|
|
83
84
|
map_type="global atmosphere",
|
|
84
85
|
)
|
|
85
|
-
|
|
86
|
-
if map_cube.units.name == "kelvin":
|
|
87
|
-
map_cube.convert_units("degC")
|
|
88
|
-
return map_cube
|
|
86
|
+
return helpers.cubes.convert_units(map_cube)
|
|
@@ -128,7 +128,4 @@ class OifsGlobalMeanYearMeanTimeseries(Timeseries):
|
|
|
128
128
|
title=f"{timeseries_cube.long_name} (annual mean)",
|
|
129
129
|
comment=comment,
|
|
130
130
|
)
|
|
131
|
-
|
|
132
|
-
if timeseries_cube.units.name == "kelvin":
|
|
133
|
-
timeseries_cube.convert_units("degC")
|
|
134
|
-
return timeseries_cube
|
|
131
|
+
return helpers.cubes.convert_units(timeseries_cube)
|
|
@@ -71,7 +71,4 @@ class OifsYearMeanTemporalmap(Temporalmap):
|
|
|
71
71
|
comment=f"Annual mean of **{varname}**.",
|
|
72
72
|
map_type="global atmosphere",
|
|
73
73
|
)
|
|
74
|
-
|
|
75
|
-
if temporalmap_cube.units.name == "kelvin":
|
|
76
|
-
temporalmap_cube.convert_units("degC")
|
|
77
|
-
return temporalmap_cube
|
|
74
|
+
return helpers.cubes.convert_units(temporalmap_cube)
|
|
@@ -18,14 +18,12 @@ _meta_dict = {
|
|
|
18
18
|
"long_name": "Sea-Ice Volume",
|
|
19
19
|
"standard_name": "sea_ice_volume",
|
|
20
20
|
"var_name": "sivol",
|
|
21
|
-
"old_unit": "m3",
|
|
22
21
|
"new_unit": "1e3 km3",
|
|
23
22
|
},
|
|
24
23
|
"siconc": {
|
|
25
24
|
"long_name": "Sea-Ice Area",
|
|
26
25
|
"standard_name": "sea_ice_area",
|
|
27
26
|
"var_name": "siarea",
|
|
28
|
-
"old_unit": "m2",
|
|
29
27
|
"new_unit": "1e6 km2",
|
|
30
28
|
},
|
|
31
29
|
}
|
|
@@ -98,21 +96,11 @@ class Si3HemisSumMonthMeanTimeseries(Timeseries):
|
|
|
98
96
|
this_leg = helpers.cubes.mask_other_hemisphere(this_leg, hemisphere)
|
|
99
97
|
this_leg = helpers.cubes.annual_time_bounds(this_leg)
|
|
100
98
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"ignore",
|
|
105
|
-
"Collapsing a multi-dimensional coordinate.",
|
|
106
|
-
UserWarning,
|
|
107
|
-
)
|
|
108
|
-
this_leg_summed = this_leg.collapsed(
|
|
109
|
-
["latitude", "longitude"],
|
|
110
|
-
iris.analysis.SUM,
|
|
111
|
-
weights=helpers.nemo.spatial_weights(this_leg, domain, "T"),
|
|
112
|
-
)
|
|
99
|
+
this_leg_summed = helpers.nemo.compute_global_aggregate(
|
|
100
|
+
this_leg, domain, "T", iris.analysis.SUM
|
|
101
|
+
)
|
|
113
102
|
|
|
114
103
|
this_leg_summed.standard_name = _meta_dict[varname]["standard_name"]
|
|
115
|
-
this_leg_summed.units = cf_units.Unit(_meta_dict[varname]["old_unit"])
|
|
116
104
|
this_leg_summed.convert_units(_meta_dict[varname]["new_unit"])
|
|
117
105
|
this_leg_summed.long_name = (
|
|
118
106
|
f"{long_name} {helpers.dates.month_name(month)} {hemisphere}"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=59.7", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[tool.setuptools]
|
|
6
|
+
packages = ["helpers", "monitoring"]
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "scriptengine-tasks-ecearth"
|
|
10
|
+
version = "0.7.0"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Valentina Schueller", email = "valentina.schueller@gmail.com" },
|
|
13
|
+
{ name = "Uwe Fladrich", email = "uwe.fladrich@protonmail.com" },
|
|
14
|
+
]
|
|
15
|
+
description = "ScriptEngine tasks for use with the EC-Earth climate model"
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
]
|
|
22
|
+
requires-python = ">=3.8"
|
|
23
|
+
dependencies = [
|
|
24
|
+
"scriptengine>=0.8.1",
|
|
25
|
+
"pyYAML>=5.1",
|
|
26
|
+
"matplotlib>=3.1",
|
|
27
|
+
"numpy>=1.18",
|
|
28
|
+
"imageio>=2.18",
|
|
29
|
+
"scitools-iris>=3.5",
|
|
30
|
+
"cartopy>=0.20",
|
|
31
|
+
"python-redmine",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
"Homepage" = "https://github.com/uwefladrich/scriptengine-tasks-ecearth"
|
|
36
|
+
"Bug Tracker" = "https://github.com/uwefladrich/scriptengine-tasks-ecearth/issues"
|
|
37
|
+
|
|
38
|
+
[project.entry-points."scriptengine.tasks"]
|
|
39
|
+
"ece.mon.scalar" = "monitoring.scalar:Scalar"
|
|
40
|
+
"ece.mon.timeseries" = "monitoring.timeseries:Timeseries"
|
|
41
|
+
"ece.mon.diskusage_rte_scalar" = "monitoring.diskusage_rte_scalar:DiskusageRteScalar"
|
|
42
|
+
"ece.mon.simulatedyears_rte_scalar" = "monitoring.simulatedyears_rte_scalar:SimulatedyearsRteScalar"
|
|
43
|
+
"ece.mon.nemo_global_mean_year_mean_timeseries" = "monitoring.nemo_timeseries:NemoGlobalMeanYearMeanTimeseries"
|
|
44
|
+
"ece.mon.nemo_global_sum_year_mean_timeseries" = "monitoring.nemo_timeseries:NemoGlobalSumYearMeanTimeseries"
|
|
45
|
+
"ece.mon.nemo_year_mean_timeseries" = "monitoring.nemo_timeseries:NemoYearMeanTimeseries"
|
|
46
|
+
"ece.mon.nemo_all_mean_map" = "monitoring.nemo_all_mean_map:NemoAllMeanMap"
|
|
47
|
+
"ece.mon.nemo_month_mean_temporalmap" = "monitoring.nemo_time_mean_temporalmap:NemoMonthMeanTemporalmap"
|
|
48
|
+
"ece.mon.nemo_year_mean_temporalmap" = "monitoring.nemo_time_mean_temporalmap:NemoYearMeanTemporalmap"
|
|
49
|
+
"ece.mon.si3_hemis_sum_month_mean_timeseries" = "monitoring.si3_hemis_sum_month_mean_timeseries:Si3HemisSumMonthMeanTimeseries"
|
|
50
|
+
"ece.mon.si3_hemis_point_month_mean_all_mean_map" = "monitoring.si3_hemis_point_month_mean_all_mean_map:Si3HemisPointMonthMeanAllMeanMap"
|
|
51
|
+
"ece.mon.si3_hemis_point_month_mean_temporalmap" = "monitoring.si3_hemis_point_month_mean_temporalmap:Si3HemisPointMonthMeanTemporalmap"
|
|
52
|
+
"ece.mon.oifs_all_mean_map" = "monitoring.oifs_all_mean_map:OifsAllMeanMap"
|
|
53
|
+
"ece.mon.oifs_year_mean_temporalmap" = "monitoring.oifs_year_mean_temporalmap:OifsYearMeanTemporalmap"
|
|
54
|
+
"ece.mon.oifs_global_mean_year_mean_timeseries" = "monitoring.oifs_global_mean_year_mean_timeseries:OifsGlobalMeanYearMeanTimeseries"
|
|
55
|
+
"ece.mon.presentation.markdown" = "monitoring.markdown:Markdown"
|
|
56
|
+
"ece.mon.presentation.redmine" = "monitoring.redmine:Redmine"
|
|
57
|
+
"ece.mon.linear_combination" = "monitoring.linear_combination:LinearCombination"
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: scriptengine-tasks-ecearth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: ScriptEngine tasks for use with the EC-Earth climate model
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: Valentina Schueller <valentina.schueller@gmail.com>, Uwe Fladrich <uwe.fladrich@protonmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/uwefladrich/scriptengine-tasks-ecearth
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/uwefladrich/scriptengine-tasks-ecearth/issues
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: scriptengine>=0.8.1
|
|
15
|
+
Requires-Dist: pyYAML>=5.1
|
|
16
|
+
Requires-Dist: matplotlib>=3.1
|
|
17
|
+
Requires-Dist: numpy>=1.18
|
|
18
|
+
Requires-Dist: imageio>=2.18
|
|
19
|
+
Requires-Dist: scitools-iris>=3.5
|
|
20
|
+
Requires-Dist: cartopy>=0.20
|
|
21
|
+
Requires-Dist: python-redmine
|
|
14
22
|
|
|
15
23
|
[](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
|
|
16
24
|
[](https://coveralls.io/github/uwefladrich/scriptengine-tasks-ecearth)
|
|
@@ -15,8 +15,8 @@ monitoring/linear_combination.py
|
|
|
15
15
|
monitoring/map.py
|
|
16
16
|
monitoring/markdown.py
|
|
17
17
|
monitoring/nemo_all_mean_map.py
|
|
18
|
-
monitoring/nemo_global_mean_year_mean_timeseries.py
|
|
19
18
|
monitoring/nemo_time_mean_temporalmap.py
|
|
19
|
+
monitoring/nemo_timeseries.py
|
|
20
20
|
monitoring/oifs_all_mean_map.py
|
|
21
21
|
monitoring/oifs_global_mean_year_mean_timeseries.py
|
|
22
22
|
monitoring/oifs_year_mean_temporalmap.py
|
|
@@ -34,7 +34,6 @@ scriptengine_tasks_ecearth.egg-info/dependency_links.txt
|
|
|
34
34
|
scriptengine_tasks_ecearth.egg-info/entry_points.txt
|
|
35
35
|
scriptengine_tasks_ecearth.egg-info/requires.txt
|
|
36
36
|
scriptengine_tasks_ecearth.egg-info/top_level.txt
|
|
37
|
-
tests/__init__.py
|
|
38
37
|
tests/test_cubes.py
|
|
39
38
|
tests/test_dates.py
|
|
40
39
|
tests/test_diskusage_rte_scalar.py
|
|
@@ -44,8 +43,8 @@ tests/test_map.py
|
|
|
44
43
|
tests/test_map_type_handling.py
|
|
45
44
|
tests/test_markdown.py
|
|
46
45
|
tests/test_nemo_all_mean_map.py
|
|
47
|
-
tests/test_nemo_global_mean_year_mean_timeseries.py
|
|
48
46
|
tests/test_nemo_time_mean_temporalmap.py
|
|
47
|
+
tests/test_nemo_timeseries.py
|
|
49
48
|
tests/test_oifs_all_mean_map.py
|
|
50
49
|
tests/test_oifs_global_mean_year_mean_timeseries.py
|
|
51
50
|
tests/test_oifs_year_mean_temporalmap.py
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
ece.mon.diskusage_rte_scalar = monitoring.diskusage_rte_scalar:DiskusageRteScalar
|
|
3
3
|
ece.mon.linear_combination = monitoring.linear_combination:LinearCombination
|
|
4
4
|
ece.mon.nemo_all_mean_map = monitoring.nemo_all_mean_map:NemoAllMeanMap
|
|
5
|
-
ece.mon.nemo_global_mean_year_mean_timeseries = monitoring.
|
|
5
|
+
ece.mon.nemo_global_mean_year_mean_timeseries = monitoring.nemo_timeseries:NemoGlobalMeanYearMeanTimeseries
|
|
6
|
+
ece.mon.nemo_global_sum_year_mean_timeseries = monitoring.nemo_timeseries:NemoGlobalSumYearMeanTimeseries
|
|
6
7
|
ece.mon.nemo_month_mean_temporalmap = monitoring.nemo_time_mean_temporalmap:NemoMonthMeanTemporalmap
|
|
7
8
|
ece.mon.nemo_year_mean_temporalmap = monitoring.nemo_time_mean_temporalmap:NemoYearMeanTemporalmap
|
|
9
|
+
ece.mon.nemo_year_mean_timeseries = monitoring.nemo_timeseries:NemoYearMeanTimeseries
|
|
8
10
|
ece.mon.oifs_all_mean_map = monitoring.oifs_all_mean_map:OifsAllMeanMap
|
|
9
11
|
ece.mon.oifs_global_mean_year_mean_timeseries = monitoring.oifs_global_mean_year_mean_timeseries:OifsGlobalMeanYearMeanTimeseries
|
|
10
12
|
ece.mon.oifs_year_mean_temporalmap = monitoring.oifs_year_mean_temporalmap:OifsYearMeanTemporalmap
|
|
@@ -120,3 +120,17 @@ def test_annual_time_bounds():
|
|
|
120
120
|
]
|
|
121
121
|
)
|
|
122
122
|
assert (new_bounds == annual_bounds).all()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.mark.parametrize(
|
|
126
|
+
("unit", "converted_unit"),
|
|
127
|
+
(
|
|
128
|
+
("m", "m"),
|
|
129
|
+
("m-s^-1", "m-s^-1"),
|
|
130
|
+
("kelvin", "degC"),
|
|
131
|
+
("meter^-2-kilogram-second^-1", "meter^-2-kilogram-day^-1"),
|
|
132
|
+
),
|
|
133
|
+
)
|
|
134
|
+
def test_unit_conversions(unit, converted_unit):
|
|
135
|
+
cube = Cube(np.array([1]), units=unit)
|
|
136
|
+
assert helpers.cubes.convert_units(cube).units == cf_units.Unit(converted_unit)
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_file_handling.py
RENAMED
|
@@ -38,7 +38,8 @@ def test_2d_spatial_weights(tmp_path):
|
|
|
38
38
|
domain_file = str(tmp_path / "domain.nc")
|
|
39
39
|
iris.save(domain, domain_file)
|
|
40
40
|
expected_weights = np.array([6.0])
|
|
41
|
-
|
|
41
|
+
helpers.nemo._add_cell_size(data, domain_file, "t")
|
|
42
|
+
assert data.cell_measure("cell_size").data == expected_weights
|
|
42
43
|
|
|
43
44
|
|
|
44
45
|
def test_3d_spatial_weights(tmp_path):
|
|
@@ -66,4 +67,5 @@ def test_3d_spatial_weights(tmp_path):
|
|
|
66
67
|
domain_file = str(tmp_path / "domain.nc")
|
|
67
68
|
iris.save(domain, domain_file)
|
|
68
69
|
expected_weights = np.array([24.0])
|
|
69
|
-
|
|
70
|
+
helpers.nemo._add_cell_size(data, domain_file, "t")
|
|
71
|
+
assert data.cell_measure("cell_size").data == expected_weights
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Tests for monitoring/nemo_global_mean_year_mean_timeseries.py"""
|
|
2
|
+
|
|
3
|
+
import cf_units
|
|
4
|
+
import iris
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pytest
|
|
7
|
+
import scriptengine.exceptions
|
|
8
|
+
|
|
9
|
+
from monitoring.nemo_timeseries import (
|
|
10
|
+
NemoGlobalMeanYearMeanTimeseries,
|
|
11
|
+
NemoGlobalSumYearMeanTimeseries,
|
|
12
|
+
NemoYearMeanTimeseries,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_load_collapse_save(tmp_path):
|
|
17
|
+
# Tests for issue #53, caused by a bug in Iris 3.2.0.post0
|
|
18
|
+
|
|
19
|
+
src = "tests/testdata/NEMO_output_sivolu-199003.nc"
|
|
20
|
+
dst = tmp_path / "test.nc"
|
|
21
|
+
var = "sivolu"
|
|
22
|
+
|
|
23
|
+
cube = iris.load_cube(src, var).collapsed("latitude", iris.analysis.MEAN)
|
|
24
|
+
# print(cube) # Workaround for the Iris bug
|
|
25
|
+
iris.save(cube, str(dst))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_nemo_global_mean_year_mean_timeseries_working(tmp_path):
|
|
29
|
+
init = {
|
|
30
|
+
"src": ["./tests/testdata/NEMO_output_sivolu-199003.nc"],
|
|
31
|
+
"dst": str(tmp_path / "test.nc"),
|
|
32
|
+
"domain": "./tests/testdata/domain_cfg_example.nc",
|
|
33
|
+
"varname": "sivolu",
|
|
34
|
+
"grid": "T",
|
|
35
|
+
}
|
|
36
|
+
global_avg = NemoGlobalMeanYearMeanTimeseries(init)
|
|
37
|
+
global_avg.run(init)
|
|
38
|
+
cube = iris.load_cube(init["dst"])
|
|
39
|
+
assert cube.name() == "sea_ice_thickness"
|
|
40
|
+
assert cube.units == cf_units.Unit("m") # no unit change
|
|
41
|
+
assert cube.attributes["title"] is not None
|
|
42
|
+
assert cube.attributes["comment"] is not None
|
|
43
|
+
assert cube.attributes["diagnostic_type"] == "time series"
|
|
44
|
+
assert cube.cell_methods == (
|
|
45
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
46
|
+
iris.coords.CellMethod("mean", coords="area"),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_nemo_global_sum_year_mean_timeseries_working(tmp_path):
|
|
51
|
+
init = {
|
|
52
|
+
"src": ["./tests/testdata/NEMO_output_sivolu-199003.nc"],
|
|
53
|
+
"dst": str(tmp_path / "test.nc"),
|
|
54
|
+
"domain": "./tests/testdata/domain_cfg_example.nc",
|
|
55
|
+
"varname": "sivolu",
|
|
56
|
+
"grid": "T",
|
|
57
|
+
}
|
|
58
|
+
global_avg = NemoGlobalSumYearMeanTimeseries(init)
|
|
59
|
+
global_avg.run(init)
|
|
60
|
+
cube = iris.load_cube(init["dst"])
|
|
61
|
+
assert cube.name() == "sea_ice_thickness"
|
|
62
|
+
assert cube.units == cf_units.Unit("m3") # units were changed due to integration
|
|
63
|
+
assert cube.attributes["title"] is not None
|
|
64
|
+
assert cube.attributes["comment"] is not None
|
|
65
|
+
assert cube.attributes["diagnostic_type"] == "time series"
|
|
66
|
+
assert cube.cell_methods == (
|
|
67
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
68
|
+
iris.coords.CellMethod("sum", coords="area"),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_nemo_year_mean_timeseries_wrong_dim(tmp_path):
|
|
73
|
+
init = {
|
|
74
|
+
"src": ["./tests/testdata/NEMO_output_sivolu-199003.nc"],
|
|
75
|
+
"dst": str(tmp_path / "test.nc"),
|
|
76
|
+
"varname": "sivolu",
|
|
77
|
+
}
|
|
78
|
+
year_mean_ts = NemoYearMeanTimeseries(init)
|
|
79
|
+
pytest.raises(
|
|
80
|
+
scriptengine.exceptions.ScriptEngineTaskArgumentInvalidError,
|
|
81
|
+
year_mean_ts.run,
|
|
82
|
+
init,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_nemo_year_mean_timeseries_working(tmp_path):
|
|
87
|
+
init = {
|
|
88
|
+
"src": ["./tests/testdata/a8gx_bgc_5d_bioscalar_1990-1990.nc"],
|
|
89
|
+
"dst": str(tmp_path / "test.nc"),
|
|
90
|
+
"varname": "tdenit",
|
|
91
|
+
}
|
|
92
|
+
year_mean_ts = NemoYearMeanTimeseries(init)
|
|
93
|
+
year_mean_ts.run(init)
|
|
94
|
+
out_cube = iris.load_cube(init["dst"])
|
|
95
|
+
assert out_cube.shape == (1,)
|
|
96
|
+
assert out_cube.coord().has_bounds()
|
|
97
|
+
assert out_cube.cell_methods == (
|
|
98
|
+
iris.coords.CellMethod("mean", coords="time", intervals="1 year"),
|
|
99
|
+
)
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"""Processing Task that calculates the annual global average of a given extensive quantity."""
|
|
2
|
-
|
|
3
|
-
import warnings
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
import iris
|
|
7
|
-
from scriptengine.tasks.core import timed_runner
|
|
8
|
-
|
|
9
|
-
import helpers.cubes
|
|
10
|
-
import helpers.nemo
|
|
11
|
-
|
|
12
|
-
from .timeseries import Timeseries
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class NemoGlobalMeanYearMeanTimeseries(Timeseries):
|
|
16
|
-
"""NemoGlobalMeanYearMeanTimeseries Processing Task"""
|
|
17
|
-
|
|
18
|
-
_required_arguments = (
|
|
19
|
-
"src",
|
|
20
|
-
"domain",
|
|
21
|
-
"varname",
|
|
22
|
-
"dst",
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
def __init__(self, arguments):
|
|
26
|
-
NemoGlobalMeanYearMeanTimeseries.check_arguments(arguments)
|
|
27
|
-
super().__init__(
|
|
28
|
-
{**arguments, "title": None, "coord_value": None, "data_value": None}
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
@timed_runner
|
|
32
|
-
def run(self, context):
|
|
33
|
-
|
|
34
|
-
src = self.getarg("src", context)
|
|
35
|
-
dst = Path(self.getarg("dst", context))
|
|
36
|
-
var_name = self.getarg("varname", context)
|
|
37
|
-
domain = self.getarg("domain", context)
|
|
38
|
-
grid = self.getarg("grid", context, default="T")
|
|
39
|
-
|
|
40
|
-
comment = (
|
|
41
|
-
f"Global average time series of **{var_name}**. "
|
|
42
|
-
"Each data point represents the (spatial and temporal) "
|
|
43
|
-
"average over one leg."
|
|
44
|
-
)
|
|
45
|
-
self.log_info(f"Create time series for ocean variable {var_name} at {dst}.")
|
|
46
|
-
self.log_debug(f"Domain: {domain}, Source file(s): {src}")
|
|
47
|
-
|
|
48
|
-
self.check_file_extension(dst)
|
|
49
|
-
|
|
50
|
-
var_data = helpers.cubes.load_input_cube(src, var_name)
|
|
51
|
-
with warnings.catch_warnings():
|
|
52
|
-
# Suppress warning about insufficient metadata.
|
|
53
|
-
warnings.filterwarnings(
|
|
54
|
-
"ignore",
|
|
55
|
-
"Collapsing a multi-dimensional coordinate.",
|
|
56
|
-
UserWarning,
|
|
57
|
-
)
|
|
58
|
-
global_avg = var_data.collapsed(
|
|
59
|
-
helpers.nemo.spatial_coords(var_data),
|
|
60
|
-
iris.analysis.MEAN,
|
|
61
|
-
weights=helpers.nemo.spatial_weights(var_data, domain, grid),
|
|
62
|
-
)
|
|
63
|
-
# Remove auxiliary time coordinate before collapsing cube
|
|
64
|
-
global_avg.remove_coord(global_avg.coord("time", dim_coords=False))
|
|
65
|
-
global_annual_avg = global_avg.collapsed(
|
|
66
|
-
"time",
|
|
67
|
-
iris.analysis.MEAN,
|
|
68
|
-
weights=helpers.cubes.compute_time_weights(global_avg),
|
|
69
|
-
)
|
|
70
|
-
# Promote time from scalar to dimension coordinate
|
|
71
|
-
global_annual_avg = iris.util.new_axis(global_annual_avg, "time")
|
|
72
|
-
|
|
73
|
-
global_annual_avg = helpers.cubes.set_metadata(
|
|
74
|
-
global_annual_avg,
|
|
75
|
-
title=f"{global_annual_avg.long_name} (annual mean)",
|
|
76
|
-
comment=comment,
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
global_annual_avg.cell_methods = (
|
|
80
|
-
iris.coords.CellMethod("mean", coords="time", intervals="1 month"),
|
|
81
|
-
iris.coords.CellMethod(
|
|
82
|
-
"mean",
|
|
83
|
-
coords=("area", helpers.nemo.depth_coord(global_annual_avg).name())
|
|
84
|
-
if helpers.nemo.has_depth(global_annual_avg)
|
|
85
|
-
else "area",
|
|
86
|
-
),
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
self.save(global_annual_avg, dst)
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import codecs
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
import setuptools
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def read(rel_path):
|
|
8
|
-
"""
|
|
9
|
-
Helper function to read file in relative path.
|
|
10
|
-
"""
|
|
11
|
-
here = Path(__file__).parent.resolve()
|
|
12
|
-
with codecs.open(here / rel_path, "r") as fp:
|
|
13
|
-
return fp.read()
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def get_version(rel_path):
|
|
17
|
-
"""
|
|
18
|
-
Helper function to get package version.
|
|
19
|
-
"""
|
|
20
|
-
for line in read(rel_path).splitlines():
|
|
21
|
-
if line.startswith("__version__"):
|
|
22
|
-
delim = '"' if '"' in line else "'"
|
|
23
|
-
return line.split(delim)[1]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
setuptools.setup(
|
|
27
|
-
name="scriptengine-tasks-ecearth",
|
|
28
|
-
version=get_version("version.py"),
|
|
29
|
-
author="Valentina Schueller, Uwe Fladrich",
|
|
30
|
-
author_email="valentina.schueller@gmail.com, uwe.fladrich@protonmail.com",
|
|
31
|
-
description="ScriptEngine tasks for use with the EC-Earth climate model",
|
|
32
|
-
long_description=read("README.md"),
|
|
33
|
-
long_description_content_type="text/markdown",
|
|
34
|
-
url="https://github.com/uwefladrich/scriptengine-tasks-ecearth",
|
|
35
|
-
packages=[
|
|
36
|
-
"helpers",
|
|
37
|
-
"monitoring",
|
|
38
|
-
"tests",
|
|
39
|
-
],
|
|
40
|
-
classifiers=[
|
|
41
|
-
"Programming Language :: Python :: 3",
|
|
42
|
-
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
43
|
-
"Operating System :: OS Independent",
|
|
44
|
-
],
|
|
45
|
-
python_requires=">=3.7",
|
|
46
|
-
install_requires=[
|
|
47
|
-
"scriptengine>=0.8.1",
|
|
48
|
-
"pyYAML>=5.1",
|
|
49
|
-
"matplotlib>=3.1",
|
|
50
|
-
"numpy>=1.18",
|
|
51
|
-
"imageio>=2.18",
|
|
52
|
-
"scitools-iris>=3.1,!=3.2.0,!=3.2.0.post0",
|
|
53
|
-
"cartopy>=0.20",
|
|
54
|
-
"python-redmine",
|
|
55
|
-
],
|
|
56
|
-
entry_points={
|
|
57
|
-
"scriptengine.tasks": [
|
|
58
|
-
"ece.mon.scalar = monitoring.scalar:Scalar",
|
|
59
|
-
"ece.mon.timeseries = monitoring.timeseries:Timeseries",
|
|
60
|
-
"ece.mon.diskusage_rte_scalar = monitoring.diskusage_rte_scalar:DiskusageRteScalar",
|
|
61
|
-
"ece.mon.simulatedyears_rte_scalar = monitoring.simulatedyears_rte_scalar:SimulatedyearsRteScalar",
|
|
62
|
-
"ece.mon.nemo_global_mean_year_mean_timeseries = monitoring.nemo_global_mean_year_mean_timeseries:NemoGlobalMeanYearMeanTimeseries",
|
|
63
|
-
"ece.mon.nemo_all_mean_map = monitoring.nemo_all_mean_map:NemoAllMeanMap",
|
|
64
|
-
"ece.mon.nemo_month_mean_temporalmap = monitoring.nemo_time_mean_temporalmap:NemoMonthMeanTemporalmap",
|
|
65
|
-
"ece.mon.nemo_year_mean_temporalmap = monitoring.nemo_time_mean_temporalmap:NemoYearMeanTemporalmap",
|
|
66
|
-
"ece.mon.si3_hemis_sum_month_mean_timeseries = monitoring.si3_hemis_sum_month_mean_timeseries:Si3HemisSumMonthMeanTimeseries",
|
|
67
|
-
"ece.mon.si3_hemis_point_month_mean_all_mean_map = monitoring.si3_hemis_point_month_mean_all_mean_map:Si3HemisPointMonthMeanAllMeanMap",
|
|
68
|
-
"ece.mon.si3_hemis_point_month_mean_temporalmap = monitoring.si3_hemis_point_month_mean_temporalmap:Si3HemisPointMonthMeanTemporalmap",
|
|
69
|
-
"ece.mon.oifs_all_mean_map = monitoring.oifs_all_mean_map:OifsAllMeanMap",
|
|
70
|
-
"ece.mon.oifs_year_mean_temporalmap = monitoring.oifs_year_mean_temporalmap:OifsYearMeanTemporalmap",
|
|
71
|
-
"ece.mon.oifs_global_mean_year_mean_timeseries = monitoring.oifs_global_mean_year_mean_timeseries:OifsGlobalMeanYearMeanTimeseries",
|
|
72
|
-
"ece.mon.presentation.markdown = monitoring.markdown:Markdown",
|
|
73
|
-
"ece.mon.presentation.redmine = monitoring.redmine:Redmine",
|
|
74
|
-
"ece.mon.linear_combination = monitoring.linear_combination:LinearCombination",
|
|
75
|
-
]
|
|
76
|
-
},
|
|
77
|
-
)
|
|
File without changes
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"""Tests for monitoring/nemo_global_mean_year_mean_timeseries.py"""
|
|
2
|
-
|
|
3
|
-
import iris
|
|
4
|
-
|
|
5
|
-
from monitoring.nemo_global_mean_year_mean_timeseries import (
|
|
6
|
-
NemoGlobalMeanYearMeanTimeseries,
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def test_load_collapse_save(tmp_path):
|
|
11
|
-
# Tests for issue #53, caused by a bug in Iris 3.2.0.post0
|
|
12
|
-
|
|
13
|
-
src = "tests/testdata/NEMO_output_sivolu-199003.nc"
|
|
14
|
-
dst = tmp_path / "test.nc"
|
|
15
|
-
var = "sivolu"
|
|
16
|
-
|
|
17
|
-
cube = iris.load_cube(src, var).collapsed("latitude", iris.analysis.MEAN)
|
|
18
|
-
# print(cube) # Workaround for the Iris bug
|
|
19
|
-
iris.save(cube, str(dst))
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def test_nemo_global_mean_year_mean_timeseries_working(tmp_path):
|
|
23
|
-
init = {
|
|
24
|
-
"src": ["./tests/testdata/NEMO_output_sivolu-199003.nc"],
|
|
25
|
-
"dst": str(tmp_path / "test.nc"),
|
|
26
|
-
"domain": "./tests/testdata/domain_cfg_example.nc",
|
|
27
|
-
"varname": "sivolu",
|
|
28
|
-
"grid": "T",
|
|
29
|
-
}
|
|
30
|
-
global_avg = NemoGlobalMeanYearMeanTimeseries(init)
|
|
31
|
-
global_avg.run(init)
|
|
32
|
-
cube = iris.load_cube(init["dst"])
|
|
33
|
-
assert cube.name() == "sea_ice_thickness"
|
|
34
|
-
assert cube.attributes["title"] is not None
|
|
35
|
-
assert cube.attributes["comment"] is not None
|
|
36
|
-
assert cube.attributes["diagnostic_type"] == "time series"
|
|
37
|
-
assert cube.cell_methods == (
|
|
38
|
-
iris.coords.CellMethod("mean", coords="time", intervals="1 month"),
|
|
39
|
-
iris.coords.CellMethod("mean", coords="area"),
|
|
40
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/markdown.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/temporalmap.py
RENAMED
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/timeseries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_markdown.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_temporalmap.py
RENAMED
|
File without changes
|
{scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_timeseries.py
RENAMED
|
File without changes
|