-
Notifications
You must be signed in to change notification settings - Fork 287
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add NameConstraint with relaxed name loading #3463
Add NameConstraint with relaxed name loading #3463
Conversation
Requires a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m curious about the inclusion of STASH in the names
property. It’s a code, rather than a name. Also we have advice to use an AttributeConstraint on STASH, further down that same section of user guide.
lib/iris/_constraints.py
Outdated
iris.NameConstraint(standard_name='air_temperature', | ||
STASH=lambda stash: stash.item == 203 | ||
|
||
.. note:: Name constraint names are case sensitive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name constraint names are case sensitive. Is it worth having an example where the lambda uses e.g. long_name.lower()
, to show how you can make a non case sensitive constraint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rcomer Just to be clear (and perhaps this is what requires to be communicated more clearly) what I mean here is that it's:
STASH=lambda stash: stash.item == 203
, and- not
stash=lambda stash: stash.item == 203
It's the keyword argument key that is case sensitive, and the user can't change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah OK, that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rcomer I've updated the doc-string in an attempt to clarify, HTH 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better, thanks 😀
I haven't time to look at this in detail yet. But I want to say right away that I'm strongly opposed to the specific support for the STASH attribute. |
I was thinking that, but then I remembered that so is |
lib/iris/_constraints.py
Outdated
|
||
""" | ||
self._names = names | ||
super(NameConstraint, self).__init__(cube_func=self._cube_func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're in Python 3 now, I believe this can be written as super().__init__(cube_func=self._cube_func)
.
@pp-mo This isn't anything new. This PR is just highlighting the existing behaviour of >>> print(cube)
air_temperature / (K) (latitude: 73; longitude: 96)
Dimension coordinates:
latitude x -
longitude - x
Scalar coordinates:
forecast_period: 6477 hours, bound=(-28083.0, 6477.0) hours
forecast_reference_time: 1998-03-01 03:00:00
pressure: 1000.0 hPa
time: 1998-12-01 00:00:00, bound=(1994-12-01 00:00:00, 1998-12-01 00:00:00)
Attributes:
STASH: m01s16i203
source: Data from Met Office Unified Model
Cell methods:
mean within years: time
mean over years: time
>>> cube.standard_name = None
>>> cube.extract('m01s16i203')
<iris 'Cube' of m01s16i203 / (K) (latitude: 73; longitude: 96)> The above example is using So you seem to be opposed to something that already exists. I'm not quite sure how that can be addressed here in this PR? |
As it stands, I don't think the |
@stephenworsley The It's allowing you to perform a conjunction of names for a constraint match against a cube. It has no association whatsoever with the |
Well, I didn't actually know that ! Mind you, even if it does that already, I don't have to like it. |
48e7e76
to
a759170
Compare
I'm not too convinced by that. I guess In a sense that "could" be true of STASH too, but I don't see how it could have an unambiguous value for any data not from a UM source. |
@bjlittle I was considering the acceptance criteria of #3407, specifically:
Is this backwards compatibility being addressed? I would have thought there would still need to be some way to compare against (On a related note, this line in the docstring probably needs changing too). |
@stephenworsley Thanks. We don't need to be fully backwards compatible here, regardless of the demands of #3407, hence the major release. This PR is addressing several use cases, not just #3407. Given the relaxed load/extract behaviour of this PR my expectation is that most users will see no change in behaviour. It'll just work. For those that find the relaxed behaviour results in additional cubes being returned, then If you think this isn't the case, then I'd love to know, with a concrete example to support it, if possible. |
@bjlittle Have you considered extracting cubes with no names whos |
@@ -454,7 +454,7 @@ def __init__(self, **attributes): | |||
|
|||
""" | |||
self._attributes = attributes | |||
Constraint.__init__(self, cube_func=self._cube_func) | |||
super().__init__(cube_func=self._cube_func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one comes for free, whilst I'm here...
I'm going to add a convenience to NameConstraint(standard_name='air_temperature', long_name='air temp')
NameConstraint('air_temperature', 'air temp')
NameConstraint('air_temperature', long_name='air temp') etc... as I can imaging users typically performing a |
bb75f43
to
258b3ab
Compare
@lbdreyer I'm now satisfied with this PR. It meets a thorny brief in an area of The changes in this PR provide the user with more explicit and flexible control to load and extract cubes. On reflection, we have been relying on a very weak contract to identify cubes through the Anyways, over to you. I'm bias, but I'd vote for banking this PR, moving forward, and supplement it with further documentation and/or doc-strings if you deem that further clarity is required. |
lib/iris/_cube_coord_common.py
Outdated
stash_name = self.attributes.get('STASH') | ||
if stash_name is not None: | ||
stash_name = str(stash_name) | ||
return (standard_name, long_name, var_name, stash_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the addition of this names
method on CFVariableMixin.
stash_name
makes sense for a cube but not a coordinate (or cell measure or ancillary variable etc )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The introduction of the names
property is in total alignment with the existing name
method and its behaviour.
The name
method also doesn't make sense for anything other than a cube
, and yet we have it applied to coordinates and else where. So your argument also applies to that, and yet it still stands. This PR is highlighting existing behaviour already available in iris
- to the surprise of @pp-mo.
So either we honour this relationship, or we remove the use of STASH
from both the names
property and the name
method. If we did, then that would be a breaking change for the API, rather than an additive change.
Note that, the names
property is only public as it's referenced from within iris.Constraint._coordless_match
method.
lib/iris/_constraints.py
Outdated
|
||
""" | ||
def __init__(self, standard_name='none', long_name='none', | ||
var_name='none', STASH='none'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trouble is that this does introduce another way of constraining on a stash code, which could now be done either by NameConstraint
or AttributeConstraint
, which goes against the zen of Python
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this is in alignment with the name
method. As it stands, it's completely possible to perform a stash constraint at least four other ways that I know of, excluding this PR, without thinking about it to much. IMHO iris
is so anti-zen here already, that really the whole interface needs a re-design.
That said, the NameConstraint
gives explicit control back to the user, so it does have value, and it also rights some wrongs to boot. The question that really needs answering here is whether stash should be part of the name
method, names
property and NameConstraint
?
I know what my answer is, but I'm keen to know what others think... and in formulating an answer I suspect the conflict will come between a purist zen of Python philosophy and user convenience to avoid an ugly iris
constraints framework.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of small suggestions, nothing earthshaking 📳
Thanks @bjlittle. |
7ba58bb
to
1e10bda
Compare
@pp-mo Serviced requested review actions or commented on why not. Back to you 👍 |
Nice, definitely improved. Just a couple of outstanding queries. And one brand new one... |
@pp-mo Okay, this PR is nearing saturation point for discovering what new actions you want me to take...there is a lot of noise. Okay, I've tackled a couple of the issues that you raised. If you've raised more and I've not addressed them, then that's simply because I can't find them, sorry. BTW I've just nuked the additonal Please let me know if there are more outstanding actions to perform or if I've missed something. Thanks! |
@pp-mo Sweet 🎉 Thanks for perservering... above and beyond! 👏 |
* Bump version to 2.4.0rc0. * unpin mpl (#3468) * Merge pull request #3301 from bayliffe/fastpercentilemethod_mask_test Analysis percentile method - update applicability test for fast_percentile_method * Have Travis test with iris-grib, remove problem tests (#3469) * Have Travis test with iris-grib, remove problem tests * mock GribInternalError correctly * Update license headers * account for changes in handling of grib message defaults * Test against the latest version of python-eccodes * Moved irir-grib skip to iris.tests * Merge pull request #2608 from cpelley/PICKLEABLE_FORMATS TEST: Extends #2569 to unpickle * _regrid_area_weighted_array: Move axes creation over which weights are calculated to before loop (#3519) * Purge iris.experimental.regrid np<1.7 support (#3539) * Add NameConstraint with relaxed name loading (#3463) * _regrid_area_weighted_array: move indices variable nearer to use (#3564) * _regrid_area_weighted_array: Tweak variable order to near other use in code (#3571) * Fix problems with export and echo command. (#3577) * Pushdocs fix2 (#3580) * Revert to single-line command for doctr invocation. * Added script comment, partly to force Github respin. * Bracketed six.moves and __future__ imports. * Fixes required due to the release of iris-grib v0.15.0 (#3582) * Fix python-eccodes pin in travis (#3593) * PI-2472: Optimise the area weighted regridding routine (#3598) * PI-2472: Tweak area weighting regrid move xdim and ydim axes (#3594) * _regrid_area_weighted_array: Set axis order to y_dim, x_dim last dimensions * _regrid_area_weighted_array: Extra tests for axes ordering * PI-2472: Tweak area weighting regrid enforce xdim ydim (#3595) * _regrid_area_weighted_array: Set axis order to y_dim, x_dim last dimensions * _regrid_area_weighted_array: Extra tests for axes ordering * _regrid_area_weighted_array: Ensure x_dim and y_dim * PI-2472: Tweak area weighting regrid move averaging out of loop (#3596) * _regrid_area_weighted_array: Refactor weights and move averaging outside loop * Pin pillow to make graphics tests work again. (#3630) * PI-2472: Area weighted regridding (#3623) * The Area-weights routine is refactored into the "__prepare" and "__perform" structure, in-line with our other regridding methods. * The area-weights are now computed in the "__prepare", so are calculated once. * The information required for checking the regridding weights and target grid info are now cached on the "regridder" object. * This is inline with the general use already described in the documentation. * pep8 conformance. * pep8 compliance. * Allow some 'key=None' args in Geostationary creation. (#3628) LGTM * Allow some 'key=None' args in Geostationary creation. * Integration test loading netcdf geostationary without offset properties. * pep8 conformance. * pep8 conformance. * pep8 conformance. * test_NameConstraint get mock from iris.tests. * Remove use of super() in _constraints.py for Py2 compatibility. * Updated license headers. * Updated iris-grib reference in extensions.txt. * Py2 support for iris-grib in Travis. * Updates for auto docs for Iris 2.4 release. * What's new entry to unpinning mpl. * Edited Py2 support for iris-grib in Travis. * Renamed whatsnew contributions folder for v2.4. * Hacked tests.integration.test_grib2 to avoid import error from iris-grib version < 0.15. * Only test grib with python 3. * Compiled v2.4 whatsnew. Co-authored-by: Martin Yeo <40734014+trexfeathers@users.noreply.github.com> Co-authored-by: Bill Little <bill.little@metoffice.gov.uk> Co-authored-by: stephenworsley <49274989+stephenworsley@users.noreply.github.com> Co-authored-by: abooton <anna.booton@metoffice.gov.uk> Co-authored-by: lbdreyer <lbdreyer@users.noreply.github.com> Co-authored-by: Emma Hogan <ehogan@users.noreply.github.com>
This PR introduces the
names
property to both cubes and coordinates - a property that returns a tuple of thestandard_name
,long_name
,var_name
andSTASH
.This property is needed as a means to support more flexible
name
loading i.e., airis._constraints.Constraint._coordless_match
that will succeed for a match on either of thenames
property values, rather than depending on the behaviour of theiris._cube_coord_common.CFVariableMixin.name
method. Note that, this also applies toiris.cube.Cube.extract
andiris.cube.CubeList.extract
et al.This PR also introduces the
iris.NameConstraint
for more specific control ofnames
related matching.Closes #3407