From ac39b4d32cbe9cbcfda48eb7d78dd0f30f51e81f Mon Sep 17 00:00:00 2001 From: "Tonneau Anne-Sophie (CELAD)" Date: Tue, 24 Mar 2026 14:26:32 +0100 Subject: [PATCH 1/4] chore: pyinterp version 2026.2.0 --- .github/workflows/doc.yaml | 2 +- .github/workflows/tests.yaml | 4 ++-- pyproject.toml | 8 ++++++-- src/fcollections/geometry/_box.py | 19 +++++++++---------- src/fcollections/geometry/_distances.py | 17 ++++++++++++++--- .../geometry/_track_orientation.py | 2 +- tests/geometry/test_box.py | 6 +++--- tests/geometry/test_distances.py | 2 +- 8 files changed, 37 insertions(+), 23 deletions(-) diff --git a/.github/workflows/doc.yaml b/.github/workflows/doc.yaml index 71d1878..5feb8b2 100644 --- a/.github/workflows/doc.yaml +++ b/.github/workflows/doc.yaml @@ -56,7 +56,7 @@ jobs: beautifulsoup4 shapely geopandas - pyinterp<2026.2.0 + pyinterp>=2026.2.0 dask - name: Install package (for autodoc) shell: bash -l {0} 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 ( diff --git a/tests/geometry/test_distances.py b/tests/geometry/test_distances.py index e005dff..8f2406c 100644 --- a/tests/geometry/test_distances.py +++ b/tests/geometry/test_distances.py @@ -94,7 +94,7 @@ def test_great_circle_distances_axis( assert np.array_equal(computedT.T, computed) -def test_spheroid_distances_along_axis_axis( +def test_spheroid_distances_along_axis( longitudes: np_t.NDArray[np.float64], latitudes: np_t.NDArray[np.float64], ): From 95192314cbb9388504bef2f988cae128899a1e74 Mon Sep 17 00:00:00 2001 From: rchevrier Date: Tue, 12 May 2026 10:34:13 +0000 Subject: [PATCH 2/4] Switch to pyinterp 2026.4.0 version --- .github/workflows/doc.yaml | 2 +- .github/workflows/tests.yaml | 4 ++-- pyproject.toml | 2 +- src/fcollections/geometry/_distances.py | 20 ++++++-------------- tests/geometry/test_distances.py | 2 +- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/.github/workflows/doc.yaml b/.github/workflows/doc.yaml index 5feb8b2..6787498 100644 --- a/.github/workflows/doc.yaml +++ b/.github/workflows/doc.yaml @@ -56,7 +56,7 @@ jobs: beautifulsoup4 shapely geopandas - pyinterp>=2026.2.0 + pyinterp>=2026.4.0 dask - name: Install package (for autodoc) shell: bash -l {0} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e3caafd..fa17f3d 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.4.0 dask - name: Install python dependencies shell: bash -el {0} @@ -94,7 +94,7 @@ jobs: pyftpdlib shapely geopandas - pyinterp>=2026.2.0 + pyinterp>=2026.4.0 dask - name: Install python dependencies shell: bash -el {0} diff --git a/pyproject.toml b/pyproject.toml index f18c775..fa167ba 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.4.0", "dask", "numba"] doc = ["cartopy", "matplotlib", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx-book-theme", "myst-nb"] diff --git a/src/fcollections/geometry/_distances.py b/src/fcollections/geometry/_distances.py index 8df50de..417536e 100644 --- a/src/fcollections/geometry/_distances.py +++ b/src/fcollections/geometry/_distances.py @@ -1,8 +1,8 @@ """Adapts the distance computation to multiple data shapes.""" import numpy as np -from pyinterp.geometry.geographic import Point, Spheroid -from pyinterp.geometry.geographic.algorithms import distance +from pyinterp.geometry.geographic import MultiPoint, Spheroid +from pyinterp.geometry.geographic.algorithms import for_each_point_pairwise_distance from fcollections.utilities.reshape import slice_along_axis @@ -82,16 +82,6 @@ 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, @@ -105,8 +95,10 @@ 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(), spheroid=wgs + return for_each_point_pairwise_distance( + MultiPoint(lon0.ravel(), lat0.ravel()), + MultiPoint(lon1.ravel(), lat1.ravel()), + spheroid=wgs, ).reshape(lon0.shape) diff --git a/tests/geometry/test_distances.py b/tests/geometry/test_distances.py index 8f2406c..e005dff 100644 --- a/tests/geometry/test_distances.py +++ b/tests/geometry/test_distances.py @@ -94,7 +94,7 @@ def test_great_circle_distances_axis( assert np.array_equal(computedT.T, computed) -def test_spheroid_distances_along_axis( +def test_spheroid_distances_along_axis_axis( longitudes: np_t.NDArray[np.float64], latitudes: np_t.NDArray[np.float64], ): From f57f7a4623a984e44353e7c1cb005b6074128e71 Mon Sep 17 00:00:00 2001 From: rchevrier Date: Tue, 12 May 2026 10:36:54 +0000 Subject: [PATCH 3/4] Try without pytest warning --- pyproject.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fa167ba..ebafbe5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,8 +70,4 @@ filterwarnings = [ # Can be safely ignored according to # https://github.com/Unidata/netcdf4-python/issues/1354 "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", ] From cb46731b768061525cc7f60f6bd57409c15efaad Mon Sep 17 00:00:00 2001 From: rchevrier Date: Tue, 12 May 2026 10:49:34 +0000 Subject: [PATCH 4/4] Update install documentation --- docs/install.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/install.rst b/docs/install.rst index 595b4dc..d4fe89b 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -24,7 +24,7 @@ How to install .. code:: bash - conda install files_collections shapely geopandas pyinterp dask numba -c conda-forge + conda install files_collections shapely geopandas 'pyinterp>=2026.4.0' dask numba -c conda-forge This will install a set of dependencies similar to ``python -m pip install files-collections[geo]`` @@ -66,19 +66,19 @@ These optional dependencies and their associated functionalities are listed below. -+--------------+-----------------------------------------------------------------------------------------+ -| Dependency | Description | -+==============+=========================================================================================+ -| `dask`_ | Activate ``map()`` method in collections, Enable parallel file reading | -+--------------+-----------------------------------------------------------------------------------------+ -| `geopandas`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | -+--------------+-----------------------------------------------------------------------------------------+ -| `numba`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | -+--------------+-----------------------------------------------------------------------------------------+ -| `pyinterp`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | -+--------------+-----------------------------------------------------------------------------------------+ -| `shapely`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | -+--------------+-----------------------------------------------------------------------------------------+ ++--------------+-----------------------------------------------------------------------------------------+-------------+ +| Dependency | Description | Version | ++==============+=========================================================================================+=============+ +| `dask`_ | Activate ``map()`` method in collections, Enable parallel file reading | | ++--------------+-----------------------------------------------------------------------------------------+-------------+ +| `geopandas`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | | ++--------------+-----------------------------------------------------------------------------------------+-------------+ +| `numba`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | | ++--------------+-----------------------------------------------------------------------------------------+-------------+ +| `pyinterp`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | >= 2026.4.0 | ++--------------+-----------------------------------------------------------------------------------------+-------------+ +| `shapely`_ | Enable geometry intersection, introduce the ``bbox`` argument in the ``query()`` method | | ++--------------+-----------------------------------------------------------------------------------------+-------------+ .. _dask: https://www.dask.org/ .. _geopandas: https://geopandas.org/en/stable/