From b2d000e09ee53ef20caa9b1a8dc4de274036831f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 22 Jun 2023 11:32:53 +0200 Subject: [PATCH 1/8] fix cython-lint complains --- src/gstools/field/summator.pyx | 13 +++-- src/gstools/krige/krigesum.pyx | 3 +- src/gstools/variogram/estimator.pyx | 82 ++++++++++++++--------------- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/gstools/field/summator.pyx b/src/gstools/field/summator.pyx index cad20e1d8..c66f1027b 100644 --- a/src/gstools/field/summator.pyx +++ b/src/gstools/field/summator.pyx @@ -1,12 +1,10 @@ -#cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True """ This is the randomization method summator, implemented in cython. """ import numpy as np -cimport cython - from cython.parallel import prange cimport numpy as np @@ -18,7 +16,7 @@ def summate( const double[:] z_1, const double[:] z_2, const double[:, :] pos - ): +): cdef int i, j, d cdef double phase cdef int dim = pos.shape[0] @@ -53,7 +51,7 @@ def summate_incompr( const double[:] z_1, const double[:] z_2, const double[:, :] pos - ): +): cdef int i, j, d cdef double phase cdef double k_2 @@ -76,6 +74,7 @@ def summate_incompr( phase += cov_samples[d, j] * pos[d, i] for d in range(dim): proj[d] = e1[d] - cov_samples[d, j] * cov_samples[0, j] / k_2 - summed_modes[d, i] += proj[d] * (z_1[j] * cos(phase) + z_2[j] * sin(phase)) - + summed_modes[d, i] += ( + proj[d] * (z_1[j] * cos(phase) + z_2[j] * sin(phase)) + ) return np.asarray(summed_modes) diff --git a/src/gstools/krige/krigesum.pyx b/src/gstools/krige/krigesum.pyx index de3a43b1e..3b9848442 100644 --- a/src/gstools/krige/krigesum.pyx +++ b/src/gstools/krige/krigesum.pyx @@ -1,11 +1,10 @@ -#cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True """ This is a summator for the kriging routines """ import numpy as np -cimport cython from cython.parallel import prange cimport numpy as np diff --git a/src/gstools/variogram/estimator.pyx b/src/gstools/variogram/estimator.pyx index 528004feb..7f1a32a25 100644 --- a/src/gstools/variogram/estimator.pyx +++ b/src/gstools/variogram/estimator.pyx @@ -1,4 +1,4 @@ -#cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True # distutils: language = c++ """ This is the variogram estimater, implemented in cython. @@ -6,8 +6,6 @@ This is the variogram estimater, implemented in cython. import numpy as np -cimport cython - from cython.parallel import parallel, prange cimport numpy as np @@ -16,20 +14,20 @@ from libc.math cimport M_PI, acos, atan2, cos, fabs, isnan, pow, sin, sqrt cdef inline double dist_euclid( const int dim, - const double[:,:] pos, + const double[:, :] pos, const int i, const int j, ) nogil: cdef int d cdef double dist_squared = 0.0 for d in range(dim): - dist_squared += ((pos[d,i] - pos[d,j]) * (pos[d,i] - pos[d,j])) + dist_squared += ((pos[d, i] - pos[d, j]) * (pos[d, i] - pos[d, j])) return sqrt(dist_squared) cdef inline double dist_haversine( const int dim, - const double[:,:] pos, + const double[:, :] pos, const int i, const int j, ) nogil: @@ -48,7 +46,7 @@ cdef inline double dist_haversine( ctypedef double (*_dist_func)( const int, - const double[:,:], + const double[:, :], const int, const int, ) nogil @@ -56,9 +54,9 @@ ctypedef double (*_dist_func)( cdef inline bint dir_test( const int dim, - const double[:,:] pos, + const double[:, :] pos, const double dist, - const double[:,:] direction, + const double[:, :] direction, const double angles_tol, const double bandwidth, const int i, @@ -74,12 +72,12 @@ cdef inline bint dir_test( # scalar-product calculation for bandwidth projection and angle calculation for k in range(dim): - s_prod += (pos[k,i] - pos[k,j]) * direction[d,k] + s_prod += (pos[k, i] - pos[k, j]) * direction[d, k] # calculate band-distance by projection of point-pair-vec to direction line if bandwidth > 0.0: for k in range(dim): - tmp = (pos[k,i] - pos[k,j]) - s_prod * direction[d,k] + tmp = (pos[k, i] - pos[k, j]) - s_prod * direction[d, k] b_dist += tmp * tmp in_band = sqrt(b_dist) < bandwidth @@ -130,32 +128,31 @@ ctypedef void (*_normalization_func)( ) cdef inline void normalization_matheron_vec( - double[:,:] variogram, - long[:,:] counts, + double[:, :] variogram, + long[:, :] counts, ): - cdef int d, i + cdef int d for d in range(variogram.shape[0]): normalization_matheron(variogram[d, :], counts[d, :]) cdef inline void normalization_cressie_vec( - double[:,:] variogram, - long[:,:] counts, + double[:, :] variogram, + long[:, :] counts, ): - cdef int d, i - cdef long cnt + cdef int d for d in range(variogram.shape[0]): normalization_cressie(variogram[d, :], counts[d, :]) ctypedef void (*_normalization_func_vec)( - double[:,:], - long[:,:], + double[:, :], + long[:, :], ) cdef _estimator_func choose_estimator_func(str estimator_type): cdef _estimator_func estimator_func if estimator_type == 'm': estimator_func = estimator_matheron - else: # estimator_type == 'c' + else: # estimator_type == 'c' estimator_func = estimator_cressie return estimator_func @@ -163,7 +160,7 @@ cdef _normalization_func choose_estimator_normalization(str estimator_type): cdef _normalization_func normalization_func if estimator_type == 'm': normalization_func = normalization_matheron - else: # estimator_type == 'c' + else: # estimator_type == 'c' normalization_func = normalization_cressie return normalization_func @@ -171,16 +168,16 @@ cdef _normalization_func_vec choose_estimator_normalization_vec(str estimator_ty cdef _normalization_func_vec normalization_func_vec if estimator_type == 'm': normalization_func_vec = normalization_matheron_vec - else: # estimator_type == 'c' + else: # estimator_type == 'c' normalization_func_vec = normalization_cressie_vec return normalization_func_vec def directional( - const double[:,:] f, + const double[:, :] f, const double[:] bin_edges, - const double[:,:] pos, - const double[:,:] direction, # should be normed + const double[:, :] pos, + const double[:, :] direction, # should be normed const double angles_tol=M_PI/8.0, const double bandwidth=-1.0, # negative values to turn of bandwidth search const bint separate_dirs=False, # whether the direction bands don't overlap @@ -207,8 +204,8 @@ def directional( cdef int k_max = pos.shape[1] cdef int f_max = f.shape[0] - cdef double[:,:] variogram = np.zeros((d_max, len(bin_edges)-1)) - cdef long[:,:] counts = np.zeros((d_max, len(bin_edges)-1), dtype=long) + cdef double[:, :] variogram = np.zeros((d_max, len(bin_edges)-1)) + cdef long[:, :] counts = np.zeros((d_max, len(bin_edges)-1), dtype=long) cdef int i, j, k, m, d cdef double dist @@ -219,13 +216,15 @@ def directional( if dist < bin_edges[i] or dist >= bin_edges[i+1]: continue # skip if not in current bin for d in range(d_max): - if not dir_test(dim, pos, dist, direction, angles_tol, bandwidth, k, j, d): + if not dir_test( + dim, pos, dist, direction, angles_tol, bandwidth, k, j, d + ): continue # skip if not in current direction for m in range(f_max): # skip no data values - if not (isnan(f[m,k]) or isnan(f[m,j])): + if not (isnan(f[m, k]) or isnan(f[m, j])): counts[d, i] += 1 - variogram[d, i] += estimator_func(f[m,k] - f[m,j]) + variogram[d, i] += estimator_func(f[m, k] - f[m, j]) # once we found a fitting direction # break the search if directions are separated if separate_dirs: @@ -234,10 +233,11 @@ def directional( normalization_func_vec(variogram, counts) return np.asarray(variogram), np.asarray(counts) + def unstructured( - const double[:,:] f, + const double[:, :] f, const double[:] bin_edges, - const double[:,:] pos, + const double[:, :] pos, str estimator_type='m', str distance_type='e', ): @@ -280,15 +280,15 @@ def unstructured( continue # skip if not in current bin for m in range(f_max): # skip no data values - if not (isnan(f[m,k]) or isnan(f[m,j])): + if not (isnan(f[m, k]) or isnan(f[m, j])): counts[i] += 1 - variogram[i] += estimator_func(f[m,k] - f[m,j]) + variogram[i] += estimator_func(f[m, k] - f[m, j]) normalization_func(variogram, counts) return np.asarray(variogram), np.asarray(counts) -def structured(const double[:,:] f, str estimator_type='m'): +def structured(const double[:, :] f, str estimator_type='m'): cdef _estimator_func estimator_func = choose_estimator_func(estimator_type) cdef _normalization_func normalization_func = ( choose_estimator_normalization(estimator_type) @@ -307,15 +307,15 @@ def structured(const double[:,:] f, str estimator_type='m'): for j in range(j_max): for k in prange(1, k_max-i): counts[k] += 1 - variogram[k] += estimator_func(f[i,j] - f[i+k,j]) + variogram[k] += estimator_func(f[i, j] - f[i+k, j]) normalization_func(variogram, counts) return np.asarray(variogram) def ma_structured( - const double[:,:] f, - const bint[:,:] mask, + const double[:, :] f, + const bint[:, :] mask, str estimator_type='m', ): cdef _estimator_func estimator_func = choose_estimator_func(estimator_type) @@ -335,9 +335,9 @@ def ma_structured( for i in range(i_max): for j in range(j_max): for k in prange(1, k_max-i): - if not mask[i,j] and not mask[i+k,j]: + if not mask[i, j] and not mask[i+k, j]: counts[k] += 1 - variogram[k] += estimator_func(f[i,j] - f[i+k,j]) + variogram[k] += estimator_func(f[i, j] - f[i+k, j]) normalization_func(variogram, counts) return np.asarray(variogram) From b2583e05cb81e5c180cf4c2ef974c542337e535c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 22 Jun 2023 11:41:51 +0200 Subject: [PATCH 2/8] add lint opt deps; add cython-lint check in CI --- .github/workflows/main.yml | 11 +++++++---- pyproject.toml | 6 ++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c3bf56e0d..a48126fb8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,20 +32,23 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install black 'pylint<3' 'isort[colors]<6' - pip install -v --editable . + pip install -v --editable .[lint] - name: black check run: | python -m black --check --diff --color . + - name: isort check + run: | + python -m isort --check --diff --color . + - name: pylint check run: | python -m pylint src/gstools/ - - name: isort check + - name: cython-lint check run: | - python -m isort --check --diff --color . + cython-lint src/gstools/ build_wheels: name: wheels for ${{ matrix.cfg.os }} / ${{ matrix.cfg.arch }} diff --git a/pyproject.toml b/pyproject.toml index 3a6c7ec07..39948c191 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,6 +72,12 @@ plotting = [ ] rust = ["gstools_core>=0.2.0,<1"] test = ["pytest-cov>=3"] +lint = [ + "black", + "pylint<3", + "isort[colors]<6", + "cython-lint", +] [project.urls] Changelog = "https://github.com/GeoStat-Framework/GSTools/blob/main/CHANGELOG.md" From 2615b539e753c4642d3f289a071bc1e996c099d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 22 Jun 2023 11:47:02 +0200 Subject: [PATCH 3/8] apply isort to pyx files --- src/gstools/field/summator.pyx | 1 - src/gstools/krige/krigesum.pyx | 2 +- src/gstools/variogram/estimator.pyx | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gstools/field/summator.pyx b/src/gstools/field/summator.pyx index c66f1027b..29239c074 100644 --- a/src/gstools/field/summator.pyx +++ b/src/gstools/field/summator.pyx @@ -4,7 +4,6 @@ This is the randomization method summator, implemented in cython. """ import numpy as np - from cython.parallel import prange cimport numpy as np diff --git a/src/gstools/krige/krigesum.pyx b/src/gstools/krige/krigesum.pyx index 3b9848442..2f79d3adb 100644 --- a/src/gstools/krige/krigesum.pyx +++ b/src/gstools/krige/krigesum.pyx @@ -4,8 +4,8 @@ This is a summator for the kriging routines """ import numpy as np - from cython.parallel import prange + cimport numpy as np diff --git a/src/gstools/variogram/estimator.pyx b/src/gstools/variogram/estimator.pyx index 7f1a32a25..611f5efbd 100644 --- a/src/gstools/variogram/estimator.pyx +++ b/src/gstools/variogram/estimator.pyx @@ -5,7 +5,6 @@ This is the variogram estimater, implemented in cython. """ import numpy as np - from cython.parallel import parallel, prange cimport numpy as np From 1238f81cb7310051ec08c9e262932d2d877c9bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Fri, 3 Nov 2023 15:45:42 +0100 Subject: [PATCH 4/8] cython: switch to cython >3.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 39948c191..daa4c4bd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "setuptools>=64", "setuptools_scm>=7", "oldest-supported-numpy", - "Cython>=0.29.32,<3.0", + "Cython>=3.0", "extension-helpers>=1", ] build-backend = "setuptools.build_meta" From 7d8d6817b19e924cb33c506bff697d30bce90b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Fri, 3 Nov 2023 15:50:23 +0100 Subject: [PATCH 5/8] lint: remove caps for lint deps --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index daa4c4bd7..cf5048c96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,8 +74,8 @@ rust = ["gstools_core>=0.2.0,<1"] test = ["pytest-cov>=3"] lint = [ "black", - "pylint<3", - "isort[colors]<6", + "pylint", + "isort[colors]", "cython-lint", ] From 8e82b3c9445e12265b878d89f5dd551430d19104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Fri, 3 Nov 2023 15:56:31 +0100 Subject: [PATCH 6/8] python: drop py37 and add 312 --- .github/workflows/main.yml | 4 ++-- pyproject.toml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a48126fb8..e116c4832 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,7 +71,7 @@ jobs: fetch-depth: '0' - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.16.2 env: CIBW_ARCHS: ${{ matrix.cfg.arch }} with: @@ -88,7 +88,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v2 diff --git a/pyproject.toml b/pyproject.toml index cf5048c96..70b7d0a62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ requires = [ build-backend = "setuptools.build_meta" [project] -requires-python = ">=3.7" +requires-python = ">=3.8" name = "gstools" description = "GSTools: A geostatistical toolbox." authors = [ @@ -32,11 +32,11 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: GIS", "Topic :: Scientific/Engineering :: Hydrology", @@ -104,11 +104,11 @@ line_length = 79 [tool.black] line-length = 79 target-version = [ - "py37", "py38", "py39", "py310", "py311", + "py312", ] [tool.coverage] @@ -160,8 +160,8 @@ target-version = [ [tool.cibuildwheel] # Switch to using build build-frontend = "build" -# Disable building PyPy wheels on all platforms, 32bit for py3.10/11 and musllinux builds, py3.6 -skip = ["cp36-*", "pp*", "cp31*-win32", "cp31*-manylinux_i686", "*-musllinux_*"] +# Disable building PyPy wheels on all platforms, 32bit for py3.10/11/12, musllinux builds, py3.6/7 +skip = ["cp36-*", "cp37-*", "pp*", "cp31*-win32", "cp31*-manylinux_i686", "*-musllinux_*"] # Run the package tests using `pytest` test-extras = "test" test-command = "pytest -v {package}/tests" From 702e2b90d796b38e5fb1110726a64a8aa36b095e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Fri, 3 Nov 2023 16:00:16 +0100 Subject: [PATCH 7/8] update changelog --- CHANGELOG.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 633b50b4e..00513d23b 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to **GSTools** will be documented in this file. +## [1.5.1] - Nifty Neon - 2023-11 + +### Enhancements + +see [#317](https://github.com/GeoStat-Framework/GSTools/pull/317) + +- added wheels for Python 3.12 +- dropped support for Python 3.7 (EOL) +- linted Cython files with cython-lint +- use Cython 3 to build extensions + + ## [1.5.0] - Nifty Neon - 2023-06 ### Enhancements @@ -404,7 +416,8 @@ See: [#197](https://github.com/GeoStat-Framework/GSTools/issues/197) First release of GSTools. -[Unreleased]: https://github.com/GeoStat-Framework/gstools/compare/v1.5.0...HEAD +[Unreleased]: https://github.com/GeoStat-Framework/gstools/compare/v1.5.1...HEAD +[1.5.1]: https://github.com/GeoStat-Framework/gstools/compare/v1.5.0...v1.5.1 [1.5.0]: https://github.com/GeoStat-Framework/gstools/compare/v1.4.1...v1.5.0 [1.4.1]: https://github.com/GeoStat-Framework/gstools/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/GeoStat-Framework/gstools/compare/v1.3.5...v1.4.0 From 5638e15f9f30371745ef7895c5da910de794779a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Fri, 3 Nov 2023 16:09:05 +0100 Subject: [PATCH 8/8] rtd config fix --- .readthedocs.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 2ef05a17d..7dd176079 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,12 +1,16 @@ version: 2 +build: + os: ubuntu-22.04 + tools: + python: "3.11" + sphinx: configuration: docs/source/conf.py formats: all python: - version: 3.8 install: - method: pip path: .