Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,10 @@ linux_task_template: &LINUX_TASK_TEMPLATE

tests_task:
matrix:
# TODO: iris-grib does not currently work with iris-main, see Github issue
# #288 and #277.
#- name: "${CIRRUS_OS} tests: iris=repo-main python=3.8"
# env:
# PY_VER: 3.8
# IRIS_SOURCE: "source"
- name: "${CIRRUS_OS} tests: iris=conda-release python=3.7"
- name: "${CIRRUS_OS} tests: iris=repo-main python=3.8"
env:
PY_VER: 3.7
IRIS_SOURCE: "conda-forge"
PY_VER: 3.8
IRIS_SOURCE: "source"
- name: "${CIRRUS_OS} tests: iris=conda-release python=3.8"
env:
PY_VER: 3.8
Expand Down
12 changes: 8 additions & 4 deletions iris_grib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,12 @@ def phenomenon_points(self, time_unit):

"""
time_reference = '%s since epoch' % time_unit
return cf_units.date2num(self._phenomenonDateTime, time_reference,
cf_units.CALENDAR_GREGORIAN)
return float(
cf_units.date2num(
self._phenomenonDateTime, time_reference,
cf_units.CALENDAR_GREGORIAN
)
)

def phenomenon_bounds(self, time_unit):
"""
Expand All @@ -630,8 +634,8 @@ def phenomenon_bounds(self, time_unit):
# TODO #576 Investigate when it's valid to get phenomenon_bounds
time_reference = '%s since epoch' % time_unit
unit = cf_units.Unit(time_reference, cf_units.CALENDAR_GREGORIAN)
return [unit.date2num(self._periodStartDateTime),
unit.date2num(self._periodEndDateTime)]
return [float(unit.date2num(self._periodStartDateTime)),
float(unit.date2num(self._periodEndDateTime))]


def _longitude_is_cyclic(points):
Expand Down
6 changes: 3 additions & 3 deletions iris_grib/_load_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def reference_time_coord(section):
# Current GRIBAPI does not cover GRIB Section 1 - Octets 22-nn (optional)
# which are part of GRIB spec v12.
unit = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN)
point = unit.date2num(dt)
point = float(unit.date2num(dt))

# Reference Code Table 1.2.
significanceOfReferenceTime = section['significanceOfReferenceTime']
Expand Down Expand Up @@ -1839,15 +1839,15 @@ def coord_timedelta(coord, value):
# Calculate validity (phenomenon) time in forecast-reference-time units.
frt_point = frt_coord.units.num2date(frt_coord.points[0])
point_delta = coord_timedelta(fp_coord, fp_coord.points[0])
point = frt_coord.units.date2num(frt_point + point_delta)
point = float(frt_coord.units.date2num(frt_point + point_delta))

# Calculate bounds (if any) in the same way.
if fp_coord.bounds is None:
bounds = None
else:
bounds_deltas = [coord_timedelta(fp_coord, bound_point)
for bound_point in fp_coord.bounds[0]]
bounds = [frt_coord.units.date2num(frt_point + delta)
bounds = [float(frt_coord.units.date2num(frt_point + delta))
for delta in bounds_deltas]

# Create the time scalar coordinate.
Expand Down
22 changes: 14 additions & 8 deletions iris_grib/_save_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import cf_units
import gribapi
from gribapi import GRIB_MISSING_LONG
import numpy as np
import numpy.ma as ma

Expand Down Expand Up @@ -180,13 +181,16 @@ def shape_of_the_earth(cube, grib):
# assume latlon
cs = cube.coord(dimensions=[0]).coord_system

# Initially set shape_of_earth keys to missing (255 for byte, -1 for long).
# Initially set shape_of_earth keys to missing (255 for byte).
gribapi.grib_set_long(grib, "scaleFactorOfRadiusOfSphericalEarth", 255)
gribapi.grib_set_long(grib, "scaledValueOfRadiusOfSphericalEarth", -1)
gribapi.grib_set_long(grib, "scaledValueOfRadiusOfSphericalEarth",
GRIB_MISSING_LONG)
gribapi.grib_set_long(grib, "scaleFactorOfEarthMajorAxis", 255)
gribapi.grib_set_long(grib, "scaledValueOfEarthMajorAxis", -1)
gribapi.grib_set_long(grib, "scaledValueOfEarthMajorAxis",
GRIB_MISSING_LONG)
gribapi.grib_set_long(grib, "scaleFactorOfEarthMinorAxis", 255)
gribapi.grib_set_long(grib, "scaledValueOfEarthMinorAxis", -1)
gribapi.grib_set_long(grib, "scaledValueOfEarthMinorAxis",
GRIB_MISSING_LONG)

if isinstance(cs, GeogCS):
ellipsoid = cs
Expand Down Expand Up @@ -923,9 +927,10 @@ def set_fixed_surfaces(cube, grib, full3d_cube=None):
gribapi.grib_set(grib, "scaleFactorOfFirstFixedSurface", 0)
gribapi.grib_set(grib, "scaledValueOfFirstFixedSurface", 0)
# Set secondary surface = 'missing'.
gribapi.grib_set(grib, "typeOfSecondFixedSurface", -1)
gribapi.grib_set(grib, "typeOfSecondFixedSurface", 255)
gribapi.grib_set(grib, "scaleFactorOfSecondFixedSurface", 255)
gribapi.grib_set(grib, "scaledValueOfSecondFixedSurface", -1)
gribapi.grib_set(grib, "scaledValueOfSecondFixedSurface",
GRIB_MISSING_LONG)
elif not v_coord.has_bounds():
# No second surface
output_v = v_coord.units.convert(v_coord.points[0], output_unit)
Expand All @@ -936,9 +941,10 @@ def set_fixed_surfaces(cube, grib, full3d_cube=None):
gribapi.grib_set(grib, "typeOfFirstFixedSurface", grib_v_code)
gribapi.grib_set(grib, "scaleFactorOfFirstFixedSurface", 0)
gribapi.grib_set(grib, "scaledValueOfFirstFixedSurface", output_v)
gribapi.grib_set(grib, "typeOfSecondFixedSurface", -1)
gribapi.grib_set(grib, "typeOfSecondFixedSurface", 255)
gribapi.grib_set(grib, "scaleFactorOfSecondFixedSurface", 255)
gribapi.grib_set(grib, "scaledValueOfSecondFixedSurface", -1)
gribapi.grib_set(grib, "scaledValueOfSecondFixedSurface",
GRIB_MISSING_LONG)
else:
# bounded : set lower+upper surfaces
output_v = v_coord.units.convert(v_coord.bounds[0], output_unit)
Expand Down
11 changes: 11 additions & 0 deletions iris_grib/tests/integration/format_interop/test_name_grib.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def name_cb(cube, field, filename):
if z_coord:
z_coord[0].standard_name = "height"
z_coord[0].long_name = "height above ground level"
z_coord[0].attributes = {'positive': 'up'}


class TestNameToGRIB(tests.IrisGribTest):
Expand Down Expand Up @@ -71,6 +72,11 @@ def test_name2_field(self):
warnings.warn(msg.format(i, name_cube.name()))
continue

# Iris>=3.2 loads in an extra 'z' coordinate which cannot currently
# be save to GRIB.
if name_cube.coords('z'):
name_cube.remove_coord('z')

with self.temp_filename(".grib2") as temp_filename:
iris.save(name_cube, temp_filename)
grib_cube = iris.load_cube(temp_filename, callback=name_cb)
Expand All @@ -92,6 +98,11 @@ def test_name3_field(self):
filepath = tests.get_data_path(("NAME", "NAMEIII_field.txt"))
name_cubes = iris.load(filepath)
for i, name_cube in enumerate(name_cubes):
# Iris>=3.2 loads in an extra 'z' coordinate which cannot currently
# be save to GRIB.
if name_cube.coord('z') is not None:
name_cube.remove_coord('z')

with self.temp_filename(".grib2") as temp_filename:
iris.save(name_cube, temp_filename)
grib_cube = iris.load_cube(temp_filename, callback=name_cb)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
<dimCoord bounds="[[0.0, 3.0]]" id="1d45e087" points="[3.0]" shape="(1,)" standard_name="forecast_period" units="Unit('hours')" value_type="float64"/>
</coord>
<coord>
<dimCoord bounds="[[0.0, 100.0]]" id="c87e380b" long_name="height above ground level" points="[50.0]" shape="(1,)" standard_name="height" units="Unit('m')" value_type="float64"/>
<dimCoord bounds="[[0.0, 100.0]]" id="1a539915" long_name="height above ground level" points="[50.0]" shape="(1,)" standard_name="height" units="Unit('m')" value_type="float64">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: these two coords remain 'float' as before (in contrast to #288),
but the id's changed because of the additional attribute.

<attributes>
<attribute name="positive" value="up"/>
</attributes>
</dimCoord>
</coord>
<coord datadims="[0]">
<dimCoord id="77a50eb5" points="[52.367102, 52.368208, 52.369314, ..., 52.584984,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
<dimCoord bounds="[[0.0, 3.0]]" id="1d45e087" points="[3.0]" shape="(1,)" standard_name="forecast_period" units="Unit('hours')" value_type="float64"/>
</coord>
<coord>
<dimCoord bounds="[[0.0, 100.0]]" id="c87e380b" long_name="height above ground level" points="[50.0]" shape="(1,)" standard_name="height" units="Unit('m')" value_type="float64"/>
<dimCoord bounds="[[0.0, 100.0]]" id="1a539915" long_name="height above ground level" points="[50.0]" shape="(1,)" standard_name="height" units="Unit('m')" value_type="float64">
<attributes>
<attribute name="positive" value="up"/>
</attributes>
</dimCoord>
</coord>
<coord datadims="[0]">
<dimCoord id="77a50eb5" points="[52.367102, 52.368208, 52.369314, ..., 52.584984,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def expected(self, y_dim, x_dim):
units='m',
coord_system=cs)
ny = 213
y_origin = 253793.10903714446
y_origin = 253793.10903714459

dy = 12000
y = iris.coords.DimCoord(np.arange(ny) * dy + y_origin,
'projection_y_coordinate',
Expand Down
15 changes: 9 additions & 6 deletions iris_grib/tests/unit/save_rules/test_set_fixed_surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from unittest import mock

import gribapi
from gribapi import GRIB_MISSING_LONG
import numpy as np

import iris.cube
Expand Down Expand Up @@ -99,11 +100,11 @@ def test_altitude_point(self, mock_set):
mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0)
mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface",
12345)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", 255)
mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface",
255)
mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface",
-1)
GRIB_MISSING_LONG)

@mock.patch.object(gribapi, "grib_set")
def test_height_point(self, mock_set):
Expand All @@ -116,9 +117,10 @@ def test_height_point(self, mock_set):
mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 103)
mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0)
mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", 255)
mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255)
mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface",
GRIB_MISSING_LONG)

@mock.patch.object(gribapi, "grib_set")
def test_no_vertical(self, mock_set):
Expand All @@ -128,9 +130,10 @@ def test_no_vertical(self, mock_set):
mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 1)
mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0)
mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 0)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1)
mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", 255)
mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255)
mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface",
GRIB_MISSING_LONG)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def _session_lockfile(session: nox.sessions.Session) -> Path:

"""
lockfile_name = f"py{session.python.replace('.', '')}-linux-64.lock"
return Path("requirements/nox.lock") / lockfile_name
return Path("requirements/ci/nox.lock") / lockfile_name


def _file_content(file_path: Path) -> str:
Expand Down
2 changes: 1 addition & 1 deletion requirements/ci/iris-grib.yml
Loading