From 35a0558a7f7434e52ba0933ce043314cc0c253eb Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Thu, 7 May 2020 14:05:07 +0300 Subject: [PATCH] Check the area slices, add tests --- pyresample/geometry.py | 9 ++++++--- pyresample/test/test_utils.py | 29 +++++++++++++++++++++++++++++ pyresample/utils/__init__.py | 10 ++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/pyresample/geometry.py b/pyresample/geometry.py index b294f197a..28d43bb9b 100644 --- a/pyresample/geometry.py +++ b/pyresample/geometry.py @@ -37,7 +37,8 @@ from pyresample._spatial_mp import Cartesian, Cartesian_MP, Proj, Proj_MP from pyresample.boundary import AreaDefBoundary, Boundary, SimpleBoundary from pyresample.utils import (proj4_str_to_dict, proj4_dict_to_str, - convert_proj_floats, proj4_radius_parameters) + convert_proj_floats, proj4_radius_parameters, + check_slice_orientation) from pyresample.area_config import create_area_def try: @@ -1964,7 +1965,8 @@ def get_area_slices(self, area_to_cover, shape_divisible_by=None): xstop = self.width if x[1] is np.ma.masked else x[1] + 1 ystop = self.height if y[0] is np.ma.masked else y[0] + 1 - return slice(xstart, xstop), slice(ystart, ystop) + return (check_slice_orientation(slice(xstart, xstop)), + check_slice_orientation(slice(ystart, ystop))) if self.proj_dict.get('proj') != 'geos': raise NotImplementedError("Source projection must be 'geos' if " @@ -1995,7 +1997,8 @@ def get_area_slices(self, area_to_cover, shape_divisible_by=None): y_slice = _make_slice_divisible(y_slice, self.height, factor=shape_divisible_by) - return (x_slice, y_slice) + return (check_slice_orientation(x_slice), + check_slice_orientation(y_slice)) def crop_around(self, other_area): """Crop this area around `other_area`.""" diff --git a/pyresample/test/test_utils.py b/pyresample/test/test_utils.py index e7675da6d..80008ed21 100644 --- a/pyresample/test/test_utils.py +++ b/pyresample/test/test_utils.py @@ -645,3 +645,32 @@ def test_norotation_yaml(self): test_area = load_area(f.name, 'regionB') self.assertEqual(test_area.rotation, 0) os.remove(f.name) + + +def test_check_slice_orientation(): + """Test that slicing fix is doing what it should.""" + from pyresample.utils import check_slice_orientation + + # Forward slicing should not be changed + start, stop, step = 0, 10, None + slice_in = slice(start, stop, step) + res = check_slice_orientation(slice_in) + assert res is slice_in + + # Reverse slicing should not be changed if the step is negative + start, stop, step = 10, 0, -1 + slice_in = slice(start, stop, step) + res = check_slice_orientation(slice_in) + assert res is slice_in + + # Reverse slicing should be fixed if step is positive + start, stop, step = 10, 0, 2 + slice_in = slice(start, stop, step) + res = check_slice_orientation(slice_in) + assert res == slice(start, stop, -step) + + # Reverse slicing should be fixed if step is None + start, stop, step = 10, 0, None + slice_in = slice(start, stop, step) + res = check_slice_orientation(slice_in) + assert res == slice(start, stop, -1) diff --git a/pyresample/utils/__init__.py b/pyresample/utils/__init__.py index 70c9c3801..d9324f90a 100644 --- a/pyresample/utils/__init__.py +++ b/pyresample/utils/__init__.py @@ -243,3 +243,13 @@ def recursive_dict_update(d, u): def is_pyproj2(): """Determine whether the current pyproj version is >= 2.0""" return pyproj.__version__ >= '2' + + +def check_slice_orientation(sli): + """Check that the slice is slicing the right way.""" + if sli.start > sli.stop: + if sli.step is None or sli.step > 0: + step = -(sli.step or 1) + sli = slice(sli.start, sli.stop, step) + + return sli