Skip to content

Gdt40 save#813

Draft
pp-mo wants to merge 11 commits into
SciTools:mainfrom
pp-mo:gdt40_save
Draft

Gdt40 save#813
pp-mo wants to merge 11 commits into
SciTools:mainfrom
pp-mo:gdt40_save

Conversation

@pp-mo

@pp-mo pp-mo commented Jun 24, 2026

Copy link
Copy Markdown
Member

Addresses #785

So far, so highly sketchy + experimental

NOTE: I don't really like 94a3d38 because we only want to support calling without coords for the sake of the existing unit tests.
But I tried adapting some of the existing mock-ist tests + it's really quite awkward

@scitools-ci scitools-ci Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Templating

This PR includes changes that may be worth sharing via templating. For each file listed below, please either:

  • Action the suggestion via a pull request editing/adding the relevant file in the SciTools/.github templates/ directory. 1
  • Raise an issue against the SciTools/.github repo for the above action if you really don't have 10mins spare right now. Include an assignee, to avoid it being forgotten.
  • Dismiss the suggestion if the changes are not suitable for templating.

You will need to dismiss this review before this PR can be merged. Recommend the reviewer does this as their final action before merging, as this text will continually update as commits come in.

Templated files

The following changed files are templated:

Footnotes

  1. Include this text in the PR body to avoid any notifications about applying the template changes back to the source repo!
    @scitools-templating: please no update notification on: iris-grib

@codecov-commenter

codecov-commenter commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.82353% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.70%. Comparing base (56bf257) to head (3b89c6c).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
src/iris_grib/_save_rules.py 84.61% 8 Missing and 6 partials ⚠️
src/iris_grib/_grib1_legacy/grib1_load_rules.py 37.50% 4 Missing and 1 partial ⚠️
src/iris_grib/__init__.py 88.23% 1 Missing and 1 partial ⚠️
src/iris_grib/_grib2_convert.py 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #813      +/-   ##
==========================================
- Coverage   90.05%   89.70%   -0.36%     
==========================================
  Files          10       10              
  Lines        2564     2680     +116     
  Branches      420      440      +20     
==========================================
+ Hits         2309     2404      +95     
- Misses        156      169      +13     
- Partials       99      107       +8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pp-mo pp-mo linked an issue Jul 21, 2026 that may be closed by this pull request
@pp-mo

pp-mo commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Update 2026-07-21

  • Successfully saves to GDT40, and reads back as matching cubes (though not specifically tested)
  • all tests passing
  • reviewed content for sanity, added/fixed comments
  • checked that GRIB1 gaussian data is also compatible, and will save by adding a GRIB2_GRID_TEMPLATE = 40
    (but we don't have any in iris-test-data)

Not implemented:

  • ability to save suitable regular gaussian data to GDT40
    • currently will save, but as 'irregular lat-lon' which is GDT4
    • ideally, would respect the GRIB2_GRID_TEMPLATE to enable this?
  • check that the parallel values in the cube exactly match what "would" be the values for the resulting GDT40 grib message

Still to-do:

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds experimental support for saving GRIB2 reduced Gaussian grids (GDT 3.40) by recording the original grid template on load and using it to select an appropriate ecCodes sample/template during save.

Changes:

  • Record GRIB2 grid template number on load via a new TEMPLATE_RECORD control and attach a gaussian_grid DimCoord for reduced Gaussian grids.
  • Add save-rule logic for GDT 3.40 (including detection + template 40 writer) and update the save pipeline to select a reduced-gg sample.
  • Update/extend unit + integration tests and expected CML outputs to include the new gaussian_grid coordinate and round-trip behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/iris_grib/_save_rules.py Adds GDT 3.40 detection and encoding logic; threads chosen x/y coords through save rules.
src/iris_grib/_grib2_convert.py Adds TEMPLATE_RECORD and records GRIB2_GRID_TEMPLATE; adds gaussian_grid DimCoord on reduced-gg load.
src/iris_grib/__init__.py Updates save path to fall back to aux lat/lon for reduced-gg and select an ecCodes reduced-gg sample when enabled.
src/iris_grib/_grib1_legacy/grib1_load_rules.py Adds special-case reference handling for surface pressure and introduces gaussian_grid DimCoord for that case.
src/iris_grib/tests/unit/grib2_convert/test_grid_definition_template_40.py Updates expected metadata for GDT40 reduced load to include the gaussian_grid DimCoord.
src/iris_grib/tests/integration/round_trip/test_grid_definition_section.py Converts tests to pytest style and adds an experimental GDT40 load→save→load test.
src/iris_grib/tests/results/**/reduced*.cml Updates expected serialized cube outputs to include gaussian_grid.
pyproject.toml Adjusts mypy configuration (disallow_untyped_decorators = false).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

eccodes.codes_set(grib, "longitudeOfFirstGridPoint", int(1.0e6 * lon0))
eccodes.codes_set(grib, "longitudeOfLastGridPoint", int(1.0e6 * lon1))

eccodes.codes_set(grib, "N", n_lat_vals / 2)
Comment on lines +993 to +994
# N.B. we could here be dealing with data on a "rotated gaussion" grid,
# (GDT 3.41 or 3.43), but we don't yet support those.
Comment thread src/iris_grib/__init__.py
Comment on lines +379 to +382
grib_message = eccodes.codes_grib_new_from_samples(template_name)
result = _save_rules.run(slice2D, grib_message, cube, x_coord, y_coord)
if result is not None:
grib_message = result
Comment on lines +1403 to +1404
When present, the 'GRIB_GRID_TEMPLATE' attribute is used to control how certain
types of data are saved -- notably, for gaussian grids.
def test_gdt40_loadsave(tmp_path, record):
loadpath = tests.get_data_path(("GRIB", "reduced", "reduced_gg.grib2"))
cube = load_cube(loadpath)
print(cube)
Comment on lines +213 to +217
print("\nORIGINAL:")
print(cube)
print(coord_dims_names(cube))
print("\n\nRELOADED:")
print(cube_reloaded)
print(coord_dims_names(cube))
print("\n\nRELOADED:")
print(cube_reloaded)
print(coord_dims_names(cube_reloaded))
print(cube_reloaded)
print(coord_dims_names(cube_reloaded))
assert coord_dims_names(cube_reloaded) == coord_dims_names(cube)
assert np.all(cube_reloaded.data == cube.data)
ReferenceTarget("ref_surface_pressure", ensure_surface_air_pressure_name)
)
dim_coords_and_dims.append(
(DimCoord(np.arange(grib._x_points.shape[0]), long_name="gaussian_grid"), 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Support saving to GDT 40

4 participants