-
Notifications
You must be signed in to change notification settings - Fork 285
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
BUG: Assumptions made in _discontiguity_in_bounds #3345
Comments
I think the diagrams make issue 1 pretty clear. For issue 2, this has real implications for the UGrid work related to LFRic, using the 2D flexible mesh topology (the full model is 3D layered mesh, but for simplicity, let's stick to a single layer here): http://ugrid-conventions.github.io/ugrid-conventions/#2d-flexible-mesh-mixed-triangles-quadrilaterals-etc-topology Since the latitudes of the cell centres are 1-dimensional but the nodes are 4-dimensional*, the obvious iris representation is a coordinate with the points representing the cell centres and 4-D bounds being derived from the nodes. Using an example from a C4 mesh:
(and a similar representation for longitude). The complete C4 mesh does tessellate the globe, and is contiguous. Extending the example from @cpelley, it'd be great if the logic was:
* Strictly speaking, the convention is N-dimensional bounds - our use case is 4-dimensional, but maybe a more general solution is appropriate? |
Thanks for your input @hdyson |
I don't get this bit
From my reading, CF does enforce the starting position and order. As it says ...
|
Re:
I do agree that it is right for the code to be strict with the relationship between coordinate dims and bounds, but I believe that relationship is actually enforced anyway, in the means of creating coords, i.e. " IIRC the only flexibility is the size of the bounds dimension. I think that is arbitrary but, as I said above, plotting behaviour only works when it is as expected. I don't think we should be adding any additional interpretations here, whether based on UGRID or not. |
Thanks @hdyson @cpelley For instance ...
That's perfectly true, but there is no CF interpretation of what that should actually mean. If you think valid cases are missing, we'd better focus on specific testcases. |
Thanks @pp-mo . I'm going to be sticking to the particular use case of UGrid data, because that's where my thinking has been. @cpelley may contribute to the more general case. UGrid specifies that corner nodes (the UGrid equivalent of the bounds) should be:
http://ugrid-conventions.github.io/ugrid-conventions/#2d-triangular-mesh-topology So for the bounds we're discussing here, UGrid is effectively the same as CF.
For our specific case, p-sided cells, CF-conventions has:
So for the UGrid case, anticlockwise bounds is fine, but the starting vertex/node/bound can be arbitrary. For what it's worth, I notice the next sentence after your quote ends is:
Which I think means that the general case may be different?
I don't believe the issue @cpelley identified was originally with UGrid files. I'm hoping the solution for his issues can also avoid future issues with UGrid data too - two birds with one stone - but please don't let UGrid distract unnecessarily.
I think the "Bounds for multi-dimensional coordinate variables with p-sided cells" subsection of the CF conventions (I don't see a way to link directly to it?) covers this reasonably well? Consider a cell that extends from 0 degrees lat/lon to 1 degree lat lon - it could be represented by a cell with with latitude bounds of [0, 1] and longitude bounds of [0,1], or in the p-sided cell representation by a cell with latitude bounds of [0, 0, 1, 1] and longitude bounds of [0, 1, 1, 0]. The area defined by the cell is the same in both cases. If the cell isn't exactly rectangular, though, the first representation is no longer valid, and only the p-sided cell representation works. This is the case for UGrid. |
That isn't my reading. I read this as illustration of the way in which the bounds 'can be' indexed.
Sorry, my demonstration of constraint has mislead the point I was trying to make. I meant That is, my constraint example should have been something like: if self.ndim == 1 and self.bounds.shape[-1] == 2:
...
elif self.ndim ==1 and self.bounds.shape[-1] == 4:
# Some UGrid-aware contiguity check
....
elif self.ndim == 2 and `self.bounds.shape[-1] == 4:
...
else:
msg = 'Contiguity check on coord.ndim {} bounds.ndim {} not currently supported'
raise RuntimeError(msg.format(self.ndim, self.bounds.ndim)) Hopefully I worded this right this time...
To clarify, there is one main motivating usecase that I attempted to highlight in the ticket description. This is of providing 2D points and 3D bounds (4-bounds per cell). Our usecase starts at a different corner than iris expects so forces us to reform the bounds for us to plot it. We could plot the data in iris1 but cannot with iris2. Sorry if this wasn't clear from the description. The other issues I'm pointing out are endemic of the same problem that gives rise to my usecase, which is the lack of constraints (no checks on the shape of the bounds), assumed direction and assumed starting vertex. The second usecase is driven by Harold in #3345 (comment) which is in supporting contiguity checks for UGRID (1D points with 2D (4-bounds per cell)). At the very least, iris should be constrained and raising a suitable exception (which I cover under issue2). At best, we would support this at the same time as making the other fixes here - I don't think this is major work. |
bump |
Workaround for iris bounds handling is to have a conditional in our code to convert direction based on a conditional: clockwise = not LinearRing([(lon, lat) for lon, lat in zip(lons, lats)]).is_ccw
if clockwise:
... A more generalised workaround for iris is to readjust the bounds starting index so that it too iris' expectations. |
I've been looking at this + re-reading. But, in saying all that, I am specifically describing the "case where the horizontal grid is described by two-dimensional auxiliary coordinate variables in latitude lat(n,m) and longitude lon(n,m)...". So I don't think the reading of that is at all clear. From a practical point of view, we are very limited on resource here at present, so I'm not sure how to proceed with this. I'm concerned at the potential cost of having to 'rotate' each cell individually, if we really have to support that, and the coding is not obvious. |
Also, FWIW Another point I'd push back on is the idea that this "worked in Iris 1". IIRC Iris 1 would plot a pcolormesh of data with unbounded 2d coords : however, the plot was actually not correct -- matplotlib would interprete the coordinate point arrays as corners and quietly ignore the "extra" row+column in the provided data array. |
Thanks @pp-mo
You're right, the plots look to me like they were using index. So "worked in Iris 1" is perhaps not strictly true.
I hadn't until now as I felt we needed to agree on what behavioural change would be accepted. I don't disagree that CF isn't well worded - as usual :p. However, I think a case can be made that if you can understand how a dataset is described, then iris should be made to accommodate. Specifically, it's clear how to support 2D coord (4bounds per cell) clockwise/counterclockwise bounds with any starting index with no huge performance implication if all cells are assumed to be ordered in the same way. In my opinion, it's on save that iris should more strictly constrain its behaviour to safely/clearly understood parts of the CF spec. An approach to achieve this might be to reform bounds on load or even on save. I think there is potentially a difference in our motivations over making such a change in iris so I think it makes sense to take this to our own library (Issue1). On looking back at Issue2, unless I'm mistaken, looks like is a non-issue since #3153 (I must have been testing against 1.13 at the time??). Cheers |
Issue1
Introduced in #3144,
_discontiguity_in_bounds
(lib/iris/coords.py#L1053) assumes the starting location of the bounds for 2D grids (bottom left). This means thatiris 2.*
plotting of data with 2D coordinates breaks with failed contiguity check (for contiguous bounds) unless the ordering of bounds is as iris currently assumes.iris 1.*
wasn't subject to this contiguity function check and so worked fine for us. Here is the stack trace:The relevant code problem is here:
iris/lib/iris/coords.py
Lines 1053 to 1058 in b209642
So this assumes the following ordering:
The following should be equally applicable to CF:
Counter-clockwise (extended):
Clockwise:
CF specification relating is here which doesn't enforce the starting location (corner) of the bound. Neither does is enforce anticlockwise for 4-sided cells. Since iris assumes the starting location, this makes iris also sensitive to the direction even though it determines the absolute difference. This means it can be even checking
x
rather thany
and checkingy
rather thanx
under certain starting locations/orderings.Issue2
Assumptions are made about the coordinates bounds under the two conditionals here:
iris/lib/iris/coords.py
Line 1043 in b209642
iris/lib/iris/coords.py
Line 1049 in b209642
This should really be constrained to something like:
Note that a 1D coordinate with 4 bounds to each cell is a perfectly reasonable coordinate to define and iris allows us to instantiate such coordinates:
However, the contiguity check works under this assumption above that the bounds are 2D and proceeds 'thanks' to numpy broadcasting, even though bounds are 4D and should not be treated this way.
The text was updated successfully, but these errors were encountered: