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.
Files changed (66) hide show
  1. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/PKG-INFO +14 -6
  2. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/cubes.py +43 -1
  3. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/map_type_handling.py +3 -3
  4. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/nemo.py +33 -2
  5. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/presentation_objects.py +17 -0
  6. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/linear_combination.py +0 -1
  7. scriptengine_tasks_ecearth-0.7.0/monitoring/nemo_timeseries.py +157 -0
  8. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_all_mean_map.py +2 -4
  9. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_global_mean_year_mean_timeseries.py +1 -4
  10. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/oifs_year_mean_temporalmap.py +1 -4
  11. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_sum_month_mean_timeseries.py +3 -15
  12. scriptengine_tasks_ecearth-0.7.0/pyproject.toml +57 -0
  13. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/PKG-INFO +14 -6
  14. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/SOURCES.txt +2 -3
  15. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/entry_points.txt +3 -1
  16. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/requires.txt +1 -1
  17. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/top_level.txt +0 -1
  18. scriptengine_tasks_ecearth-0.7.0/setup.py +5 -0
  19. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_cubes.py +14 -0
  20. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_file_handling.py +4 -2
  21. scriptengine_tasks_ecearth-0.7.0/tests/test_nemo_timeseries.py +99 -0
  22. scriptengine-tasks-ecearth-0.6.2/monitoring/nemo_global_mean_year_mean_timeseries.py +0 -89
  23. scriptengine-tasks-ecearth-0.6.2/pyproject.toml +0 -6
  24. scriptengine-tasks-ecearth-0.6.2/setup.py +0 -77
  25. scriptengine-tasks-ecearth-0.6.2/tests/__init__.py +0 -0
  26. scriptengine-tasks-ecearth-0.6.2/tests/test_nemo_global_mean_year_mean_timeseries.py +0 -40
  27. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/LICENSE +0 -0
  28. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/README.md +0 -0
  29. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/__init__.py +0 -0
  30. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/dates.py +0 -0
  31. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/exceptions.py +0 -0
  32. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/helpers/files.py +0 -0
  33. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/diskusage_rte_scalar.py +0 -0
  34. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/map.py +0 -0
  35. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/markdown.py +0 -0
  36. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/nemo_all_mean_map.py +0 -0
  37. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/nemo_time_mean_temporalmap.py +0 -0
  38. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/redmine.py +0 -0
  39. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/scalar.py +0 -0
  40. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_point_month_mean_all_mean_map.py +0 -0
  41. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/si3_hemis_point_month_mean_temporalmap.py +0 -0
  42. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/simulatedyears_rte_scalar.py +0 -0
  43. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/temporalmap.py +0 -0
  44. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/monitoring/timeseries.py +0 -0
  45. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/scriptengine_tasks_ecearth.egg-info/dependency_links.txt +0 -0
  46. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/setup.cfg +0 -0
  47. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_dates.py +0 -0
  48. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_diskusage_rte_scalar.py +0 -0
  49. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_linear_combination.py +0 -0
  50. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_map.py +0 -0
  51. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_map_type_handling.py +0 -0
  52. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_markdown.py +0 -0
  53. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_nemo_all_mean_map.py +0 -0
  54. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_nemo_time_mean_temporalmap.py +0 -0
  55. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_all_mean_map.py +0 -0
  56. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_global_mean_year_mean_timeseries.py +0 -0
  57. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_oifs_year_mean_temporalmap.py +0 -0
  58. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_presentation_objects.py +0 -0
  59. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_redmine.py +0 -0
  60. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_scalar.py +0 -0
  61. {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
  62. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_si3_hemis_point_month_mean_temporalmap.py +0 -0
  63. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_si3_hemis_sum_month_mean_timeseries.py +0 -0
  64. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_simulatedyears_rte_scalar.py +0 -0
  65. {scriptengine-tasks-ecearth-0.6.2 → scriptengine_tasks_ecearth-0.7.0}/tests/test_temporalmap.py +0 -0
  66. {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
1
+ Metadata-Version: 2.2
2
2
  Name: scriptengine-tasks-ecearth
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: ScriptEngine tasks for use with the EC-Earth climate model
5
- Home-page: https://github.com/uwefladrich/scriptengine-tasks-ecearth
6
- Author: Valentina Schueller, Uwe Fladrich
7
- Author-email: valentina.schueller@gmail.com, uwe.fladrich@protonmail.com
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.7
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
  [![Tests](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions/workflows/pytest.yml/badge.svg)](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
16
24
  [![Coverage Status](https://coveralls.io/repos/github/uwefladrich/scriptengine-tasks-ecearth/badge.svg)](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
 
@@ -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 spatial_weights(cube, domain_file, grid):
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
- return np.broadcast_to(weights.data, cube.shape)
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()
@@ -12,7 +12,6 @@ import helpers.cubes
12
12
 
13
13
 
14
14
  class LinearCombination(Task):
15
-
16
15
  _required_arguments = (
17
16
  "src",
18
17
  "dst",
@@ -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
- # Convert unit to °C if varname is given in K
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
- # Convert unit to °C if varname is given in K
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
- # Convert unit to °C if varname is given in K
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
- with warnings.catch_warnings():
102
- # Suppress warning about insufficient metadata.
103
- warnings.filterwarnings(
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
1
+ Metadata-Version: 2.2
2
2
  Name: scriptengine-tasks-ecearth
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: ScriptEngine tasks for use with the EC-Earth climate model
5
- Home-page: https://github.com/uwefladrich/scriptengine-tasks-ecearth
6
- Author: Valentina Schueller, Uwe Fladrich
7
- Author-email: valentina.schueller@gmail.com, uwe.fladrich@protonmail.com
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.7
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
  [![Tests](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions/workflows/pytest.yml/badge.svg)](https://github.com/uwefladrich/scriptengine-tasks-ecearth/actions)
16
24
  [![Coverage Status](https://coveralls.io/repos/github/uwefladrich/scriptengine-tasks-ecearth/badge.svg)](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.nemo_global_mean_year_mean_timeseries:NemoGlobalMeanYearMeanTimeseries
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
@@ -3,6 +3,6 @@ pyYAML>=5.1
3
3
  matplotlib>=3.1
4
4
  numpy>=1.18
5
5
  imageio>=2.18
6
- scitools-iris!=3.2.0,!=3.2.0.post0,>=3.1
6
+ scitools-iris>=3.5
7
7
  cartopy>=0.20
8
8
  python-redmine
@@ -0,0 +1,5 @@
1
+ import setuptools
2
+
3
+
4
+ if __name__ == "__main__":
5
+ setuptools.setup()
@@ -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)
@@ -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
- assert helpers.nemo.spatial_weights(data, domain_file, "t") == expected_weights
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
- assert helpers.nemo.spatial_weights(data, domain_file, "t") == expected_weights
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,6 +0,0 @@
1
- [build-system]
2
- requires = [
3
- "setuptools>=42",
4
- "wheel"
5
- ]
6
- build-backend = "setuptools.build_meta"
@@ -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
- )