Description
✨ Feature Request
Following the introduction of split local/global attribute handling in Iris 3.8 (PR #5152), it would be useful to have the ability to set global attributes on a Mesh. Setting an attribute on a mesh currently sets a local attribute on the mesh topology variable. Global attributes that do exist on the file (for example added via the python netcdf4 library, or the Conventions attribute that iris always adds on save) are lost on load.
Motivation
The motivation is to be able to add attributes such as history, provenance, etc. which make sense at the file level (i.e. global) rather than the variable level. Especially in the case where multiple meshes exist in a single file.
Additional context
Example current behaviour (iris 3.9):
>>> from iris.experimental.ugrid import save_mesh
>>> from iris.tests.stock.mesh import sample_mesh
>>> mesh = sample_mesh()
>>> mesh.var_name = "dynamics"
>>> mesh.attributes["history"] = "timestamp"
>>> print(mesh)
Mesh : 'dynamics'
topology_dimension: 2
node
node_dimension: 'Mesh2d_node'
node coordinates
<AuxCoord: longitude / (degrees_east) [...] shape(15,)>
<AuxCoord: latitude / (unknown) [...] shape(15,)>
edge
edge_dimension: 'Mesh2d_edge'
edge_node_connectivity: <Connectivity: unknown / (unknown) [...] shape(5, 2)>
edge coordinates
<AuxCoord: longitude / (unknown) [...] shape(5,)>
<AuxCoord: latitude / (unknown) [...] shape(5,)>
face
face_dimension: 'Mesh2d_face'
face_node_connectivity: <Connectivity: unknown / (unknown) [...] shape(3, 4)>
face coordinates
<AuxCoord: longitude / (unknown) [...] shape(3,)>
<AuxCoord: latitude / (unknown) [...] shape(3,)>
var_name: 'dynamics'
attributes:
history 'timestamp'
>>> save_mesh(mesh, "dynamics_mesh.nc")
Inspecting the saved netCDF file:
$ ncdump -h dynamics_mesh.nc
netcdf dynamics_mesh {
dimensions:
Mesh2d_node = 15 ;
Mesh2d_edge = 5 ;
Mesh2d_face = 3 ;
dynamics_face_N_nodes = 4 ;
dynamics_edge_N_nodes = 2 ;
variables:
int dynamics ;
dynamics:cf_role = "mesh_topology" ;
dynamics:topology_dimension = 2 ;
dynamics:history = "timestamp" ;
dynamics:node_coordinates = "var_name latitude" ;
dynamics:edge_coordinates = "longitude latitude_0" ;
dynamics:face_coordinates = "longitude_0 latitude_1" ;
dynamics:face_node_connectivity = "mesh2d_face" ;
dynamics:edge_node_connectivity = "mesh2d_edge" ;
int64 var_name(Mesh2d_node) ;
var_name:units = "degrees_east" ;
var_name:standard_name = "longitude" ;
var_name:long_name = "long-name" ;
var_name:a = 1LL ;
var_name:b = "c" ;
int64 latitude(Mesh2d_node) ;
latitude:standard_name = "latitude" ;
int64 longitude(Mesh2d_edge) ;
longitude:standard_name = "longitude" ;
int64 latitude_0(Mesh2d_edge) ;
latitude_0:standard_name = "latitude" ;
int64 longitude_0(Mesh2d_face) ;
longitude_0:standard_name = "longitude" ;
int64 latitude_1(Mesh2d_face) ;
latitude_1:standard_name = "latitude" ;
int64 mesh2d_face(Mesh2d_face, dynamics_face_N_nodes) ;
mesh2d_face:cf_role = "face_node_connectivity" ;
mesh2d_face:start_index = 0LL ;
int64 mesh2d_edge(Mesh2d_edge, dynamics_edge_N_nodes) ;
mesh2d_edge:cf_role = "edge_node_connectivity" ;
mesh2d_edge:start_index = 0LL ;
// global attributes:
:Conventions = "CF-1.7" ;
}
Desired output:
$ ncdump -h dynamics_mesh.nc
netcdf dynamics_mesh {
dimensions:
Mesh2d_node = 15 ;
Mesh2d_edge = 5 ;
Mesh2d_face = 3 ;
dynamics_face_N_nodes = 4 ;
dynamics_edge_N_nodes = 2 ;
variables:
int dynamics ;
dynamics:cf_role = "mesh_topology" ;
dynamics:topology_dimension = 2 ;
dynamics:node_coordinates = "var_name latitude" ;
dynamics:edge_coordinates = "longitude latitude_0" ;
dynamics:face_coordinates = "longitude_0 latitude_1" ;
dynamics:face_node_connectivity = "mesh2d_face" ;
dynamics:edge_node_connectivity = "mesh2d_edge" ;
int64 var_name(Mesh2d_node) ;
var_name:units = "degrees_east" ;
var_name:standard_name = "longitude" ;
var_name:long_name = "long-name" ;
var_name:a = 1LL ;
var_name:b = "c" ;
int64 latitude(Mesh2d_node) ;
latitude:standard_name = "latitude" ;
int64 longitude(Mesh2d_edge) ;
longitude:standard_name = "longitude" ;
int64 latitude_0(Mesh2d_edge) ;
latitude_0:standard_name = "latitude" ;
int64 longitude_0(Mesh2d_face) ;
longitude_0:standard_name = "longitude" ;
int64 latitude_1(Mesh2d_face) ;
latitude_1:standard_name = "latitude" ;
int64 mesh2d_face(Mesh2d_face, dynamics_face_N_nodes) ;
mesh2d_face:cf_role = "face_node_connectivity" ;
mesh2d_face:start_index = 0LL ;
int64 mesh2d_edge(Mesh2d_edge, dynamics_edge_N_nodes) ;
mesh2d_edge:cf_role = "edge_node_connectivity" ;
mesh2d_edge:start_index = 0LL ;
// global attributes:
:Conventions = "CF-1.7" ;
:history = "timestamp" ;
}
Interestingly, a global Conventions
attribute is already added on save.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Status