diff --git a/.github/workflows/doc.yaml b/.github/workflows/doc.yaml index 3b3f99d..8018255 100644 --- a/.github/workflows/doc.yaml +++ b/.github/workflows/doc.yaml @@ -52,16 +52,16 @@ jobs: beautifulsoup4 shapely geopandas - pyinterp<2026.2.0 + pyinterp>=2026.2.0 dask - - name: Install package (for autodoc) - shell: bash -l {0} - run: | - pip install -e . - name: Install AVISO Client shell: bash -l {0} run: | pip install altimetry-downloader-aviso + - name: Install package (for autodoc) + shell: bash -l {0} + run: | + pip install -e . - name: Restore cached sample data uses: actions/cache@v4 id: restore_samples diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index a2caac2..e3caafd 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -40,7 +40,7 @@ jobs: pyftpdlib shapely geopandas - pyinterp<2026.2.0 + pyinterp>=2026.2.0 dask - name: Install python dependencies shell: bash -el {0} @@ -94,7 +94,7 @@ jobs: pyftpdlib shapely geopandas - pyinterp<2026.2.0 + pyinterp>=2026.2.0 dask - name: Install python dependencies shell: bash -el {0} diff --git a/pyproject.toml b/pyproject.toml index 2b0efed..f18c775 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ Repository='https://github.com/robin-cls/fcollections' [project.optional-dependencies] testing = ["pytest", "pytest-cov", "sympy", "beautifulsoup4", "pyftpdlib", "pyasynchat"] -geo = ["shapely", "geopandas", "pyinterp<2026.2.0", "dask", "numba"] +geo = ["shapely", "geopandas", "pyinterp>=2026.2.0", "dask", "numba"] doc = ["cartopy", "matplotlib", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx-book-theme", "myst-nb"] @@ -69,5 +69,9 @@ filterwarnings = [ "error", # Can be safely ignored according to # https://github.com/Unidata/netcdf4-python/issues/1354 - "ignore:numpy\\.ndarray size changed" + "ignore:numpy\\.ndarray size changed", + # Can be safely ignored according to + # https://github.com/giampaolo/pyftpdlib/issues/560 + "ignore:The asyncore module is deprecated:DeprecationWarning", + "ignore:The asynchat module is deprecated:DeprecationWarning", ] diff --git a/src/fcollections/geometry/_box.py b/src/fcollections/geometry/_box.py index 03ed482..31f08d5 100644 --- a/src/fcollections/geometry/_box.py +++ b/src/fcollections/geometry/_box.py @@ -1,9 +1,10 @@ +import numpy as np import pyinterp as pyi -import pyinterp.geodetic as pyi_geod import pyinterp.geohash as pyi_geoh +import pyinterp.geometry.geographic as pyi_geom -def expand_box(box: pyi_geod.Box, precision: int) -> pyi_geod.Box: +def expand_box(box: pyi_geom.Box, precision: int) -> pyi_geom.Box: """Expand a geohash box with a given precision. The method looks for the geohashes of the input box's corners with a given @@ -12,24 +13,24 @@ def expand_box(box: pyi_geod.Box, precision: int) -> pyi_geod.Box: Parameters ---------- - box: pyinterp.geodetic.Box + box: geographic.Box the box to expand precision: int the precision to expand the box to Returns ------- - a pyinterp.geodetic.Box expanded to a lower precision + a geographic.Box expanded to a lower precision """ geohashes = pyi_geoh.encode( - [box.min_corner.lon, box.max_corner.lon], - [box.min_corner.lat, box.max_corner.lat], + np.array([box.min_corner.lon, box.max_corner.lon]), + np.array([box.min_corner.lat, box.max_corner.lat]), precision=precision, ) min_lon, min_lat, max_lon, max_lat = (None,) * 4 for g in geohashes: - box = pyi.GeoHash.from_string(g).bounding_box() + box = pyi_geoh.GeoHash.from_string(g.decode()).bounding_box() min_lon = ( min(box.min_corner.lon, min_lon) if min_lon is not None @@ -50,6 +51,4 @@ def expand_box(box: pyi_geod.Box, precision: int) -> pyi_geod.Box: if max_lat is not None else box.max_corner.lat ) - return pyi_geod.Box( - pyi_geod.Point(min_lon, min_lat), pyi_geod.Point(max_lon, max_lat) - ) + return pyi_geom.Box(min_corner=(min_lon, min_lat), max_corner=(max_lon, max_lat)) diff --git a/src/fcollections/geometry/_distances.py b/src/fcollections/geometry/_distances.py index af6dde3..8df50de 100644 --- a/src/fcollections/geometry/_distances.py +++ b/src/fcollections/geometry/_distances.py @@ -1,7 +1,8 @@ """Adapts the distance computation to multiple data shapes.""" import numpy as np -from pyinterp.geodetic import Spheroid, coordinate_distances +from pyinterp.geometry.geographic import Point, Spheroid +from pyinterp.geometry.geographic.algorithms import distance from fcollections.utilities.reshape import slice_along_axis @@ -81,6 +82,16 @@ def distances_along_axis( return distances_along_axis +def _coordinate_distances(lon1, lat1, lon2, lat2, spheroid: Spheroid = Spheroid()): + distances = np.array( + [ + distance(Point(lo1, la1), Point(lo2, la2), spheroid=spheroid) + for lo1, la1, lo2, la2 in zip(lon1, lat1, lon2, lat2) + ] + ) + return distances + + def _spheroid_distances_along_axis( longitudes: np.ndarray, latitudes: np.ndarray, @@ -94,8 +105,8 @@ def _spheroid_distances_along_axis( lat1 = slice_along_axis(latitudes, axis, slice(1, None)) # Compute distance on ellipsoid - return coordinate_distances( - lon0.ravel(), lat0.ravel(), lon1.ravel(), lat1.ravel(), wgs=wgs + return _coordinate_distances( + lon0.ravel(), lat0.ravel(), lon1.ravel(), lat1.ravel(), spheroid=wgs ).reshape(lon0.shape) diff --git a/src/fcollections/geometry/_track_orientation.py b/src/fcollections/geometry/_track_orientation.py index e52f1ff..102f877 100644 --- a/src/fcollections/geometry/_track_orientation.py +++ b/src/fcollections/geometry/_track_orientation.py @@ -3,7 +3,7 @@ import typing as tp import numpy as np -from pyinterp.geodetic import Spheroid +from pyinterp.geometry.geographic import Spheroid from fcollections.utilities.reshape import slice_along_axis diff --git a/tests/geometry/test_box.py b/tests/geometry/test_box.py index d5b7909..4c0a7ee 100644 --- a/tests/geometry/test_box.py +++ b/tests/geometry/test_box.py @@ -1,4 +1,4 @@ -import pyinterp.geodetic as pyi_geod +import pyinterp.geometry.geographic as pyi_geom import pytest from fcollections.geometry import expand_box @@ -18,8 +18,8 @@ def test_expand_box( expected: tuple[tuple[float, float], tuple[float, float]], ): """Test box expansion with a given precision.""" - box = pyi_geod.Box(pyi_geod.Point(*box[0]), pyi_geod.Point(*box[1])) - expected = pyi_geod.Box(pyi_geod.Point(*expected[0]), pyi_geod.Point(*expected[1])) + box = pyi_geom.Box(min_corner=box[0], max_corner=box[1]) + expected = pyi_geom.Box(min_corner=expected[0], max_corner=expected[1]) actual = expand_box(box, precision=3) assert (