scriptengine-tasks-ecearth 0.6.3__tar.gz → 0.7.1__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.3 → scriptengine_tasks_ecearth-0.7.1}/PKG-INFO +12 -3
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/cubes.py +43 -1
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/map_type_handling.py +3 -3
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/nemo.py +33 -2
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/presentation_objects.py +17 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/linear_combination.py +0 -1
- scriptengine_tasks_ecearth-0.7.1/monitoring/nemo_timeseries.py +157 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/oifs_all_mean_map.py +2 -4
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/oifs_global_mean_year_mean_timeseries.py +1 -4
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/oifs_year_mean_temporalmap.py +1 -4
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/si3_hemis_sum_month_mean_timeseries.py +9 -18
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/pyproject.toml +6 -4
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/PKG-INFO +12 -3
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/SOURCES.txt +25 -2
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/entry_points.txt +3 -1
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/requires.txt +1 -1
- scriptengine_tasks_ecearth-0.7.1/tests/test_cubes.py +136 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_dates.py +22 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_diskusage_rte_scalar.py +66 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_file_handling.py +71 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_linear_combination.py +244 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_map.py +38 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_map_type_handling.py +28 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_markdown.py +37 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_nemo_all_mean_map.py +41 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_nemo_time_mean_temporalmap.py +92 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_nemo_timeseries.py +99 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_oifs_all_mean_map.py +38 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_oifs_global_mean_year_mean_timeseries.py +42 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_oifs_year_mean_temporalmap.py +37 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_presentation_objects.py +189 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_redmine.py +112 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_scalar.py +104 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_si3_hemis_point_month_mean_all_mean_map.py +75 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_si3_hemis_point_month_mean_temporalmap.py +74 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_si3_hemis_sum_month_mean_timeseries.py +69 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_simulatedyears_rte_scalar.py +19 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_temporalmap.py +22 -0
- scriptengine_tasks_ecearth-0.7.1/tests/test_timeseries.py +170 -0
- scriptengine-tasks-ecearth-0.6.3/monitoring/nemo_global_mean_year_mean_timeseries.py +0 -89
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/LICENSE +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/README.md +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/__init__.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/dates.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/exceptions.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/helpers/files.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/diskusage_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/markdown.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/nemo_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/nemo_time_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/redmine.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/si3_hemis_point_month_mean_all_mean_map.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/si3_hemis_point_month_mean_temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/simulatedyears_rte_scalar.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/temporalmap.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/monitoring/timeseries.py +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/dependency_links.txt +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/scriptengine_tasks_ecearth.egg-info/top_level.txt +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/setup.cfg +0 -0
- {scriptengine-tasks-ecearth-0.6.3 → scriptengine_tasks_ecearth-0.7.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptengine-tasks-ecearth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: ScriptEngine tasks for use with the EC-Earth climate model
|
|
5
5
|
Author-email: Valentina Schueller <valentina.schueller@gmail.com>, Uwe Fladrich <uwe.fladrich@protonmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/uwefladrich/scriptengine-tasks-ecearth
|
|
@@ -8,9 +8,18 @@ Project-URL: Bug Tracker, https://github.com/uwefladrich/scriptengine-tasks-ecea
|
|
|
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
|
|
22
|
+
Dynamic: license-file
|
|
14
23
|
|
|
15
24
|
[](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
|
|
16
25
|
[](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.3 → scriptengine_tasks_ecearth-0.7.1}/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)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Processing Task that calculates the seasonal cycle of sea ice variables in one leg."""
|
|
2
2
|
|
|
3
|
-
import warnings
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
6
5
|
import cf_units
|
|
@@ -18,15 +17,15 @@ _meta_dict = {
|
|
|
18
17
|
"long_name": "Sea-Ice Volume",
|
|
19
18
|
"standard_name": "sea_ice_volume",
|
|
20
19
|
"var_name": "sivol",
|
|
21
|
-
"old_unit": "m3",
|
|
22
20
|
"new_unit": "1e3 km3",
|
|
21
|
+
"old_unit": "m3",
|
|
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",
|
|
28
|
+
"old_unit": "m2",
|
|
30
29
|
},
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -77,7 +76,7 @@ class Si3HemisSumMonthMeanTimeseries(Timeseries):
|
|
|
77
76
|
self.log_warning(
|
|
78
77
|
(
|
|
79
78
|
f"Invalid varname '{varname}', must be one of {_meta_dict.keys()}; "
|
|
80
|
-
"diagnostic will
|
|
79
|
+
"diagnostic will be ignored."
|
|
81
80
|
)
|
|
82
81
|
)
|
|
83
82
|
return
|
|
@@ -86,7 +85,7 @@ class Si3HemisSumMonthMeanTimeseries(Timeseries):
|
|
|
86
85
|
self.log_warning(
|
|
87
86
|
(
|
|
88
87
|
f"Invalid hemisphere '{hemisphere}', must be 'north' or 'south'; "
|
|
89
|
-
"diagnostic will
|
|
88
|
+
"diagnostic will be ignored."
|
|
90
89
|
)
|
|
91
90
|
)
|
|
92
91
|
return
|
|
@@ -98,21 +97,13 @@ class Si3HemisSumMonthMeanTimeseries(Timeseries):
|
|
|
98
97
|
this_leg = helpers.cubes.mask_other_hemisphere(this_leg, hemisphere)
|
|
99
98
|
this_leg = helpers.cubes.annual_time_bounds(this_leg)
|
|
100
99
|
|
|
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
|
-
)
|
|
100
|
+
this_leg_summed = helpers.nemo.compute_global_aggregate(
|
|
101
|
+
this_leg, domain, "T", iris.analysis.SUM
|
|
102
|
+
)
|
|
113
103
|
|
|
114
|
-
|
|
104
|
+
# sivolu and siarea do not have units assigned, we need to add them manually
|
|
115
105
|
this_leg_summed.units = cf_units.Unit(_meta_dict[varname]["old_unit"])
|
|
106
|
+
this_leg_summed.standard_name = _meta_dict[varname]["standard_name"]
|
|
116
107
|
this_leg_summed.convert_units(_meta_dict[varname]["new_unit"])
|
|
117
108
|
this_leg_summed.long_name = (
|
|
118
109
|
f"{long_name} {helpers.dates.month_name(month)} {hemisphere}"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "scriptengine-tasks-ecearth"
|
|
10
|
-
version = "0.
|
|
10
|
+
version = "0.7.1"
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "Valentina Schueller", email = "valentina.schueller@gmail.com" },
|
|
13
13
|
{ name = "Uwe Fladrich", email = "uwe.fladrich@protonmail.com" },
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
20
20
|
"Operating System :: OS Independent",
|
|
21
21
|
]
|
|
22
|
-
requires-python = ">=3.
|
|
22
|
+
requires-python = ">=3.8"
|
|
23
23
|
dependencies = [
|
|
24
24
|
"scriptengine>=0.8.1",
|
|
25
25
|
"pyYAML>=5.1",
|
|
26
26
|
"matplotlib>=3.1",
|
|
27
27
|
"numpy>=1.18",
|
|
28
28
|
"imageio>=2.18",
|
|
29
|
-
"scitools-iris>=3.
|
|
29
|
+
"scitools-iris>=3.5",
|
|
30
30
|
"cartopy>=0.20",
|
|
31
31
|
"python-redmine",
|
|
32
32
|
]
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
"ece.mon.timeseries" = "monitoring.timeseries:Timeseries"
|
|
41
41
|
"ece.mon.diskusage_rte_scalar" = "monitoring.diskusage_rte_scalar:DiskusageRteScalar"
|
|
42
42
|
"ece.mon.simulatedyears_rte_scalar" = "monitoring.simulatedyears_rte_scalar:SimulatedyearsRteScalar"
|
|
43
|
-
"ece.mon.nemo_global_mean_year_mean_timeseries" = "monitoring.
|
|
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"
|
|
44
46
|
"ece.mon.nemo_all_mean_map" = "monitoring.nemo_all_mean_map:NemoAllMeanMap"
|
|
45
47
|
"ece.mon.nemo_month_mean_temporalmap" = "monitoring.nemo_time_mean_temporalmap:NemoMonthMeanTemporalmap"
|
|
46
48
|
"ece.mon.nemo_year_mean_temporalmap" = "monitoring.nemo_time_mean_temporalmap:NemoYearMeanTemporalmap"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptengine-tasks-ecearth
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: ScriptEngine tasks for use with the EC-Earth climate model
|
|
5
5
|
Author-email: Valentina Schueller <valentina.schueller@gmail.com>, Uwe Fladrich <uwe.fladrich@protonmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/uwefladrich/scriptengine-tasks-ecearth
|
|
@@ -8,9 +8,18 @@ Project-URL: Bug Tracker, https://github.com/uwefladrich/scriptengine-tasks-ecea
|
|
|
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
|
|
22
|
+
Dynamic: license-file
|
|
14
23
|
|
|
15
24
|
[](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
|
|
16
25
|
[](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
|
|
@@ -33,4 +33,27 @@ scriptengine_tasks_ecearth.egg-info/SOURCES.txt
|
|
|
33
33
|
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
|
-
scriptengine_tasks_ecearth.egg-info/top_level.txt
|
|
36
|
+
scriptengine_tasks_ecearth.egg-info/top_level.txt
|
|
37
|
+
tests/test_cubes.py
|
|
38
|
+
tests/test_dates.py
|
|
39
|
+
tests/test_diskusage_rte_scalar.py
|
|
40
|
+
tests/test_file_handling.py
|
|
41
|
+
tests/test_linear_combination.py
|
|
42
|
+
tests/test_map.py
|
|
43
|
+
tests/test_map_type_handling.py
|
|
44
|
+
tests/test_markdown.py
|
|
45
|
+
tests/test_nemo_all_mean_map.py
|
|
46
|
+
tests/test_nemo_time_mean_temporalmap.py
|
|
47
|
+
tests/test_nemo_timeseries.py
|
|
48
|
+
tests/test_oifs_all_mean_map.py
|
|
49
|
+
tests/test_oifs_global_mean_year_mean_timeseries.py
|
|
50
|
+
tests/test_oifs_year_mean_temporalmap.py
|
|
51
|
+
tests/test_presentation_objects.py
|
|
52
|
+
tests/test_redmine.py
|
|
53
|
+
tests/test_scalar.py
|
|
54
|
+
tests/test_si3_hemis_point_month_mean_all_mean_map.py
|
|
55
|
+
tests/test_si3_hemis_point_month_mean_temporalmap.py
|
|
56
|
+
tests/test_si3_hemis_sum_month_mean_timeseries.py
|
|
57
|
+
tests/test_simulatedyears_rte_scalar.py
|
|
58
|
+
tests/test_temporalmap.py
|
|
59
|
+
tests/test_timeseries.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
|