From 8d53762817f5fa725b9701f931ccc22bf32e2df7 Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:12:26 +0100 Subject: [PATCH 1/6] add `utils`, `to_linspace` --- hdc/algo/utils.py | 21 +++++++++++++++++++++ tests/test_utils.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 hdc/algo/utils.py create mode 100644 tests/test_utils.py diff --git a/hdc/algo/utils.py b/hdc/algo/utils.py new file mode 100644 index 0000000..0be2585 --- /dev/null +++ b/hdc/algo/utils.py @@ -0,0 +1,21 @@ +from typing import List, Tuple + +import numpy as np + + +def to_linspace(x) -> Tuple[np.ndarray, List[int]]: + """Maps input array to linear space. + + Returns array with linear index (0 - n-1) and list of + original keys matching the indices. + """ + keys = np.unique(x) + keys.sort() + values = np.arange(keys.size) + + idx = np.searchsorted(keys, x.ravel()).reshape(x.shape) + idx[idx == keys.size] = 0 + mask = keys[idx] == x.data + new_pix = np.where(mask, values[idx], 0) + + return new_pix, list(keys) diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..0714876 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,29 @@ +"""Test utility functions.""" + +import numpy as np +import pytest + +from hdc.algo.utils import to_linspace + + +@pytest.mark.parametrize( + "input_array, expected_output", + [ + # Test case 1: Array with unique values + ( + np.array([[1, 2, 3], [4, 5, 6]]), + (np.array([[0, 1, 2], [3, 4, 5]]), [1, 2, 3, 4, 5, 6]), + ), + # Test case 2: Array with repeated values + ( + np.array([[1, 2, 2], [3, 4, 4]]), + (np.array([[0, 1, 1], [2, 3, 3]]), [1, 2, 3, 4]), + ), + # Test case 3: Empty array + (np.array([]), (np.array([]), [])), + ], +) +def test_to_linspace(input_array, expected_output): + x, y = to_linspace(input_array) + np.testing.assert_equal(x, expected_output[0]) + np.testing.assert_equal(y, expected_output[1]) From 3e7b700acf81c88142b540e033c4247a5c779d91 Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:12:44 +0100 Subject: [PATCH 2/6] add `linspace` period accessor --- hdc/algo/accessors.py | 5 +++++ tests/test_accessors.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/hdc/algo/accessors.py b/hdc/algo/accessors.py index 51a91bb..2f8cc3b 100644 --- a/hdc/algo/accessors.py +++ b/hdc/algo/accessors.py @@ -1,4 +1,5 @@ """Xarray Accesor classes.""" + from typing import Iterable, List, Optional, Union from warnings import warn @@ -120,6 +121,10 @@ def end_date(self): def raw(self): return self._tseries.apply(lambda x: self._period_cls(x).raw).to_xarray() + @property + def linspace(self): + return self.yidx - 1 + @xarray.register_dataset_accessor("dekad") @xarray.register_dataarray_accessor("dekad") diff --git a/tests/test_accessors.py b/tests/test_accessors.py index 24dc9b5..1c331d7 100644 --- a/tests/test_accessors.py +++ b/tests/test_accessors.py @@ -1,4 +1,5 @@ """Tests for xarray accessors""" + # pylint: disable=redefined-outer-name,unused-import,no-member,no-name-in-module,missing-function-docstring # pyright: reportGeneralTypeIssues=false @@ -73,6 +74,11 @@ def test_period_yidx_dekad(darr): np.testing.assert_array_equal(darr.time.dekad.yidx, [1, 2, 3, 3, 4]) +def test_period_yidx_linspace_dekad(darr): + assert isinstance(darr.time.dekad.linspace, xr.DataArray) + np.testing.assert_array_equal(darr.time.dekad.linspace, [0, 1, 2, 2, 3]) + + def test_period_ndays_dekad(darr): assert isinstance(darr.time.dekad.ndays, xr.DataArray) np.testing.assert_equal( From 1743a7b2017c4b26e9352429c5f58fa9764fce8b Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:14:02 +0100 Subject: [PATCH 3/6] bump & apply new black --- hdc/algo/__init__.py | 1 + hdc/algo/_version.py | 1 + hdc/algo/dekad.py | 1 + hdc/algo/ops/__init__.py | 1 + hdc/algo/ops/autocorr.py | 1 + hdc/algo/ops/lroo.py | 1 + hdc/algo/ops/stats.py | 1 + hdc/algo/ops/tinterpolate.py | 1 + hdc/algo/ops/whit.py | 1 + hdc/algo/ops/ws2d.py | 1 + hdc/algo/ops/ws2dgu.py | 1 + hdc/algo/ops/ws2doptv.py | 1 + hdc/algo/ops/ws2doptvp.py | 1 + hdc/algo/ops/ws2doptvplc.py | 1 + hdc/algo/ops/ws2dpgu.py | 1 + hdc/algo/ops/ws2dwcvp.py | 1 + hdc/algo/ops/zonal.py | 1 + requirements_dev.txt | 2 +- 18 files changed, 18 insertions(+), 1 deletion(-) diff --git a/hdc/algo/__init__.py b/hdc/algo/__init__.py index ae64da9..2036ce2 100644 --- a/hdc/algo/__init__.py +++ b/hdc/algo/__init__.py @@ -1,4 +1,5 @@ """Seasonal Monitoring Algorithms.""" + # isort: skip_file from ._version import __version__ diff --git a/hdc/algo/_version.py b/hdc/algo/_version.py index e349a3a..117ab6e 100644 --- a/hdc/algo/_version.py +++ b/hdc/algo/_version.py @@ -1,2 +1,3 @@ """Version only in this file.""" + __version__ = "0.3.1" diff --git a/hdc/algo/dekad.py b/hdc/algo/dekad.py index b3cd387..49e7060 100644 --- a/hdc/algo/dekad.py +++ b/hdc/algo/dekad.py @@ -1,4 +1,5 @@ """Dekad helper class.""" + from datetime import date, datetime, timedelta from typing import Tuple, Union, overload diff --git a/hdc/algo/ops/__init__.py b/hdc/algo/ops/__init__.py index 4f34950..7b1a295 100644 --- a/hdc/algo/ops/__init__.py +++ b/hdc/algo/ops/__init__.py @@ -1,4 +1,5 @@ """Numba implementations.""" + from .autocorr import autocorr, autocorr_1d, autocorr_tyx from .lroo import lroo from .tinterpolate import tinterpolate diff --git a/hdc/algo/ops/autocorr.py b/hdc/algo/ops/autocorr.py index 3cd6489..e5400b7 100644 --- a/hdc/algo/ops/autocorr.py +++ b/hdc/algo/ops/autocorr.py @@ -1,4 +1,5 @@ """Lag-1 autocorrelations.""" + from numba import njit from numba.core.types import float32, float64, int64 from numpy import isnan, zeros diff --git a/hdc/algo/ops/lroo.py b/hdc/algo/ops/lroo.py index e6b3817..190b32d 100644 --- a/hdc/algo/ops/lroo.py +++ b/hdc/algo/ops/lroo.py @@ -1,4 +1,5 @@ """Calculate the longest run of ones inside a 1d array.""" + import numpy as np from numba import guvectorize diff --git a/hdc/algo/ops/stats.py b/hdc/algo/ops/stats.py index 5d81f1a..37a0140 100644 --- a/hdc/algo/ops/stats.py +++ b/hdc/algo/ops/stats.py @@ -1,4 +1,5 @@ """Numba accelerated statistical funtions.""" + from math import erf, log, sqrt diff --git a/hdc/algo/ops/tinterpolate.py b/hdc/algo/ops/tinterpolate.py index a938a7b..d7d24df 100644 --- a/hdc/algo/ops/tinterpolate.py +++ b/hdc/algo/ops/tinterpolate.py @@ -1,4 +1,5 @@ """Interpolation numba functions.""" + from numba import guvectorize from numba.core.types import float64, int16, int32, uint8 diff --git a/hdc/algo/ops/whit.py b/hdc/algo/ops/whit.py index ce970bf..49f6770 100644 --- a/hdc/algo/ops/whit.py +++ b/hdc/algo/ops/whit.py @@ -1,4 +1,5 @@ """Numba accelerated Whittaker functions.""" + # pyright: reportGeneralTypeIssues=false # pylint: disable=C0103,C0301,E0401,R0912,R0913,R0914,R0915,too-many-lines from math import log, pow, sqrt # pylint: disable=W0622 diff --git a/hdc/algo/ops/ws2d.py b/hdc/algo/ops/ws2d.py index 211cebf..1d73e8a 100644 --- a/hdc/algo/ops/ws2d.py +++ b/hdc/algo/ops/ws2d.py @@ -1,4 +1,5 @@ """Whittaker filter with differences of 2nd order for a 1d array.""" + from numba import njit from numpy import zeros diff --git a/hdc/algo/ops/ws2dgu.py b/hdc/algo/ops/ws2dgu.py index 07fb8cc..7056e82 100644 --- a/hdc/algo/ops/ws2dgu.py +++ b/hdc/algo/ops/ws2dgu.py @@ -1,4 +1,5 @@ """Whittaker smoother with fixed lambda (S).""" + import numpy as np from numba import guvectorize from numba.core.types import float64, int16 diff --git a/hdc/algo/ops/ws2doptv.py b/hdc/algo/ops/ws2doptv.py index 7587580..214c79d 100644 --- a/hdc/algo/ops/ws2doptv.py +++ b/hdc/algo/ops/ws2doptv.py @@ -1,4 +1,5 @@ """Whittaker filter V-curve optimization os S.""" + from math import log, sqrt import numpy as np diff --git a/hdc/algo/ops/ws2doptvp.py b/hdc/algo/ops/ws2doptvp.py index 90b3c8c..a7c5225 100644 --- a/hdc/algo/ops/ws2doptvp.py +++ b/hdc/algo/ops/ws2doptvp.py @@ -1,4 +1,5 @@ """Whittaker filter V-curve optimization of S and asymmetric weights.""" + # pyright: reportGeneralTypeIssues=false from math import log, sqrt diff --git a/hdc/algo/ops/ws2doptvplc.py b/hdc/algo/ops/ws2doptvplc.py index 398b269..bf7d16c 100644 --- a/hdc/algo/ops/ws2doptvplc.py +++ b/hdc/algo/ops/ws2doptvplc.py @@ -3,6 +3,7 @@ numba implementations. """ + # pyright: reportGeneralTypeIssues=false from math import log, sqrt diff --git a/hdc/algo/ops/ws2dpgu.py b/hdc/algo/ops/ws2dpgu.py index 9c54f07..99b9e24 100644 --- a/hdc/algo/ops/ws2dpgu.py +++ b/hdc/algo/ops/ws2dpgu.py @@ -1,4 +1,5 @@ """Whittaker smoother with asymmetric smoothing and fixed lambda (S).""" + import numpy as np from numba import guvectorize from numba.core.types import float64, int16 diff --git a/hdc/algo/ops/ws2dwcvp.py b/hdc/algo/ops/ws2dwcvp.py index fa2f772..352b7a9 100644 --- a/hdc/algo/ops/ws2dwcvp.py +++ b/hdc/algo/ops/ws2dwcvp.py @@ -1,4 +1,5 @@ """Whittaker filter V-curve optimization of S and asymmetric weights.""" + # pyright: reportGeneralTypeIssues=false import numpy as np from numba import guvectorize, jit diff --git a/hdc/algo/ops/zonal.py b/hdc/algo/ops/zonal.py index dce7789..8259a94 100644 --- a/hdc/algo/ops/zonal.py +++ b/hdc/algo/ops/zonal.py @@ -1,4 +1,5 @@ """Numba accelerated zonal statistics.""" + from numba import njit import numpy as np diff --git a/requirements_dev.txt b/requirements_dev.txt index 40ddb4f..47ba709 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -3,7 +3,7 @@ twine pytest pytest-runner pytest-cov -black +black>=24.1.0 pylint==2.17.2 astroid==2.15.3 pydocstyle From 2a36623a9f3594eafda8dca87b14e1057162e537 Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:14:39 +0100 Subject: [PATCH 4/6] bump version --- hdc/algo/_version.py | 2 +- hdc/algo/utils.py | 4 +++- tests/test_algos.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hdc/algo/_version.py b/hdc/algo/_version.py index 117ab6e..f735d11 100644 --- a/hdc/algo/_version.py +++ b/hdc/algo/_version.py @@ -1,3 +1,3 @@ """Version only in this file.""" -__version__ = "0.3.1" +__version__ = "0.4.0" diff --git a/hdc/algo/utils.py b/hdc/algo/utils.py index 0be2585..3b65cc2 100644 --- a/hdc/algo/utils.py +++ b/hdc/algo/utils.py @@ -1,10 +1,12 @@ +"""hcd-algo utility functions.""" + from typing import List, Tuple import numpy as np def to_linspace(x) -> Tuple[np.ndarray, List[int]]: - """Maps input array to linear space. + """Map input array to linear space. Returns array with linear index (0 - n-1) and list of original keys matching the indices. diff --git a/tests/test_algos.py b/tests/test_algos.py index 2a631d1..9aeb6a4 100644 --- a/tests/test_algos.py +++ b/tests/test_algos.py @@ -1,4 +1,5 @@ """Tests for pixel alogrithms""" + # pylint: disable=no-name-in-module,redefined-outer-name,no-value-for-parameter # pyright: reportGeneralTypeIssues=false import numpy as np From 6c6fc9a71f84cc6d073dfb606533f9c83bd15927 Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:30:21 +0100 Subject: [PATCH 5/6] bump GH actions --- .github/workflows/conda.yaml | 4 ++-- .github/workflows/main.yaml | 30 +++++++++++++++--------------- .github/workflows/publish-s3.yaml | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/conda.yaml b/.github/workflows/conda.yaml index 43065e3..78a081a 100644 --- a/.github/workflows/conda.yaml +++ b/.github/workflows/conda.yaml @@ -22,7 +22,7 @@ jobs: conda: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Conda environment with Micromamba uses: mamba-org/setup-micromamba@v1 @@ -77,7 +77,7 @@ jobs: ls -lh pkgs/ - name: Upload results (artifact) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pkgs path: pkgs diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 499d08d..d596a79 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -11,7 +11,7 @@ jobs: cache-path: ${{ steps.cfg.outputs.cache-path }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: @@ -24,7 +24,7 @@ jobs: echo "cache-key=${cache_key}" >> $GITHUB_OUTPUT echo "cache-path=${cache_path}" >> $GITHUB_OUTPUT - name: cache deps - uses: actions/cache@v3 + uses: actions/cache@v4 id: py_cache with: path: ${{ steps.cfg.outputs.cache-path }} @@ -51,9 +51,9 @@ jobs: - pyenv runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Python Env from Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: key: ${{ needs.pyenv.outputs.cache-key }} path: ${{ needs.pyenv.outputs.cache-path }} @@ -74,9 +74,9 @@ jobs: - pyenv runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Python Env from Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: key: ${{ needs.pyenv.outputs.cache-key }} path: ${{ needs.pyenv.outputs.cache-path }} @@ -100,9 +100,9 @@ jobs: - black runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Python Env from Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: key: ${{ needs.pyenv.outputs.cache-key }} path: ${{ needs.pyenv.outputs.cache-path }} @@ -114,7 +114,7 @@ jobs: env: py_path: ${{ needs.pyenv.outputs.cache-path }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: wheels_cache with: path: ./wheels @@ -150,7 +150,7 @@ jobs: python setup.py sdist -d wheels - name: Upload results (artifact) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: wheels path: wheels @@ -162,9 +162,9 @@ jobs: - black runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Python Env from Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: key: ${{ needs.pyenv.outputs.cache-key }} path: ${{ needs.pyenv.outputs.cache-path }} @@ -190,9 +190,9 @@ jobs: - wheels runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Python Env from Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: key: ${{ needs.pyenv.outputs.cache-key }} path: ${{ needs.pyenv.outputs.cache-path }} @@ -205,7 +205,7 @@ jobs: py_path: ${{ needs.pyenv.outputs.cache-path }} - name: Get Wheels - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: wheels path: wheels diff --git a/.github/workflows/publish-s3.yaml b/.github/workflows/publish-s3.yaml index d474df2..046472f 100644 --- a/.github/workflows/publish-s3.yaml +++ b/.github/workflows/publish-s3.yaml @@ -14,8 +14,8 @@ jobs: id-token: write contents: read steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 id: wheels_cache with: path: ./wheels From 0a18b7309ec82de2b277f416eeb3d19b7ed24944 Mon Sep 17 00:00:00 2001 From: valpesendorfer Date: Wed, 7 Feb 2024 10:31:05 +0100 Subject: [PATCH 6/6] bump s3 cred rule and mask ID --- .github/workflows/publish-s3.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-s3.yaml b/.github/workflows/publish-s3.yaml index 046472f..b14e394 100644 --- a/.github/workflows/publish-s3.yaml +++ b/.github/workflows/publish-s3.yaml @@ -22,10 +22,11 @@ jobs: key: wheels-${{ github.sha }} - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v2 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_S3_UPLOAD_ROLE }} aws-region: eu-central-1 + mask-aws-account-id: true - name: upload wheels to S3 run: |