160 rotating coords - #163
Conversation
Josh Rackham (jrackham-mo)
left a comment
There was a problem hiding this comment.
The logic of this looks sensible to me. I've added some specific review comments inline. I also have a more general comment that we should probably save some metadata about the coordinate reference system alongside the shapefile. We should also check that this is picked up and respected on load by downstream applications (e.g. fill_n_merge).
In terms of how to implement this, it looks like the projection should be saved to a .prj file (wikipedia), and this is supported by GDAL.
Another general thing to think about is how/if we should handle polygons close to the boundary of the domain (i.e. the antimeridian). Looks like there is a library for this (antimeridian), but whether this is necessary for our purposes I don't know.
| valid_crs = not ( | ||
| ants.utils.ndarray.allclose( | ||
| [grid_lon, grid_lat, pole_lon_rotation], [0.0, 90.0, 0.0] | ||
| ) | ||
| ) | ||
| if not valid_crs: |
There was a problem hiding this comment.
Just a minor style point here, there's a double negative here which makes it a little harder to follow. It might be better to have:
| valid_crs = not ( | |
| ants.utils.ndarray.allclose( | |
| [grid_lon, grid_lat, pole_lon_rotation], [0.0, 90.0, 0.0] | |
| ) | |
| ) | |
| if not valid_crs: | |
| invalid_crs = ( | |
| ants.utils.ndarray.allclose( | |
| [grid_lon, grid_lat, pole_lon_rotation], [0.0, 90.0, 0.0] | |
| ) | |
| ) | |
| if invalid_crs: |
I suppose then you'd return not invalid_crs
There was a problem hiding this comment.
I agree, I have changed this
| return rotated_points | ||
|
|
||
|
|
||
| def _load_polygon_from_json(json_file, target_lsm_path, source_cube_path): |
There was a problem hiding this comment.
I think this function may have become complex enough to warrant splitting into two parts. The original load can probably stay as it was (perhaps returning a numpy array rather than the polygon object though, I think you said there was some difficulty with transforming the polygon object directly?), then have a separate standalone transform function that takes a loaded array, a source and a target cube, and does the transform.
There was a problem hiding this comment.
I've changed the function to only load points from a json file
|
Here are the comments I've addressed:
The main comment I have not addressed is adding a .prj file, which I don't think is possible for rotated poles, see the issue |
| parser.add_argument( | ||
| "--source-cube", | ||
| type=ants.config.filepath_readable, | ||
| required=False, | ||
| help="Path to an iris cube which specifies the coordinate" | ||
| " system of the json file.", | ||
| ) |
There was a problem hiding this comment.
I think it would be more appropriate to call this source-netcdf or just source. The iris cube only exists in memory, rather than being a file.
|
|
||
| if not polygon.is_valid: | ||
| raise ValueError(f"Polygon is invalid: {explain_validity(polygon)}") | ||
| if polygon.exterior.is_ccw != ccw_expected: |
There was a problem hiding this comment.
I'm unsure whether there are any cases where transforming the polygon would change the orientation? Is this something you've seen in testing?
There was a problem hiding this comment.
Noting that we discussed adding a comment on why this check is included
| closed_lon = np.vstack([rotated_points, rotated_points[0, :]]) | ||
| lon_diff = np.abs(closed_lon[:-1, 0] - closed_lon[1:, 0]) | ||
|
|
||
| if np.any(lon_diff > 180.0): | ||
| neg_indices = np.where(rotated_points[:, 0] < 0) | ||
| rotated_points[neg_indices, 0] += 360.0 |
There was a problem hiding this comment.
I think a comment would be good here to explain the logic, and mention it in the docstring (i.e. negative longitudes will be shifted by +360 degrees if a jump of 180 degrees is detected)
Could we also throw a warning here, or logger.info?
An additional check I'd like to see is if any of the transformed points fall outside of the target domain, and throw an error if they do.
There was a problem hiding this comment.
I've included some comments to explain what is going on and also added a warning.
I also added a check for the transformed points landing in the target domain. I haven't included a check on if the polygon is defined on an equivalent domain (for example rotated 360.0) because it seems that fill_n_merge doesn't check for this.
| self.assertTrue(_validate_orientation(self.sphere_rotated_target_lsm)) | ||
|
|
||
|
|
||
| class Test__transform_coordinates(ants.tests.TestCase): |
There was a problem hiding this comment.
Could we add a test case using the ite polygon, transformed to a standard UK domain (pole_lat=37.5, pole_lon=177.5)?
It would also be good to have a test case with the target cube having a regional domain (i.e. non-global) to test that an error is raised if any of the transformed points lie outside the target domain.
There was a problem hiding this comment.
Yes that's a good idea, I've added a test case for both
| longitude.""" | ||
|
|
||
| true_lats = np.array([90, 45, 0, -45, -90]) | ||
| true_lons = np.array([np.nan, -180.0, -180.0, -180.0, -180.0]) |
There was a problem hiding this comment.
Can we double check if the nans are needed? If a point lies on the rotated pole, I think we should probably throw an error. Maybe we should check if nans appear in the output?
There was a problem hiding this comment.
I've changed these tests to be more representative of what will actually be passed into the function. Rather than just a handful of points the passed points are in a square and the poles are no longer near the points.
| @mock.patch("builtins.open", new_callable=mock.mock_open) | ||
| class Test__load_points_from_json(ants.tests.TestCase): |
There was a problem hiding this comment.
I think we can remove this test
There was a problem hiding this comment.
General comment on the unit tests is that there's a lot of things created in the setup methods that are only used by one test. It might make it more readable to only create the cubes in the test you need them, unless the cubes are used by multiple tests.
There was a problem hiding this comment.
I agree, I have tried to make the tests more readable
|
Also need to add a .txt file saving information on the crs (source and target) |
Closes #160
To be completed prior to review request and updated as required during the review process.
If the answer to an item on the list is not applicable, feel free to replace the checkbox with 'N/A' to give extra clarity.
All developers are reminded to follow the ancil working practices
Branch
Related branches (e.g. ancillary-file-science):
[please link any related branches here]
ANTS rose stem logs
[https://cylchub/services/cylc-review/taskjobs/alasdair.roy/?suite=ANTS_160%2Frun2]
ancillary-file-science rose stem logs
[please enter the workflow name here as it has been run e.g. ancillary-file-science/run1]
Testing
For core ANTS only tests, the bare minimum that will be accepted is the
group=unittestsbut many, if not most, changes will need to test other groups to ensure they meet reviewer expectations. In general, it should be possible and is advised to run thegroup=allgroup prior to review submission as this will catch any consequential issues. Additionally you must run theancillary-file-sciencetests, pointing at your branch, withgroup=allto capture any behaviour changes affecting Science codes.If your change will alter existing science results, you will need to seek appropriate Scientific validation and confirm that the model has been initialised with your new development. Inspecting a change in xconv/pyplot/visualiser of choice is not sufficient to demonstrate the model can be initialised from your file.
Impact of change
cylc vip ./rose-stem -z group=alltestscylc vip ./rose-stem -z group=alltestsApprovals for this change
New functionality further testing
These tasks must succeed for your ticket to pass review.
Other
Rose stem logs
Please copy in the contents of your trac_status.log file(s) below (found in the cylc-run directory for your rose stem run) to your rose-stem testing here. Note: if your changes lead to a change in answers, you must run
cylc vip ./rose-stem -z group=allto help ensure all affected configurations has been flagged up.Test Results - Summary
Test Results - Detail