-
Notifications
You must be signed in to change notification settings - Fork 283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
name to grib #835
name to grib #835
Conversation
@@ -393,7 +393,7 @@ def type_of_statistical_processing(cube, grib, coord): | |||
if len(coord_names) == 1 and coord_names[0] == coord.name(): | |||
if cell_method.method == 'mean': | |||
stat_code = 0 | |||
elif cell_method.method == 'accumulation': | |||
elif cell_method.method in ['accumulation', 'sum']: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since your in this space anyway, 'accumulation' doesn't look like it's a valid cf cell method. Is this captured in any of the tests? Might be worth removing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually... while you're here, why not do a dictionary lookup?
Why is this PR limited to NAMEII/III fields? What about NAMEIII trajectories for example, is it not applicable here too? |
# Prepare for comparison | ||
grib_cube.coord('forecast_period').convert_units('minutes') | ||
name_cube.rename('unknown') | ||
name_cube.units = 'unknown' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take a close look at these comparisons once #833 is in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doing so now
I think this PR definitely warrants adding information to the |
@@ -318,6 +318,18 @@ def convert(grib): | |||
|
|||
if \ | |||
(grib.edition == 2) and \ | |||
(grib.typeOfFirstFixedSurface == 103) and \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my own reference, this corresponds to 'Specified height level above ground'
Over to you @bblay |
I'm quite happy with the integration tests here, I would have unit tested the grib load rules added by mocking out the grib API (which I believe is already in the iris codebase ) and also unittesting the changes made within lib/iris/fileformats/name_loaders.py What do you think @rhattersley? |
That's just the user story I'm working on , as pasted into this PR's description. |
Fair comment. I was probably wrong to omit those tests, but everything you mention is actually being tested already, which gives an interesting effort vs benefit question. I thought I'd see where that lead. For starters, it's not too safe, as it relies on indirect tests which could change. |
Review actions + rebased onto latest master.
I tested GRIB2 height level loading, but only one of the two new rules as it looked horribly mockist otherwise :D, and they're pretty much the same. For the name loading, that's properly tested already, as we can see in the results. |
@@ -393,7 +393,7 @@ def type_of_statistical_processing(cube, grib, coord): | |||
if len(coord_names) == 1 and coord_names[0] == coord.name(): | |||
if cell_method.method == 'mean': | |||
stat_code = 0 | |||
elif cell_method.method == 'accumulation': | |||
elif cell_method.method == 'sum': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason, why you object to a dictionary lookup? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done that, I just haven't pushed any of the review actions since the original request.
You have not taken action on the issues surrounding your coordinates: >>> coord='time'; print name_cube.coord(coord); print grib_cube.coord(coord)
DimCoord([2010-01-26 12:00:00], bounds=[[2010-01-26 09:00:00, 2010-01-26 12:00:00]], standard_name='time', calendar='gregorian')
DimCoord([2010-01-26 10:30:00], bounds=[[2010-01-26 09:00:00, 2010-01-26 12:00:00]], standard_name='time', calendar='gregorian')
>>> coord='height'; print name_cube.coord(coord); print grib_cube.coord(coord)
DimCoord(array([ 50.]), bounds=array([[ 0., 100.]]), standard_name='height', units=Unit('m'))
DimCoord(array([ 50.]), bounds=array([[ 0., 100.]]), standard_name=None, units=Unit('m'), long_name='height') You will need to correct this and address your tests which don't currently compare the coordinates due to the logic you have used.
I'm now more inclined to conduct unittesting :) |
self.assertTrue(np.allclose(name_cube.data, grib_cube.data)) | ||
self.assertTrue(name_cube.is_compatible(grib_cube)) | ||
for coord in name_cube.coords(): | ||
if grib_cube.coords(coord): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your tests will pass whatever happens, as this won't be True
Over to you @bblay |
I haven't push any of the new review actions yet! 😀 |
There has been quite a big change in the way time is handled here, so I've made a new, single commit as a new starting point. More specifically, I was not interpreting the NAME dates properly, confusing "run time" with "model start time". We can't actually get the model start time, so we can't calculate a CF-style forecast_period on loading NAME fields. This has the knock on effect of not being able to save to grib2 without changes to the grib saving ruies, which are in this new commit. |
('integration', 'name_grib', 'NAMEII', | ||
'{}_{}.cml'.format(i, name_cube.name())))) | ||
|
||
def test_name3_field(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty much identical to the name2 test, happy to squidge them together if preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have a private method which puts all this common stuff together, but still have two separate unittest functions, one for the NAMEII and the other for the NAMEIII which calls it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In future, I would not have added these 'acceptance tests', these are internally driven and should not replace a proper coverage using unittests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have not pulled out the common code into a private method of the class. In addition, I would also mention that these integration tests will be moved into internal acceptance tests in future.
Back to you, @cpelley |
just getting set up at home to fix that test... |
if fp_coord is not None: | ||
if fp_coord.has_bounds(): | ||
raise iris.exceptions.TranslationError( | ||
"Bounds not expected for 'forecast_period'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth changing this message, the problem is with interpreting a bounded forecast period when exporting to GRIB specifically, is it not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scratch that, the exception will come up in grib_save_rules
self.assertEqual((coord.name(), coord.units, coord.points[0]), | ||
('height', 'm', 2.0)) | ||
|
||
def test_grib2_height(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move these to unittests dir
In future can you put the cml changes in a separate commit :) |
stat_code = 6 | ||
stat_codes = {'mean': 0, 'sum': 1, 'maximum': 2, 'minimum': 3, | ||
'standard_deviation': 6} | ||
stat_code = stat_codes[cell_method.method] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type_of_statistical_processing
is still not being unittested
Technically speaking, this is also the time to build the mock framework for both NameII and NameIII fields as unittests since you should check that |
|
||
class TestNameToGRIB(tests.IrisTest): | ||
def _assert_cube_equal(self, path_name, path_result): | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_assert_cube_equal
not being used
Just checking, that's not a request to do that now, right? |
Well you have changed them, I would have |
Just to mention.. this PR has now substantially increased in size, another side-effect of stringent unit-testing. |
class TestNameToGRIB(tests.IrisTest): | ||
|
||
def check_common(self, name_cube, grib_cube): | ||
self.assertTrue(np.allclose(name_cube.data, name_cube.data)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have used, the iris self.assertArrayAlmostEqua(a, b)
This results in a test failure with the latitude
, longitude
coords however.
On discussion with you, you have confirmed that the difference in precision can be accounted for in the way that grib packs data.
OK, happy for merging |
Reviewer: cpelley
Enhance NAME to GRIB translation, such that comparable cubes can be loaded back in.
The internal user story is as follows:
TODO:
[ ] pr metarelateRaised https://github.com/SciTools/iris-code-generators/pull/23 to mirror the rule changes...