Skip to content

Conversation

@hsteptoe
Copy link
Contributor

🚀 Pull Request

Description

Fixes #6126 by exposing the shape geometry to the user. Adds to docs and docstrings to make it clearer how to use this.


Consult Iris pull request check list


Add any of the below labels to trigger actions on this PR:

  • benchmark_this Request that this pull request be benchmarked to check if it introduces performance shifts

@pp-mo
Copy link
Member

pp-mo commented Aug 28, 2024

From @SciTools/peloton : discussed what we are seeing here and in #6126.
We think this is looking useful, but the two of you seem to have it covered @hsteptoe @acchamber ?
Please shout if you need help.

@hsteptoe
Copy link
Contributor Author

Discussion with @acchamber notes:

  • Don't move imports out of functions as this creates circular import errors
  • Check target_crs assignment for occasion when cube doesn't have a CRS
  • Re-write conversion of 0-360 -> -180-180 coords in case of degree based CRSs

@hsteptoe
Copy link
Contributor Author

What are @SciTools/peloton (@pp-mo) thoughts about adding rasterio as a Iris dependency?

This would facilitate better handling of shapes to rasters (which is essentially the problem we're solving) with the added bonus that we could also mask to other shape types, like lines, to extract a trajectory from a Cube, for example.

@acchamber
Copy link
Contributor

I've had a few other discussions with other users now where they can't use this function with OSGB shapefiles which this PR would fix. Where are we on being able to include it in the next release?

@hsteptoe @pp-mo

@hsteptoe
Copy link
Contributor Author

hsteptoe commented Dec 2, 2024

I've had a few other discussions with other users now where they can't use this function with OSGB shapefiles which this PR would fix. Where are we on being able to include it in the next release?

@hsteptoe @pp-mo

I was planning on going to the AVD surgery this week to discuss some changes and/or make the case for rasterio

@trexfeathers
Copy link
Contributor

Thanks for your patience everyone. It's sometimes a struggle to balance everything and we just haven't had an opportunity to discuss this. Coming to the Surgery (UK Met Office) is an ideal next step.

@stephenworsley
Copy link
Contributor

@pp-mo, @trexfeathers and @stephenworsley have discussed this at the Surgery and agree in principle that we could consider adding rasterio as an optional dependency.

@trexfeathers
Copy link
Contributor

From @SciTools/peloton: would @hsteptoe and @acchamber appreciate any more input from core devs at this point?

@hsteptoe
Copy link
Contributor Author

hsteptoe commented Feb 5, 2025

From @SciTools/peloton: would @hsteptoe and @acchamber appreciate any more input from core devs at this point?

I just need to find more time, which is in short supply as we get near the end of FY...

@hsteptoe
Copy link
Contributor Author

hsteptoe commented Feb 14, 2025

This is now ready for some initial (alpha?) testing 🎉. @acchamber are you available to try out the new features? (Updates to docs etc. will follow if this is successful) Tests are incomplete are should not be review yet.

This is a fairly substantial re-write. New/improved features include:

  • Automatic CRS transforms. Will handle situation where the cube and geometry have different CRSs by transforming the geometry.
  • Handles all shape types, including Points, Lines and MultiPolygons.

There are some breaking changes, principally moving away from having a minimum_weight keyword, replacing it with an all_touched keyword. The rational here is for consistency across shape types. Minimum weight doesn't make sense for Points and Lines. Instead, Line pixilation is based on Bresenham's line algorithm. Polygon pixilation is based on either: (a) pixel centres that intersect the polygon, or (b) all pixels touched by the polygon irrespective of the area of intersection.

My informal tests so far show working behaviour for iris test data from rotated_pole.nc, toa_brightness_stereographic.nc, E1_north_america.nc, air_temp.pp. Know limitation (not-working) for semi-structured model grids, such as orca2_votemper.nc. Some test shapefiles 👉test_shapefiles.zip

@bjlittle bjlittle added this to the v3.13 milestone Feb 17, 2025
@hsteptoe
Copy link
Contributor Author

@stephenworsley @trexfeathers Can you advise on apparently nox related errors that I'm seeing in the current CI failures, giving an error message: CondaHTTPError: HTTP 401 CONNECTION FAILED for url...
And, do you know why my local pre-commit version of numpydoc-validation might pass, but the github action one fails?

@hsteptoe really sorry for missing this. There is a MO-specific step you will need to do for the lockfiles, will message you offline.

I'm less sure about pre-commit. There is some nuance about only testing files which have been edited; perhaps the merge from main means that your PR is changing more than your local branch was.

pre-commit related errors may have been something wrong going on with my pre-commit cache. Did a pre-commit clean and re-ran and that seemed to resolve the inconsistency issues.

Copy link
Contributor

@trexfeathers trexfeathers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still left to review:

  • _shapefiles.py
  • tests
  • lock files

A number between 0-1 describing what % of a cube cell area must the shape overlap to be masked.
Only applied to polygon shapes. If the shape is a line or point then this is ignored.
Other Parameters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you decide which ones were kwargs and which ones were named parameters?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided that kwargs would be parameters that are specifically used by rasterio functions only, but I'm happy to expose them if that's clearer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that's true of invert. And you are doing a little handling of all_touched too. It's not like the 10s of Matplotlib arguments which iris.plot passes straight down; I think in this case it would be clearer to have everything as normal Parameters.

Today I learned that Sphinx sticks Parameters and Other Parameters together when rendering 🤷

Copy link
Contributor

@trexfeathers trexfeathers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still left to review:

  • tests
  • lock files
  • confirm stable behaviour given the heavy refactor

Comment on lines +35 to +36
# to "OFF" in the environment. Having PROJ_NETWORK = "ON"
# can lead to some coordinate transformations resulting in Inf values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a pointless feature! I'd be interested to know why.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be safe, please could we turn this off at the beginning of create_shape_mask(), then reactivate at the end? I don't know if other users might be relying on it so don't want to a make a permanent change.

Comment on lines 205 to 214
# Define raster transform based on cube
# This maps the geometry domain onto the cube domain
tr = _make_raster_cube_transform(cube)
# Generate mask from geometry
mask_template = rfeatures.geometry_mask(
geometries=shapely.get_parts(geometry),
out_shape=(h, w),
transform=tr,
all_touched=all_touched,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be up for giving me a 5 minute lesson about this?

@codecov
Copy link

codecov bot commented Oct 24, 2025

Codecov Report

❌ Patch coverage is 93.27731% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.32%. Comparing base (9c06cca) to head (cef3fcc).

Files with missing lines Patch % Lines
lib/iris/_shapefiles.py 92.66% 3 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6129      +/-   ##
==========================================
+ Coverage   90.29%   90.32%   +0.02%     
==========================================
  Files          91       91              
  Lines       24656    24696      +40     
  Branches     4618     4626       +8     
==========================================
+ Hits        22264    22307      +43     
+ Misses       1620     1613       -7     
- Partials      772      776       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

⏱️ Performance Benchmark Report: b6002b8

Performance shifts

Full benchmark results

Benchmarks that have stayed the same:

| Change   | Before [9c06cca1]    | After [b6002b85]    |   Ratio | Benchmark (Parameter)                                                                       |
|----------|----------------------|---------------------|---------|---------------------------------------------------------------------------------------------|
|          | 20.7±0.2ms           | 21.0±0.1ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_COUNT(False)                              |
|          | 55.4±1ms             | 56.4±0.5ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_COUNT(True)                               |
|          | 34.3±0.2ms           | 35.1±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_FAST_PERCENTILE(False)                    |
|          | 193±3ms              | 193±2ms             |    1    | aggregate_collapse.Aggregation.time_aggregated_by_FAST_PERCENTILE(True)                     |
|          | 22.7±0.1ms           | 23.5±0.3ms          |    1.04 | aggregate_collapse.Aggregation.time_aggregated_by_GMEAN(False)                              |
|          | 33.9±0.7ms           | 34.3±0.5ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_GMEAN(True)                               |
|          | 22.7±0.2ms           | 23.1±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_HMEAN(False)                              |
|          | 33.9±0.3ms           | 34.7±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_HMEAN(True)                               |
|          | 20.5±0.2ms           | 20.9±0.3ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MAX(False)                                |
|          | 46.5±0.7ms           | 47.4±0.8ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MAX(True)                                 |
|          | 124±0.4ms            | 129±3ms             |    1.04 | aggregate_collapse.Aggregation.time_aggregated_by_MAX_RUN(False)                            |
|          | 128±1ms              | 131±2ms             |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MAX_RUN(True)                             |
|          | 21.6±0.2ms           | 22.1±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MEAN(False)                               |
|          | 50.9±0.8ms           | 52.0±2ms            |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MEAN(True)                                |
|          | 23.1±0.3ms           | 23.4±0.1ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_MEDIAN(False)                             |
|          | 59.6±1ms             | 60.4±1ms            |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_MEDIAN(True)                              |
|          | 20.5±0.3ms           | 21.0±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MIN(False)                                |
|          | 46.8±0.6ms           | 47.6±1ms            |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MIN(True)                                 |
|          | 1.07±0.01s           | 1.08±0.01s          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_PEAK(False)                               |
|          | 1.07±0.01s           | 1.07±0.01s          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_PEAK(True)                                |
|          | 217±2ms              | 214±4ms             |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_PERCENTILE(False)                         |
|          | 377±8ms              | 377±10ms            |    1    | aggregate_collapse.Aggregation.time_aggregated_by_PERCENTILE(True)                          |
|          | 21.5±0.2ms           | 21.9±0.2ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_PROPORTION(False)                         |
|          | 32.2±0.5ms           | 32.7±0.6ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_PROPORTION(True)                          |
|          | 21.9±0.3ms           | 22.5±0.3ms          |    1.03 | aggregate_collapse.Aggregation.time_aggregated_by_RMS(False)                                |
|          | 61.3±0.8ms           | 62.8±1ms            |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_RMS(True)                                 |
|          | 22.8±0.3ms           | 23.3±0.5ms          |    1.03 | aggregate_collapse.Aggregation.time_aggregated_by_STD_DEV(False)                            |
|          | 64.4±1ms             | 65.4±2ms            |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_STD_DEV(True)                             |
|          | 22.4±0.3ms           | 23.0±0.2ms          |    1.03 | aggregate_collapse.Aggregation.time_aggregated_by_VARIANCE(False)                           |
|          | 59.6±1ms             | 60.8±0.9ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_VARIANCE(True)                            |
|          | 7.87±0.1ms           | 8.06±0.1ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_COUNT(False)                               |
|          | 24.0±0.3ms           | 24.2±0.8ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_COUNT(True)                                |
|          | 19.6±0.2ms           | 19.9±0.1ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_FAST_PERCENTILE(False)                     |
|          | 145±2ms              | 148±1ms             |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_FAST_PERCENTILE(True)                      |
|          | 8.20±0.2ms           | 8.38±0.08ms         |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_GMEAN(False)                               |
|          | 22.1±0.5ms           | 22.8±0.7ms          |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_GMEAN(True)                                |
|          | 8.25±0.1ms           | 8.41±0.1ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_HMEAN(False)                               |
|          | 22.0±0.4ms           | 23.1±0.7ms          |    1.05 | aggregate_collapse.Aggregation.time_collapsed_by_HMEAN(True)                                |
|          | 7.73±0.1ms           | 7.93±0.1ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MAX(False)                                 |
|          | 22.9±0.6ms           | 23.2±0.4ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MAX(True)                                  |
|          | 24.5±0.4ms           | 24.9±0.5ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MAX_RUN(False)                             |
|          | 36.8±0.5ms           | 37.5±0.8ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MAX_RUN(True)                              |
|          | 7.98±0.1ms           | 8.25±0.09ms         |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_MEAN(False)                                |
|          | 23.1±0.4ms           | 23.3±0.5ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_MEAN(True)                                 |
|          | 9.02±0.1ms           | 9.20±0.08ms         |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MEDIAN(False)                              |
|          | 25.1±0.2ms           | 26.0±0.7ms          |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_MEDIAN(True)                               |
|          | 7.72±0.1ms           | 7.97±0.09ms         |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_MIN(False)                                 |
|          | 22.9±0.5ms           | 23.1±0.6ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_MIN(True)                                  |
|          | 526±1ms              | 527±2ms             |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PEAK(False)                                |
|          | 538±1ms              | 539±2ms             |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PEAK(True)                                 |
|          | 45.2±0.6ms           | 46.0±0.7ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_PERCENTILE(False)                          |
|          | 159±3ms              | 159±2ms             |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PERCENTILE(True)                           |
|          | 8.10±0.1ms           | 8.26±0.08ms         |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_PROPORTION(False)                          |
|          | 22.0±0.3ms           | 22.1±0.5ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_PROPORTION(True)                           |
|          | 8.07±0.1ms           | 8.27±0.07ms         |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_RMS(False)                                 |
|          | 25.4±0.8ms           | 25.6±1ms            |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_RMS(True)                                  |
|          | 8.22±0.1ms           | 8.50±0.06ms         |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_STD_DEV(False)                             |
|          | 24.1±0.4ms           | 24.7±0.4ms          |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_STD_DEV(True)                              |
|          | 8.33±0.1ms           | 8.45±0.07ms         |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_VARIANCE(False)                            |
|          | 24.1±0.4ms           | 24.2±0.3ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_VARIANCE(True)                             |
|          | 22.3±0.3ms           | 22.5±0.2ms          |    1.01 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_MEAN(False)                     |
|          | 85.0±2ms             | 84.9±1ms            |    1    | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_MEAN(True)                      |
|          | 22.1±0.1ms           | 22.5±0.1ms          |    1.02 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_RMS(False)                      |
|          | 98.4±2ms             | 98.2±2ms            |    1    | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_RMS(True)                       |
|          | 20.8±0.09ms          | 21.3±0.2ms          |    1.02 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_SUM(False)                      |
|          | 57.4±0.8ms           | 58.5±1ms            |    1.02 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_SUM(True)                       |
|          | 8.37±0.09ms          | 8.49±0.09ms         |    1.01 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_MEAN(False)                      |
|          | 29.4±0.7ms           | 30.3±0.7ms          |    1.03 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_MEAN(True)                       |
|          | 8.30±0.07ms          | 8.34±0.1ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_RMS(False)                       |
|          | 30.6±0.6ms           | 31.0±0.6ms          |    1.01 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_RMS(True)                        |
|          | 8.02±0.08ms          | 8.10±0.07ms         |    1.01 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_SUM(False)                       |
|          | 24.7±0.8ms           | 24.8±0.8ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_SUM(True)                        |
|          | 221±1ms              | 226±4ms             |    1.02 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_WPERCENTILE(False)               |
|          | 307±2ms              | 308±4ms             |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_WPERCENTILE(True)                |
|          | 1.11±0.01ms          | 1.14±0.01ms         |    1.03 | cube.CubeCreation.time_create(False, 'construct')                                           |
|          | 386±7μs              | 398±5μs             |    1.03 | cube.CubeCreation.time_create(False, 'instantiate')                                         |
|          | 1.94±0.03ms          | 1.98±0.02ms         |    1.02 | cube.CubeCreation.time_create(True, 'construct')                                            |
|          | 1.37±0.02ms          | 1.40±0.01ms         |    1.02 | cube.CubeCreation.time_create(True, 'instantiate')                                          |
|          | 90.1±2ms             | 89.0±1ms            |    0.99 | cube.CubeEquality.time_equality(False, False, 'all_equal')                                  |
|          | 24.5±0.2ms           | 25.2±2ms            |    1.03 | cube.CubeEquality.time_equality(False, False, 'coord_inequality')                           |
|          | 103±2ms              | 103±2ms             |    1    | cube.CubeEquality.time_equality(False, False, 'data_inequality')                            |
|          | 16.4±0.2μs           | 17.0±0.2μs          |    1.03 | cube.CubeEquality.time_equality(False, False, 'metadata_inequality')                        |
|          | 93.3±1ms             | 92.8±1ms            |    0.99 | cube.CubeEquality.time_equality(False, True, 'all_equal')                                   |
|          | 27.9±0.5ms           | 28.6±0.9ms          |    1.03 | cube.CubeEquality.time_equality(False, True, 'coord_inequality')                            |
|          | 108±1ms              | 106±1ms             |    0.99 | cube.CubeEquality.time_equality(False, True, 'data_inequality')                             |
|          | 16.2±0.2μs           | 16.8±0.2μs          |    1.03 | cube.CubeEquality.time_equality(False, True, 'metadata_inequality')                         |
|          | 200±6ms              | 196±2ms             |    0.98 | cube.CubeEquality.time_equality(True, False, 'all_equal')                                   |
|          | 80.2±1ms             | 80.3±0.8ms          |    1    | cube.CubeEquality.time_equality(True, False, 'coord_inequality')                            |
|          | 229±4ms              | 225±1ms             |    0.98 | cube.CubeEquality.time_equality(True, False, 'data_inequality')                             |
|          | 51.0±0.4μs           | 52.8±0.6μs          |    1.03 | cube.CubeEquality.time_equality(True, False, 'metadata_inequality')                         |
|          | 297±7ms              | 290±2ms             |    0.98 | cube.CubeEquality.time_equality(True, True, 'all_equal')                                    |
|          | 178±6ms              | 174±1ms             |    0.98 | cube.CubeEquality.time_equality(True, True, 'coord_inequality')                             |
|          | 328±7ms              | 318±3ms             |    0.97 | cube.CubeEquality.time_equality(True, True, 'data_inequality')                              |
|          | 366±4μs              | 375±5μs             |    1.02 | cube.CubeEquality.time_equality(True, True, 'metadata_inequality')                          |
|          | 798±9μs              | 795±6μs             |    1    | import_iris.Iris.time__concatenate                                                          |
|          | 186±2μs              | 185±1μs             |    1    | import_iris.Iris.time__constraints                                                          |
|          | 114±1μs              | 115±0.9μs           |    1.01 | import_iris.Iris.time__data_manager                                                         |
|          | 92.0±0.3μs           | 92.6±1μs            |    1.01 | import_iris.Iris.time__deprecation                                                          |
|          | 162±5μs              | 163±1μs             |    1    | import_iris.Iris.time__lazy_data                                                            |
|          | 905±10μs             | 913±10μs            |    1.01 | import_iris.Iris.time__merge                                                                |
|          | 73.1±0.4μs           | 76.5±1μs            |    1.05 | import_iris.Iris.time__representation                                                       |
|          | 607±8μs              | 609±4μs             |    1    | import_iris.Iris.time_analysis                                                              |
|          | 141±2μs              | 142±1μs             |    1.01 | import_iris.Iris.time_analysis__area_weighted                                               |
|          | 106±1μs              | 108±3μs             |    1.01 | import_iris.Iris.time_analysis__grid_angles                                                 |
|          | 247±2μs              | 250±2μs             |    1.01 | import_iris.Iris.time_analysis__interpolation                                               |
|          | 192±3μs              | 194±3μs             |    1.01 | import_iris.Iris.time_analysis__regrid                                                      |
|          | 111±1μs              | 110±1μs             |    1    | import_iris.Iris.time_analysis__scipy_interpolate                                           |
|          | 139±3μs              | 138±2μs             |    0.99 | import_iris.Iris.time_analysis_calculus                                                     |
|          | 324±3μs              | 324±2μs             |    1    | import_iris.Iris.time_analysis_cartography                                                  |
|          | 89.8±0.7μs           | 94.5±0.6μs          |    1.05 | import_iris.Iris.time_analysis_geomerty                                                     |
|          | 211±2μs              | 213±3μs             |    1.01 | import_iris.Iris.time_analysis_maths                                                        |
|          | 96.1±9μs             | 95.4±0.5μs          |    0.99 | import_iris.Iris.time_analysis_stats                                                        |
|          | 170±1μs              | 174±3μs             |    1.02 | import_iris.Iris.time_analysis_trajectory                                                   |
|          | 323±5μs              | 324±4μs             |    1    | import_iris.Iris.time_aux_factory                                                           |
|          | 79.9±0.5μs           | 82.0±2μs            |    1.03 | import_iris.Iris.time_common                                                                |
|          | 160±3μs              | 161±1μs             |    1.01 | import_iris.Iris.time_common_lenient                                                        |
|          | 1.35±0.01ms          | 1.35±0.01ms         |    1    | import_iris.Iris.time_common_metadata                                                       |
|          | 169±2μs              | 168±2μs             |    1    | import_iris.Iris.time_common_mixin                                                          |
|          | 1.16±0.01ms          | 1.17±0.01ms         |    1.01 | import_iris.Iris.time_common_resolve                                                        |
|          | 197±2μs              | 200±2μs             |    1.01 | import_iris.Iris.time_config                                                                |
|          | 130±1μs              | 128±1μs             |    0.99 | import_iris.Iris.time_coord_categorisation                                                  |
|          | 380±8μs              | 379±2μs             |    1    | import_iris.Iris.time_coord_systems                                                         |
|          | 769±10μs             | 763±5μs             |    0.99 | import_iris.Iris.time_coords                                                                |
|          | 691±20μs             | 682±3μs             |    0.99 | import_iris.Iris.time_cube                                                                  |
|          | 245±3μs              | 244±2μs             |    0.99 | import_iris.Iris.time_exceptions                                                            |
|          | 73.3±0.2μs           | 74.8±0.7μs          |    1.02 | import_iris.Iris.time_experimental                                                          |
|          | 179±1μs              | 181±2μs             |    1.01 | import_iris.Iris.time_fileformats                                                           |
|          | 258±5μs              | 258±3μs             |    1    | import_iris.Iris.time_fileformats__ff                                                       |
|          | 2.51±0.04ms          | 2.55±0.01ms         |    1.01 | import_iris.Iris.time_fileformats__ff_cross_references                                      |
|          | 76.4±1μs             | 77.1±1μs            |    1.01 | import_iris.Iris.time_fileformats__pp_lbproc_pairs                                          |
|          | 113±1μs              | 114±2μs             |    1.01 | import_iris.Iris.time_fileformats_abf                                                       |
|          | 443±5μs              | 441±4μs             |    1    | import_iris.Iris.time_fileformats_cf                                                        |
|          | 4.70±0.2ms           | 4.76±0.04ms         |    1.01 | import_iris.Iris.time_fileformats_dot                                                       |
|          | 72.8±0.9μs           | 72.1±0.9μs          |    0.99 | import_iris.Iris.time_fileformats_name                                                      |
|          | 249±2μs              | 253±2μs             |    1.01 | import_iris.Iris.time_fileformats_name_loaders                                              |
|          | 115±2μs              | 117±2μs             |    1.02 | import_iris.Iris.time_fileformats_netcdf                                                    |
|          | 121±2μs              | 121±0.6μs           |    1    | import_iris.Iris.time_fileformats_nimrod                                                    |
|          | 207±3μs              | 208±2μs             |    1.01 | import_iris.Iris.time_fileformats_nimrod_load_rules                                         |
|          | 794±7μs              | 799±7μs             |    1.01 | import_iris.Iris.time_fileformats_pp                                                        |
|          | 183±3μs              | 190±6μs             |    1.04 | import_iris.Iris.time_fileformats_pp_load_rules                                             |
|          | 137±3μs              | 138±1μs             |    1.01 | import_iris.Iris.time_fileformats_pp_save_rules                                             |
|          | 540±3μs              | 541±3μs             |    1    | import_iris.Iris.time_fileformats_rules                                                     |
|          | 218±3μs              | 222±6μs             |    1.02 | import_iris.Iris.time_fileformats_structured_array_identification                           |
|          | 79.7±0.8μs           | 80.8±1μs            |    1.01 | import_iris.Iris.time_fileformats_um                                                        |
|          | 158±2μs              | 158±4μs             |    1    | import_iris.Iris.time_fileformats_um__fast_load                                             |
|          | 139±2μs              | 138±2μs             |    1    | import_iris.Iris.time_fileformats_um__fast_load_structured_fields                           |
|          | 71.9±0.9μs           | 74.0±0.7μs          |    1.03 | import_iris.Iris.time_fileformats_um__ff_replacement                                        |
|          | 77.1±1μs             | 78.7±0.7μs          |    1.02 | import_iris.Iris.time_fileformats_um__optimal_array_structuring                             |
|          | 946±20μs             | 942±9μs             |    1    | import_iris.Iris.time_fileformats_um_cf_map                                                 |
|          | 136±2μs              | 137±1μs             |    1.01 | import_iris.Iris.time_io                                                                    |
|          | 180±5μs              | 177±1μs             |    0.98 | import_iris.Iris.time_io_format_picker                                                      |
|          | 210±2μs              | 214±0.6μs           |    1.02 | import_iris.Iris.time_iris                                                                  |
|          | 126±3μs              | 126±0.8μs           |    0.99 | import_iris.Iris.time_iterate                                                               |
|          | 8.09±0.08ms          | 8.12±0.05ms         |    1    | import_iris.Iris.time_palette                                                               |
|          | 1.76±0.01ms          | 1.80±0.02ms         |    1.02 | import_iris.Iris.time_plot                                                                  |
|          | 219±3μs              | 221±2μs             |    1.01 | import_iris.Iris.time_quickplot                                                             |
|          | 2.11±0.05ms          | 2.14±0.02ms         |    1.02 | import_iris.Iris.time_std_names                                                             |
|          | 1.81±0.04ms          | 1.82±0.01ms         |    1.01 | import_iris.Iris.time_symbols                                                               |
|          | 108±1ms              | 107±0.7ms           |    0.99 | import_iris.Iris.time_tests                                                                 |
|          | 251±6μs              | 257±3μs             |    1.02 | import_iris.Iris.time_third_party_cartopy                                                   |
|          | 5.07±0.04ms          | 5.07±0.03ms         |    1    | import_iris.Iris.time_third_party_cf_units                                                  |
|          | 116±0.8μs            | 117±2μs             |    1.01 | import_iris.Iris.time_third_party_cftime                                                    |
|          | 2.71±0.05ms          | 2.72±0.04ms         |    1    | import_iris.Iris.time_third_party_matplotlib                                                |
|          | 1.32±0ms             | 1.34±0.01ms         |    1.02 | import_iris.Iris.time_third_party_numpy                                                     |
|          | 168±2μs              | 170±1μs             |    1.02 | import_iris.Iris.time_third_party_scipy                                                     |
|          | 99.8±1μs             | 99.8±1μs            |    1    | import_iris.Iris.time_time                                                                  |
|          | 848±5μs              | 864±5μs             |    1.02 | import_iris.Iris.time_util                                                                  |
|          | 70.6±0.6μs           | 73.9±0.7μs          |    1.05 | iterate.IZip.time_izip                                                                      |
|          | 10.0±0.09ms          | 10.1±0.05ms         |    1    | load.LoadAndRealise.time_load((1280, 960, 5), False, 'FF')                                  |
|          | 18.3±0.2ms           | 18.4±0.5ms          |    1.01 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'NetCDF')                              |
|          | 9.94±0.03ms          | 10.4±0.1ms          |    1.04 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'PP')                                  |
|          | 9.91±0.1ms           | 10.2±0.1ms          |    1.03 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'FF')                                   |
|          | 15.7±0.3ms           | 15.8±0.05ms         |    1.01 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'NetCDF')                               |
|          | 10.0±0.04ms          | 10.2±0.07ms         |    1.02 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'PP')                                   |
|          | 1.50±0.01s           | 1.51±0s             |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'FF')                                    |
|          | 14.5±0.09ms          | 14.9±0.3ms          |    1.03 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'NetCDF')                                |
|          | 1.51±0s              | 1.53±0.02s          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'PP')                                    |
|          | 1.47±0.01s           | 1.52±0.01s          |    1.03 | load.LoadAndRealise.time_load((2, 2, 1000), True, 'FF')                                     |
|          | 14.6±0.09ms          | 14.6±0.1ms          |    1    | load.LoadAndRealise.time_load((2, 2, 1000), True, 'NetCDF')                                 |
|          | 1.53±0.01s           | 1.54±0.01s          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), True, 'PP')                                     |
|          | 5.29±0.02ms          | 5.47±0.04ms         |    1.03 | load.LoadAndRealise.time_load((50, 50, 2), False, 'FF')                                     |
|          | 14.1±0.1ms           | 14.4±0.2ms          |    1.02 | load.LoadAndRealise.time_load((50, 50, 2), False, 'NetCDF')                                 |
|          | 5.23±0.04ms          | 5.41±0.06ms         |    1.03 | load.LoadAndRealise.time_load((50, 50, 2), False, 'PP')                                     |
|          | 5.29±0.06ms          | 5.38±0.03ms         |    1.02 | load.LoadAndRealise.time_load((50, 50, 2), True, 'FF')                                      |
|          | 14.3±0.2ms           | 14.5±0.1ms          |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), True, 'NetCDF')                                  |
|          | 5.25±0.04ms          | 5.37±0.03ms         |    1.02 | load.LoadAndRealise.time_load((50, 50, 2), True, 'PP')                                      |
|          | 24.3±1ms             | 22.9±1ms            |    0.94 | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'FF')                               |
|          | 26.3±0.8ms           | 26.2±0.8ms          |    1    | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'NetCDF')                           |
|          | 12.7±1ms             | 12.3±0.5ms          |    0.97 | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'PP')                               |
|          | 28.7±1ms             | 28.3±1ms            |    0.98 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'FF')                                |
|          | 96.4±0.6ms           | 95.8±0.6ms          |    0.99 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'NetCDF')                            |
|          | 27.8±1ms             | 28.1±1ms            |    1.01 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'PP')                                |
|          | 597±2ms              | 608±2ms             |    1.02 | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'FF')                                 |
|          | 5.43±0.2ms           | 5.55±0.09ms         |    1.02 | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'NetCDF')                             |
|          | 601±5ms              | 607±2ms             |    1.01 | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'PP')                                 |
|          | 615±6ms              | 614±3ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'FF')                                  |
|          | 5.61±0.3ms           | 5.54±0.09ms         |    0.99 | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'NetCDF')                              |
|          | 609±9ms              | 612±3ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'PP')                                  |
|          | 2.07±0.08ms          | 2.18±0.06ms         |    1.05 | load.LoadAndRealise.time_realise((50, 50, 2), False, 'FF')                                  |
|          | 5.45±0.08ms          | 5.57±0.2ms          |    1.02 | load.LoadAndRealise.time_realise((50, 50, 2), False, 'NetCDF')                              |
|          | 2.02±0.06ms          | 2.08±0.04ms         |    1.03 | load.LoadAndRealise.time_realise((50, 50, 2), False, 'PP')                                  |
|          | 2.08±0.07ms          | 2.09±0.03ms         |    1.01 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'FF')                                   |
|          | 5.59±0.2ms           | 5.70±0.2ms          |    1.02 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'NetCDF')                               |
|          | 2.04±0.06ms          | 2.12±0.04ms         |    1.04 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'PP')                                   |
|          | 344±6ms              | 345±2ms             |    1.01 | load.ManyCubes.time_many_cube_load                                                          |
|          | 88.3±2ms             | 89.7±0.6ms          |    1.02 | load.ManyVars.time_many_var_load                                                            |
|          | 10.0±0.04ms          | 10.2±0.05ms         |    1.02 | load.STASHConstraint.time_stash_constraint((1280, 960, 5), 'FF')                            |
|          | 10.1±0.2ms           | 10.3±0.1ms          |    1.02 | load.STASHConstraint.time_stash_constraint((1280, 960, 5), 'PP')                            |
|          | 1.51±0.01s           | 1.54±0.01s          |    1.02 | load.STASHConstraint.time_stash_constraint((2, 2, 1000), 'FF')                              |
|          | 1.54±0.02s           | 1.56±0.01s          |    1.01 | load.STASHConstraint.time_stash_constraint((2, 2, 1000), 'PP')                              |
|          | 5.31±0.02ms          | 5.45±0.02ms         |    1.03 | load.STASHConstraint.time_stash_constraint((2, 2, 2), 'FF')                                 |
|          | 5.31±0.09ms          | 5.39±0.04ms         |    1.02 | load.STASHConstraint.time_stash_constraint((2, 2, 2), 'PP')                                 |
|          | 9.06±0.1ms           | 9.06±0.1ms          |    1    | load.StructuredFF.time_structured_load((1280, 960, 5), False)                               |
|          | 5.59±0.08ms          | 5.70±0.03ms         |    1.02 | load.StructuredFF.time_structured_load((1280, 960, 5), True)                                |
|          | 1.47±0.01s           | 1.51±0.01s          |    1.02 | load.StructuredFF.time_structured_load((2, 2, 1000), False)                                 |
|          | 417±6ms              | 427±6ms             |    1.02 | load.StructuredFF.time_structured_load((2, 2, 1000), True)                                  |
|          | 4.37±0.02ms          | 4.51±0.04ms         |    1.03 | load.StructuredFF.time_structured_load((2, 2, 2), False)                                    |
|          | 4.18±0.02ms          | 4.31±0.04ms         |    1.03 | load.StructuredFF.time_structured_load((2, 2, 2), True)                                     |
|          | 153±4ms              | 157±1ms             |    1.03 | load.TimeConstraint.time_time_constraint(20, 'FF')                                          |
|          | 17.3±0.5ms           | 17.5±0.2ms          |    1.01 | load.TimeConstraint.time_time_constraint(20, 'NetCDF')                                      |
|          | 156±2ms              | 156±0.4ms           |    1    | load.TimeConstraint.time_time_constraint(20, 'PP')                                          |
|          | 31.0±0.2ms           | 31.2±0.3ms          |    1.01 | load.TimeConstraint.time_time_constraint(3, 'FF')                                           |
|          | 17.0±0.5ms           | 17.2±0.2ms          |    1.01 | load.TimeConstraint.time_time_constraint(3, 'NetCDF')                                       |
|          | 31.1±0.3ms           | 31.6±0.1ms          |    1.01 | load.TimeConstraint.time_time_constraint(3, 'PP')                                           |
|          | 21.3±0.2ms           | 21.3±0.4ms          |    1    | load.ugrid.BasicLoading.time_load_file(1)                                                   |
|          | 53.6±0.9ms           | 53.3±0.5ms          |    0.99 | load.ugrid.BasicLoading.time_load_file(200000)                                              |
|          | 11.3±0.2ms           | 11.0±0.08ms         |    0.98 | load.ugrid.BasicLoading.time_load_mesh(1)                                                   |
|          | 21.1±1ms             | 20.8±0.3ms          |    0.99 | load.ugrid.BasicLoading.time_load_mesh(200000)                                              |
|          | 21.2±0.7ms           | 21.3±0.2ms          |    1.01 | load.ugrid.BasicLoadingTime.time_load_file(1)                                               |
|          | 22.2±0.8ms           | 21.7±0.2ms          |    0.98 | load.ugrid.BasicLoadingTime.time_load_file(200000)                                          |
|          | 11.2±0.1ms           | 11.1±0.3ms          |    0.99 | load.ugrid.BasicLoadingTime.time_load_mesh(1)                                               |
|          | 14.5±0.6ms           | 14.1±0.2ms          |    0.97 | load.ugrid.BasicLoadingTime.time_load_mesh(200000)                                          |
|          | 23.9±0.4ms           | 23.9±0.2ms          |    1    | load.ugrid.Callback.time_load_file_callback(1)                                              |
|          | 65.3±1ms             | 66.4±0.4ms          |    1.02 | load.ugrid.Callback.time_load_file_callback(200000)                                         |
|          | 23.6±0.5ms           | 23.7±0.3ms          |    1.01 | load.ugrid.CallbackTime.time_load_file_callback(1)                                          |
|          | 25.4±0.6ms           | 25.2±0.3ms          |    0.99 | load.ugrid.CallbackTime.time_load_file_callback(200000)                                     |
|          | 5.59±0.3ms           | 5.48±0.2ms          |    0.98 | load.ugrid.DataRealisation.time_realise_data(10000)                                         |
|          | 8.41±0.3ms           | 8.54±0.09ms         |    1.02 | load.ugrid.DataRealisation.time_realise_data(200000)                                        |
|          | 40.6±2ms             | 40.0±2ms            |    0.99 | load.ugrid.DataRealisationTime.time_realise_data(10000)                                     |
|          | 805±8ms              | 798±20ms            |    0.99 | load.ugrid.DataRealisationTime.time_realise_data(200000)                                    |
|          | 1.44±0.04s           | 1.41±0.03s          |    0.98 | merge_concat.Concatenate.time_concatenate(False)                                            |
|          | 449±7ms              | 450±3ms             |    1    | merge_concat.Concatenate.time_concatenate(True)                                             |
|          | 2.42±0G              | 2.42±0G             |    1    | merge_concat.Concatenate.tracemalloc_concatenate(False)                                     |
|          | 110±4M               | 110±2M              |    1    | merge_concat.Concatenate.tracemalloc_concatenate(True)                                      |
|          | 38.1±1ms             | 34.8±1ms            |    0.91 | merge_concat.Merge.time_merge                                                               |
|          | 126±0.03M            | 126±0.03M           |    1    | merge_concat.Merge.tracemalloc_merge                                                        |
|          | 362±2ns              | 383±4ns             |    1.06 | mesh.utils.regions_combine.CombineRegionsComputeRealData.time_compute_data(50)              |
|          | 197±1ms              | 199±2ms             |    1.01 | mesh.utils.regions_combine.CombineRegionsComputeRealData.time_compute_data(500)             |
|          | 771±0.5k             | 771±0.5k            |    1    | mesh.utils.regions_combine.CombineRegionsComputeRealData.tracemalloc_compute_data(50)       |
|          | 60.2±0M              | 60.2±0M             |    1    | mesh.utils.regions_combine.CombineRegionsComputeRealData.tracemalloc_compute_data(500)      |
|          | 18.9±0.2ms           | 19.1±0.2ms          |    1.01 | mesh.utils.regions_combine.CombineRegionsCreateCube.time_create_combined_cube(50)           |
|          | 22.4±0.2ms           | 22.6±0.3ms          |    1.01 | mesh.utils.regions_combine.CombineRegionsCreateCube.time_create_combined_cube(500)          |
|          | 1.27±0.04M           | 1.27±0.04M          |    1    | mesh.utils.regions_combine.CombineRegionsCreateCube.tracemalloc_create_combined_cube(50)    |
|          | 25±0.04M             | 25±0.04M            |    1    | mesh.utils.regions_combine.CombineRegionsCreateCube.tracemalloc_create_combined_cube(500)   |
|          | 174±3ms              | 176±5ms             |    1.01 | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.time_stream_file2file(50)         |
|          | 649±4ms              | 650±9ms             |    1    | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.time_stream_file2file(500)        |
|          | 1.49±0.03M           | 1.49±0.03M          |    1    | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.tracemalloc_stream_file2file(50)  |
|          | 96.5±0.03M           | 96.5±0.02M          |    1    | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.tracemalloc_stream_file2file(500) |
|          | 121±1ms              | 122±2ms             |    1.01 | mesh.utils.regions_combine.CombineRegionsSaveData.time_save(50)                             |
|          | 588±4ms              | 587±5ms             |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.time_save(500)                            |
|          | 1.43±0.02M           | 1.43±0.02M          |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.tracemalloc_save(50)                      |
|          | 96.5±0.03M           | 96.5±0.03M          |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.tracemalloc_save(500)                     |
|          | 2.1752849999999997   | 2.1752849999999997  |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.track_filesize_saved(50)                  |
|          | 216.01528499999998   | 216.01528499999998  |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.track_filesize_saved(500)                 |
|          | 6.54±0.3ms           | 6.62±0.1ms          |    1.01 | plot.AuxSort.time_aux_sort                                                                  |
|          | 85.1±4ms             | 85.9±3ms            |    1.01 | regridding.CurvilinearRegridding.time_regrid_pic                                            |
|          | 136±3M               | 136±3M              |    1    | regridding.CurvilinearRegridding.tracemalloc_regrid_pic                                     |
|          | 108±7ms              | 106±7ms             |    0.99 | regridding.HorizontalChunkedRegridding.time_regrid_area_w                                   |
|          | 61.5±3ms             | 66.0±3ms            |    1.07 | regridding.HorizontalChunkedRegridding.time_regrid_area_w_new_grid                          |
|          | 107±0.08M            | 107±0.09M           |    1    | regridding.HorizontalChunkedRegridding.tracemalloc_regrid_area_w                            |
|          | 147±0.04M            | 147±0.04M           |    1    | regridding.HorizontalChunkedRegridding.tracemalloc_regrid_area_w_new_grid                   |
|          | 6.84±0.3ms           | 6.73±0.05ms         |    0.98 | save.NetcdfSave.time_netcdf_save_cube(50, False)                                            |
|          | 122±4ms              | 123±0.4ms           |    1.01 | save.NetcdfSave.time_netcdf_save_cube(50, True)                                             |
|          | 44.8±0.5ms           | 44.5±0.7ms          |    0.99 | save.NetcdfSave.time_netcdf_save_cube(600, False)                                           |
|          | 521±4ms              | 523±4ms             |    1    | save.NetcdfSave.time_netcdf_save_cube(600, True)                                            |
|          | 94.8±7ns             | 92.1±1ns            |    0.97 | save.NetcdfSave.time_netcdf_save_mesh(50, False)                                            |
|          | 101±0.9ms            | 102±0.7ms           |    1.01 | save.NetcdfSave.time_netcdf_save_mesh(50, True)                                             |
|          | 95.5±9ns             | 91.7±3ns            |    0.96 | save.NetcdfSave.time_netcdf_save_mesh(600, False)                                           |
|          | 466±7ms              | 467±5ms             |    1    | save.NetcdfSave.time_netcdf_save_mesh(600, True)                                            |
|          | 31.7±0.4k            | 31.9±0.3k           |    1    | save.NetcdfSave.tracemalloc_netcdf_save(50, False)                                          |
|          | 1.9±0.2M             | 1.84±0.1M           |    0.97 | save.NetcdfSave.tracemalloc_netcdf_save(50, True)                                           |
|          | 31.8±0.5k            | 31.8±0.3k           |    1    | save.NetcdfSave.tracemalloc_netcdf_save(600, False)                                         |
|          | 225±20M              | 208±20M             |    0.92 | save.NetcdfSave.tracemalloc_netcdf_save(600, True)                                          |
|          | 39.4±0.6ms           | 39.6±0.4ms          |    1.01 | stats.PearsonR.time_lazy                                                                    |
|          | 9.45±0.2ms           | 9.46±0.3ms          |    1    | stats.PearsonR.time_real                                                                    |
|          | 29.4±0.9M            | 29.4±0.6M           |    1    | stats.PearsonR.tracemalloc_lazy                                                             |
|          | 18.3±0.01M           | 18.3±0.01M          |    1    | stats.PearsonR.tracemalloc_real                                                             |
|          | 27.5±0.5ms           | 27.9±0.5ms          |    1.01 | trajectory.TrajectoryInterpolation.time_trajectory_linear                                   |
|          | 64.1±0.3ms           | 65.4±0.5ms          |    1.02 | trajectory.TrajectoryInterpolation.time_trajectory_nearest                                  |
|          | 17.6±0.02M           | 17.6±0.02M          |    1    | trajectory.TrajectoryInterpolation.tracemalloc_trajectory_linear                            |
|          | 7.75±0.02M           | 7.75±0.02M          |    1    | trajectory.TrajectoryInterpolation.tracemalloc_trajectory_nearest                           |

Generated by GHA run 18778161660

@hsteptoe hsteptoe requested a review from trexfeathers October 24, 2025 12:46
Copy link
Contributor

@trexfeathers trexfeathers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

End-of-review! Thanks again @hsteptoe

--------
For best masking results, both the cube _and_ masking geometry should have a
coordinate reference system (CRS) defined. Note that CRS of the masking geometry
must be provided explicitly to this function (via ``geometry_crs``), whereas the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
must be provided explicitly to this function (via ``geometry_crs``), whereas the
must be provided explicitly to this function (via ``shape_crs``), whereas the

If a CRS is _not_ provided for the the masking geometry, the CRS of the cube is assumed.
This function requires additional dependencies: ``rasterio`` and ``affine``.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning should also be against mask_cube_from_shapefile(), and we should probably warn existing users in the existing What's New as well - their experience will change.

I didn't think of this side of things before; obliging people to adopt new dependencies is a pretty big breakage to include in a minor release. At this late stage I'm inclined to roll with it and we can back it out if it becomes a massive issue (unlikely).

x_coord = cube.coord(axis="X", dim_coords=True)

# Check for CRS equality and transform if necessary
cube_crs = cube.coord_system().as_cartopy_projection() # type: ignore[union-attr]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things:

  • You don't need to call cube.coord_system() again here - you already assigned that on line 147.
  • One of the cube_crs variables should be renamed, otherwise cube_crs has two different types depending on which line you are running.

These things will fix the MyPy error, which will make Iris more safely typed, making future maintenance simpler.

raise ValueError(err_msg)

# Get cube coordinates
x_coord, y_coord = [cube.coord(axis=a, dim_coords=True) for a in ("X", "Y")] # type: ignore[arg-type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
x_coord, y_coord = [cube.coord(axis=a, dim_coords=True) for a in ("X", "Y")] # type: ignore[arg-type]
axes: tuple[Axis, Axis] = ("X", "Y")
x_coord, y_coord = [cube.coord(axis=a, dim_coords=True) for a in axes]

And at the top of the file:

if typing.TYPE_CHECKING:
    from iris.util import Axis

cube = cube.intersection(iris.coords.CoordExtent(x_coord.name(), -180, 180))
# Get revised x coordinate
x_coord = cube.coord(axis="X", dim_coords=True)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert isinstance(x_coord, DimCoord)
assert isinstance(y_coord, DimCoord)

I think this clears out the remaining type hinting. There's probably a way to better label cube.coord() but not something for right now.

Comment on lines +17 to +18
wgs84 = CRS.from_epsg(4326) # WGS84 coordinate system
osgb = CRS.from_epsg(27700) # OSGB coordinate system
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get these into a fixture (as mentioned in integration/test_mask_cube_from_shape.py)

Comment on lines +40 to +48
Polygon(
[
(686600.5247600826, 18834.835866007765),
(622998.2965261642, 1130592.5248690117),
(-45450.06302316813, 1150844.967615187),
(-172954.59474739246, 41898.60193228102),
(686600.5247600826, 18834.835866007765),
]
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mark this as Known Good Output to protect our future developers from confusion!

masked_cube = mask_cube_from_shape(
mock_cube, shape, shape_crs=CRS.from_epsg(4326), in_place=True
)
assert masked_cube is None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also assert that the change has taken effect on mock_cube.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you've achieved test coverage elsewhere but it's important to have some coverage at this level - we're free to make any changes to _shapefiles so long as the top layer behaviour remains the same; coverage at the top level helps ensure that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comments on unit/util/test_mask_cube_from_shape.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

benchmark_this Request that this pull request be benchmarked to check if it introduces performance shifts Type: Bug

Projects

Status: No status
Status: 👀 In Review

Development

Successfully merging this pull request may close these issues.

_transform_coord_system geometry is always assume to be None

9 participants