diff --git a/continuous_integration/environment.yaml b/continuous_integration/environment.yaml index df1f9d01a..e0cfb3810 100644 --- a/continuous_integration/environment.yaml +++ b/continuous_integration/environment.yaml @@ -27,3 +27,4 @@ dependencies: - pytest-lazy-fixture - importlib-metadata - sphinx-reredirects + - odc-geo diff --git a/pyresample/geometry.py b/pyresample/geometry.py index 9674f2847..969cbd52a 100644 --- a/pyresample/geometry.py +++ b/pyresample/geometry.py @@ -57,6 +57,11 @@ except ImportError: da = None +try: + import odc.geo as odc_geo +except ModuleNotFoundError: + odc_geo = None + from pyproj import CRS from pyproj.enums import TransformDirection @@ -1998,6 +2003,18 @@ def _cartopy_proj_params(self): return "EPSG:{}".format(self.crs.to_epsg()) return self.crs.to_proj4() + def to_odc_geobox(self): + """Convert AreaDefinition to ODC GeoBox. + + See: https://odc-geo.readthedocs.io/en/latest/ + """ + if odc_geo is None: + raise ModuleNotFoundError("Please install 'odc-geo' to use this method.") + + return odc_geo.geobox.GeoBox.from_bbox(bbox=self.area_extent, crs=self.crs, + resolution=odc_geo.Resolution(x=self.pixel_size_x, y=-self.pixel_size_y), + tight=True) + def create_areas_def(self): """Generate YAML formatted representation of this area. diff --git a/pyresample/test/test_geometry/test_area.py b/pyresample/test/test_geometry/test_area.py index d1aeda7ee..0ff9cb63a 100644 --- a/pyresample/test/test_geometry/test_area.py +++ b/pyresample/test/test_geometry/test_area.py @@ -404,6 +404,45 @@ def test_cartopy_crs_latlon_bounds(self, create_test_area): latlong_crs = area_def.to_cartopy_crs() np.testing.assert_allclose(latlong_crs.bounds, [-180, 180, -90, 90]) + def test_to_odc_geobox_odc_missing(self, monkeypatch, stere_area): + """Test odc-geo not installed.""" + area = stere_area + + with monkeypatch.context() as m: + m.setattr(pyresample.geometry, "odc_geo", None) + + with pytest.raises(ModuleNotFoundError): + area.to_odc_geobox() + + def test_to_odc_geobox(self, stere_area, create_test_area): + """Test conversion from area definition to odc GeoBox.""" + from odc.geo.geobox import GeoBox + + europe = stere_area + seviri = create_test_area( + { + 'proj': 'geos', + 'lon_0': 0.0, + 'a': 6378169.00, + 'b': 6356583.80, + 'h': 35785831.00, + 'units': 'm'}, + 123, + 123, + (-5500000, -5500000, 5500000, 5500000)) + + for area_def in [europe, seviri]: + geobox = area_def.to_odc_geobox() + + assert isinstance(geobox, GeoBox) + + # Affine coefficiants + af = geobox.affine + assert af.a == area_def.pixel_size_x + assert af.e == -area_def.pixel_size_y + assert af.xoff == area_def.area_extent[0] + assert af.yoff == area_def.area_extent[3] + def test_dump(self, create_test_area): """Test exporting area defs.""" from io import StringIO diff --git a/setup.py b/setup.py index a32992196..be4b5f31b 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ requirements.append('importlib_metadata') test_requires = ['rasterio', 'dask', 'xarray', 'cartopy>=0.20.0', 'pillow', 'matplotlib', 'scipy', 'zarr', - 'pytest-lazy-fixtures', 'shapely'] + 'pytest-lazy-fixtures', 'shapely', 'odc-geo'] extras_require = {'numexpr': ['numexpr'], 'quicklook': ['matplotlib', 'cartopy>=0.20.0', 'pillow'], 'rasterio': ['rasterio'], @@ -40,8 +40,14 @@ 'cf': ['xarray'], 'gradient_search': ['shapely'], 'xarray_bilinear': ['xarray', 'dask', 'zarr'], + 'odc-geo': ['odc-geo'], 'tests': test_requires} +all_extras = [] +for extra_deps in extras_require.values(): + all_extras.extend(extra_deps) +extras_require['all'] = list(set(all_extras)) + if sys.platform.startswith("win"): extra_compile_args = [] else: