diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 46e64f6..cd9518a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,17 +20,17 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Set up Python 3.8 - uses: actions/setup-python@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip - pip install black 'isort[colors]<6' + pip install -v --editable .[lint] - name: black check run: | @@ -40,63 +40,79 @@ jobs: run: | python -m isort --check --diff --color . + - name: cython-lint check + run: | + cython-lint src/pykrige/ + build_wheels: - name: wheels for ${{ matrix.cfg.os }} / ${{ matrix.cfg.arch }} - runs-on: ${{ matrix.cfg.os }} + name: wheels for ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - cfg: - - { os: ubuntu-latest, arch: x86_64 } - - { os: ubuntu-latest, arch: i686 } - - { os: windows-latest, arch: AMD64 } - - { os: windows-latest, arch: x86 } - - { os: macos-latest, arch: x86_64 } - - { os: macos-latest, arch: arm64 } - - { os: macos-latest, arch: universal2 } + # macos-13 is an intel runner, macos-14 is apple silicon + os: [ubuntu-latest, windows-latest, macos-13, macos-14] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: '0' - name: Build wheels - uses: pypa/cibuildwheel@v2.16.2 - env: - CIBW_ARCHS: ${{ matrix.cfg.arch }} + uses: pypa/cibuildwheel@v2.18.0 with: output-dir: dist - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./dist/*.whl build_sdist: - name: sdist and coveralls - runs-on: ubuntu-latest + name: sdist on ${{ matrix.os }} with py ${{ matrix.ver.py }} numpy${{ matrix.ver.np }} scipy${{ matrix.ver.sp }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false - + matrix: + os: [ubuntu-latest, windows-latest, macos-13, macos-14] + # https://github.com/scipy/oldest-supported-numpy/blob/main/setup.cfg + ver: + - {py: '3.8', np: '==1.20.0', sp: '==1.5.4'} + - {py: '3.9', np: '==1.20.0', sp: '==1.5.4'} + - {py: '3.10', np: '==1.21.6', sp: '==1.7.2'} + - {py: '3.11', np: '==1.23.2', sp: '==1.9.2'} + - {py: '3.12', np: '==1.26.2', sp: '==1.11.2'} + - {py: '3.12', np: '>=2.0.0rc1', sp: '>=1.13.0'} + exclude: + - os: macos-14 + ver: {py: '3.8', np: '==1.20.0', sp: '==1.5.4'} + - os: macos-14 + ver: {py: '3.9', np: '==1.20.0', sp: '==1.5.4'} + - os: macos-14 + ver: {py: '3.10', np: '==1.21.6', sp: '==1.7.2'} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: '0' - - name: Set up Python 3.8 - uses: actions/setup-python@v2 + - name: Set up Python ${{ matrix.ver.py }} + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: ${{ matrix.ver.py }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install build coveralls>=3.0.0 + pip install build "coveralls>=3.0.0" + + - name: Install PyKrige + run: | pip install -v --editable .[test] - name: Run tests env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + pip install "numpy${{ matrix.ver.np }}" "scipy${{ matrix.ver.sp }}" python -m pytest --cov pykrige --cov-report term-missing -v tests/ python -m coveralls --service=github @@ -105,7 +121,8 @@ jobs: # PEP 517 package builder from pypa python -m build --sdist --outdir dist . - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 + if: matrix.os == 'ubuntu-latest' && matrix.ver.py == '3.9' with: path: dist/*.tar.gz diff --git a/.readthedocs.yml b/.readthedocs.yml index 7dd1760..4291bf8 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,7 +8,7 @@ build: sphinx: configuration: docs/source/conf.py -formats: all +formats: [pdf] python: install: diff --git a/CHANGELOG.md b/CHANGELOG.md index e51a115..b0fd898 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ Changelog ========= +Version 1.7.2 +------------- +*May 27, 2024* + +**New features** + +* added support for numpy 2 ([#290](https://github.com/GeoStat-Framework/PyKrige/pull/290)) + +**Changes** + +* remove universal2 wheels for macos (we already provide separate intel and arm64 wheels) ([#290](https://github.com/GeoStat-Framework/PyKrige/pull/290)) + +**Bug fixes** + +* fixed cython long / longlong issue on windows ([#290](https://github.com/GeoStat-Framework/PyKrige/issues/290)) + + Version 1.7.1 ------------- *October 14, 2023* diff --git a/LICENSE b/LICENSE index 3811878..35695b7 100755 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2022, PyKrige Developers +Copyright (c) 2015-2024, PyKrige Developers All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/pyproject.toml b/pyproject.toml index eea7231..8a59fe4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,11 @@ requires = [ "setuptools>=64", "setuptools_scm>=7", - "oldest-supported-numpy", - "scipy>=1.1.0,<2", - "Cython>=0.28.3,<3.0", + "numpy>=2.0.0rc1,<2.3; python_version >= '3.9'", + "scipy>=1.13.0,<2; python_version >= '3.9'", + "oldest-supported-numpy; python_version < '3.9'", + "scipy>=1.3.2,<2; python_version < '3.9'", + "Cython>=3.0.10,<3.1.0", ] build-backend = "setuptools.build_meta" @@ -46,21 +48,21 @@ classifiers = [ "Topic :: Utilities", ] dependencies = [ - "numpy>=1.14.5,<2", + "numpy>=1.20.0", "scipy>=1.1.0,<2", ] [project.optional-dependencies] doc = [ - "gstools>=1.3,<2", + "gstools>=1.4,<2", "pillow", "scikit-learn>=0.19", "m2r2>=0.2.8", "matplotlib>=3", "numpydoc>=1.1", - "sphinx>=4", + "sphinx>=7", "sphinx-gallery>=0.8", - "sphinx-rtd-theme>=1", + "sphinx-rtd-theme>=2", ] plot = ["matplotlib>=3,<4"] sklearn = ["scikit-learn>=0.19"] @@ -69,6 +71,12 @@ test = [ "scikit-learn>=0.19", "gstools>=1.4,<2", ] +lint = [ + "black>=23,<24", + "pylint", + "isort[colors]", + "cython-lint", +] [project.urls] Changelog = "https://github.com/GeoStat-Framework/PyKrige/blob/main/CHANGELOG.md" @@ -92,7 +100,16 @@ profile = "black" multi_line_output = 3 [tool.black] -target-version = ["py38"] +target-version = [ + "py38", + "py39", + "py310", + "py311", + "py312", +] + +[tool.cython-lint] +max-line-length = 100 [tool.coverage] [tool.coverage.run] @@ -121,6 +138,7 @@ target-version = ["py38"] [tool.pylint.message_control] disable = [ "R0801", + "C0103", # lots of invalid variable names ] [tool.pylint.reports] @@ -137,12 +155,8 @@ target-version = ["py38"] [tool.cibuildwheel] # Switch to using build build-frontend = "build" -# Disable building PyPy wheels on all platforms, 32bit for py3.10/11/12 and musllinux builds, py3.6/7 -skip = ["cp36-*", "cp37-*", "pp*", "cp31*-win32", "cp31*-manylinux_i686", "*-musllinux_*"] +# Disable building PyPy wheels on all platforms, 32bit and musllinux builds, py3.6/7 +skip = ["cp36-*", "cp37-*", "pp*", "*-win32", "*-manylinux_i686", "*-musllinux_*"] # Run the package tests using `pytest` test-extras = "test" test-command = "pytest -v {package}/tests" -# Skip trying to test arm64 builds on Intel Macs -test-skip = "*-macosx_arm64 *-macosx_universal2:arm64" -# no wheels for linux-32bit anymore for numpy>=1.22 -environment = "PIP_PREFER_BINARY=1" diff --git a/src/pykrige/lib/__init__.py b/src/pykrige/lib/__init__.py index 3da76c4..5b5c3b7 100644 --- a/src/pykrige/lib/__init__.py +++ b/src/pykrige/lib/__init__.py @@ -1 +1 @@ -__all__ = ["cok", "lapack", "variogram_models"] +__all__ = ["cok", "variogram_models"] diff --git a/src/pykrige/lib/cok.pyx b/src/pykrige/lib/cok.pyx index 91455f1..9a350e1 100644 --- a/src/pykrige/lib/cok.pyx +++ b/src/pykrige/lib/cok.pyx @@ -1,9 +1,7 @@ -#cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True -# -*- coding: utf-8 -*- +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True import numpy as np cimport numpy as np -from libc.math cimport sqrt import scipy.linalg @@ -13,12 +11,14 @@ from scipy.linalg.cython_lapack cimport dgesv from .variogram_models cimport get_variogram_model -cpdef _c_exec_loop(double [:, ::1] a_all, - double [:, ::1] bd_all, - char [::1] mask, - long n, - dict pars): - cdef long i, j, k +cpdef _c_exec_loop( + double [:, ::1] a_all, + double [:, ::1] bd_all, + char [::1] mask, + long n, + dict pars +): + cdef long i, k npt = bd_all.shape[0] @@ -34,13 +34,11 @@ cpdef _c_exec_loop(double [:, ::1] a_all, nb = n + 1 - c_variogram_function = get_variogram_model(pars['variogram_function'].__name__) cdef double [::1] variogram_model_parameters = np.asarray(pars['variogram_model_parameters']) - cdef double [::1,:] a_inv = np.asfortranarray(np.empty_like(a_all)) - + cdef double [::1, :] a_inv = np.asfortranarray(np.empty_like(a_all)) if pars['pseudo_inv']: if pars['pseudo_inv_type'] == "pinv": @@ -54,8 +52,8 @@ cpdef _c_exec_loop(double [:, ::1] a_all, else: a_inv = np.asfortranarray(scipy.linalg.inv(a_all)) - - for i in range(npt): # same thing as range(npt) if mask is not defined, otherwise take the non masked elements + # same thing as range(npt) if mask is not defined, otherwise take the non masked elements + for i in range(npt): if mask[i]: continue bd = bd_all[i] @@ -69,22 +67,20 @@ cpdef _c_exec_loop(double [:, ::1] a_all, if pars['exact_values']: check_b_vect(n, bd, b, eps) - # Do the BLAS matrix-vector multiplication call - dgemv( - # # Compute y := alpha*A*x + beta*y - 'N', # char *trans, # {'T','C'}: o(A)=A'; {'N'}: o(A)=A - &nb, # int *m, # Rows of A (prior to transpose from *trans) - &nb, # int *n, # Columns of A / min(len(x)) - &alpha, # np.float64_t *alpha, # Scalar multiple - &(a_inv[0,0]), # np.float64_t *a, # Matrix A: mxn - &nb, # int *lda, # The size of the first dimension of A (in memory) - &(b[0]), # np.float64_t *x, # Vector x, min(len(x)) = n - &inc, # int *incx, # The increment between elements of x (usually 1) - &beta, # np.float64_t *beta, # Scalar multiple - &(x[0]), # np.float64_t *y, # Vector y, min(len(y)) = m - &inc # int *incy # The increment between elements of y (usually 1) - ) + dgemv( # Compute y := alpha*A*x + beta*y + 'N', # char *trans, # {'T','C'}: o(A)=A'; {'N'}: o(A)=A + &nb, # int *m, # Rows of A (prior to transpose from *trans) + &nb, # int *n, # Columns of A / min(len(x)) + &alpha, # np.float64_t *alpha, # Scalar multiple + &(a_inv[0, 0]), # np.float64_t *a, # Matrix A: mxn + &nb, # int *lda, # The size of the first dimension of A (in memory) + &(b[0]), # np.float64_t *x, # Vector x, min(len(x)) = n + &inc, # int *incx, # The increment between elements of x (usually 1) + &beta, # np.float64_t *beta, # Scalar multiple + &(x[0]), # np.float64_t *y, # Vector y, min(len(y)) = m + &inc # int *incy # The increment between elements of y (usually 1) + ) z_tmp = 0.0 ss_tmp = 0.0 @@ -99,12 +95,14 @@ cpdef _c_exec_loop(double [:, ::1] a_all, return zvalues.base, sigmasq.base -cpdef _c_exec_loop_moving_window(double [:, ::1] a_all, - double [:, ::1] bd_all, - char [::1] mask, - long [:,::1] bd_idx, - long n_max, - dict pars): +cpdef _c_exec_loop_moving_window( + double [:, ::1] a_all, + double [:, ::1] bd_all, + char [::1] mask, + long [:, ::1] bd_idx, + long n_max, + dict pars +): cdef long i, j, k, p_i, p_j, npt, n npt = bd_all.shape[0] @@ -121,19 +119,14 @@ cpdef _c_exec_loop_moving_window(double [:, ::1] a_all, cdef double z_tmp, ss_tmp, eps=pars['eps'] cdef int nb, nrhs=1, info cdef int [::1] ipiv = np.zeros(n_max+1, dtype='int32') - cdef double alpha=1.0, beta=0.0 cdef long [::1] bd_idx_sel nb = n + 1 - - c_variogram_function = get_variogram_model(pars['variogram_function'].__name__) cdef double [::1] variogram_model_parameters = np.asarray(pars['variogram_model_parameters']) - - for i in range(npt): if mask[i]: continue @@ -142,7 +135,6 @@ cpdef _c_exec_loop_moving_window(double [:, ::1] a_all, bd_idx_sel = bd_idx[i, :] - for k in range(n): p_i = bd_idx_sel[k] for j in range(n): @@ -167,8 +159,8 @@ cpdef _c_exec_loop_moving_window(double [:, ::1] a_all, x[k] = b[k] # higher level (and slower) call to do the same thing as dgesv below - #a2D = a_selection.base[:nb*nb].reshape((nb, nb)) - #x = scipy.linalg.solve(a2D, b.base[:nb]) + # a2D = a_selection.base[:nb*nb].reshape((nb, nb)) + # x = scipy.linalg.solve(a2D, b.base[:nb]) dgesv( &nb, @@ -186,7 +178,6 @@ cpdef _c_exec_loop_moving_window(double [:, ::1] a_all, elif info < 0: raise ValueError('Wrong arguments') - z_tmp = 0.0 ss_tmp = 0.0 for k in range(n): diff --git a/src/pykrige/lib/variogram_models.pxd b/src/pykrige/lib/variogram_models.pxd index b04e366..3dca66d 100644 --- a/src/pykrige/lib/variogram_models.pxd +++ b/src/pykrige/lib/variogram_models.pxd @@ -1,4 +1,4 @@ - +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True ctypedef void (*variogram_model_t)(double [::1], long, double [::1], double [::1]) cdef variogram_model_t get_variogram_model(function_name) diff --git a/src/pykrige/lib/variogram_models.pyx b/src/pykrige/lib/variogram_models.pyx index 6318a57..fb821c2 100644 --- a/src/pykrige/lib/variogram_models.pyx +++ b/src/pykrige/lib/variogram_models.pyx @@ -1,13 +1,8 @@ -#cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True -# -*- coding: utf-8 -*- -import numpy as np -cimport numpy as np +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True from libc.math cimport exp -# copied from variogram_model.py - - +# copied from variogram_model.py cdef variogram_model_t get_variogram_model(name): cdef variogram_model_t c_func @@ -27,7 +22,9 @@ cdef variogram_model_t get_variogram_model(name): return c_func -cdef void _c_linear_variogram_model(double [::1] params, long n, double [::1] dist, double[::1] out) nogil: +cdef void _c_linear_variogram_model( + double [::1] params, long n, double [::1] dist, double[::1] out +) noexcept nogil: cdef long k cdef double a, b a = params[0] @@ -36,17 +33,21 @@ cdef void _c_linear_variogram_model(double [::1] params, long n, double [::1] d out[k] = a*dist[k] + b -cdef void _c_power_variogram_model(double [::1] params, long n, double [::1] dist, double[::1] out) nogil: +cdef void _c_power_variogram_model( + double [::1] params, long n, double [::1] dist, double[::1] out +) noexcept nogil: cdef long k cdef double a, b, c a = params[0] b = params[1] c = params[2] for k in range(n): - out[k] = a*(dist[k]**b) + c + out[k] = a*(dist[k]**b) + c -cdef void _c_gaussian_variogram_model(double [::1] params, long n, double [::1] dist, double [::1] out) nogil: +cdef void _c_gaussian_variogram_model( + double [::1] params, long n, double [::1] dist, double [::1] out +) noexcept nogil: cdef long k cdef double a, b, c a = params[0] @@ -56,7 +57,9 @@ cdef void _c_gaussian_variogram_model(double [::1] params, long n, double [::1] out[k] = a*(1 - exp(-(dist[k]/(b*4.0/7.0))**2)) + c -cdef void _c_exponential_variogram_model(double [::1] params, long n, double[::1] dist, double[::1] out) nogil: +cdef void _c_exponential_variogram_model( + double [::1] params, long n, double[::1] dist, double[::1] out +) noexcept nogil: cdef long k cdef double a, b, c a = params[0] @@ -66,7 +69,9 @@ cdef void _c_exponential_variogram_model(double [::1] params, long n, double[::1 out[k] = a*(1 - exp(-dist[k]/(b/3.0))) + c -cdef void _c_spherical_variogram_model(double [::1] params, long n, double[::1] dist, double[::1] out) nogil: +cdef void _c_spherical_variogram_model( + double [::1] params, long n, double[::1] dist, double[::1] out +) noexcept nogil: cdef long k cdef double a, b, c a = params[0] diff --git a/src/pykrige/ok.py b/src/pykrige/ok.py index 6e53a91..2eb0a7a 100644 --- a/src/pykrige/ok.py +++ b/src/pykrige/ok.py @@ -975,7 +975,7 @@ def execute( a, bd, mask.astype("int8"), - bd_idx.astype(int), + bd_idx.astype("long"), self.X_ADJUSTED.shape[0], c_pars, )