Unstructured meshes attached to cubes should be read-only
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 25/100
Research direction
Start with the cube.mesh, Mesh, MeshCoord.points, and Mesh.to_MeshCoord entry points described in the issue, then reproduce the lazy and realised examples with the ugrid_data.nc input. Done should mean mesh-related values cannot be mutated in ways that create inconsistent sharing between cubes and mesh coordinates, with the intended behaviour covered by tests.
Written by the indexing model from the issue text.
Description
The cube.mesh, or its component parts, should probably be read-only values.
When loading a ugrid netcdf file, all cubes returned:
- share a reference to the same
Meshobject with lazy realisation of mesh properties such as nodes and face-edges. - have their own
MeshCoordcoordinate objects that point to the same dask objects as those in theMesh.
When iris realises data on e.g. calling .points it replaces the dask array with the numpy array, but only at the specific object on which it was called. Which means:
- while the
Meshobject with lazy properties is shared between cubes, realised instantiations of those properties are not, and will be held only by the cube, or mesh, separately - memory taken by these numpy arrays will not be shared
- changing the values at one location does not change them elsewhere
A concrete example:
cube1, cube2 = iris.load('ugrid_data.nc')
# both cubes point to the same mesh object
assert cube1.mesh is cube2.mesh
# both cube meshcoord core_points point to the same dask object
assert cube1.coord('latitude').core_points() is cube2.coord('latitude').core_points()
# but if we realise one set of points, they become detached
cube1.coord('latitude').points[0] = 999
print(cube2.coord('latitude').points[0]) # => 37
The same will apply if the values on the cube.mesh are changed. Realising the nodes on cube.mesh does not replace the dask graph references in the meshcoords so changes will not propagate through.
# create two meshcoords from the (lazy) mesh
mc1_lazy = mesh.to_MeshCoord(location='face', axis='y')
mc2_lazy = mesh.to_MeshCoord(location='face', axis='y')
mc1_lazy.points[0] = 999
print(mc2_lazy.points[0]) # => 37
All of this does not hold if the mesh is initialised with real data instead of dask arrays. then all objects do share the same numpy buffer and changing one will affect the others:
# realise the latitude points on the faces
mesh.face_coords.face_y.points
# generate two new meshcoords now that the data is realised
mc1_real = mesh.to_MeshCoord(location='face', axis='y')
mc2_real = mesh.to_MeshCoord(location='face', axis='y')
mc1_real.points[0] = 999
print(mc2_real.points[0]) # => 999
All of this is very confusing. There may be better ways of dealing with this complexity (ideas welcome!) but for now a good first step might be to make the mesh properties read-only to avoid these inconsistencies from occurring
- Dominant language
- Python
- Stars
- 724
- Forks
- 317
- Avg merge
- 3d 20h
- Merged PRs (30d)
- 9
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SciTools/iris
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
bancolombia/sentinel#23 ·
-
test md OpenCI
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
bug client
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100