Skip to content

Commit

Permalink
Renaming to SphericalBoundary and PlanarBoundary
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiggi committed Nov 27, 2023
1 parent 61240eb commit 7069197
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 86 deletions.
4 changes: 2 additions & 2 deletions docs/source/howtos/spherical_geometry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ satellite passes. See trollschedule_ how to generate a list of satellite overpas

>>> from pyresample.spherical_utils import GetNonOverlapUnions

>>> area_boundary = area_def.geographic_boundary(vertices_per_side=100) # doctest: +SKIP
>>> area_boundary = area_def.boundary(vertices_per_side=100) # doctest: +SKIP
>>> area_boundary = area_boundary.polygon # doctest: +SKIP

>>> list_of_polygons = []
>>> for mypass in passes: # doctest: +SKIP
>>> list_of_polygons.append(mypass.geographic_boundary().polygon) # doctest: +SKIP
>>> list_of_polygons.append(mypass.boundary().polygon) # doctest: +SKIP

>>> non_overlaps = GetNonOverlapUnions(list_of_polygons) # doctest: +SKIP
>>> non_overlaps.merge() # doctest: +SKIP
Expand Down
2 changes: 1 addition & 1 deletion pyresample/bilinear/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ def get_valid_indices_from_lonlat_boundaries(
"""Get valid indices from lonlat boundaries."""
# Resampling from swath to grid or from grid to grid
try:
sides_lons, sides_lats = target_geo_def.geographic_boundary().sides
sides_lons, sides_lats = target_geo_def.boundary().sides
valid_indices = data_reduce.get_valid_index_from_lonlat_boundaries(sides_lons, sides_lats,
source_lons, source_lats,
radius_of_influence)
Expand Down
8 changes: 4 additions & 4 deletions pyresample/boundary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
"""The Boundary classes."""

from pyresample.boundary.area_boundary import AreaBoundary, AreaDefBoundary
from pyresample.boundary.geographic_boundary import GeographicBoundary
from pyresample.boundary.projection_boundary import ProjectionBoundary
from pyresample.boundary.planar_boundary import PlanarBoundary
from pyresample.boundary.simple_boundary import SimpleBoundary
from pyresample.boundary.spherical_boundary import SphericalBoundary

__all__ = [
"GeographicBoundary",
"ProjectionBoundary",
"SphericalBoundary",
"PlanarBoundary",
# Deprecated
"SimpleBoundary",
"AreaBoundary",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Define the ProjectionBoundary class."""
"""Define the PlanarBoundary class."""

import logging

Expand All @@ -37,7 +37,7 @@ def _is_projection_boundary_clockwise(sides_x, sides_y):
return not polygon.exterior.is_ccw


class ProjectionBoundary(BaseBoundary):
class PlanarBoundary(BaseBoundary):
"""Projection Boundary object.
The inputs must be the x and y sides of the projection.
Expand All @@ -46,7 +46,7 @@ class ProjectionBoundary(BaseBoundary):

@classmethod
def _check_is_boundary_clockwise(cls, sides_x, sides_y, area=None):
"""GeographicBoundary specific implementation."""
"""SphericalBoundary specific implementation."""
return _is_projection_boundary_clockwise(sides_x=sides_x, sides_y=sides_y)

@classmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Define the GeographicBoundary class."""
"""Define the SphericalBoundary class."""

import logging

Expand Down Expand Up @@ -106,8 +106,8 @@ def _check_is_clockwise(area, sides_x, sides_y):
return True


class GeographicBoundary(BaseBoundary, OldBoundary):
"""GeographicBoundary object.
class SphericalBoundary(BaseBoundary, OldBoundary):
"""SphericalBoundary object.
The inputs must be the list of longitude and latitude boundary sides.
"""
Expand All @@ -117,7 +117,7 @@ class GeographicBoundary(BaseBoundary, OldBoundary):

@classmethod
def _check_is_boundary_clockwise(cls, sides_x, sides_y, area):
"""GeographicBoundary specific implementation."""
"""SphericalBoundary specific implementation."""
return _check_is_clockwise(area, sides_x, sides_y)

@classmethod
Expand Down
6 changes: 3 additions & 3 deletions pyresample/future/geometry/_subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# must be imported inside functions in the geometry modules if needed
# to avoid circular dependencies
from pyresample._caching import cache_to_json_if
from pyresample.boundary import GeographicBoundary
from pyresample.boundary import SphericalBoundary
from pyresample.utils import check_slice_orientation

if TYPE_CHECKING:
Expand Down Expand Up @@ -97,13 +97,13 @@ def _get_slice_starts_stops(src_area, area_to_cover):
return xstart, xstop, ystart, ystop


def _get_area_boundary(area_to_cover: AreaDefinition) -> GeographicBoundary:
def _get_area_boundary(area_to_cover: AreaDefinition) -> SphericalBoundary:
try:
if area_to_cover.is_geostationary:
vertices_per_side = None
else:
vertices_per_side = max(max(*area_to_cover.shape) // 100 + 1, 3)
return area_to_cover.geographic_boundary(vertices_per_side=vertices_per_side)
return area_to_cover.boundary(vertices_per_side=vertices_per_side)
except ValueError as err:
raise NotImplementedError("Can't determine boundary of area to cover") from err

Expand Down
60 changes: 25 additions & 35 deletions pyresample/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def get_proj_coords(self, data_slice=None, chunks=None, **kwargs):
def get_boundary_lonlats(self):
"""Return Boundary objects."""
warnings.warn("'get_boundary_lonlats' is deprecated. Please use "
"'area.geographic_boundary().sides'.", DeprecationWarning, stacklevel=2)
"'area.boundary().sides'.", DeprecationWarning, stacklevel=2)
s1_lon, s1_lat = self.get_lonlats(data_slice=(0, slice(None)))
s2_lon, s2_lat = self.get_lonlats(data_slice=(slice(None), -1))
s3_lon, s3_lat = self.get_lonlats(data_slice=(-1, slice(None, None, -1)))
Expand Down Expand Up @@ -339,7 +339,7 @@ def get_bbox_lonlats(self, vertices_per_side: Optional[int] = None,

vertices_per_side = vertices_per_side or frequency
sides_lons, sides_lats = self._get_geographic_sides(vertices_per_side=vertices_per_side)
warnings.warn("`get_bbox_lonlats` is pending deprecation. Use `area.geographic_boundary().sides` instead",
warnings.warn("`get_bbox_lonlats` is pending deprecation. Use `area.boundary().sides` instead",
PendingDeprecationWarning, stacklevel=2)
if force_clockwise and not self._corner_is_clockwise(
sides_lons[0][-2], sides_lats[0][-2],
Expand Down Expand Up @@ -436,8 +436,6 @@ def _get_geographic_sides(self, vertices_per_side: Optional[int] = None) -> tupl
Each list element is a numpy array representing a specific side of the geometry.
The order of the sides are [top", "right", "bottom", "left"]
"""
if len(self.lons.shape) == 1:
raise ValueError("The area must have 2 dimensions to retrieve the boundary sides.")
is_swath = self.__class__.__name__ == "SwathDefinition"
if not is_swath and _is_any_corner_out_of_earth_disk(self):
# Geostationary
Expand Down Expand Up @@ -500,6 +498,8 @@ def _get_bbox_slices(self, vertices_per_side):
The output structure is a tuple of four slices, one for each side.
The order of the sides are [top", "right", "bottom", "left"]
"""
if len(self.shape) == 1:
raise ValueError("The area must have 2 dimensions to retrieve the boundary sides.")
height, width = self.shape
if vertices_per_side is None:
row_num = height
Expand Down Expand Up @@ -555,13 +555,13 @@ def get_edge_lonlats(self, vertices_per_side=None, frequency=None):
warnings.warn("The `frequency` argument is pending deprecation, use `vertices_per_side` instead.",
PendingDeprecationWarning, stacklevel=2)
msg = "`get_edge_lonlats` is pending deprecation"
msg += "Use `area.geographic_boundary(vertices_per_side=vertices_per_side).contour()` instead."
msg += "Use `area.boundary(vertices_per_side=vertices_per_side).contour()` instead."
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
vertices_per_side = vertices_per_side or frequency
lons, lats = self.geographic_boundary(vertices_per_side=vertices_per_side).contour()
lons, lats = self.boundary(vertices_per_side=vertices_per_side).contour()
return lons, lats

def boundary(self, *, vertices_per_side=None, force_clockwise=False, frequency=None):
def boundary(self, *, vertices_per_side=None, force_clockwise=None, frequency=None):
"""Retrieve the AreaBoundary object.
Parameters
Expand All @@ -573,7 +573,7 @@ def boundary(self, *, vertices_per_side=None, force_clockwise=False, frequency=N
(i.e. full disc geostationary area, Robinson projection, polar projections, ...)
by default only 50 points are selected.
force_clockwise:
DEPRECATED.
DEPRECATED. IS NOT USED ANYMORE !
Performed minimal checks and reordering of coordinates to ensure
that the returned coordinates follow a clockwise direction.
This is important for compatibility with
Expand All @@ -582,28 +582,16 @@ def boundary(self, *, vertices_per_side=None, force_clockwise=False, frequency=N
operations assume that coordinates are clockwise.
Default is False.
"""
from pyresample.boundary import SphericalBoundary
if frequency is not None:
warnings.warn("The `frequency` argument is pending deprecation, use `vertices_per_side` instead",
PendingDeprecationWarning, stacklevel=2)
warnings.warn("The `boundary` method is pending deprecation. Use `geographic_boundary` instead",
PendingDeprecationWarning, stacklevel=2)
if force_clockwise is not None:
warnings.warn("The `force_clockwise` argument is not used anymore. "
"Please remove the argument from the boundary() call !!!",
PendingDeprecationWarning, stacklevel=2)
vertices_per_side = vertices_per_side or frequency
return self.geographic_boundary(vertices_per_side=vertices_per_side)

def geographic_boundary(self, vertices_per_side=None):
"""Retrieve the GeographicBoundary object.
Parameters
----------
vertices_per_side:
The number of points to provide for each side.
By default (None) the full width and height will be provided.
If the area object is an AreaDefinition with any corner out of the Earth disk
(i.e. full disc geostationary area, Robinson projection, polar projections, ...)
by default only 50 points are selected.
"""
from pyresample.boundary import GeographicBoundary
return GeographicBoundary(area=self, vertices_per_side=vertices_per_side)
return SphericalBoundary(area=self, vertices_per_side=vertices_per_side)

def get_cartesian_coords(self, nprocs=None, data_slice=None, cache=False):
"""Retrieve cartesian coordinates of geometry definition.
Expand Down Expand Up @@ -1143,7 +1131,7 @@ def compute_optimal_bb_area(self, proj_dict=None, resolution=None):
proj_dict = self.compute_bb_proj_params(proj_dict)

area = DynamicAreaDefinition(area_id, description, proj_dict)
lons, lats = self.geographic_boundary(vertices_per_side=None).contour()
lons, lats = self.boundary(vertices_per_side=None).contour()
return area.freeze((lons, lats), shape=(height, width))


Expand All @@ -1157,7 +1145,7 @@ class DynamicAreaDefinition(object):
Note that if the provided projection is geographic (lon/lat degrees) and
the provided longitude and latitude data crosses the anti-meridian
(-180/180), the resulting area will be the smallest possible in order to
contain that data and avoid a large area spanning from -180 to 180
contain that data and boundaryspanning from -180 to 180
longitude. This means the resulting AreaDefinition will have a right-most
X extent greater than 180 degrees. This does not apply to data crossing
the north or south pole as there is no "smallest" area in this case.
Expand Down Expand Up @@ -1762,7 +1750,10 @@ def _get_projection_sides(self, vertices_per_side: Optional[int] = None) -> tupl
return sides_x, sides_y

def projection_boundary(self, vertices_per_side=None):
"""Retrieve the ProjectionBoundary object.
"""Retrieve the boundary object in projection coordinates.
If the CRS of the AreaDefinition is geographic, the returned boundary
object is a SphericalBoundary, otherwise a PlanarBoundary is returned.
Parameters
----------
Expand All @@ -1773,11 +1764,10 @@ def projection_boundary(self, vertices_per_side=None):
(i.e. full disc geostationary area, Robinson projection, polar projections, ...)
by default only 50 points are selected..
"""
from pyresample.boundary import ProjectionBoundary
from pyresample.boundary import PlanarBoundary
if self.crs.is_geographic:
return self.geographic_boundary(vertices_per_side=vertices_per_side)
return ProjectionBoundary(area=self,
vertices_per_side=vertices_per_side)
return self.boundary(vertices_per_side=vertices_per_side)
return PlanarBoundary(area=self, vertices_per_side=vertices_per_side)

def get_edge_bbox_in_projection_coordinates(self, vertices_per_side: Optional[int] = None,
frequency: Optional[int] = None):
Expand Down Expand Up @@ -2964,7 +2954,7 @@ def get_geostationary_bounding_box_in_lonlats(geos_area, nb_points=50):
nb_points: Number of points on the polygon
"""
warnings.warn("'get_geostationary_bounding_box_in_lonlats' is deprecated. Please call "
"'area.geographic_boundary().contour()' instead.",
"'area.boundary().contour()' instead.",
DeprecationWarning, stacklevel=2)
return _get_geostationary_bounding_box(geos_area,
coordinates="geographic",
Expand All @@ -2980,7 +2970,7 @@ def get_geostationary_bounding_box(geos_area, nb_points=50):
"""
warnings.warn("'get_geostationary_bounding_box' is deprecated. Please call "
"'area.geographic_boundary().contour()' instead.",
"'area.boundary().contour()' instead.",
DeprecationWarning, stacklevel=2)
return _get_geostationary_bounding_box_in_lonlats(geos_area, nb_points)

Expand Down
2 changes: 1 addition & 1 deletion pyresample/gradient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def _get_border_lonlats(geo_def: AreaDefinition, vertices_per_side=None):
"""Get the border x- and y-coordinates."""
if geo_def.is_geostationary:
vertices_per_side = 3600
lon_b, lat_b = geo_def.geographic_boundary(vertices_per_side=vertices_per_side).contour(closed=True)
lon_b, lat_b = geo_def.boundary(vertices_per_side=vertices_per_side).contour(closed=True)
return lon_b, lat_b


Expand Down
4 changes: 2 additions & 2 deletions pyresample/kd_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def _get_valid_input_index(source_geo_def,
# Resampling from swath to grid or from grid to grid
# - If invalid sides, return np.ones
try:
sides_lons, sides_lats = target_geo_def.geographic_boundary().sides
sides_lons, sides_lats = target_geo_def.boundary().sides
# Combine reduced and legal values
valid_input_index &= \
data_reduce.get_valid_index_from_lonlat_boundaries(
Expand Down Expand Up @@ -445,7 +445,7 @@ def _get_valid_output_index(source_geo_def, target_geo_def, target_lons,
# Resampling from grid to swath
# - If invalid sides, return np.ones
try:
sides_lons, sides_lats = source_geo_def.geographic_boundary().sides
sides_lons, sides_lats = source_geo_def.boundary().sides
valid_output_index = \
data_reduce.get_valid_index_from_lonlat_boundaries(
sides_lons,
Expand Down
2 changes: 1 addition & 1 deletion pyresample/slicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def _get_chunk_polygons_for_swath_to_crop(swath_to_crop):
line_slice = expand_slice(line_slice)
col_slice = expand_slice(col_slice)
smaller_swath = swath_to_crop[line_slice, col_slice]
smaller_poly = smaller_swath.geographic_boundary(vertices_per_side=10).to_shapely_polygon()
smaller_poly = smaller_swath.boundary(vertices_per_side=10).to_shapely_polygon()
res.append((smaller_poly, (line_slice, col_slice)))
return res

Expand Down
34 changes: 17 additions & 17 deletions pyresample/test/test_boundary/test_geographic_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Test the GeographicBoundary objects."""
"""Test the SphericalBoundary objects."""

import numpy as np
import pytest

from pyresample import SwathDefinition
from pyresample.boundary import GeographicBoundary
from pyresample.boundary import SphericalBoundary


class TestSwathGeographicBoundary():
"""Test 'GeographicBoundary' class for SwathDefinition."""
class TestSwathSphericalBoundary():
"""Test 'SphericalBoundary' class for SwathDefinition."""

def setup_method(self):
sides_lons = [np.array([1.0, 1.5, 2.0]),
Expand All @@ -50,9 +50,9 @@ def setup_method(self):
self.point_inside = (2.5, 7.5)

def test_creation(self):
"""Test GeographicBoundary creation."""
# Define GeographicBoundary
boundary = GeographicBoundary(self.area)
"""Test SphericalBoundary creation."""
# Define SphericalBoundary
boundary = SphericalBoundary(self.area)

# Assert sides coincides
for b_lon, src_lon in zip(boundary.sides_lons, self.sides_lons):
Expand All @@ -65,12 +65,12 @@ def test_minimum_swath_size(self):
"""Test swath has minimum 2 dimensions."""
area = SwathDefinition(self.lons[0], self.lats[1])
with pytest.raises(ValueError):
GeographicBoundary(area)
SphericalBoundary(area)

def test_vertices_property(self):
"""Test GeographicBoundary vertices property."""
# Define GeographicBoundary
boundary = GeographicBoundary(self.area)
"""Test SphericalBoundary vertices property."""
# Define SphericalBoundary
boundary = SphericalBoundary(self.area)
# Assert vertices
expected_vertices = np.array([[1., 6.],
[1.5, 6.5],
Expand All @@ -81,18 +81,18 @@ def test_vertices_property(self):
assert np.allclose(boundary.vertices, expected_vertices)

def test_contour(self):
"""Test that GeographicBoundary.contour(closed=False) returns the correct (lon,lat) tuple."""
# Define GeographicBoundary
boundary = GeographicBoundary(self.area)
"""Test that SphericalBoundary.contour(closed=False) returns the correct (lon,lat) tuple."""
# Define SphericalBoundary
boundary = SphericalBoundary(self.area)
# Assert contour
lons, lats = boundary.contour()
assert np.allclose(lons, np.array([1., 1.5, 2., 3., 3.5, 4.]))
assert np.allclose(lats, np.array([6., 6.5, 7., 8., 8.5, 9.]))

def test_contour_closed(self):
"""Test that GeographicBoundary.contour(closed=True) returns the correct (lon,lat) tuple."""
# Define GeographicBoundary
boundary = GeographicBoundary(self.area)
"""Test that SphericalBoundary.contour(closed=True) returns the correct (lon,lat) tuple."""
# Define SphericalBoundary
boundary = SphericalBoundary(self.area)
lons, lats = boundary.contour(closed=True)
assert np.allclose(lons, np.array([1., 1.5, 2., 3., 3.5, 4., 1.]))
assert np.allclose(lats, np.array([6., 6.5, 7., 8., 8.5, 9., 6.]))
Loading

0 comments on commit 7069197

Please sign in to comment.