[Git][debian-gis-team/python-geotiepoints][upstream] New upstream version 1.7.0
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Tue Dec 26 07:53:32 GMT 2023
Antonio Valentino pushed to branch upstream at Debian GIS Project / python-geotiepoints
Commits:
2e9e4afc by Antonio Valentino at 2023-11-22T07:24:29+00:00
New upstream version 1.7.0
- - - - -
23 changed files:
- + .github/dependabot.yml
- .github/workflows/ci.yaml
- .github/workflows/deploy.yaml
- CHANGELOG.md
- continuous_integration/environment.yaml
- + cython_test.pyx
- + cython_test2.pyx
- doc/source/conf.py
- geotiepoints/__init__.py
- geotiepoints/_modis_interpolator.pyx
- geotiepoints/_modis_utils.pxd
- geotiepoints/_modis_utils.pyx
- geotiepoints/_simple_modis_interpolator.pyx
- geotiepoints/interpolator.py
- geotiepoints/modisinterpolator.py
- geotiepoints/multilinear.py
- geotiepoints/multilinear_cython.pyx
- geotiepoints/tests/__init__.py
- geotiepoints/tests/test_geointerpolator.py
- geotiepoints/tests/test_interpolator.py
- geotiepoints/version.py
- pyproject.toml
- setup.py
Changes:
=====================================
.github/dependabot.yml
=====================================
@@ -0,0 +1,11 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "github-actions" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
=====================================
.github/workflows/ci.yaml
=====================================
@@ -7,13 +7,13 @@ jobs:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental }}
strategy:
- fail-fast: true
+ fail-fast: false
matrix:
os: ["windows-latest", "ubuntu-latest", "macos-latest"]
- python-version: ["3.8", "3.9", "3.10"]
+ python-version: ["3.9", "3.11", "3.12"]
experimental: [false]
include:
- - python-version: "3.9"
+ - python-version: "3.12"
os: "ubuntu-latest"
experimental: true
@@ -25,17 +25,18 @@ jobs:
steps:
- name: Checkout source
- uses: actions/checkout at v2
+ uses: actions/checkout at v4
- name: Setup Conda Environment
uses: conda-incubator/setup-miniconda at v2
with:
- miniconda-version: "latest"
+ miniforge-variant: Mambaforge
+ miniforge-version: latest
+ use-mamba: true
+ channel-priority: strict
python-version: ${{ matrix.python-version }}
- mamba-version: "*"
- channels: conda-forge,defaults
- environment-file: continuous_integration/environment.yaml
activate-environment: test-environment
+ environment-file: continuous_integration/environment.yaml
- name: Install unstable dependencies
if: matrix.experimental == true
@@ -74,15 +75,14 @@ jobs:
# cd doc && mkdir doctest && sphinx-build -E -n -b doctest ./source ./doctest && cd ..
- name: Upload unittest coverage to Codecov
- uses: codecov/codecov-action at v1
+ uses: codecov/codecov-action at v3
with:
flags: unittests
file: ./coverage.xml
env_vars: OS,PYTHON_VERSION,UNSTABLE
- name: Coveralls Parallel
- # See https://github.com/AndreMiras/coveralls-python-action/pull/16
- uses: djhoese/coveralls-python-action at feature-cython-coverage
+ uses: AndreMiras/coveralls-python-action at develop
with:
flag-name: run-${{ matrix.test_number }}
parallel: true
@@ -93,8 +93,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
- # See https://github.com/AndreMiras/coveralls-python-action/pull/16
- uses: djhoese/coveralls-python-action at feature-cython-coverage
+ uses: AndreMiras/coveralls-python-action at develop
with:
parallel-finished: true
=====================================
.github/workflows/deploy.yaml
=====================================
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source
- uses: actions/checkout at v2
+ uses: actions/checkout at v4
- name: Create sdist
shell: bash -l {0}
@@ -22,7 +22,7 @@ jobs:
python -m build -s
- name: Upload sdist to build artifacts
- uses: actions/upload-artifact at v2
+ uses: actions/upload-artifact at v3
with:
name: sdist
path: dist/*.tar.gz
@@ -44,12 +44,12 @@ jobs:
docker-image: manylinux2014_x86_64
steps:
- - uses: actions/checkout at v2
+ - uses: actions/checkout at v4
- run: |
git fetch --prune --unshallow
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python at v1
+ uses: actions/setup-python at v4
with:
python-version: "${{ matrix.python-version }}"
@@ -83,7 +83,7 @@ jobs:
python -c "import geotiepoints; assert 'unknown' not in geotiepoints.__version__, 'incorrect version found'"
- name: Upload wheel(s) as build artifacts
- uses: actions/upload-artifact at v2
+ uses: actions/upload-artifact at v3
with:
name: wheels
path: dist/*.whl
@@ -93,18 +93,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download sdist artifact
- uses: actions/download-artifact at v2
+ uses: actions/download-artifact at v3
with:
name: sdist
path: dist
- name: Download wheels artifact
- uses: actions/download-artifact at v2
+ uses: actions/download-artifact at v3
with:
name: wheels
path: dist
- name: Publish package to PyPI
if: github.event.action != 'published'
- uses: pypa/gh-action-pypi-publish at v1.4.1
+ uses: pypa/gh-action-pypi-publish at v1.8.10
with:
user: __token__
password: ${{ secrets.test_pypi_password }}
@@ -115,18 +115,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download sdist artifact
- uses: actions/download-artifact at v2
+ uses: actions/download-artifact at v3
with:
name: sdist
path: dist
- name: Download wheels artifact
- uses: actions/download-artifact at v2
+ uses: actions/download-artifact at v3
with:
name: wheels
path: dist
- name: Publish package to PyPI
if: github.event.action == 'published'
- uses: pypa/gh-action-pypi-publish at v1.4.1
+ uses: pypa/gh-action-pypi-publish at v1.8.10
with:
user: __token__
password: ${{ secrets.pypi_password }}
=====================================
CHANGELOG.md
=====================================
@@ -1,3 +1,30 @@
+## Version 1.7.0 (2023/11/21)
+
+### Issues Closed
+
+* [Issue 56](https://github.com/pytroll/python-geotiepoints/issues/56) - Upgrade to Cython 3.0 and check annotations ([PR 57](https://github.com/pytroll/python-geotiepoints/pull/57) by [@djhoese](https://github.com/djhoese))
+* [Issue 47](https://github.com/pytroll/python-geotiepoints/issues/47) - Help wanted: verify the interpolation of MERSI-2 1000M GEO to 250M GEO
+* [Issue 23](https://github.com/pytroll/python-geotiepoints/issues/23) - Docstring headers still include authors.
+* [Issue 21](https://github.com/pytroll/python-geotiepoints/issues/21) - Interpolation of MODIS lat/lons is incorrect
+* [Issue 18](https://github.com/pytroll/python-geotiepoints/issues/18) - Make the interpolators dask-compatible
+
+In this release 5 issues were closed.
+
+### Pull Requests Merged
+
+#### Bugs fixed
+
+* [PR 60](https://github.com/pytroll/python-geotiepoints/pull/60) - Add missing noexcept on cython function
+* [PR 46](https://github.com/pytroll/python-geotiepoints/pull/46) - Fix tests on i386 architectures
+
+#### Features added
+
+* [PR 61](https://github.com/pytroll/python-geotiepoints/pull/61) - Fix geogrid chunking to accept "auto" and to preserve dtype
+* [PR 57](https://github.com/pytroll/python-geotiepoints/pull/57) - Upgrade to Cython 3+ in building ([56](https://github.com/pytroll/python-geotiepoints/issues/56))
+
+In this release 4 pull requests were closed.
+
+
## Version 1.6.0 (2023/03/17)
=====================================
continuous_integration/environment.yaml
=====================================
@@ -4,18 +4,15 @@ channels:
dependencies:
- xarray
- dask
- - distributed
- - toolz
- Cython
- sphinx
- pillow
- pyyaml
- coveralls
- coverage
- - codecov
- scipy
- h5py
- pytest
- pytest-cov
- - pyproj
+ - pyproj >=3
- pyresample
=====================================
cython_test.pyx
=====================================
@@ -0,0 +1,17 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
+cimport cython
+import numpy as np
+cimport numpy as np
+
+np.import_array()
+
+def test_func():
+ cdef np.ndarray[float, ndim=2] arr = np.zeros((5, 5), dtype=np.float32)
+ cdef float[:, ::1] arr_view = arr
+ _run(arr_view)
+
+cdef void _run(float[:, ::1] arr_view) noexcept nogil:
+ cdef float[:, :] tmp = _get_upper_left_corner(arr_view)
+
+cdef inline float[:, :] _get_upper_left_corner(float[:, ::1] arr) noexcept nogil:
+ return arr[:1, :1]
=====================================
cython_test2.pyx
=====================================
@@ -0,0 +1,34 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
+cimport cython
+import numpy as np
+cimport numpy as np
+
+np.import_array()
+
+def test_func():
+ cdef np.ndarray[float, ndim=2] arr = np.zeros((5, 5), dtype=np.float32)
+ cdef float[:, ::1] arr_view = arr
+ t = Test(5.0)
+ t.call_me(arr_view)
+
+
+cdef class Test:
+
+ cdef float _a
+
+ def __cinit__(self, float a):
+ self._a = a
+
+ cdef void call_me(self, float[:, ::1] my_arr) noexcept:
+ with nogil:
+ self._call_me(my_arr)
+
+ cdef void _call_me(self, float[:, ::1] my_arr) noexcept nogil:
+ cdef Py_ssize_t idx
+ cdef float[:, :] my_arr2 = _get_upper_left_corner(my_arr)
+ for idx in range(my_arr2.shape[0]):
+ my_arr2[idx, 0] = self._a
+
+
+cdef inline float[:, :] _get_upper_left_corner(float[:, ::1] arr) noexcept nogil:
+ return arr[:3, :3]
=====================================
doc/source/conf.py
=====================================
@@ -74,7 +74,7 @@ master_doc = 'index'
# General information about the project.
project = u'python-geotiepoints'
-copyright = u'2012-%d, Pytroll Team' % datetime.utcnow().year # noqa
+copyright = u'2012-%d, Python-geotiepoints Developers' % datetime.utcnow().year # noqa
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
=====================================
geotiepoints/__init__.py
=====================================
@@ -1,29 +1,18 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2010-2018.
-
-# Author(s):
-
-# Adam Dybbroe <adam.dybbroe at smhise>
-# Martin Raspaud <martin.raspaud at smhi.se>
-# Panu Lahtinen <panu.lahtinen at fmi.fi>
-
+# Copyright (c) 2010-2018 Python-geotiepoints developers
+#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-
+#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""Interpolation of geographical tiepoints.
-"""
+"""Interpolation of geographical tiepoints."""
from multiprocessing import Pool
=====================================
geotiepoints/_modis_interpolator.pyx
=====================================
@@ -1,3 +1,4 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
cimport cython
from ._modis_utils cimport lonlat2xyz, xyz2lonlat, floating, deg2rad
from .simple_modis_interpolator import scanline_mapblocks
@@ -10,6 +11,8 @@ DEF R = 6370.997
# Aqua altitude in km
DEF H = 709.0
+np.import_array()
+
@scanline_mapblocks
def interpolate(
@@ -35,12 +38,8 @@ def interpolate(
return interp.interpolate(lon1, lat1, satz1)
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
- at cython.initializedcheck(False)
cdef void _compute_expansion_alignment(floating[:, :] satz_a, floating [:, :] satz_b, int scan_width,
- floating[:, ::1] c_expansion, floating[:, ::1] c_alignment) nogil:
+ floating[:, ::1] c_expansion, floating[:, ::1] c_alignment) noexcept nogil:
"""Fill in expansion and alignment.
Input angles should be in degrees and will be converted to radians.
@@ -71,48 +70,24 @@ cdef void _compute_expansion_alignment(floating[:, :] satz_a, floating [:, :] sa
c_alignment[i, j] = 4 * e * sin(zeta) / denominator
-cdef inline floating _compute_phi(floating zeta) nogil:
+cdef inline floating _compute_phi(floating zeta) noexcept nogil:
return asin(R * sin(zeta) / (R + H))
-cdef inline floating _compute_theta(floating zeta, floating phi) nogil:
+cdef inline floating _compute_theta(floating zeta, floating phi) noexcept nogil:
return zeta - phi
-cdef inline floating _compute_zeta(floating phi) nogil:
+cdef inline floating _compute_zeta(floating phi) noexcept nogil:
return asin((R + H) * sin(phi) / R)
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
- at cython.initializedcheck(False)
-cdef inline floating[:, :] _get_upper_left_corner(floating[:, ::1] arr) nogil:
- return arr[:-1, :-1]
-
-
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
- at cython.initializedcheck(False)
-cdef inline floating[:, :] _get_upper_right_corner(floating[:, ::1] arr) nogil:
- return arr[:-1, 1:]
-
-
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
- at cython.initializedcheck(False)
-cdef inline floating[:, :] _get_lower_right_corner(floating[:, ::1] arr) nogil:
- return arr[1:, 1:]
+cdef inline floating[:, :] _get_upper_left_corner(floating[:, ::1] arr) noexcept nogil:
+ return arr[:arr.shape[0] - 1, :arr.shape[1] - 1]
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
- at cython.initializedcheck(False)
-cdef inline floating[:, :] _get_lower_left_corner(floating[:, ::1] arr) nogil:
- return arr[1:, :-1]
+cdef inline floating[:, :] _get_upper_right_corner(floating[:, ::1] arr) noexcept nogil:
+ return arr[:arr.shape[0] - 1, 1:]
cdef class MODISInterpolator:
@@ -132,8 +107,6 @@ cdef class MODISInterpolator:
cdef int _fine_resolution
cdef Py_ssize_t _factor_5km
- @cython.cdivision(True)
- @cython.wraparound(False)
def __cinit__(self, unsigned int coarse_resolution, unsigned int fine_resolution, unsigned int coarse_scan_width=0):
if coarse_resolution == 1000:
self._coarse_scan_length = 10
@@ -154,11 +127,7 @@ cdef class MODISInterpolator:
# partial rows/columns to repeat: 5km->1km => 2, 5km->500m => 4, 5km->250m => 8
self._factor_5km = self._fine_pixels_per_coarse_pixel // self._coarse_pixels_per_1km * 2
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
- cdef interpolate(
+ cdef tuple interpolate(
self,
np.ndarray[floating, ndim=2] lon1,
np.ndarray[floating, ndim=2] lat1,
@@ -238,15 +207,11 @@ cdef class MODISInterpolator:
x, y = self._get_coords_5km()
return x, y
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _get_coords_1km(
self,
floating[::1] x_view,
floating[::1] y_view,
- ) nogil:
+ ) noexcept nogil:
cdef unsigned int scan_idx
cdef int i
cdef int fine_idx
@@ -263,9 +228,7 @@ cdef class MODISInterpolator:
for i in range(self._fine_pixels_per_coarse_pixel):
x_view[(self._fine_scan_width - self._fine_pixels_per_coarse_pixel) + i] = self._fine_pixels_per_coarse_pixel + i
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.initializedcheck(False)
+ @cython.wraparound(True)
cdef tuple _get_coords_5km(self):
cdef np.ndarray[np.float32_t, ndim=1] y = np.arange(self._fine_pixels_per_coarse_pixel * self._coarse_scan_length, dtype=np.float32) - 2
cdef np.ndarray[np.float32_t, ndim=1] x = (np.arange(self._fine_scan_width, dtype=np.float32) - 2) % self._fine_pixels_per_coarse_pixel
@@ -285,10 +248,6 @@ cdef class MODISInterpolator:
x[-1] = 11
return x, y
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _interpolate_lons_lats(self,
unsigned int scans,
floating[:, ::1] coarse_lons,
@@ -306,7 +265,7 @@ cdef class MODISInterpolator:
floating[:, :, ::1] fine_xyz,
floating[:, ::1] fine_lons,
floating[:, ::1] fine_lats,
- ) nogil:
+ ) noexcept nogil:
cdef floating[:, ::1] lons_scan, lats_scan, satz_scan
cdef floating[:, ::1] new_lons_scan, new_lats_scan
cdef Py_ssize_t scan_idx
@@ -333,10 +292,6 @@ cdef class MODISInterpolator:
xyz2lonlat(fine_xyz, new_lons_scan, new_lats_scan)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _get_atrack_ascan(
self,
floating[:, ::1] satz,
@@ -348,7 +303,7 @@ cdef class MODISInterpolator:
floating[:, ::1] c_ali_fine,
floating[:, ::1] a_track,
floating[:, ::1] a_scan
- ) nogil:
+ ) noexcept nogil:
cdef floating[:, :] satz_a_view = _get_upper_left_corner(satz)
cdef floating[:, :] satz_b_view = _get_upper_right_corner(satz)
cdef Py_ssize_t scan_idx
@@ -370,10 +325,6 @@ cdef class MODISInterpolator:
c_exp_fine, c_ali_fine,
a_track, a_scan)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _calculate_atrack_ascan(
self,
floating[::1] coords_x,
@@ -382,7 +333,7 @@ cdef class MODISInterpolator:
floating[:, ::1] c_ali_full,
floating[:, ::1] a_track,
floating[:, ::1] a_scan,
- ) nogil:
+ ) noexcept nogil:
cdef Py_ssize_t i, j
cdef floating s_s, s_t
for j in range(coords_y.shape[0]):
@@ -392,10 +343,6 @@ cdef class MODISInterpolator:
a_track[j, i] = s_t
a_scan[j, i] = s_s + s_s * (1 - s_s) * c_exp_full[j, i] + s_t * (1 - s_t) * c_ali_full[j, i]
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _compute_fine_xyz(
self,
floating[:, ::1] a_track_view,
@@ -406,14 +353,14 @@ cdef class MODISInterpolator:
floating[:, ::1] data_tiepoint_c_view,
floating[:, ::1] data_tiepoint_d_view,
floating[:, :, ::1] xyz_comp_view,
- ) nogil:
+ ) noexcept nogil:
cdef Py_ssize_t k
cdef floating[:, :] comp_a_view, comp_b_view, comp_c_view, comp_d_view
for k in range(3): # xyz
- comp_a_view = xyz_view[:-1, :-1, k] # upper left
- comp_b_view = xyz_view[:-1, 1:, k] # upper right
+ comp_a_view = xyz_view[:xyz_view.shape[0] - 1, :xyz_view.shape[1] - 1, k] # upper left
+ comp_b_view = xyz_view[:xyz_view.shape[0] - 1, 1:, k] # upper right
comp_c_view = xyz_view[1:, 1:, k] # lower right
- comp_d_view = xyz_view[1:, :-1, k] # lower left
+ comp_d_view = xyz_view[1:, :xyz_view.shape[1] - 1, k] # lower left
self._expand_tiepoint_array(comp_a_view, data_tiepoint_a_view)
self._expand_tiepoint_array(comp_b_view, data_tiepoint_b_view)
self._expand_tiepoint_array(comp_c_view, data_tiepoint_c_view)
@@ -429,10 +376,6 @@ cdef class MODISInterpolator:
k,
)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _compute_fine_xyz_component(
self,
floating[:, ::1] a_track_view,
@@ -443,7 +386,7 @@ cdef class MODISInterpolator:
floating[:, ::1] data_d_2d_view,
floating[:, :, ::1] xyz_comp_view,
Py_ssize_t k,
- ) nogil:
+ ) noexcept nogil:
cdef Py_ssize_t i, j
cdef floating scan1_tmp, scan2_tmp, atrack1, ascan1
for i in range(a_scan_view.shape[0]):
@@ -458,25 +401,17 @@ cdef class MODISInterpolator:
self,
floating[:, :] input_arr,
floating[:, ::1] output_arr,
- ) nogil:
+ ) noexcept nogil:
if self._coarse_scan_length == 10:
self._expand_tiepoint_array_1km(input_arr, output_arr)
else:
self._expand_tiepoint_array_5km(input_arr, output_arr)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
- cdef void _expand_tiepoint_array_1km(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) nogil:
+ cdef void _expand_tiepoint_array_1km(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) noexcept nogil:
self._expand_tiepoint_array_1km_main(input_arr, expanded_arr)
self._expand_tiepoint_array_1km_right_column(input_arr, expanded_arr)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
- cdef void _expand_tiepoint_array_1km_main(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) nogil:
+ cdef void _expand_tiepoint_array_1km_main(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, length_repeat_cycle, width_repeat_cycle, half_coarse_pixel_fine_offset, row_offset, col_offset
cdef Py_ssize_t row_repeat_offset, col_repeat_offset
@@ -502,15 +437,11 @@ cdef class MODISInterpolator:
tiepoint_value = input_arr[row_idx, col_idx]
self._expand_tiepoint_array_1km_with_repeat(tiepoint_value, expanded_arr, row_offset, col_offset)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_1km_right_column(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr
- ) nogil:
+ ) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, length_repeat_cycle, width_repeat_cycle, half_coarse_pixel_fine_offset, row_offset, col_offset
cdef Py_ssize_t row_repeat_offset, col_repeat_offset
@@ -525,15 +456,11 @@ cdef class MODISInterpolator:
self._expand_tiepoint_array_1km_right_column_top_row(input_arr, expanded_arr)
self._expand_tiepoint_array_1km_right_column_bottom_row(input_arr, expanded_arr)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_1km_right_column_top_row(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr
- ) nogil:
+ ) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, row_offset, col_offset
row_idx = 0
@@ -543,15 +470,11 @@ cdef class MODISInterpolator:
col_offset = col_idx * self._fine_pixels_per_coarse_pixel + self._fine_pixels_per_coarse_pixel
self._expand_tiepoint_array_1km_with_repeat(tiepoint_value, expanded_arr, row_offset, col_offset)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_1km_right_column_bottom_row(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr
- ) nogil:
+ ) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, row_offset, col_offset
row_idx = input_arr.shape[0] - 1
@@ -561,17 +484,13 @@ cdef class MODISInterpolator:
col_offset = col_idx * self._fine_pixels_per_coarse_pixel + self._fine_pixels_per_coarse_pixel
self._expand_tiepoint_array_1km_with_repeat(tiepoint_value, expanded_arr, row_offset, col_offset)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_1km_with_repeat(
self,
floating tiepoint_value,
floating[:, ::1] expanded_arr,
Py_ssize_t row_offset,
Py_ssize_t col_offset,
- ) nogil:
+ ) noexcept nogil:
cdef Py_ssize_t length_repeat_cycle, width_repeat_cycle
cdef Py_ssize_t row_repeat_offset, col_repeat_offset
for length_repeat_cycle in range(self._fine_pixels_per_coarse_pixel):
@@ -580,22 +499,14 @@ cdef class MODISInterpolator:
col_repeat_offset = col_offset + width_repeat_cycle
expanded_arr[row_repeat_offset, col_repeat_offset] = tiepoint_value
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
- cdef void _expand_tiepoint_array_5km(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) nogil:
+ cdef void _expand_tiepoint_array_5km(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) noexcept nogil:
self._expand_tiepoint_array_5km_main(input_arr, expanded_arr)
self._expand_tiepoint_array_5km_left(input_arr, expanded_arr)
if self._coarse_scan_width == 270:
self._expand_tiepoint_array_5km_270_extra_column(input_arr, expanded_arr)
self._expand_tiepoint_array_5km_right(input_arr, expanded_arr)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
- cdef void _expand_tiepoint_array_5km_main(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) nogil:
+ cdef void _expand_tiepoint_array_5km_main(self, floating[:, :] input_arr, floating[:, ::1] expanded_arr) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, row_offset, col_offset
for row_idx in range(input_arr.shape[0]):
@@ -610,15 +521,11 @@ cdef class MODISInterpolator:
col_offset,
self._fine_pixels_per_coarse_pixel)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_5km_270_extra_column(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr
- ) nogil:
+ ) noexcept nogil:
"""Copy an extra coarse pixel column between the main copied area and the right-most columns."""
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, col_idx, row_offset, col_offset
@@ -634,43 +541,31 @@ cdef class MODISInterpolator:
col_offset,
self._fine_pixels_per_coarse_pixel)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_5km_left(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr,
- ) nogil:
+ ) noexcept nogil:
self._expand_tiepoint_array_5km_edges(input_arr, expanded_arr, 0, 0)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_5km_right(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr,
- ) nogil:
+ ) noexcept nogil:
self._expand_tiepoint_array_5km_edges(
input_arr,
expanded_arr,
input_arr.shape[1] - 1,
expanded_arr.shape[1] - self._factor_5km)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_5km_edges(
self,
floating[:, :] input_arr,
floating[:, ::1] expanded_arr,
Py_ssize_t course_col_idx,
Py_ssize_t fine_col_idx,
- ) nogil:
+ ) noexcept nogil:
cdef floating tiepoint_value
cdef Py_ssize_t row_idx, row_offset
for row_idx in range(input_arr.shape[0]):
@@ -683,10 +578,6 @@ cdef class MODISInterpolator:
fine_col_idx,
self._factor_5km)
- @cython.boundscheck(False)
- @cython.cdivision(True)
- @cython.wraparound(False)
- @cython.initializedcheck(False)
cdef void _expand_tiepoint_array_5km_with_repeat(
self,
floating tiepoint_value,
@@ -694,7 +585,7 @@ cdef class MODISInterpolator:
Py_ssize_t row_offset,
Py_ssize_t col_offset,
Py_ssize_t col_width,
- ) nogil:
+ ) noexcept nogil:
cdef Py_ssize_t length_repeat_cycle, width_repeat_cycle
for length_repeat_cycle in range(self._fine_pixels_per_coarse_pixel * 2):
for width_repeat_cycle in range(col_width):
=====================================
geotiepoints/_modis_utils.pxd
=====================================
@@ -1,3 +1,4 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
cimport numpy as np
ctypedef fused floating:
@@ -8,7 +9,7 @@ cdef void lonlat2xyz(
floating[:, ::1] lons,
floating[:, ::1] lats,
floating[:, :, ::1] xyz,
-) nogil
+) noexcept nogil
cdef void xyz2lonlat(
floating[:, :, ::1] xyz,
@@ -16,7 +17,7 @@ cdef void xyz2lonlat(
floating[:, ::1] lats,
bint low_lat_z=*,
floating thr=*,
-) nogil
+) noexcept nogil
-cdef floating rad2deg(floating x) nogil
-cdef floating deg2rad(floating x) nogil
+cdef floating rad2deg(floating x) noexcept nogil
+cdef floating deg2rad(floating x) noexcept nogil
=====================================
geotiepoints/_modis_utils.pyx
=====================================
@@ -1,3 +1,4 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
from functools import wraps
cimport cython
@@ -5,6 +6,8 @@ cimport numpy as np
from libc.math cimport asin, sin, cos, sqrt, acos, M_PI
import numpy as np
+np.import_array()
+
try:
import dask.array as da
except ImportError:
@@ -20,14 +23,11 @@ except ImportError:
DEF EARTH_RADIUS = 6370997.0
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
cdef void lonlat2xyz(
floating[:, ::1] lons,
floating[:, ::1] lats,
floating[:, :, ::1] xyz,
-) nogil:
+) noexcept nogil:
"""Convert lons and lats to cartesian coordinates."""
cdef Py_ssize_t i, j, k
cdef floating lon_rad, lat_rad
@@ -40,15 +40,12 @@ cdef void lonlat2xyz(
xyz[i, j, 2] = EARTH_RADIUS * sin(lat_rad)
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
cdef void xyz2lonlat(
floating[:, :, ::1] xyz,
floating[:, ::1] lons,
floating[:, ::1] lats,
bint low_lat_z=True,
- floating thr=0.8) nogil:
+ floating thr=0.8) noexcept nogil:
"""Get longitudes from cartesian coordinates."""
cdef Py_ssize_t i, j
cdef np.float64_t x, y, z
@@ -68,17 +65,15 @@ cdef void xyz2lonlat(
lats[i, j] = _sign(z) * (90 - rad2deg(asin(sqrt(x ** 2 + y ** 2) / EARTH_RADIUS)))
-cdef inline int _sign(floating x) nogil:
+cdef inline int _sign(floating x) noexcept nogil:
return 1 if x > 0 else (-1 if x < 0 else 0)
- at cython.cdivision(True)
-cdef inline floating rad2deg(floating x) nogil:
+cdef inline floating rad2deg(floating x) noexcept nogil:
return x * (180.0 / M_PI)
- at cython.cdivision(True)
-cdef inline floating deg2rad(floating x) nogil:
+cdef inline floating deg2rad(floating x) noexcept nogil:
return x * (M_PI / 180.0)
@@ -173,7 +168,7 @@ def _rechunk_dask_arrays_if_needed(args, rows_per_scan: int):
row_chunks = first_arr.chunks[0]
col_chunks = first_arr.chunks[1]
num_rows = first_arr.shape[0]
- num_cols = first_arr.shape[-1]
+ num_cols = first_arr.shape[1]
good_row_chunks = all(x % rows_per_scan == 0 for x in row_chunks)
good_col_chunks = len(col_chunks) == 1 and col_chunks[0] != num_cols
all_orig_chunks = [arr.chunks for arr in args if hasattr(arr, "chunks")]
=====================================
geotiepoints/_simple_modis_interpolator.pyx
=====================================
@@ -1,3 +1,4 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
cimport cython
from ._modis_utils cimport floating
@@ -7,6 +8,7 @@ cimport numpy as np
import numpy as np
from scipy.ndimage import map_coordinates
+np.import_array()
def interpolate_geolocation_cartesian(
np.ndarray[floating, ndim=2] lon_array,
@@ -69,7 +71,7 @@ def interpolate_geolocation_cartesian(
cdef void _compute_yx_coordinate_arrays(
unsigned int res_factor,
floating[:, :, ::1] coordinates,
-) nogil:
+) noexcept nogil:
cdef Py_ssize_t i, j
for j in range(coordinates.shape[1]):
for i in range(coordinates.shape[2]):
@@ -85,7 +87,7 @@ cdef void _compute_interpolated_xyz_scan(
floating[:, :, ::1] coordinates_view,
floating[:, :, ::1] xyz_input_view,
floating[:, :, ::1] xyz_result_view,
-) nogil:
+) noexcept nogil:
cdef Py_ssize_t comp_index
cdef floating[:, :] input_view, result_view
with gil:
@@ -137,7 +139,7 @@ cdef void _call_map_coordinates(
cdef void _extrapolate_xyz_rightmost_columns(
floating[:, :] result_view,
int num_columns,
-) nogil:
+) noexcept nogil:
cdef Py_ssize_t row_idx, col_offset
cdef floating last_interp_col_diff
for row_idx in range(result_view.shape[0]):
@@ -155,7 +157,7 @@ cdef void _extrapolate_xyz_rightmost_columns(
cdef void _interpolate_xyz_250(
floating[:, :] result_view,
floating[:, :, ::1] coordinates_view,
-) nogil:
+) noexcept nogil:
cdef Py_ssize_t col_idx
cdef floating m, b
cdef floating[:] result_col_view
@@ -194,7 +196,7 @@ cdef void _interpolate_xyz_250(
cdef void _interpolate_xyz_500(
floating[:, :] result_view,
floating[:, :, ::1] coordinates_view,
-) nogil:
+) noexcept nogil:
cdef Py_ssize_t col_idx
cdef floating m, b
for col_idx in range(result_view.shape[1]):
@@ -231,7 +233,7 @@ cdef inline floating _calc_slope_250(
floating[:] result_view,
floating[:, ::1] y,
Py_ssize_t offset,
-) nogil:
+) noexcept nogil:
return (result_view[offset + 3] - result_view[offset]) / \
(y[offset + 3, 0] - y[offset, 0])
@@ -245,7 +247,7 @@ cdef inline floating _calc_offset_250(
floating[:, ::1] y,
floating m,
Py_ssize_t offset,
-) nogil:
+) noexcept nogil:
return result_view[offset + 3] - m * y[offset + 3, 0]
@@ -257,7 +259,7 @@ cdef inline floating _calc_slope_500(
floating[:] result_view,
floating[:, ::1] y,
Py_ssize_t offset,
-) nogil:
+) noexcept nogil:
return (result_view[offset + 1] - result_view[offset]) / \
(y[offset + 1, 0] - y[offset, 0])
@@ -271,5 +273,5 @@ cdef inline floating _calc_offset_500(
floating[:, ::1] y,
floating m,
Py_ssize_t offset,
-) nogil:
+) noexcept nogil:
return result_view[offset + 1] - m * y[offset + 1, 0]
=====================================
geotiepoints/interpolator.py
=====================================
@@ -1,25 +1,17 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2013-2018 PyTroll community
-
-# Author(s):
-
-# Martin Raspaud <martin.raspaud at smhi.se>
-
+# Copyright (c) 2013-2018 Python-geotiepoints developers
+#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-
+#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
"""Generic interpolation routines."""
import numpy as np
@@ -218,9 +210,6 @@ class Interpolator:
if np.array_equal(self.hrow_indices, self.row_indices):
return self._interp1d()
- xpoints, ypoints = np.meshgrid(self.hrow_indices,
- self.hcol_indices)
-
for num, data in enumerate(self.tie_data):
spl = RectBivariateSpline(self.row_indices,
self.col_indices,
@@ -229,8 +218,7 @@ class Interpolator:
kx=self.kx_,
ky=self.ky_)
- new_data_ = spl.ev(xpoints.ravel(), ypoints.ravel())
- self.new_data[num] = new_data_.reshape(xpoints.shape).T.copy(order='C')
+ self.new_data[num] = spl(self.hrow_indices, self.hcol_indices, grid=True)
def _interp1d(self):
"""Interpolate in one dimension."""
@@ -287,38 +275,29 @@ class SingleGridInterpolator:
"""Interpolate (lazily) to a dask array."""
from dask.base import tokenize
import dask.array as da
+ from dask.array.core import normalize_chunks
v_fine_points, h_fine_points = fine_points
shape = len(v_fine_points), len(h_fine_points)
- try:
- v_chunk_size, h_chunk_size = chunks
- except TypeError:
- v_chunk_size, h_chunk_size = chunks, chunks
-
- vchunks = range(0, shape[0], v_chunk_size)
- hchunks = range(0, shape[1], h_chunk_size)
+ chunks = normalize_chunks(chunks, shape, dtype=self.values.dtype)
- token = tokenize(v_chunk_size, h_chunk_size, self.points, self.values, fine_points, method)
+ token = tokenize(chunks, self.points, self.values, fine_points, method)
name = 'interpolate-' + token
- dskx = {(name, i, j): (self.interpolate_slices,
- (slice(vcs, min(vcs + v_chunk_size, shape[0])),
- slice(hcs, min(hcs + h_chunk_size, shape[1]))),
- method
- )
- for i, vcs in enumerate(vchunks)
- for j, hcs in enumerate(hchunks)
- }
+ dskx = {(name, ) + position: (self.interpolate_slices,
+ slices,
+ method)
+ for position, slices in _enumerate_chunk_slices(chunks)}
res = da.Array(dskx, name, shape=list(shape),
- chunks=(v_chunk_size, h_chunk_size),
+ chunks=chunks,
dtype=self.values.dtype)
return res
def interpolate_numpy(self, fine_points, method="linear"):
"""Interpolate to a numpy array."""
fine_x, fine_y = np.meshgrid(*fine_points, indexing='ij')
- return self.interpolator((fine_x, fine_y), method=method)
+ return self.interpolator((fine_x, fine_y), method=method).astype(self.values.dtype)
def interpolate_slices(self, fine_points, method="linear"):
"""Interpolate using slices.
@@ -333,6 +312,18 @@ class SingleGridInterpolator:
return self.interpolate_numpy(fine_points, method=method)
+def _enumerate_chunk_slices(chunks):
+ """Enumerate chunks with slices."""
+ for position in np.ndindex(tuple(map(len, (chunks)))):
+ slices = []
+ for pos, chunk in zip(position, chunks):
+ chunk_size = chunk[pos]
+ offset = sum(chunk[:pos])
+ slices.append(slice(offset, offset + chunk_size))
+
+ yield (position, slices)
+
+
class MultipleGridInterpolator:
"""Interpolator that works on multiple data arrays."""
=====================================
geotiepoints/modisinterpolator.py
=====================================
@@ -1,22 +1,15 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2018 PyTroll community
-
-# Author(s):
-
-# Martin Raspaud <martin.raspaud at smhi.se>
-
+# Copyright (c) 2018-2023 Python-geotiepoints developers
+#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-
+#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Interpolation of MODIS data using satellite zenith angle.
=====================================
geotiepoints/multilinear.py
=====================================
@@ -17,8 +17,7 @@ def mlinspace(smin, smax, orders):
class MultilinearInterpolator:
-
- '''Multilinear interpolation
+ """Multilinear interpolation.
Methods
-------
@@ -55,14 +54,14 @@ class MultilinearInterpolator:
interpolated_values = interp(random_points)
exact_values = f(random_points)
- '''
+ """
__grid__ = None
def __init__(self, smin, smax, orders, values=None, dtype=np.float64):
- self.smin = np.array(smin, dtype=dtype)
- self.smax = np.array(smax, dtype=dtype)
- self.orders = np.array(orders, dtype=np.int_)
+ self.smin = np.array(smin, dtype=dtype, copy=False)
+ self.smax = np.array(smax, dtype=dtype, copy=False)
+ self.orders = np.array(orders, dtype=np.int_, copy=False)
self.d = len(orders)
self.dtype = dtype
if values is not None:
=====================================
geotiepoints/multilinear_cython.pyx
=====================================
@@ -1,71 +1,61 @@
+# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
-# generation options
-
-# some helper functions
-
-from libc.math cimport fmin, fmax, floor
cimport cython
from cython.parallel import prange,parallel
+from cython cimport floating
cimport numpy as np
import numpy as np
-ctypedef fused floating:
- float
- double
+np.import_array()
+
def multilinear_interpolation(floating[:] smin, floating[:] smax, long[:] orders, floating[:,::1] values, floating[:,::1] s):
- cdef int d = np.size(s,0)
- cdef int n_s = np.size(s,1)
- cdef int n_v = np.size(values,0)
+ cdef Py_ssize_t d = s.shape[0]
+ cdef Py_ssize_t n_s = s.shape[1]
+ cdef Py_ssize_t n_v = values.shape[0]
if floating is float:
dtype = np.single
else:
dtype = np.double
- cdef floating[:,::1] result = np.zeros((n_v,n_s), dtype=dtype)
+ cdef np.ndarray[floating, ndim=2] result_arr = np.empty((n_v, n_s), dtype=dtype)
+ cdef floating[:, ::1] result = result_arr
cdef floating[:] vals
cdef floating[:] res
+ if d > 4:
+ raise Exception("Can't interpolate in dimension strictly greater than 5")
- for i in range(n_v):
- vals = values[i,:]
- res = result[i,:]
- if False:
- pass
- elif d==1:
- multilinear_interpolation_1d(smin, smax, orders, vals, n_s, s, res)
- elif d==2:
- multilinear_interpolation_2d(smin, smax, orders, vals, n_s, s, res)
- elif d==3:
- multilinear_interpolation_3d(smin, smax, orders, vals, n_s, s, res)
- elif d==4:
- multilinear_interpolation_4d(smin, smax, orders, vals, n_s, s, res)
- else:
- raise Exception("Can't interpolate in dimension strictly greater than 5")
-
- return np.array(result,dtype=dtype)
-
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
-cdef multilinear_interpolation_1d(floating[:] smin, floating[:] smax,
- long[:] orders, floating[:] V,
- int n_s, floating[:,::1] s, floating[:] output):
-
- cdef int d = 1
+ with nogil:
+ for i in range(n_v):
+ vals = values[i, :]
+ res = result[i, :]
+ if d == 1:
+ multilinear_interpolation_1d(smin, smax, orders, vals, n_s, s, res)
+ elif d == 2:
+ multilinear_interpolation_2d(smin, smax, orders, vals, n_s, s, res)
+ elif d == 3:
+ multilinear_interpolation_3d(smin, smax, orders, vals, n_s, s, res)
+ elif d == 4:
+ multilinear_interpolation_4d(smin, smax, orders, vals, n_s, s, res)
+
+ return result_arr
- cdef int i
+cdef void multilinear_interpolation_1d(floating[:] smin, floating[:] smax,
+ long[:] orders, floating[:] V,
+ int n_s, floating[:,::1] s, floating[:] output) noexcept nogil:
+ cdef int i
cdef floating lam_0, s_0, sn_0, snt_0
cdef int order_0 = orders[0]
cdef int q_0
cdef floating v_0
cdef floating v_1
- with nogil, parallel():
+ with parallel():
for i in prange(n_s):
# (s_1, ..., s_d) : evaluation point
@@ -88,18 +78,11 @@ cdef multilinear_interpolation_1d(floating[:] smin, floating[:] smax,
output[i] = (1-lam_0)*(v_0) + (lam_0)*(v_1)
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
-cdef multilinear_interpolation_2d(floating[:] smin, floating[:] smax,
- long[:] orders, floating[:] V,
- int n_s, floating[:,::1] s, floating[:] output):
-
- cdef int d = 2
+cdef void multilinear_interpolation_2d(floating[:] smin, floating[:] smax,
+ long[:] orders, floating[:] V,
+ int n_s, floating[:,::1] s, floating[:] output) noexcept nogil:
cdef int i
-
-
cdef floating lam_0, s_0, sn_0, snt_0
cdef floating lam_1, s_1, sn_1, snt_1
cdef int order_0 = orders[0]
@@ -111,7 +94,7 @@ cdef multilinear_interpolation_2d(floating[:] smin, floating[:] smax,
cdef floating v_01
cdef floating v_10
cdef floating v_11
- with nogil, parallel():
+ with parallel():
for i in prange(n_s):
# (s_1, ..., s_d) : evaluation point
@@ -140,18 +123,10 @@ cdef multilinear_interpolation_2d(floating[:] smin, floating[:] smax,
output[i] = (1-lam_0)*((1-lam_1)*(v_00) + (lam_1)*(v_01)) + (lam_0)*((1-lam_1)*(v_10) + (lam_1)*(v_11))
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
-cdef multilinear_interpolation_3d(floating[:] smin, floating[:] smax,
- long[:] orders, floating[:] V,
- int n_s, floating[:,::1] s, floating[:] output):
-
- cdef int d = 3
-
+cdef void multilinear_interpolation_3d(floating[:] smin, floating[:] smax,
+ long[:] orders, floating[:] V,
+ int n_s, floating[:,::1] s, floating[:] output) noexcept nogil:
cdef int i
-
-
cdef floating lam_0, s_0, sn_0, snt_0
cdef floating lam_1, s_1, sn_1, snt_1
cdef floating lam_2, s_2, sn_2, snt_2
@@ -171,7 +146,7 @@ cdef multilinear_interpolation_3d(floating[:] smin, floating[:] smax,
cdef floating v_101
cdef floating v_110
cdef floating v_111
- with nogil, parallel():
+ with parallel():
for i in prange(n_s):
# (s_1, ..., s_d) : evaluation point
@@ -208,18 +183,11 @@ cdef multilinear_interpolation_3d(floating[:] smin, floating[:] smax,
output[i] = (1-lam_0)*((1-lam_1)*((1-lam_2)*(v_000) + (lam_2)*(v_001)) + (lam_1)*((1-lam_2)*(v_010) + (lam_2)*(v_011))) + (lam_0)*((1-lam_1)*((1-lam_2)*(v_100) + (lam_2)*(v_101)) + (lam_1)*((1-lam_2)*(v_110) + (lam_2)*(v_111)))
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
-cdef multilinear_interpolation_4d(floating[:] smin, floating[:] smax,
- long[:] orders, floating[:] V,
- int n_s, floating[:,::1] s, floating[:] output):
-
- cdef int d = 4
+cdef void multilinear_interpolation_4d(floating[:] smin, floating[:] smax,
+ long[:] orders, floating[:] V,
+ int n_s, floating[:,::1] s, floating[:] output) noexcept nogil:
cdef int i
-
-
cdef floating lam_0, s_0, sn_0, snt_0
cdef floating lam_1, s_1, sn_1, snt_1
cdef floating lam_2, s_2, sn_2, snt_2
@@ -251,7 +219,7 @@ cdef multilinear_interpolation_4d(floating[:] smin, floating[:] smax,
cdef floating v_1101
cdef floating v_1110
cdef floating v_1111
- with nogil, parallel():
+ with parallel():
for i in prange(n_s):
# (s_1, ..., s_d) : evaluation point
@@ -300,18 +268,10 @@ cdef multilinear_interpolation_4d(floating[:] smin, floating[:] smax,
output[i] = (1-lam_0)*((1-lam_1)*((1-lam_2)*((1-lam_3)*(v_0000) + (lam_3)*(v_0001)) + (lam_2)*((1-lam_3)*(v_0010) + (lam_3)*(v_0011))) + (lam_1)*((1-lam_2)*((1-lam_3)*(v_0100) + (lam_3)*(v_0101)) + (lam_2)*((1-lam_3)*(v_0110) + (lam_3)*(v_0111)))) + (lam_0)*((1-lam_1)*((1-lam_2)*((1-lam_3)*(v_1000) + (lam_3)*(v_1001)) + (lam_2)*((1-lam_3)*(v_1010) + (lam_3)*(v_1011))) + (lam_1)*((1-lam_2)*((1-lam_3)*(v_1100) + (lam_3)*(v_1101)) + (lam_2)*((1-lam_3)*(v_1110) + (lam_3)*(v_1111))))
- at cython.boundscheck(False)
- at cython.cdivision(True)
- at cython.wraparound(False)
-cdef multilinear_interpolation_5d(floating[:] smin, floating[:] smax,
- long[:] orders, floating[:] V,
- int n_s, floating[:,::1] s, floating[:] output):
-
- cdef int d = 5
-
+cdef void multilinear_interpolation_5d(floating[:] smin, floating[:] smax,
+ long[:] orders, floating[:] V,
+ int n_s, floating[:,::1] s, floating[:] output) noexcept nogil:
cdef int i
-
-
cdef floating lam_0, s_0, sn_0, snt_0
cdef floating lam_1, s_1, sn_1, snt_1
cdef floating lam_2, s_2, sn_2, snt_2
@@ -363,7 +323,7 @@ cdef multilinear_interpolation_5d(floating[:] smin, floating[:] smax,
cdef floating v_11101
cdef floating v_11110
cdef floating v_11111
- with nogil, parallel():
+ with parallel():
for i in prange(n_s):
# (s_1, ..., s_d) : evaluation point
=====================================
geotiepoints/tests/__init__.py
=====================================
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2017 Adam.Dybbroe
+# Copyright (c) 2017 Python-geotiepoints developers
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
=====================================
geotiepoints/tests/test_geointerpolator.py
=====================================
@@ -246,6 +246,40 @@ class TestGeoGridInterpolator:
np.testing.assert_allclose(lons[0, :], lons_expected, rtol=5e-5)
np.testing.assert_allclose(lats[:, 0], lats_expected, rtol=5e-5)
+ def test_geogrid_interpolation_preserves_dtype(self):
+ """Test that the interpolator works with both explicit tie-point arrays and swath definition objects."""
+ x_points = np.array([0, 1, 3, 7])
+ y_points = np.array([0, 1, 3, 7, 15])
+
+ interpolator = GeoGridInterpolator((y_points, x_points),
+ TIE_LONS.astype(np.float32), TIE_LATS.astype(np.float32))
+
+ lons, lats = interpolator.interpolate_to_shape((16, 8))
+
+ assert lons.dtype == np.float32
+ assert lats.dtype == np.float32
+
+ def test_chunked_geogrid_interpolation(self):
+ """Test that the interpolator works with both explicit tie-point arrays and swath definition objects."""
+ dask = pytest.importorskip("dask")
+
+ x_points = np.array([0, 1, 3, 7])
+ y_points = np.array([0, 1, 3, 7, 15])
+
+ interpolator = GeoGridInterpolator((y_points, x_points),
+ TIE_LONS.astype(np.float32), TIE_LATS.astype(np.float32))
+
+ lons, lats = interpolator.interpolate_to_shape((16, 8), chunks=4)
+
+ assert lons.chunks == ((4, 4, 4, 4), (4, 4))
+ assert lats.chunks == ((4, 4, 4, 4), (4, 4))
+
+ with dask.config.set({"array.chunk-size": 64}):
+
+ lons, lats = interpolator.interpolate_to_shape((16, 8), chunks="auto")
+ assert lons.chunks == ((4, 4, 4, 4), (4, 4))
+ assert lats.chunks == ((4, 4, 4, 4), (4, 4))
+
def test_geogrid_interpolation_can_extrapolate(self):
"""Test that the interpolator can also extrapolate given the right parameters."""
x_points = np.array([0, 1, 3, 7])
=====================================
geotiepoints/tests/test_interpolator.py
=====================================
@@ -140,7 +140,8 @@ def grid_interpolator():
[2, 2, 2, 1],
[0, 3, 3, 3],
[1, 2, 1, 2],
- [4, 4, 4, 4]])
+ [4, 4, 4, 4]],
+ dtype=np.float64)
return SingleGridInterpolator((ypoints, xpoints), data)
@@ -349,12 +350,12 @@ class TestSingleGridInterpolator:
fine_y = np.arange(32)
res = grid_interpolator.interpolate((fine_y, fine_x), method="cubic")
- np.testing.assert_allclose(res, self.expected)
+ np.testing.assert_allclose(res, self.expected, atol=2e-9)
def test_interpolate_slices(self, grid_interpolator):
"""Test that interpolation from slices is working."""
res = grid_interpolator.interpolate_slices((slice(0, 32), slice(0, 16)), method="cubic")
- np.testing.assert_allclose(res, self.expected)
+ np.testing.assert_allclose(res, self.expected, atol=2e-9)
@pytest.mark.parametrize("chunks, expected_chunks", [(10, (10, 10)),
((10, 5), (10, 5))])
@@ -376,5 +377,23 @@ class TestSingleGridInterpolator:
assert res.chunks[0][0] == v_chunk
assert res.chunks[1][0] == h_chunk
- np.testing.assert_allclose(res, self.expected)
+ np.testing.assert_allclose(res, self.expected, atol=2e-9)
assert interpolate.called
+
+ def test_interpolate_preserves_dtype(self):
+ """Test that interpolation is preserving the dtype."""
+ xpoints = np.array([0, 3, 7, 15])
+ ypoints = np.array([0, 3, 7, 15, 31])
+ data = np.array([[0, 1, 0, 1],
+ [2, 2, 2, 1],
+ [0, 3, 3, 3],
+ [1, 2, 1, 2],
+ [4, 4, 4, 4]],
+ dtype=np.float32)
+
+ grid_interpolator = SingleGridInterpolator((ypoints, xpoints), data)
+ fine_x = np.arange(16)
+ fine_y = np.arange(32)
+
+ res = grid_interpolator.interpolate((fine_y, fine_x), method="cubic")
+ assert res.dtype == data.dtype
=====================================
geotiepoints/version.py
=====================================
@@ -26,9 +26,9 @@ def get_keywords():
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
# get_keywords().
- git_refnames = " (HEAD -> main, tag: v1.6.0)"
- git_full = "4f3fd0b5b3d39987a6b17619287f761a04e01ea8"
- git_date = "2023-03-17 14:32:34 +0100"
+ git_refnames = " (HEAD -> main, tag: v1.7.0)"
+ git_full = "2e8b790f6fc7679544b3a1c6b68fc01a122deb00"
+ git_date = "2023-11-21 10:02:32 +0100"
keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
return keywords
=====================================
pyproject.toml
=====================================
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools", "wheel", "oldest-supported-numpy", "Cython", "versioneer"]
+requires = ["setuptools", "wheel", "oldest-supported-numpy", "Cython>=3", "versioneer"]
build-backend = "setuptools.build_meta"
[tool.coverage.run]
=====================================
setup.py
=====================================
@@ -1,31 +1,22 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2012-2018 PyTroll community
-
-# Author(s):
-
-# Adam Dybbroe <adam.dybbroe at smhi.se>
-# Martin Raspaud <martin.raspaud at smhi.se>
-
+# Copyright (c) 2012-2023 Python-geotiepoints developers
+#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-
+#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
"""Setting up the geo_interpolator project."""
import sys
-from setuptools import setup
+from setuptools import setup, find_packages
import versioneer
import numpy as np
from Cython.Build import build_ext
@@ -77,7 +68,7 @@ except ValueError:
cython_directives = {
"language_level": "3",
}
-define_macros = []
+define_macros = [("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")]
if cython_coverage:
print("Enabling directives/macros for Cython coverage support")
cython_directives.update({
@@ -88,9 +79,9 @@ if cython_coverage:
("CYTHON_TRACE", "1"),
("CYTHON_TRACE_NOGIL", "1"),
])
- for ext in EXTENSIONS:
- ext.define_macros = define_macros
- ext.cython_directives.update(cython_directives)
+for ext in EXTENSIONS:
+ ext.define_macros = define_macros
+ ext.cython_directives.update(cython_directives)
cmdclass = versioneer.get_cmdclass(cmdclass={"build_ext": build_ext})
@@ -113,10 +104,8 @@ if __name__ == "__main__":
"Programming Language :: Cython",
"Topic :: Scientific/Engineering"],
url="https://github.com/pytroll/python-geotiepoints",
- packages=['geotiepoints'],
- # packages=find_packages(),
- setup_requires=['numpy', 'cython'],
- python_requires='>=3.7',
+ packages=find_packages(),
+ python_requires='>=3.9',
cmdclass=cmdclass,
install_requires=requirements,
ext_modules=EXTENSIONS,
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geotiepoints/-/commit/2e9e4afc1b24fe5b41de35a153ef2ac79e73f3db
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-geotiepoints/-/commit/2e9e4afc1b24fe5b41de35a153ef2ac79e73f3db
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20231226/554ba02e/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list