iris: Saving a cube with a mesh does not include `coordinate` attribute, as required by UGrid conventions
š Bug Report
It looks like the mesh support in iris is not setting the coordinates
attribute for the data variables correctly. Worse, when working with a source data file that does have the correct attributes, these are being lost in the save. This is causing an issue when trying to load the resulting files into LFRic.
How To Reproduce
Steps to reproduce the behaviour:
In [1]: import iris
In [2]: # Using scitools default version ā same behaviour is seen with default-next too.
In [3]: iris.__file__
Out[3]: '.../default-2022_11_22/lib/python3.9/site-packages/iris/__init__.py'
In [4]: # Example data does have coordinate attributes for the data variables:
In [5]: !ncdump -h ./lib/ants/tests/resources/stock/data_C4.nc | grep 'coordinates'
sample_data:coordinates = "example_C4_face_x example_C4_face_y" ;
additional_sample_data:coordinates = "example_C4_face_x example_C4_face_y" ;
example_C4:node_coordinates = "example_C4_node_y example_C4_node_x" ;
example_C4:face_coordinates = "example_C4_face_y example_C4_face_x" ;
In [6]: # (First two results are attributes on data variables, second two are for topology attributes)
In [7]: from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
In [8]: with PARSE_UGRID_ON_LOAD.context():
...: cubes = iris.load('./lib/ants/tests/resources/stock/data_C4.nc')
...:
In [9]: iris.save(cubes, 'result.nc')
In [10]: # Notice that the coordinate attributes have been dropped from the data variables
In [11]: !ncdump -h result.nc | grep 'coordinates'
example_C4:node_coordinates = "example_C4_node_x example_C4_node_y" ;
example_C4:face_coordinates = "example_C4_face_x example_C4_face_y" ;
In [12]: # Full ncdump for completeness
In [13]: !ncdump -h result.nc
netcdf result {
dimensions:
num_node = 98 ;
dim0 = 96 ;
example_C4_face_N_nodes = 4 ;
variables:
int example_C4 ;
example_C4:cf_role = "mesh_topology" ;
example_C4:topology_dimension = 2 ;
example_C4:long_name = "Topology data of 2D unstructured mesh" ;
example_C4:node_coordinates = "example_C4_node_x example_C4_node_y" ;
example_C4:face_coordinates = "example_C4_face_x example_C4_face_y" ;
example_C4:face_node_connectivity = "face_nodes" ;
double example_C4_node_x(num_node) ;
example_C4_node_x:units = "degrees_east" ;
example_C4_node_x:standard_name = "longitude" ;
example_C4_node_x:long_name = "longitude of 2D mesh nodes." ;
double example_C4_node_y(num_node) ;
example_C4_node_y:units = "degrees_north" ;
example_C4_node_y:standard_name = "latitude" ;
example_C4_node_y:long_name = "latitude of 2D mesh nodes." ;
double example_C4_face_x(dim0) ;
example_C4_face_x:units = "degrees_east" ;
example_C4_face_x:standard_name = "longitude" ;
example_C4_face_x:long_name = "longitude of 2D face centres" ;
double example_C4_face_y(dim0) ;
example_C4_face_y:units = "degrees_north" ;
example_C4_face_y:standard_name = "latitude" ;
example_C4_face_y:long_name = "latitude of 2D face centres" ;
int face_nodes(dim0, example_C4_face_N_nodes) ;
face_nodes:long_name = "Maps every quadrilateral face to its four corner nodes." ;
face_nodes:Conventions = "UGRID-1.0" ;
face_nodes:cf_role = "face_node_connectivity" ;
face_nodes:start_index = 1 ;
double sample_data(dim0) ;
sample_data:long_name = "sample_data" ;
sample_data:units = "1" ;
sample_data:mesh = "example_C4" ;
sample_data:location = "face" ;
double additional_sample_data(dim0) ;
additional_sample_data:long_name = "additional_sample_data" ;
additional_sample_data:units = "1" ;
additional_sample_data:mesh = "example_C4" ;
additional_sample_data:location = "face" ;
// global attributes:
:online_operation = "once" ;
:Conventions = "CF-1.7" ;
}
Expected behaviour
Saving a cube with a mesh should set the coordinates
attribute for the data variables, as per: http://ugrid-conventions.github.io/ugrid-conventions/#data-variables
Environment
- OS & Version: RHEL7
- Iris Version: 3.3.1 and 3.4.0
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 20 (18 by maintainers)
Thanks for the detail @arjclark. I just talked through a hypothetical with @hdyson that helped me break the link between this and roundtripping concernsā¦
During development we had interpreted the redundancy as meaning it didnāt matter about the data variable so long as there were attributes in the mesh variable. But the interpretation in this issue is that the referenced section of the UGRID docs is THE correct way things should be.
That would mean that: even if Iris loaded a file where edge/face coordinates were only referenced as attributes on the mesh variable, Iris should also add these as attributes on the data variable when saving. This sounds like a defensible idea to me, and simpler to implement than any of my previous suggestions.
I really think this one has run its course and we canāt see the wood for the trees now. Iām going to close this ticket and open up a new issue with the iris specific parts of this, and let the conventions conversations carry on in the UGrid repository.
Yes that scared me a bit too.
I have posted a bit of a request for clarification
I would certainly hope + expect Iris output to be both CF and UGRID compliant. We have an issue to include UGRID in the Conventions declaration #5030
I just put something very similar to this in an email to @pp-mo, so apologies for the redundancy but I think itās worth flagging somewhere more public. In the linked UGrid issue: https://github.com/ugrid-conventions/ugrid-conventions/issues/63 thereās discussion of the potential of UGrid compliant files that are not CF compliant.
My personal opinion is that iris should aim to be writing mesh cubes that are both UGrid and CF compliant - I think the inconsistency between CF compliant times/vertical levels/etc in the same file as CF non-compliant meshes would lead to user confusion.
Following offline conversation with @hdyson, Iām coming around to this view. In which case, it will make sense for Iris to
This also feeds back into the nascent conformance rules and the ugrid-checker