Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constrained load on MeshCoord bypasses callback #5939

Open
jrackham-mo opened this issue May 7, 2024 · 0 comments
Open

Constrained load on MeshCoord bypasses callback #5939

jrackham-mo opened this issue May 7, 2024 · 0 comments

Comments

@jrackham-mo
Copy link

馃悰 Bug Report

When applying a constraint on a MeshCoord and a callback which checks the loaded cube has a mesh, the callback is not applied on the returned cube.

How To Reproduce

Steps to reproduce the behaviour:

  1. Define a custom callback function which raises an exception if a cube does not have a mesh.
  2. Attempt to load UGrid data with a constraint on latitude (a MeshCoord) and pass the custom callback.
  3. The cube is loaded, without a mesh. The MeshCoords have been converted to AuxCoords as expected, but no exception was raised.

Expected behaviour

I expected an exception to have been raised by the custom callback function, since the returned cube has no mesh.

Reproducible example

import iris
from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
import iris.exceptions
from iris import sample_data_path

def ugrid_load(uris, constraints=None):
    """Load a UGrid file. Will not load if the file contains regular data.

    Parameters
    ----------
    uris : Any
        Location of file to load. Must be a NetCDF file.
    constraints: Any | None
        One or more iris constraints. Each constraint can be either a string,
        or an instance of :class:`iris.Constraint`. If the constraint is a string
        it will be used to match against cube.name().

    Returns
    -------
    iris.cube.CubeList
        An iris :class:`iris.cube.CubeList` containing the loaded data.

    Raises
    ------
    iris.exceptions.InvalidCubeError
        If UGrid data cannot be loaded from the file.
    """
    with PARSE_UGRID_ON_LOAD.context():
        ugrid_cubelist = iris.load(uris=uris, constraints=constraints, callback=mesh_check)
    return ugrid_cubelist

def mesh_check(cube, field, filename):
    """Check if the loaded data is UGrid or not.

    A function to be passed to callback in iris.load.

    Parameters
    ----------
    cube : iris.cube.Cube
        Loaded :class:`iris.cube.CubeList` to be checked
    field : Any
        Only present to satisfy the function signature used by callback.
    filename : Any
        Original file from which the cube data was loaded

    Raises
    ------
    iris.exceptions.InvalidCubeError
        If the loaded cube does not contain UGrid data
    """
    if cube.mesh is None:
        raise iris.exceptions.InvalidCubeError(
            f"Attempting to load from file '{filename}' did not return UGrid data."
        )
    
if __name__ == "__main__":
    latitude_constraint = iris.Constraint(latitude=lambda cell: cell > 0)

    # Try with non-UGrid netcdf first to confirm it works
    non_ugrid_path = sample_data_path("atlantic_profiles.nc")
    try:
        ugrid_load(non_ugrid_path, latitude_constraint)
    except iris.exceptions.InvalidCubeError as exc:
        print(exc)

    # Now try constraining on a MeshCoord on load of a file containing UGrid data
    # Expected to raise an exception since the returned cube has no mesh due to the constraint
    # having converted the MeshCoords to AuxCoords
    mesh_C4_path = sample_data_path("mesh_C4_synthetic_float.nc")
    ugrid_cubelist = ugrid_load(mesh_C4_path, latitude_constraint)
    if len(ugrid_cubelist) != 0:
        print(f"Data successfully loaded from '{mesh_C4_path}' with constraint '{latitude_constraint}'.")
        print(ugrid_cubelist[0])
        print(f"Cube's mesh is: {ugrid_cubelist[0].mesh}")

Output:

Attempting to load from file '.../iris_sample_data/sample_data/atlantic_profiles.nc' did not return UGrid data.
Data successfully loaded from '.../iris_sample_data/sample_data/mesh_C4_synthetic_float.nc' with constraint 'Constraint(coord_values={'latitude': <function <lambda> at 0x7fd980bc0310>})'.
synthetic / (1)                     (-- : 32)
    Auxiliary coordinates:
        latitude                        x
        longitude                       x
    Attributes:
        NCO                         'netCDF Operators version 4.7.5 (Homepage = http://nco.sf.net, Code = h ...'
        history                     'Mon Apr 12 01:44:41 2021: ncap2 -s synthetic=float(synthetic) mesh_C4_synthetic.nc ...'
        nco_openmp_thread_number    1
Cube's mesh is: None

Environment

  • OS & Version: RHEL 7.9
  • Iris Version: 3.7.1
@jrackham-mo jrackham-mo changed the title Contstrained load on MeshCoord bypasses callback Constrained load on MeshCoord bypasses callback May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

2 participants