Skip to content

Commit 0004056

Browse files
committed
Improve grib saving of shape of the earth key
1 parent 97d7941 commit 0004056

10 files changed

+129
-82
lines changed

lib/iris/fileformats/grib/_save_rules.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ def identification(cube, grib):
178178

179179

180180
def shape_of_the_earth(cube, grib):
181-
# assume latlon
182181
cs = cube.coord(dimensions=[0]).coord_system
183182

184183
# Initially set shape_of_earth keys to missing (255 for byte, -1 for long).
@@ -200,13 +199,23 @@ def shape_of_the_earth(cube, grib):
200199

201200
# Spherical earth.
202201
if ellipsoid.inverse_flattening == 0.0:
203-
gribapi.grib_set_long(grib, "shapeOfTheEarth", 1)
204-
gribapi.grib_set_long(grib, "scaleFactorOfRadiusOfSphericalEarth", 0)
202+
# Set shapeOfTheEarth key based on value of spherical earth radius.
203+
if int(ellipsoid.semi_major_axis) == 6367470:
204+
gribapi.grib_set_long(grib, "shapeOfTheEarth", 0)
205+
elif int(ellipsoid.semi_major_axis) == 6371229:
206+
gribapi.grib_set_long(grib, "shapeOfTheEarth", 6)
207+
else:
208+
gribapi.grib_set_long(grib, "shapeOfTheEarth", 1)
209+
gribapi.grib_set_long(grib,
210+
"scaleFactorOfRadiusOfSphericalEarth", 0)
205211
gribapi.grib_set_long(grib, "scaledValueOfRadiusOfSphericalEarth",
206212
ellipsoid.semi_major_axis)
207213
# Oblate spheroid earth.
208214
else:
209-
gribapi.grib_set_long(grib, "shapeOfTheEarth", 7)
215+
if isinstance(cs, iris.coord_systems.OSGB):
216+
gribapi.grib_set_long(grib, "shapeOfTheEarth", 9)
217+
else:
218+
gribapi.grib_set_long(grib, "shapeOfTheEarth", 7)
210219
gribapi.grib_set_long(grib, "scaleFactorOfEarthMajorAxis", 0)
211220
gribapi.grib_set_long(grib, "scaledValueOfEarthMajorAxis",
212221
ellipsoid.semi_major_axis)

lib/iris/tests/integration/test_grib2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def test_save_load(self):
140140
'gridDefinitionTemplateNumber = 5',
141141
'Ni = {:d}'.format(cube.shape[-1]),
142142
'Nj = {:d}'.format(cube.shape[-2]),
143-
'shapeOfTheEarth = 1',
143+
'shapeOfTheEarth = 6',
144144
'scaledValueOfRadiusOfSphericalEarth = {:d}'.format(
145145
int(UM_DEFAULT_EARTH_RADIUS)),
146146
'resolutionAndComponentFlags = 0',

lib/iris/tests/results/grib_save/latlon_forecast_plev.grib_compare.post1-12-0.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ long [productionStatusOfProcessedData]: [0] != [255]
66
[section2Length] not found in 2nd field
77
long [numberOfSection] 6 out of 7 different
88
long [numberOfSection] 5 out of 7 different
9-
long [shapeOfTheEarth]: [0] != [1]
109
scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1110
scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1211
long [numberOfSection] 6 out of 7 different

lib/iris/tests/results/grib_save/rotated_latlon.grib_compare.post1-12-0.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ long [productionStatusOfProcessedData]: [0] != [255]
66
[section2Length] not found in 2nd field
77
long [numberOfSection] 6 out of 7 different
88
long [numberOfSection] 5 out of 7 different
9-
long [shapeOfTheEarth]: [0] != [1]
109
scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1110
scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1211
long [latitudeOfLastGridPoint]: [19419996] != [19419285]

lib/iris/tests/results/grib_save/time_mean.grib_compare.post1-12-0.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ long [productionStatusOfProcessedData]: [0] != [255]
66
[section2Length] not found in 2nd field
77
long [numberOfSection] 6 out of 7 different
88
long [numberOfSection] 5 out of 7 different
9-
long [shapeOfTheEarth]: [0] != [1]
109
scaleFactorOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1110
scaledValueOfRadiusOfSphericalEarth is set to missing in 1st field is not missing in 2nd field
1211
long [latitudeOfLastGridPoint]: [-89999938] != [-89999944]

lib/iris/tests/unit/fileformats/grib/save_rules/test_grid_definition_template_0.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,6 @@ def test__template_number(self):
4242
grid_definition_template_0(self.test_cube, self.mock_grib)
4343
self._check_key('gridDefinitionTemplateNumber', 0)
4444

45-
def test__shape_of_earth_spherical(self):
46-
cs = GeogCS(semi_major_axis=1.23)
47-
test_cube = self._make_test_cube(cs=cs)
48-
grid_definition_template_0(test_cube, self.mock_grib)
49-
self._check_key('shapeOfTheEarth', 1)
50-
self._check_key('scaleFactorOfRadiusOfSphericalEarth', 0)
51-
self._check_key('scaledValueOfRadiusOfSphericalEarth', 1.23)
52-
53-
def test__shape_of_earth_flattened(self):
54-
cs = GeogCS(semi_major_axis=1.456,
55-
semi_minor_axis=1.123)
56-
test_cube = self._make_test_cube(cs=cs)
57-
grid_definition_template_0(test_cube, self.mock_grib)
58-
self._check_key('shapeOfTheEarth', 7)
59-
self._check_key('scaleFactorOfEarthMajorAxis', 0)
60-
self._check_key('scaledValueOfEarthMajorAxis', 1.456)
61-
self._check_key('scaleFactorOfEarthMinorAxis', 0)
62-
self._check_key('scaledValueOfEarthMinorAxis', 1.123)
63-
6445
def test__grid_shape(self):
6546
test_cube = self._make_test_cube(x_points=np.arange(13),
6647
y_points=np.arange(6))

lib/iris/tests/unit/fileformats/grib/save_rules/test_grid_definition_template_1.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,30 +52,6 @@ def test__template_number(self):
5252
grid_definition_template_1(self.test_cube, self.mock_grib)
5353
self._check_key('gridDefinitionTemplateNumber', 1)
5454

55-
def test__shape_of_earth_spherical(self):
56-
ellipsoid = GeogCS(1.23)
57-
cs = RotatedGeogCS(grid_north_pole_latitude=90.0,
58-
grid_north_pole_longitude=0.0,
59-
ellipsoid=ellipsoid)
60-
test_cube = self._make_test_cube(cs=cs)
61-
grid_definition_template_1(test_cube, self.mock_grib)
62-
self._check_key('shapeOfTheEarth', 1)
63-
self._check_key('scaleFactorOfRadiusOfSphericalEarth', 0)
64-
self._check_key('scaledValueOfRadiusOfSphericalEarth', 1.23)
65-
66-
def test__shape_of_earth_flattened(self):
67-
ellipsoid = GeogCS(semi_major_axis=1.456, semi_minor_axis=1.123)
68-
cs = RotatedGeogCS(grid_north_pole_latitude=90.0,
69-
grid_north_pole_longitude=0.0,
70-
ellipsoid=ellipsoid)
71-
test_cube = self._make_test_cube(cs=cs)
72-
grid_definition_template_1(test_cube, self.mock_grib)
73-
self._check_key('shapeOfTheEarth', 7)
74-
self._check_key('scaleFactorOfEarthMajorAxis', 0)
75-
self._check_key('scaledValueOfEarthMajorAxis', 1.456)
76-
self._check_key('scaleFactorOfEarthMinorAxis', 0)
77-
self._check_key('scaledValueOfEarthMinorAxis', 1.123)
78-
7955
def test__grid_shape(self):
8056
test_cube = self._make_test_cube(x_points=np.arange(13),
8157
y_points=np.arange(6))

lib/iris/tests/unit/fileformats/grib/save_rules/test_grid_definition_template_12.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,6 @@ def test__template_number(self):
6161
grid_definition_template_12(self.test_cube, self.mock_grib)
6262
self._check_key('gridDefinitionTemplateNumber', 12)
6363

64-
def test__shape_of_earth(self):
65-
grid_definition_template_12(self.test_cube, self.mock_grib)
66-
self._check_key('shapeOfTheEarth', 7)
67-
self._check_key('scaleFactorOfEarthMajorAxis', 0)
68-
self._check_key('scaledValueOfEarthMajorAxis', 6377563.396)
69-
self._check_key('scaleFactorOfEarthMinorAxis', 0)
70-
self._check_key('scaledValueOfEarthMinorAxis', 6356256.909)
71-
7264
def test__grid_shape(self):
7365
test_cube = self._make_test_cube(x_points=np.arange(13),
7466
y_points=np.arange(6))

lib/iris/tests/unit/fileformats/grib/save_rules/test_grid_definition_template_5.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,29 +56,6 @@ def test__template_number(self):
5656
grid_definition_template_5(self.test_cube, self.mock_grib)
5757
self._check_key('gridDefinitionTemplateNumber', 5)
5858

59-
def test__shape_of_earth_spherical(self):
60-
cs = RotatedGeogCS(grid_north_pole_latitude=90.0,
61-
grid_north_pole_longitude=0.0,
62-
ellipsoid=GeogCS(52431.0))
63-
test_cube = self._make_test_cube(cs=cs)
64-
grid_definition_template_5(test_cube, self.mock_grib)
65-
self._check_key('shapeOfTheEarth', 1)
66-
self._check_key('scaleFactorOfRadiusOfSphericalEarth', 0)
67-
self._check_key('scaledValueOfRadiusOfSphericalEarth', 52431.0)
68-
69-
def test__shape_of_earth_flattened(self):
70-
ellipsoid = GeogCS(semi_major_axis=1456.0, semi_minor_axis=1123.0)
71-
cs = RotatedGeogCS(grid_north_pole_latitude=90.0,
72-
grid_north_pole_longitude=0.0,
73-
ellipsoid=ellipsoid)
74-
test_cube = self._make_test_cube(cs=cs)
75-
grid_definition_template_5(test_cube, self.mock_grib)
76-
self._check_key('shapeOfTheEarth', 7)
77-
self._check_key('scaleFactorOfEarthMajorAxis', 0)
78-
self._check_key('scaledValueOfEarthMajorAxis', 1456.0)
79-
self._check_key('scaleFactorOfEarthMinorAxis', 0)
80-
self._check_key('scaledValueOfEarthMinorAxis', 1123.0)
81-
8259
def test__grid_shape(self):
8360
test_cube = self._make_test_cube(x_points=np.arange(13),
8461
y_points=np.arange(6))
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# (C) British Crown Copyright 2014, Met Office
2+
#
3+
# This file is part of Iris.
4+
#
5+
# Iris is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU Lesser General Public License as published by the
7+
# Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# Iris is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with Iris. If not, see <http://www.gnu.org/licenses/>.
17+
"""
18+
Unit tests for
19+
:meth:`iris.fileformats.grib._save_rules.shape_of_the_earth`.
20+
21+
"""
22+
23+
from __future__ import (absolute_import, division, print_function)
24+
25+
# Import iris.tests first so that some things can be initialised before
26+
# importing anything else.
27+
import iris.tests as tests
28+
29+
import numpy as np
30+
31+
from iris.coord_systems import GeogCS, TransverseMercator, OSGB
32+
from iris.exceptions import TranslationError
33+
from iris.tests.unit.fileformats.grib.save_rules import GdtTestMixin
34+
35+
from iris.fileformats.grib._save_rules import shape_of_the_earth
36+
37+
38+
class Test(tests.IrisTest, GdtTestMixin):
39+
def setUp(self):
40+
GdtTestMixin.setUp(self)
41+
42+
def _spherical_earth_test_common(self, radius):
43+
self._check_key('scaleFactorOfRadiusOfSphericalEarth', 0)
44+
self._check_key('scaledValueOfRadiusOfSphericalEarth', radius)
45+
46+
def _oblate_spheroid_earth_test_common(self, semi_major_axis,
47+
semi_minor_axis):
48+
self._check_key('scaleFactorOfEarthMajorAxis', 0)
49+
self._check_key('scaledValueOfEarthMajorAxis', semi_major_axis)
50+
self._check_key('scaleFactorOfEarthMinorAxis', 0)
51+
self._check_key('scaledValueOfEarthMinorAxis', semi_minor_axis)
52+
53+
def test_radius_of_earth_6367470(self):
54+
# Test setting shapeOfTheEarth = 0
55+
radius = 6367470
56+
cs = GeogCS(semi_major_axis=radius)
57+
test_cube = self._make_test_cube(cs=cs)
58+
shape_of_the_earth(test_cube, self.mock_grib)
59+
self._check_key('shapeOfTheEarth', 0)
60+
self._spherical_earth_test_common(radius)
61+
62+
def test_radius_of_earth_6371229(self):
63+
# Test setting shapeOfTheEarth = 6
64+
radius = 6371229
65+
cs = GeogCS(semi_major_axis=radius)
66+
test_cube = self._make_test_cube(cs=cs)
67+
shape_of_the_earth(test_cube, self.mock_grib)
68+
self._check_key('shapeOfTheEarth', 6)
69+
self._spherical_earth_test_common(radius)
70+
71+
def test_spherical_earth(self):
72+
# Test setting shapeOfTheEarth = 1
73+
radius = 1.23
74+
cs = GeogCS(semi_major_axis=radius)
75+
test_cube = self._make_test_cube(cs=cs)
76+
shape_of_the_earth(test_cube, self.mock_grib)
77+
self._check_key('shapeOfTheEarth', 1)
78+
self._spherical_earth_test_common(radius)
79+
80+
def test_oblate_spheroid_earth(self):
81+
# Test setting shapeOfTheEarth = 7
82+
semi_major_axis = 1.456
83+
semi_minor_axis = 1.123
84+
cs = GeogCS(semi_major_axis=semi_major_axis,
85+
semi_minor_axis=semi_minor_axis)
86+
test_cube = self._make_test_cube(cs=cs)
87+
shape_of_the_earth(test_cube, self.mock_grib)
88+
self._check_key('shapeOfTheEarth', 7)
89+
self._oblate_spheroid_earth_test_common(semi_major_axis,
90+
semi_minor_axis)
91+
92+
def test_OSGB(self):
93+
# Test setting shapeOfTheEarth = 9
94+
cs = OSGB()
95+
# The following are fixed for the OSGB coord system.
96+
semi_major_axis, semi_minor_axis = (6377563.396, 6356256.909)
97+
test_cube = self._make_test_cube(cs=cs)
98+
shape_of_the_earth(test_cube, self.mock_grib)
99+
self._check_key('shapeOfTheEarth', 9)
100+
self._oblate_spheroid_earth_test_common(semi_major_axis,
101+
semi_minor_axis)
102+
103+
def test_TransverseMercator_spherical(self):
104+
# Test setting shapeOfTheEarth = 1 with a non-GeogCS coord system.
105+
cs = TransverseMercator(49, -2, 400000, -100000, 0.9996012717,
106+
ellipsoid=GeogCS(6377563.396))
107+
radius = 6377563.396
108+
test_cube = self._make_test_cube(cs=cs)
109+
shape_of_the_earth(test_cube, self.mock_grib)
110+
self._check_key('shapeOfTheEarth', 1)
111+
self._spherical_earth_test_common(radius)
112+
113+
114+
if __name__ == "__main__":
115+
tests.main()

0 commit comments

Comments
 (0)