From 9e01765b36ac7d028d9c32a6614b8b3971787eca Mon Sep 17 00:00:00 2001 From: Martin Raspaud Date: Fri, 26 Jan 2024 16:01:03 +0100 Subject: [PATCH 1/3] Add attrs to future swath definition --- pyresample/future/geometry/swath.py | 36 ++++++++++++++++++++- pyresample/test/test_geometry/test_swath.py | 8 +++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pyresample/future/geometry/swath.py b/pyresample/future/geometry/swath.py index 6c3ed1881..8e91f13c4 100644 --- a/pyresample/future/geometry/swath.py +++ b/pyresample/future/geometry/swath.py @@ -19,4 +19,38 @@ from __future__ import annotations -from pyresample.geometry import CoordinateDefinition, SwathDefinition # noqa +from pyresample.geometry import CoordinateDefinition # noqa +from pyresample.geometry import SwathDefinition as LegacySwathDefinition + + +class SwathDefinition(LegacySwathDefinition): + """Swath defined by lons and lats. + + Parameters + ---------- + lons : numpy array + lats : numpy array + crs: pyproj.CRS, + The CRS to use. longlat on WGS84 by default. + attrs: dict, + A dictionary made to store metadata. + + Attributes + ---------- + shape : tuple + Swath shape + size : int + Number of elements in swath + ndims : int + Swath dimensions + lons : object + Swath lons + lats : object + Swath lats + cartesian_coords : object + Swath cartesian coordinates + """ + + def __init__(self, lons, lats, crs=None, attrs=None): + super().__init__(lons, lats, crs=crs) + self.attrs = attrs or {} diff --git a/pyresample/test/test_geometry/test_swath.py b/pyresample/test/test_geometry/test_swath.py index 5f41c6020..7d21a02ef 100644 --- a/pyresample/test/test_geometry/test_swath.py +++ b/pyresample/test/test_geometry/test_swath.py @@ -462,3 +462,11 @@ def assert_np_dict_allclose(dict1, dict2): np.testing.assert_allclose(val, dict2[key]) except TypeError: assert val == dict2[key] + + +def test_future_swath_has_attrs(): + """Test that future SwathDefinition has attrs.""" + from pyresample.future.geometry import SwathDefinition + lons, lats = _gen_swath_lons_lats() + swath = SwathDefinition(lons, lats) + assert isinstance(swath.attrs, dict) From d6df3a6d94970bf259b33748ab84ca39324fae38 Mon Sep 17 00:00:00 2001 From: Martin Raspaud Date: Thu, 15 Feb 2024 14:19:31 +0100 Subject: [PATCH 2/3] Add nprocs for backwards compatibility --- pyresample/future/geometry/swath.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyresample/future/geometry/swath.py b/pyresample/future/geometry/swath.py index 8e91f13c4..f6824932b 100644 --- a/pyresample/future/geometry/swath.py +++ b/pyresample/future/geometry/swath.py @@ -32,6 +32,8 @@ class SwathDefinition(LegacySwathDefinition): lats : numpy array crs: pyproj.CRS, The CRS to use. longlat on WGS84 by default. + nprocs : int, optional + Number of processor cores to be used for calculations. attrs: dict, A dictionary made to store metadata. @@ -51,6 +53,6 @@ class SwathDefinition(LegacySwathDefinition): Swath cartesian coordinates """ - def __init__(self, lons, lats, crs=None, attrs=None): - super().__init__(lons, lats, crs=crs) + def __init__(self, lons, lats, crs=None, nprocs=1, attrs=None): + super().__init__(lons, lats, crs=crs, nprocs=nprocs) self.attrs = attrs or {} From 5b05353ec51f18ced1ca1a51971d4ee12fe961a4 Mon Sep 17 00:00:00 2001 From: Martin Raspaud Date: Fri, 16 Feb 2024 12:24:20 +0100 Subject: [PATCH 3/3] Remove nproc from future swath def --- pyresample/future/geometry/swath.py | 34 ++++++++++++++++--- pyresample/test/conftest.py | 2 ++ pyresample/test/test_geometry/test_swath.py | 36 +++++++++++++++++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/pyresample/future/geometry/swath.py b/pyresample/future/geometry/swath.py index f6824932b..c3e89de38 100644 --- a/pyresample/future/geometry/swath.py +++ b/pyresample/future/geometry/swath.py @@ -19,7 +19,10 @@ from __future__ import annotations -from pyresample.geometry import CoordinateDefinition # noqa +import numpy as np + +from pyresample.geometry import _get_highest_level_class # noqa +from pyresample.geometry import CoordinateDefinition, DimensionError # noqa from pyresample.geometry import SwathDefinition as LegacySwathDefinition @@ -32,8 +35,6 @@ class SwathDefinition(LegacySwathDefinition): lats : numpy array crs: pyproj.CRS, The CRS to use. longlat on WGS84 by default. - nprocs : int, optional - Number of processor cores to be used for calculations. attrs: dict, A dictionary made to store metadata. @@ -53,6 +54,29 @@ class SwathDefinition(LegacySwathDefinition): Swath cartesian coordinates """ - def __init__(self, lons, lats, crs=None, nprocs=1, attrs=None): - super().__init__(lons, lats, crs=crs, nprocs=nprocs) + def __init__(self, lons, lats, crs=None, attrs=None): + super().__init__(lons, lats, crs=crs) self.attrs = attrs or {} + + def __getitem__(self, key): + """Slice a 2D geographic definition.""" + y_slice, x_slice = key + return self.__class__( + lons=self.lons[y_slice, x_slice], + lats=self.lats[y_slice, x_slice], + attrs=self.attrs + ) + + def concatenate(self, other): + """Concatenate coordinate definitions.""" + if self.ndim != other.ndim: + raise DimensionError(('Unable to concatenate %sD and %sD ' + 'geometries') % (self.ndim, other.ndim)) + if self.crs != other.crs: + raise ValueError("Incompatible CRSs.") + klass = _get_highest_level_class(self, other) + lons = np.concatenate((self.lons, other.lons)) + lats = np.concatenate((self.lats, other.lats)) + attrs = self.attrs.copy() + attrs.update(other.attrs) + return klass(lons, lats, attrs=attrs) diff --git a/pyresample/test/conftest.py b/pyresample/test/conftest.py index 6a12ca90a..04df36fc1 100644 --- a/pyresample/test/conftest.py +++ b/pyresample/test/conftest.py @@ -76,6 +76,8 @@ def create_test_swath(swath_class): """ def _create_test_swath(lons, lats, **kwargs): + if swath_class is SwathDefinition: + kwargs.pop("nproc", None) return swath_class(lons, lats, **kwargs) return _create_test_swath diff --git a/pyresample/test/test_geometry/test_swath.py b/pyresample/test/test_geometry/test_swath.py index 7d21a02ef..5aedd386a 100644 --- a/pyresample/test/test_geometry/test_swath.py +++ b/pyresample/test/test_geometry/test_swath.py @@ -468,5 +468,37 @@ def test_future_swath_has_attrs(): """Test that future SwathDefinition has attrs.""" from pyresample.future.geometry import SwathDefinition lons, lats = _gen_swath_lons_lats() - swath = SwathDefinition(lons, lats) - assert isinstance(swath.attrs, dict) + attrs = dict(meta="data") + swath = SwathDefinition(lons, lats, attrs=attrs) + assert swath.attrs == attrs + + +def test_future_swath_slice_has_attrs(): + """Test that future sliced SwathDefinition has attrs.""" + from pyresample.future.geometry import SwathDefinition + lons, lats = _gen_swath_lons_lats() + attrs = dict(meta="data") + swath = SwathDefinition(lons, lats, attrs=attrs)[0:1, 0:1] + assert swath.attrs == attrs + + +def test_future_swath_concat_has_attrs(): + """Test that future concatenated SwathDefinition has attrs.""" + from pyresample.future.geometry import SwathDefinition + lons, lats = _gen_swath_lons_lats() + attrs1 = dict(meta1="data") + swath1 = SwathDefinition(lons, lats, attrs=attrs1) + attrs2 = dict(meta2="data") + swath2 = SwathDefinition(lons, lats, attrs=attrs2) + swath = swath1.concatenate(swath2) + assert swath.attrs == dict(meta1="data", meta2="data") + + +def test_future_swath_concat_fails_on_different_crs(): + """Test that future concatenated SwathDefinition must have the same crs.""" + from pyresample.future.geometry import SwathDefinition + lons, lats = _gen_swath_lons_lats() + swath1 = SwathDefinition(lons, lats, crs="mycrs") + swath2 = SwathDefinition(lons, lats, crs="myothercrs") + with pytest.raises(ValueError, match="Incompatible CRSs."): + _ = swath1.concatenate(swath2)