Skip to content

Commit 6da796c

Browse files
committed
DAS-2361 - Update comments and names to be clearer
1 parent 69fab83 commit 6da796c

File tree

3 files changed

+22
-15
lines changed

3 files changed

+22
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
## v1.1.9
2-
### 2025-08-07
2+
### 2025-08-013
33

4-
This version of HOSS updates fixes invalid output extents for whole earth
5-
spatial subset requests on Polar grids.
4+
This version of HOSS updates fixes invalid output extents in cases where the
5+
requested bounding area (bbox, shape) extends beyond valid locations for the native
6+
projection of the data. E.g., EASE-GRID-2 North Polar (LAEA) projection becomes INF
7+
at latitude -90°.
68

79
## v1.1.8
810
### 2025-05-23

hoss/projection_utilities.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,20 +203,25 @@ def get_projected_x_y_extents(
203203
grid_lats, grid_lons = get_grid_lat_lons( # pylint: disable=unpacking-non-sequence
204204
x_values, y_values, crs
205205
)
206-
206+
# When projected, the perimeter of a bounding box or polygon in geographic
207+
# terms will become curved. To determine the X, Y extent of the requested
208+
# bounding area, we need a perimeter with a suitable density of points, such that
209+
# we catch that curve when projected. The source file resolution is used to define
210+
# the necessary number of points (density).
207211
geographic_resolution = get_geographic_resolution(grid_lons, grid_lats)
208-
points_in_requested_extent = get_resolved_geojson(
212+
densified_perimeter = get_densified_perimeter(
209213
geographic_resolution, shape_file=shape_file, bounding_box=bounding_box
210214
)
211215

212-
# get the extent of the granule.
216+
# To avoid out-of-limits projection, we need to clip the bounding perimeter to
217+
# the source file's geographic extents
213218
granule_extent = BBox(
214219
np.min(grid_lons), np.min(grid_lats), np.max(grid_lons), np.max(grid_lats)
215220
)
216221

217-
clipped_points = get_filtered_points(points_in_requested_extent, granule_extent)
222+
clipped_perimeter = get_filtered_points(densified_perimeter, granule_extent)
218223

219-
return get_x_y_extents_from_geographic_points(clipped_points, crs)
224+
return get_x_y_extents_from_geographic_points(clipped_perimeter, crs)
220225

221226

222227
def get_filtered_points(
@@ -266,7 +271,7 @@ def get_geographic_resolution(longitudes: np.ndarray, latitudes: np.ndarray) ->
266271
return np.nanmin(np.sqrt(np.add(lon_square_diffs, lat_square_diffs)))
267272

268273

269-
def get_resolved_geojson(
274+
def get_densified_perimeter(
270275
resolution: float, shape_file: str = None, bounding_box: BBox = None
271276
) -> List[Coordinates]:
272277
"""Take a shape file or bounding box, as defined by the input Harmony

tests/unit/test_projection_utilities.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
)
2828
from hoss.projection_utilities import (
2929
get_bbox_polygon,
30+
get_densified_perimeter,
3031
get_filtered_points,
3132
get_geographic_resolution,
3233
get_grid_lat_lons,
@@ -36,7 +37,6 @@
3637
get_projected_x_y_variables,
3738
get_resolved_feature,
3839
get_resolved_features,
39-
get_resolved_geojson,
4040
get_resolved_geometry,
4141
get_resolved_line,
4242
get_variable_crs,
@@ -718,7 +718,7 @@ def test_get_geographic_resolution(self):
718718
@patch('hoss.projection_utilities.get_bbox_polygon')
719719
@patch('hoss.projection_utilities.get_resolved_feature')
720720
@patch('hoss.projection_utilities.get_resolved_features')
721-
def test_get_resolved_geojson(
721+
def test_get_densified_perimeter(
722722
self,
723723
mock_get_resolved_features,
724724
mock_get_resolved_feature,
@@ -747,7 +747,7 @@ def test_get_resolved_geojson(
747747

748748
with self.subTest('Shape file is specified and used'):
749749
self.assertListEqual(
750-
get_resolved_geojson(resolution, shape_file=shape_file),
750+
get_densified_perimeter(resolution, shape_file=shape_file),
751751
resolved_features,
752752
)
753753
mock_get_resolved_features.assert_called_once_with(
@@ -760,7 +760,7 @@ def test_get_resolved_geojson(
760760

761761
with self.subTest('Bounding box is specified and used'):
762762
self.assertListEqual(
763-
get_resolved_geojson(resolution, bounding_box=bounding_box),
763+
get_densified_perimeter(resolution, bounding_box=bounding_box),
764764
resolved_feature,
765765
)
766766
mock_get_resolved_features.assert_not_called()
@@ -774,7 +774,7 @@ def test_get_resolved_geojson(
774774

775775
with self.subTest('Bounding box is used when both are specified'):
776776
self.assertListEqual(
777-
get_resolved_geojson(
777+
get_densified_perimeter(
778778
resolution, shape_file=shape_file, bounding_box=bounding_box
779779
),
780780
resolved_feature,
@@ -789,7 +789,7 @@ def test_get_resolved_geojson(
789789

790790
with self.subTest('Neither shape file nor bbox, raises exception'):
791791
with self.assertRaises(MissingSpatialSubsetInformation):
792-
get_resolved_geojson(resolution, None, None)
792+
get_densified_perimeter(resolution, None, None)
793793
mock_get_resolved_features.assert_not_called()
794794
mock_get_bbox_polygon.assert_not_called()
795795
mock_get_resolved_feature.assert_not_called()

0 commit comments

Comments
 (0)