Skip to content

Commit

Permalink
Deprecate AreaDefinition 'rotation' argument
Browse files Browse the repository at this point in the history
  • Loading branch information
djhoese committed Jan 31, 2023
1 parent d624e3f commit f644200
Show file tree
Hide file tree
Showing 6 changed files with 10 additions and 188 deletions.
11 changes: 3 additions & 8 deletions pyresample/area_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ def _create_area_def_from_dict(area_name, params):
'upper_right_xy', 'units'])
params['resolution'] = _capture_subarguments(params, 'resolution', ['resolution', 'dx', 'dy', 'units'])
params['radius'] = _capture_subarguments(params, 'radius', ['radius', 'dx', 'dy', 'units'])
params['rotation'] = _capture_subarguments(params, 'rotation', ['rotation', 'units'])
area_def = create_area_def(**params)
return area_def

Expand Down Expand Up @@ -354,10 +353,10 @@ def _create_area(area_id, area_content):
config['PCS_DEF'] = _get_proj4_args(config['PCS_DEF'])
return create_area_def(config['REGION'], config['PCS_DEF'], description=config['NAME'], proj_id=config['PCS_ID'],
shape=(config['YSIZE'], config['XSIZE']), area_extent=config['AREA_EXTENT'],
rotation=config['ROTATION'])
)


def get_area_def(area_id, area_name, proj_id, proj4_args, width, height, area_extent, rotation=0):
def get_area_def(area_id, area_name, proj_id, proj4_args, width, height, area_extent):
"""Construct AreaDefinition object from arguments.
Parameters
Expand All @@ -374,8 +373,6 @@ def get_area_def(area_id, area_name, proj_id, proj4_args, width, height, area_ex
Number of pixel in x dimension
height : int
Number of pixel in y dimension
rotation: float
Rotation in degrees (negative is cw)
area_extent : list | tuple
Area extent as a list of ints (LL_x, LL_y, UR_x, UR_y)
Expand Down Expand Up @@ -445,8 +442,6 @@ def create_area_def(area_id, projection, width=None, height=None, area_extent=No
Size of pixels: (dx, dy)
radius : list or float, optional
Length from the center to the edges of the projection (dx, dy)
rotation: float, optional
rotation in degrees(negative is cw)
nprocs : int, optional
Number of processor cores to be used
lons : numpy array, optional
Expand Down Expand Up @@ -550,7 +545,7 @@ def _make_area(
return AreaDefinition(area_id, description, proj_id, projection, width, height, area_extent, **kwargs)

return DynamicAreaDefinition(area_id=area_id, description=description, projection=projection, width=width,
height=height, area_extent=area_extent, rotation=kwargs.get('rotation'),
height=height, area_extent=area_extent,
resolution=resolution, optimize_projection=optimize_projection)


Expand Down
57 changes: 7 additions & 50 deletions pyresample/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,14 +1007,12 @@ class DynamicAreaDefinition(object):
or a scalar if pixel_size_x == pixel_size_y.
optimize_projection:
Whether the projection parameters have to be optimized.
rotation:
Rotation in degrees (negative is cw)
"""

def __init__(self, area_id=None, description=None, projection=None,
width=None, height=None, area_extent=None,
resolution=None, optimize_projection=False, rotation=None):
resolution=None, optimize_projection=False):
"""Initialize the DynamicAreaDefinition."""
self.area_id = area_id
self.description = description
Expand All @@ -1026,7 +1024,6 @@ def __init__(self, area_id=None, description=None, projection=None,
if isinstance(resolution, (int, float)):
resolution = (resolution, resolution)
self.resolution = resolution
self.rotation = rotation
self._projection = projection

# check if non-dict projections are valid
Expand Down Expand Up @@ -1210,7 +1207,7 @@ def freeze(self, lonslats=None, resolution=None, shape=None, proj_info=None,
area_extent, width, height = self.compute_domain(corners, resolution, shape, projection)
return AreaDefinition(self.area_id, self.description, '',
projection, width, height,
area_extent, self.rotation)
area_extent)

def _compute_bound_centers(self, proj_dict, lonslats, antimeridian_mode):
from pyresample.utils.proj4 import DaskFriendlyTransformer
Expand Down Expand Up @@ -1438,8 +1435,6 @@ class AreaDefinition(_ProjectionDefinition):
y dimension in number of pixels, aka number of grid rows
area_extent : list
Area extent as a list (lower_left_x, lower_left_y, upper_right_x, upper_right_y)
rotation: float, optional
rotation in degrees (negative is clockwise)
nprocs : int, optional
Number of processor cores to be used for certain calculations
Expand All @@ -1457,8 +1452,6 @@ class AreaDefinition(_ProjectionDefinition):
x dimension in number of pixels, aka number of grid columns
height : int
y dimension in number of pixels, aka number of grid rows
rotation: float
rotation in degrees (negative is cw)
size : int
Number of points in grid
area_extent_ll : tuple
Expand Down Expand Up @@ -1490,7 +1483,7 @@ class AreaDefinition(_ProjectionDefinition):
"""

def __init__(self, area_id, description, proj_id, projection, width, height,
area_extent, rotation=None, nprocs=1, lons=None, lats=None,
area_extent, nprocs=1, lons=None, lats=None,
dtype=np.float64):
"""Initialize AreaDefinition."""
super(AreaDefinition, self).__init__(lons, lats, nprocs)
Expand All @@ -1500,10 +1493,6 @@ def __init__(self, area_id, description, proj_id, projection, width, height,
self.width = int(width)
self.height = int(height)
self.crop_offset = (0, 0)
try:
self.rotation = float(rotation)
except TypeError:
self.rotation = 0
if lons is not None:
if lons.shape != self.shape:
raise ValueError('Shape of lon lat grid must match '
Expand Down Expand Up @@ -1615,7 +1604,7 @@ def copy(self, **override_kwargs):
'width': self.width,
'height': self.height,
'area_extent': self.area_extent,
'rotation': self.rotation}
}
kwargs.update(override_kwargs)
return AreaDefinition(**kwargs)

Expand Down Expand Up @@ -1685,8 +1674,6 @@ def from_extent(cls, area_id, projection, shape, area_extent, units=None, **kwar
Description/name of area. Defaults to area_id
proj_id : str, optional
ID of projection
rotation: float, optional
rotation in degrees (negative is cw)
nprocs : int, optional
Number of processor cores to be used
lons : numpy array, optional
Expand Down Expand Up @@ -1734,8 +1721,6 @@ def from_circle(cls, area_id, projection, center, radius, shape=None, resolution
Description/name of area. Defaults to area_id
proj_id : str, optional
ID of projection
rotation: float, optional
rotation in degrees (negative is cw)
nprocs : int, optional
Number of processor cores to be used
lons : numpy array, optional
Expand Down Expand Up @@ -1790,8 +1775,6 @@ def from_area_of_interest(cls, area_id, projection, shape, center, resolution, u
Description/name of area. Defaults to area_id
proj_id : str, optional
ID of projection
rotation: float, optional
rotation in degrees (negative is cw)
nprocs : int, optional
Number of processor cores to be used
lons : numpy array, optional
Expand Down Expand Up @@ -1838,8 +1821,6 @@ def from_ul_corner(cls, area_id, projection, shape, upper_left_extent, resolutio
Description/name of area. Defaults to area_id
proj_id : str, optional
ID of projection
rotation: float, optional
rotation in degrees (negative is cw)
nprocs : int, optional
Number of processor cores to be used
lons : numpy array, optional
Expand Down Expand Up @@ -2010,7 +1991,6 @@ def create_areas_def_legacy(self):
fmt += "\tPCS_DEF:\t{proj_str}\n"
fmt += "\tXSIZE:\t{x_size}\n"
fmt += "\tYSIZE:\t{y_size}\n"
# fmt += "\tROTATION:\t{rotation}\n"
fmt += "\tAREA_EXTENT: {area_extent}\n}};\n"
area_def_str = fmt.format(name=self.description, area_id=self.area_id,
proj_str=proj_str, x_size=self.width,
Expand Down Expand Up @@ -2294,14 +2274,6 @@ def get_lonlat(self, row, col):
lon, lat = self.get_lonlats(nprocs=None, data_slice=(row, col))
return lon.item(), lat.item()

@staticmethod
def _do_rotation(xspan, yspan, rot_deg=0):
"""Apply a rotation factor to a matrix of points."""
rot_rad = np.radians(rot_deg)
rot_mat = np.array([[np.cos(rot_rad), np.sin(rot_rad)], [-np.sin(rot_rad), np.cos(rot_rad)]])
x, y = np.meshgrid(xspan, yspan)
return np.einsum('ji, mni -> jmn', rot_mat, np.dstack([x, y]))

def get_proj_vectors_dask(self, chunks=None, dtype=None):
"""Get projection vectors."""
warnings.warn("'get_proj_vectors_dask' is deprecated, please use "
Expand All @@ -2310,10 +2282,8 @@ def get_proj_vectors_dask(self, chunks=None, dtype=None):
chunks = CHUNK_SIZE # FUTURE: Use a global config object instead
return self.get_proj_vectors(dtype=dtype, chunks=chunks)

def _get_proj_vectors(self, dtype=None, check_rotation=True, chunks=None):
def _get_proj_vectors(self, dtype=None, chunks=None):
"""Get 1D projection coordinates."""
if check_rotation and self.rotation != 0:
warnings.warn("Projection vectors will not be accurate because rotation is not 0", RuntimeWarning)
if dtype is None:
dtype = self.dtype
x, y = _generate_1d_proj_vectors((0, self.width),
Expand Down Expand Up @@ -2375,8 +2345,6 @@ def get_proj_coords(self, data_slice=None, dtype=None, chunks=None):
Removed 'cache' keyword argument and add 'chunks' for creating
dask arrays.
"""
if self.rotation != 0 and chunks is not None:
raise ValueError("'rotation' is not supported with dask operations.")
if dtype is None:
dtype = self.dtype
y_slice, x_slice = self._get_yx_data_slice(data_slice)
Expand All @@ -2387,18 +2355,13 @@ def get_proj_coords(self, data_slice=None, dtype=None, chunks=None):
target_y = target_y[y_slice, x_slice]
return target_x, target_y

target_x, target_y = self._get_proj_vectors(dtype=dtype, check_rotation=False, chunks=chunks)
target_x, target_y = self._get_proj_vectors(dtype=dtype, chunks=chunks)
if y_slice is not None:
target_y = target_y[y_slice]
if x_slice is not None:
target_x = target_x[x_slice]

if self.rotation != 0:
res = self._do_rotation(target_x, target_y, self.rotation)
target_x, target_y = res[0, :, :], res[1, :, :]
else:
target_x, target_y = np.meshgrid(target_x, target_y)

target_x, target_y = np.meshgrid(target_x, target_y)
return target_x, target_y

@staticmethod
Expand Down Expand Up @@ -2439,17 +2402,11 @@ def _proj_coords_dask(self, chunks, dtype):
@property
def projection_x_coords(self):
"""Return projection X coordinates."""
if self.rotation != 0:
# rotation is only supported in 'get_proj_coords' right now
return self.get_proj_coords(data_slice=(0, slice(None)))[0].squeeze()
return self.get_proj_vectors()[0]

@property
def projection_y_coords(self):
"""Return projection Y coordinates."""
if self.rotation != 0:
# rotation is only supported in 'get_proj_coords' right now
return self.get_proj_coords(data_slice=(slice(None), 0))[1].squeeze()
return self.get_proj_vectors()[1]

@property
Expand Down
4 changes: 0 additions & 4 deletions pyresample/test/test_files/areas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ test_meters:
radius:
radius: 3309.9505528339496
units: mi
rotation: 45

test_degrees:
projection:
Expand Down Expand Up @@ -170,9 +169,6 @@ test_degrees:
dx: 49.4217406986
dy: 49.4217406986
units: degrees
rotation:
rotation: 45
units: degrees

ease_sh:
description: Antarctic EASE grid
Expand Down
1 change: 0 additions & 1 deletion pyresample/test/test_geometry/test_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,6 @@ def test_create_area_def_base_combinations(self, projection, center, units, crea
radius=essentials[1],
description=description,
units=units,
rotation=45,
)

should_fail = isinstance(center, str) or len(center) != 2
Expand Down
31 changes: 0 additions & 31 deletions pyresample/test/test_geometry_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -954,36 +954,6 @@ def test_get_proj_coords_basic(self):
np.array([47500., 37500., 27500., 17500.,
7500.])))

def test_get_proj_coords_rotation(self):
"""Test basic get_proj_coords usage with rotation specified."""
from pyresample.geometry import AreaDefinition
area_id = 'test'
area_name = 'Test area with 2x2 pixels'
proj_id = 'test'
x_size = 10
y_size = 10
area_extent = [1000000, 0, 1050000, 50000]
proj_dict = {"proj": 'laea', 'lat_0': '60', 'lon_0': '0', 'a': '6371228.0', 'units': 'm'}
area_def = AreaDefinition(area_id, area_name, proj_id, proj_dict, x_size, y_size, area_extent, rotation=45)

xcoord, ycoord = area_def.get_proj_coords()
np.testing.assert_allclose(xcoord[0, :],
np.array([742462.120246, 745997.654152, 749533.188058, 753068.721964,
756604.25587, 760139.789776, 763675.323681, 767210.857587,
770746.391493, 774281.925399]))
np.testing.assert_allclose(ycoord[:, 0],
np.array([-675286.976033, -678822.509939, -682358.043845, -685893.577751,
-689429.111657, -692964.645563, -696500.179469, -700035.713375,
-703571.247281, -707106.781187]))

xcoord, ycoord = area_def.get_proj_coords(data_slice=(slice(None, None, 2), slice(None, None, 2)))
np.testing.assert_allclose(xcoord[0, :],
np.array([742462.120246, 749533.188058, 756604.25587, 763675.323681,
770746.391493]))
np.testing.assert_allclose(ycoord[:, 0],
np.array([-675286.976033, -682358.043845, -689429.111657, -696500.179469,
-703571.247281]))

def test_get_proj_coords_dask(self):
"""Test get_proj_coords usage with dask arrays."""
from pyresample import get_area_def
Expand Down Expand Up @@ -2260,7 +2230,6 @@ def test_create_area_def_base_combinations(self, projection, center, units):
radius=essentials[1],
description=description,
units=units,
rotation=45,
)

should_fail = isinstance(center, str) or len(center) != 2
Expand Down

0 comments on commit f644200

Please sign in to comment.