v3.2 (15 Feb 2022)

This document explains the changes made to Iris for this release (View all changes.)

📢 Announcements

  1. Welcome to @wjbenfold, @tinyendian, @larsbarring, @bsherratt and @aaronspring who made their first contributions to Iris. The first of many we hope!

  2. Congratulations to @wjbenfold who has become a core developer for Iris! 🎉

✨ Features

  1. @bjlittle, @pp-mo, @trexfeathers and @stephenworsley added support for unstructured meshes. This involved adding a data model (PR #3968, PR #4014, PR #4027, PR #4036, PR #4053, PR #4439) and API (PR #4063, PR #4064), and supporting representation (PR #4033, PR #4054) of data on meshes. Most of this new API can be found in iris.experimental.ugrid. The key objects introduced are iris.experimental.ugrid.mesh.Mesh, iris.experimental.ugrid.mesh.MeshCoord and iris.experimental.ugrid.load.PARSE_UGRID_ON_LOAD. A Mesh contains a full description of a UGRID type mesh. MeshCoords are coordinates that reference and represent a Mesh for use on a Cube. Cubes are also given the property mesh which returns a Mesh if one is attached to the Cube via a MeshCoord.

  2. @trexfeathers added support for loading unstructured mesh data from netcdf data, for files using the CF-UGRID conventions. The context manager PARSE_UGRID_ON_LOAD provides a way to load UGRID files so that Cubes can be returned with a Mesh attached. (PR #4058).

  3. @pp-mo added support to save cubes with meshes to netcdf files, using the CF-UGRID conventions. The existing iris.save() function now does this, when saving cubes with meshes. A routine iris.experimental.ugrid.save.save_mesh() allows saving Mesh objects to netcdf without any associated data (i.e. not attached to cubes). (PR #4318 and PR #4339).

  4. @trexfeathers added iris.experimental.ugrid.mesh.Mesh.from_coords() for inferring a Mesh from an appropriate collection of iris.coords.Coords.

  5. @larsbarring updated equalise_attributes() to return a list of dictionaries containing the attributes removed from each Cube. (PR #4357)

  6. @trexfeathers enabled streaming of all lazy arrays when saving to NetCDF files (was previously just Cube data). This is important given the much greater size of AuxCoord points and Connectivity indices under the mesh model. (PR #4375)

  7. @bsherratt added a threshold parameter to intersection() (PR #4363)

  8. @wjbenfold added test data to ci benchmarks so that it is accessible to benchmark scripts. Also added a regridding benchmark that uses this data (PR #4402)

  9. @pp-mo updated to the latest CF Standard Names Table v78 (21 Sept 2021). (Issue #4479, PR #4483)

  10. @SimonPeatman added support for filenames in the form of a PurePath in load(), load_cube(), load_cubes(), load_raw() and save() (Issue #3411, PR #3917). Support for PurePath is yet to be implemented across the rest of Iris (Issue #4523).

  11. @pp-mo removed broken tooling for deriving Iris metadata translations from Metarelate. From now we intend to manage phenonemon translation in Iris itself. (PR #4484)

  12. @pp-mo improved printout of various cube data component objects : Coord, CellMeasure, AncillaryVariable, MeshCoord and Mesh. These now all provide a more controllable summary() method, and more convenient and readable str() and repr() output in the style of the iris.cube.Cube. They also no longer realise lazy data. (PR #4499).

🐛 Bugs Fixed

  1. @rcomer fixed intersection() for special cases where one cell’s bounds align with the requested maximum and negative minimum, fixing Issue #4221. (PR #4278)

  2. @bsherratt fixed further edge cases in intersection(), including Issue #3698 (PR #4363)

  3. @tinyendian fixed the error message produced by concatenate_cube() when a cube list contains cubes with different names, which will no longer report “Cube names differ: var1 != var1” if var1 appears multiple times in the list (Issue #4342, PR #4345)

  4. @larsbarring fixed GeoCS to handle spherical ellipsoid parameter inverse_flattening = 0 (Issue #4146, PR #4348)

  5. @pdearnshaw fixed an error in the call to cftime.datetime in pp_save_rules that prevented the saving to PP of climate means for DJF (PR #4391)

  6. @wjbenfold improved the error message for failure of concatenate() to indicate that the value of a scalar coordinate may be mismatched, rather than the metadata (Issue #4096, PR #4387)

  7. @bsherratt fixed a regression to the NAME file loader introduced in 3.0.4, as well as some long-standing bugs with vertical coordinates and number formats. (PR #4411)

  8. @rcomer fixed subset() to alway return None if no value match is found. (PR #4417)

  9. @wjbenfold changed iris.util.points_step() to stop it from warning when applied to a single point (Issue #4250, PR #4367)

  10. @trexfeathers changed _DimensionalMetadata and Connectivity equality methods to preserve array laziness, allowing efficient comparisons even with larger-than-memory objects. (PR #4439)

  11. @rcomer modified aggregated_by() to calculate new coordinate bounds using minimum and maximum for unordered coordinates, fixing Issue #1528. (PR #4315)

  12. @wjbenfold changed how a delayed unit conversion is performed on a cube so that a cube with lazy data awaiting a unit conversion can be pickled. (Issue #4354, PR #4377)

  13. @pp-mo fixed a bug in netcdf loading, whereby any rotated latlon coordinate was mistakenly interpreted as a latitude, usually resulting in two ‘latitude’s instead of one latitude and one longitude. (Issue #4460, PR #4470)

  14. @wjbenfold stopped iris.coord_systems.GeogCS.as_cartopy_projection() from assuming the globe to be the Earth (Issue #4408, PR #4497)

  15. @rcomer corrected the long_name mapping from UM stash code m01s09i215 to indicate cloud fraction greater than 7.9 oktas, rather than 7.5 (Issue #3305, PR #4535)

  16. @lbdreyer fixed a bug in iris.io.load_http which was missing an import (PR #4580)

💣 Incompatible Changes

  1. N/A

🚀 Performance Enhancements

  1. @wjbenfold resolved an issue that previously caused regridding with lazy data to take significantly longer than with real data. Benchmark benchmarks.HorizontalChunkedRegridding shows a time decrease from >10s to 625ms. (Issue #4280, PR #4400)

  2. @bjlittle included an optimisation to coord_dims to avoid unnecessary processing whenever a coordinate instance that already exists within the cube is provided. (PR #4549)

🔥 Deprecations

  1. @wjbenfold removed iris.experimental.equalise_cubes. In v3.0 the experimental equalise_attributes functionality was moved to the iris.util.equalise_attributes function. Since then, calling the iris.experimental.equalise_cubes.equalise_attributes() function raised an exception. (Issue #3528, PR #4496)

  2. @wjbenfold deprecated iris.util.approx_equal() in preference for math.isclose(). The approx_equal() function will be removed in a future release of Iris. (PR #4514)

  3. @wjbenfold deprecated iris.experimental.raster as it is not believed to still be in use. The deprecation warnings invite users to contact the Iris Developers if this isn’t the case. (PR #4525)

  4. @wjbenfold deprecated iris.fileformats.abf and iris.fileformats.dot as they are not believed to still be in use. The deprecation warnings invite users to contact the Iris Developers if this isn’t the case. (PR #4515)

  5. @wjbenfold removed the iris.util.as_compatible_shape() function, which was deprecated in v3.0. Instead use iris.common.resolve.Resolve. For example, rather than calling as_compatible_shape(src_cube, target_cube) replace with Resolve(src_cube, target_cube)(target_cube.core_data()). (PR #4513)

  6. @wjbenfold deprecated iris.analysis.maths.intersection_of_cubes() in preference for iris.cube.CubeList.extract_overlapping(). The intersection_of_cubes() function will be removed in a future release of Iris. (PR #4541)

  7. @pp-mo deprecated iris.experimental.regrid_conservative. This is now replaced by iris-emsf-regrid. (PR #4551)

  8. @pp-mo deprecated everything in iris.experimental.regrid. Most features have a preferred exact alternative, as suggested, except iris.experimental.regrid.ProjectedUnstructuredLinear : that has no identical equivalent, but iris.analysis.UnstructuredNearest is suggested as being quite close (though possibly slower). (PR #4548)

🔗 Dependencies

  1. @bjlittle introduced the cartopy >=0.20 minimum pin. (PR #4331)

  2. @trexfeathers introduced the cf-units >=3 and nc-time-axis >=1.3 minimum pins. (PR #4356)

  3. @bjlittle introduced the numpy >=1.19 minimum pin, in accordance with NEP-29 deprecation policy. (PR #4386)

  4. @bjlittle dropped support for Python 3.7, as per the NEP-29 backwards compatibility and deprecation policy schedule. (PR #4481)

📚 Documentation

  1. @rcomer updated the “Plotting Wind Direction Using Quiver” Gallery example. (PR #4120)

  2. @trexfeathers included Iris GitHub Discussions in get involved. (PR #4307)

  3. @wjbenfold improved readability in userguide interpolation section. (PR #4314)

  4. @wjbenfold added explanation about the absence of | operator for iris.Constraint to userguide loading section and to api reference documentation. (PR #4321)

  5. @trexfeathers added more detail on making iris-test-data available during Running the Tests. (PR #4359)

  6. @lbdreyer added a section to the release documentation outlining the role of the Release Manager. (PR #4413)

  7. @trexfeathers encouraged contributors to include type hinting in code they are working on - Code Formatting. (PR #4390)

  8. @wjbenfold updated Cartopy documentation links to point to the renamed cartopy.mpl.geoaxes.GeoAxes. (PR #4464)

  9. @wjbenfold clarified behaviour of iris.load() in userguide loading section. (PR #4462)

  10. @bjlittle migrated readthedocs to use mambaforge for faster documentation building. (PR #4476)

  11. @wjbenfold contributed @alastair-gemmell’s step-by-step guide to contributing to the docs to the docs. (PR #4461)

  12. @pp-mo improved and corrected docstrings of iris.analysis.PointInCell, making it clear what is the actual calculation performed. (PR #4548)

  13. @pp-mo removed reference in docstring of iris.analysis.UnstructuredNearest to the obsolete (deprecated) iris.experimental.regrid.ProjectedUnstructuredNearest. (PR #4548)

💼 Internal

  1. @trexfeathers set the linkcheck to ignore http://www.nationalarchives.gov.uk/doc/open-government-licence since this always works locally, but never within CI. (PR #4307)

  2. @wjbenfold netCDF integration tests now skip TestConstrainedLoad if test data is missing (PR #4319)

  3. @wjbenfold excluded Good First Issue labelled issues from being marked stale. (PR #4317)

  4. @tkknight added additional make targets for reducing the time of the documentation build including html-noapi and html-quick. Useful for development purposes only. For more information see Building the documentation. (PR #4333)

  5. @rcomer modified the animation test to prevent it throwing a warning that sometimes interferes with unrelated tests. (PR #4330)

  6. @rcomer removed a now redundant workaround in contourf(). (PR #4349)

  7. @trexfeathers refactored iris.experimental.ugrid into sub-modules. (PR #4347).

  8. @bjlittle enabled the sort-all pre-commit hook to automatically sort __all__ entries into alphabetical order. (PR #4353)

  9. @rcomer modified a NetCDF saver test to prevent it triggering a numpy deprecation warning. (Issue #4374, PR #4376)

  10. @akuhnregnier removed addition of period from wrap_lons() and updated affected tests using assertArrayAllClose following Issue #3993. (PR #4421)

  11. @rcomer updated some tests to work with Matplotlib v3.5. (PR #4428)

  12. @rcomer applied minor fixes to some regridding tests. (PR #4432)

  13. @lbdreyer corrected the license PyPI classifier. (PR #4435)

  14. @aaronspring exchanged dask with dask-core in testing environments reducing the number of dependencies installed for testing. (PR #4434)

  15. @wjbenfold prevented github action runs in forks (Issue #4441, PR #4444)

  16. @wjbenfold fixed tests for hybrid formulae that weren’t being found by nose (Issue #4431, PR #4450)