diff --git a/.coveragerc b/.coveragerc index e24e383ed..e67fd3aa5 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,4 +10,4 @@ omit = */pywt/data/create_dat.py *.pxd stringsource -plugins = Cython.Coverage \ No newline at end of file +plugins = Cython.Coverage diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f47186786..61cd37af7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,6 @@ on: - v1.** jobs: - test_pywavelets_linux: name: linux-cp${{ matrix.python-version }}-${{ matrix.OPTIONS_NAME }} runs-on: ubuntu-latest @@ -27,7 +26,7 @@ jobs: # Ensure that a wheel builder finishes even if another fails fail-fast: false matrix: - python-version: [3.9, '3.10', '3.11'] + python-version: [3.9, "3.10", "3.11"] MINIMUM_REQUIREMENTS: [0] USE_SCIPY: [0] USE_SDIST: [0] @@ -53,7 +52,7 @@ jobs: USE_WHEEL: 1 OPTIONS_NAME: "install-from-wheel" - platform_id: manylinux_x86_64 - python-version: '3.11' + python-version: "3.11" PIP_FLAGS: "--pre" OPTIONS_NAME: "pre-releases" @@ -68,72 +67,71 @@ jobs: - name: Build package env: - VERSION: ${{ matrix.python-version }} - MINIMUM_REQUIREMENTS: ${{ matrix.MINIMUM_REQUIREMENTS }} - PIP_FLAGS: ${{ matrix.PIP_FLAGS }} - USE_WHEEL: ${{ matrix.USE_WHEEL }} - USE_SDIST: ${{ matrix.USE_SDIST }} - USE_SCIPY: ${{ matrix.USE_SCIPY }} - REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} + VERSION: ${{ matrix.python-version }} + MINIMUM_REQUIREMENTS: ${{ matrix.MINIMUM_REQUIREMENTS }} + PIP_FLAGS: ${{ matrix.PIP_FLAGS }} + USE_WHEEL: ${{ matrix.USE_WHEEL }} + USE_SDIST: ${{ matrix.USE_SDIST }} + USE_SCIPY: ${{ matrix.USE_SCIPY }} + REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} run: | - uname -a - df -h - ulimit -a - # ccache -s - which python - python --version - # sudo apt-get install libatlas-base-dev - pip install --upgrade pip build - # Set numpy version first, other packages link against it - if [ "${MINIMUM_REQUIREMENTS}" == "1" ]; then - pip install ${CYTHON_MIN} - pip install ${NUMPY_MIN} - if [ "${USE_SCIPY}" == "1" ]; then pip install ${SCIPY_MIN}; fi - else - pip install cython - pip install numpy - if [ "${USE_SCIPY}" == "1" ]; then pip install scipy; fi - fi - pip install matplotlib pytest - - set -o pipefail - if [ "${USE_WHEEL}" == "1" ]; then - # Need verbose output or TravisCI will terminate after 10 minutes - pip wheel . -v - pip install pywavelets*.whl - elif [ "${USE_SDIST}" == "1" ]; then - python -m build --sdist - pip install dist/pyw*.tar.gz -v - elif [ "${REFGUIDE_CHECK}" == "1" ]; then - pip install sphinx numpydoc - pip install . -v - else - pip install . -v - fi + uname -a + df -h + ulimit -a + # ccache -s + which python + python --version + # sudo apt-get install libatlas-base-dev + pip install --upgrade pip build + # Set numpy version first, other packages link against it + if [ "${MINIMUM_REQUIREMENTS}" == "1" ]; then + pip install ${CYTHON_MIN} + pip install ${NUMPY_MIN} + if [ "${USE_SCIPY}" == "1" ]; then pip install ${SCIPY_MIN}; fi + else + pip install cython + pip install numpy + if [ "${USE_SCIPY}" == "1" ]; then pip install scipy; fi + fi + pip install matplotlib pytest + + set -o pipefail + if [ "${USE_WHEEL}" == "1" ]; then + # Need verbose output or TravisCI will terminate after 10 minutes + pip wheel . -v + pip install pywavelets*.whl + elif [ "${USE_SDIST}" == "1" ]; then + python -m build --sdist + pip install dist/pyw*.tar.gz -v + elif [ "${REFGUIDE_CHECK}" == "1" ]; then + pip install sphinx numpydoc + pip install . -v + else + pip install . -v + fi - name: Run tests env: - PIP_FLAGS: ${{ matrix.PIP_FLAGS }} - USE_WHEEL: ${{ matrix.USE_WHEEL }} - USE_SDIST: ${{ matrix.USE_SDIST }} - REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} + PIP_FLAGS: ${{ matrix.PIP_FLAGS }} + USE_WHEEL: ${{ matrix.USE_WHEEL }} + USE_SDIST: ${{ matrix.USE_SDIST }} + REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} run: | - set -o pipefail - # Move out of source directory to avoid finding local pywt - pushd demo - if [ "${USE_WHEEL}" == "1" ]; then - pytest --pyargs pywt - python ../pywt/tests/test_doc.py - elif [ "${USE_SDIST}" == "1" ]; then - pytest --pyargs pywt - python ../pywt/tests/test_doc.py - elif [ "${REFGUIDE_CHECK}" == "1" ]; then - python util/refguide_check.py --doctests - else - pytest --pyargs pywt - fi - popd - + set -o pipefail + # Move out of source directory to avoid finding local pywt + pushd demo + if [ "${USE_WHEEL}" == "1" ]; then + pytest --pyargs pywt + python ../pywt/tests/test_doc.py + elif [ "${USE_SDIST}" == "1" ]; then + pytest --pyargs pywt + python ../pywt/tests/test_doc.py + elif [ "${REFGUIDE_CHECK}" == "1" ]; then + python util/refguide_check.py --doctests + else + pytest --pyargs pywt + fi + popd test_pywavelets_macos: name: macos-cp${{ matrix.python-version }}-${{ matrix.OPTIONS_NAME }} @@ -150,7 +148,7 @@ jobs: # Ensure that a wheel builder finishes even if another fails fail-fast: false matrix: - python-version: [3.9, '3.11'] + python-version: [3.9, "3.11"] MINIMUM_REQUIREMENTS: [0] USE_SCIPY: [0] USE_SDIST: [0] @@ -159,10 +157,10 @@ jobs: PIP_FLAGS: [""] OPTIONS_NAME: ["default"] include: - - python-version: '3.9' + - python-version: "3.9" MINIMUM_REQUIREMENTS: 1 OPTIONS_NAME: "osx-minimum-req" - - python-version: '3.11' + - python-version: "3.11" PIP_FLAGS: "--pre" OPTIONS_NAME: "pre-releases" @@ -177,64 +175,64 @@ jobs: - name: Build package env: - VERSION: ${{ matrix.python-version }} - MINIMUM_REQUIREMENTS: ${{ matrix.MINIMUM_REQUIREMENTS }} - PIP_FLAGS: ${{ matrix.PIP_FLAGS }} - USE_WHEEL: ${{ matrix.USE_WHEEL }} - USE_SDIST: ${{ matrix.USE_SDIST }} - USE_SCIPY: ${{ matrix.USE_SCIPY }} - REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} - CC: /usr/bin/clang - CXX: /usr/bin/clang++ + VERSION: ${{ matrix.python-version }} + MINIMUM_REQUIREMENTS: ${{ matrix.MINIMUM_REQUIREMENTS }} + PIP_FLAGS: ${{ matrix.PIP_FLAGS }} + USE_WHEEL: ${{ matrix.USE_WHEEL }} + USE_SDIST: ${{ matrix.USE_SDIST }} + USE_SCIPY: ${{ matrix.USE_SCIPY }} + REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} + CC: /usr/bin/clang + CXX: /usr/bin/clang++ run: | - uname -a - df -h - ulimit -a - which python - python --version - pip install --upgrade pip build - # Set numpy version first, other packages link against it - if [ "${MINIMUM_REQUIREMENTS}" == "1" ]; then - pip install ${CYTHON_MIN} ${NUMPY_MIN} - if [ "${USE_SCIPY}" == "1" ]; then pip install ${SCIPY_MIN}; fi - else - pip install cython numpy - if [ "${USE_SCIPY}" == "1" ]; then pip install scipy; fi - fi - pip install matplotlib pytest - - set -o pipefail - if [ "${USE_WHEEL}" == "1" ]; then - pip wheel . -v - pip install pywavelets*.whl -v - elif [ "${USE_SDIST}" == "1" ]; then - python -m build --sdist - pip install pywavelets* -v - elif [ "${REFGUIDE_CHECK}" == "1" ]; then - pip install sphinx numpydoc - pip install . -v - else - pip install . -v - fi + uname -a + df -h + ulimit -a + which python + python --version + pip install --upgrade pip build + # Set numpy version first, other packages link against it + if [ "${MINIMUM_REQUIREMENTS}" == "1" ]; then + pip install ${CYTHON_MIN} ${NUMPY_MIN} + if [ "${USE_SCIPY}" == "1" ]; then pip install ${SCIPY_MIN}; fi + else + pip install cython numpy + if [ "${USE_SCIPY}" == "1" ]; then pip install scipy; fi + fi + pip install matplotlib pytest + + set -o pipefail + if [ "${USE_WHEEL}" == "1" ]; then + pip wheel . -v + pip install pywavelets*.whl -v + elif [ "${USE_SDIST}" == "1" ]; then + python -m build --sdist + pip install pywavelets* -v + elif [ "${REFGUIDE_CHECK}" == "1" ]; then + pip install sphinx numpydoc + pip install . -v + else + pip install . -v + fi - name: Run tests env: - PIP_FLAGS: ${{ matrix.PIP_FLAGS }} - USE_WHEEL: ${{ matrix.USE_WHEEL }} - USE_SDIST: ${{ matrix.USE_SDIST }} - REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} + PIP_FLAGS: ${{ matrix.PIP_FLAGS }} + USE_WHEEL: ${{ matrix.USE_WHEEL }} + USE_SDIST: ${{ matrix.USE_SDIST }} + REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }} run: | - # Move out of source directory to avoid finding local pywt - pushd demo - if [ "${USE_WHEEL}" == "1" ]; then - pytest --pyargs pywt - python ../pywt/tests/test_doc.py - elif [ "${USE_SDIST}" == "1" ]; then - pytest --pyargs pywt - python ../pywt/tests/test_doc.py - elif [ "${REFGUIDE_CHECK}" == "1" ]; then - python util/refguide_check.py --doctests - else - pytest --pyargs pywt - fi - popd + # Move out of source directory to avoid finding local pywt + pushd demo + if [ "${USE_WHEEL}" == "1" ]; then + pytest --pyargs pywt + python ../pywt/tests/test_doc.py + elif [ "${USE_SDIST}" == "1" ]; then + pytest --pyargs pywt + python ../pywt/tests/test_doc.py + elif [ "${REFGUIDE_CHECK}" == "1" ]; then + python util/refguide_check.py --doctests + else + pytest --pyargs pywt + fi + popd diff --git a/.github/workflows/wheel_tests_and_release.yml b/.github/workflows/wheel_tests_and_release.yml index 07a3c2ef6..41e150a27 100644 --- a/.github/workflows/wheel_tests_and_release.yml +++ b/.github/workflows/wheel_tests_and_release.yml @@ -2,8 +2,8 @@ name: Build Wheels and Release on: push: tags: - - 'v*' - - 'buildwheels*' + - "v*" + - "buildwheels*" env: CIBW_BUILD_VERBOSITY: 2 # CIBW_BEFORE_BUILD: pip install cython @@ -11,7 +11,6 @@ env: CIBW_TEST_COMMAND: pytest --pyargs pywt CIBW_ENVIRONMENT: PIP_PREFER_BINARY=1 - jobs: build_linux_x86_64_wheels: name: Build python ${{ matrix.cibw_python }} ${{ matrix.cibw_arch }} wheels on ${{ matrix.os }} @@ -21,8 +20,8 @@ jobs: matrix: os: [ubuntu-latest] cibw_python: ["cp39-*", "cp310-*", "cp311-*"] - cibw_manylinux: [ manylinux2014 ] - cibw_arch: [ "x86_64"] + cibw_manylinux: [manylinux2014] + cibw_arch: ["x86_64"] steps: - uses: actions/checkout@v3 with: @@ -30,7 +29,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.9' + python-version: "3.9" - name: Install cibuildwheel run: | python -m pip install cibuildwheel @@ -56,7 +55,7 @@ jobs: matrix: os: [ubuntu-latest] cibw_python: ["cp39-*", "cp310-*", "cp311-*"] - cibw_manylinux: [ manylinux2014 ] + cibw_manylinux: [manylinux2014] steps: - uses: actions/checkout@v3 with: @@ -64,7 +63,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.9' + python-version: "3.9" - name: Set up QEMU uses: docker/setup-qemu-action@v1 with: @@ -92,7 +91,7 @@ jobs: fail-fast: false matrix: os: [macos-latest] - cibw_python: ["cp39-*", "cp310-*" , "cp311-*" ] + cibw_python: ["cp39-*", "cp310-*", "cp311-*"] cibw_arch: ["x86_64", "arm64"] steps: - uses: actions/checkout@v3 @@ -102,7 +101,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.9' + python-version: "3.9" - name: Install cibuildwheel run: | @@ -149,7 +148,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.9' + python-version: "3.9" - name: Install cibuildwheel run: | @@ -157,13 +156,13 @@ jobs: - name: Setup MSVC (32-bit) if: matrix.cibw_arch == 'x86' - uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 + uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 with: architecture: x86 - name: Setup MSVC (64-bit) if: matrix.cibw_arch == 'AMD64' - uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 + uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 with: architecture: x64 @@ -181,7 +180,13 @@ jobs: deploy: name: Release - needs: [build_linux_x86_64_wheels, build_linux_aarch64_wheels, build_macos_wheels, build_windows_wheels] + needs: + [ + build_linux_x86_64_wheels, + build_linux_aarch64_wheels, + build_macos_wheels, + build_windows_wheels, + ] if: github.repository_owner == 'PyWavelets' && startsWith(github.ref, 'refs/tags/v') && always() runs-on: ubuntu-latest steps: @@ -192,20 +197,20 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.9' - + python-version: "3.9" + - name: Install Twine run: | python -m pip install --upgrade pip pip install twine pip install "cython<3" numpy - + - uses: actions/download-artifact@v3 id: download with: name: wheels path: ./dist - + - name: Publish the source distribution on PyPI run: | PYWT_VERSION=$(git describe --tags) diff --git a/benchmarks/README.rst b/benchmarks/README.rst index b24123180..2035cc889 100644 --- a/benchmarks/README.rst +++ b/benchmarks/README.rst @@ -79,4 +79,3 @@ Some things to consider: - Preparing arrays etc. should generally be put in the ``setup`` method rather than the ``time_`` methods, to avoid counting preparation time together with the time of the benchmarked operation. - diff --git a/benchmarks/benchmarks/__init__.py b/benchmarks/benchmarks/__init__.py index 8b1378917..e69de29bb 100644 --- a/benchmarks/benchmarks/__init__.py +++ b/benchmarks/benchmarks/__init__.py @@ -1 +0,0 @@ - diff --git a/benchmarks/benchmarks/cwt_benchmarks.py b/benchmarks/benchmarks/cwt_benchmarks.py index eda4e4f2e..21eed8d07 100644 --- a/benchmarks/benchmarks/cwt_benchmarks.py +++ b/benchmarks/benchmarks/cwt_benchmarks.py @@ -1,8 +1,9 @@ import numpy as np + import pywt -class CwtTimeSuiteBase(object): +class CwtTimeSuiteBase: """ Set-up for CWT timing. """ diff --git a/benchmarks/benchmarks/dwt_benchmarks.py b/benchmarks/benchmarks/dwt_benchmarks.py index f1761fe94..80c526924 100644 --- a/benchmarks/benchmarks/dwt_benchmarks.py +++ b/benchmarks/benchmarks/dwt_benchmarks.py @@ -1,4 +1,5 @@ import numpy as np + import pywt try: @@ -8,7 +9,7 @@ Modes = pywt.MODES -class DwtTimeSuiteBase(object): +class DwtTimeSuiteBase: """ Set-up for (I)DWT timing. """ @@ -28,14 +29,14 @@ def time_dwt(self, n, wavelet, mode): class IdwtTimeSuite(DwtTimeSuiteBase): def setup(self, n, wavelet, mode): - super(IdwtTimeSuite, self).setup(n, wavelet, mode) + super().setup(n, wavelet, mode) self.cA, self.cD = pywt.dwt(self.data, wavelet, mode) def time_idwt(self, n, wavelet, mode): pywt.idwt(self.cA, self.cD, wavelet, mode) -class Dwt2TimeSuiteBase(object): +class Dwt2TimeSuiteBase: """ Set-up for (I)DWT2 timing. """ @@ -54,14 +55,14 @@ def time_dwt2(self, n, wavelet): class Idwt2TimeSuite(Dwt2TimeSuiteBase): def setup(self, n, wavelet): - super(Idwt2TimeSuite, self).setup(n, wavelet) + super().setup(n, wavelet) self.data = pywt.dwt2(self.data, wavelet) def time_idwt2(self, n, wavelet): pywt.idwt2(self.data, wavelet) -class DwtnTimeSuiteBase(object): +class DwtnTimeSuiteBase: """ Set-up for (I)DWTN timing. """ @@ -81,7 +82,7 @@ def time_dwtn(self, D, n, wavelet): class IdwtnTimeSuite(DwtnTimeSuiteBase): def setup(self, D, n, wavelet): - super(IdwtnTimeSuite, self).setup(D, n, wavelet) + super().setup(D, n, wavelet) self.data = pywt.dwtn(self.data, wavelet) def time_idwtn(self, D, n, wavelet): @@ -93,7 +94,7 @@ def time_idwtn(self, D, n, wavelet): """ -class WavedecTimeSuiteBase(object): +class WavedecTimeSuiteBase: """ Set-up for wavedec, waverec timing. """ @@ -113,14 +114,14 @@ def time_wavedec(self, n, wavelet, dtype): class WaverecTimeSuite(WavedecTimeSuiteBase): def setup(self, n, wavelet, dtype): - super(WaverecTimeSuite, self).setup(n, wavelet, dtype) + super().setup(n, wavelet, dtype) self.data = pywt.wavedec(self.data, wavelet) def time_waverec(self, n, wavelet, dtype): pywt.waverec(self.data, wavelet) -class Wavedec2TimeSuiteBase(object): +class Wavedec2TimeSuiteBase: """ Set-up for wavedec2, waverec2 timing. """ @@ -140,14 +141,14 @@ def time_wavedec2(self, n, wavelet, dtype): class Waverec2TimeSuite(Wavedec2TimeSuiteBase): def setup(self, n, wavelet, dtype): - super(Waverec2TimeSuite, self).setup(n, wavelet, dtype) + super().setup(n, wavelet, dtype) self.data = pywt.wavedec2(self.data, wavelet) def time_waverec2(self, n, wavelet, dtype): pywt.waverec2(self.data, wavelet) -class WavedecnTimeSuiteBase(object): +class WavedecnTimeSuiteBase: """ Set-up for wavedecn, waverecn timing. """ @@ -176,7 +177,7 @@ def setup(self, D, n, wavelet, dtype): from pywt import waverecn except ImportError: raise NotImplementedError("waverecn not available") - super(WaverecnTimeSuite, self).setup(D, n, wavelet, dtype) + super().setup(D, n, wavelet, dtype) self.data = pywt.wavedecn(self.data, wavelet) def time_waverecn(self, D, n, wavelet, dtype): diff --git a/benchmarks/benchmarks/swt_benchmarks.py b/benchmarks/benchmarks/swt_benchmarks.py index 013c2c545..5f97fbfa5 100644 --- a/benchmarks/benchmarks/swt_benchmarks.py +++ b/benchmarks/benchmarks/swt_benchmarks.py @@ -1,8 +1,9 @@ import numpy as np + import pywt -class SwtTimeSuiteBase(object): +class SwtTimeSuiteBase: """ Set-up for (I)SWT timing. """ @@ -25,14 +26,14 @@ def setup(self, n, wavelet): from pywt import iswt except ImportError: raise NotImplementedError("iswt not available") - super(IswtTimeSuite, self).setup(n, wavelet) + super().setup(n, wavelet) self.coeffs = pywt.swt(self.data, wavelet) def time_iswt(self, n, wavelet): pywt.iswt(self.coeffs, wavelet) -class Swt2TimeSuiteBase(object): +class Swt2TimeSuiteBase: """ Set-up for (I)SWT2 timing. """ @@ -60,14 +61,14 @@ def setup(self, n, wavelet): from pywt import iswt2 except ImportError: raise NotImplementedError("iswt2 not available") - super(Iswt2TimeSuite, self).setup(n, wavelet) + super().setup(n, wavelet) self.data = pywt.swt2(self.data, wavelet, self.level) def time_iswt2(self, n, wavelet): pywt.iswt2(self.data, wavelet) -class SwtnTimeSuiteBase(object): +class SwtnTimeSuiteBase: """ Set-up for (I)SWTN timing. """ @@ -97,7 +98,7 @@ def setup(self, D, n, wavelet, dtype): from pywt import iswtn except ImportError: raise NotImplementedError("iswtn not available") - super(IswtnTimeSuite, self).setup(D, n, wavelet, dtype) + super().setup(D, n, wavelet, dtype) self.data = pywt.swtn(self.data, wavelet, self.level) def time_iswtn(self, D, n, wavelet, dtype): diff --git a/demo/benchmark.py b/demo/benchmark.py index a1402fb24..61efb031c 100644 --- a/demo/benchmark.py +++ b/demo/benchmark.py @@ -1,16 +1,14 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import gc import sys import time -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt - if sys.platform == 'win32': clock = time.clock else: diff --git a/demo/cwt_analysis.py b/demo/cwt_analysis.py index 77ea8f0bb..85f53e2a8 100644 --- a/demo/cwt_analysis.py +++ b/demo/cwt_analysis.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt diff --git a/demo/dwt2_dwtn_image.py b/demo/dwt2_dwtn_image.py index 90815d7c5..a02fc6766 100644 --- a/demo/dwt2_dwtn_image.py +++ b/demo/dwt2_dwtn_image.py @@ -1,13 +1,11 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data - # Load image original = pywt.data.camera() diff --git a/demo/dwt_signal_decomposition.py b/demo/dwt_signal_decomposition.py index 23ca17d76..23b8318c8 100644 --- a/demo/dwt_signal_decomposition.py +++ b/demo/dwt_signal_decomposition.py @@ -1,20 +1,18 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data - ecg = pywt.data.ecg() data1 = np.concatenate((np.arange(1, 400), np.arange(398, 600), np.arange(601, 1024))) x = np.linspace(0.082, 2.128, num=1024)[::-1] -data2 = np.sin(40 * np.log(x)) * np.sign((np.log(x))) +data2 = np.sin(40 * np.log(x)) * np.sign(np.log(x)) mode = pywt.Modes.smooth diff --git a/demo/dwt_swt_show_coeffs.py b/demo/dwt_swt_show_coeffs.py index 9a3b1980d..dfb333497 100644 --- a/demo/dwt_swt_show_coeffs.py +++ b/demo/dwt_swt_show_coeffs.py @@ -1,20 +1,18 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data - ecg = pywt.data.ecg() data1 = np.concatenate((np.arange(1, 400), np.arange(398, 600), np.arange(601, 1024))) x = np.linspace(0.082, 2.128, num=1024)[::-1] -data2 = np.sin(40 * np.log(x)) * np.sign((np.log(x))) +data2 = np.sin(40 * np.log(x)) * np.sign(np.log(x)) mode = pywt.Modes.sp1DWT = 1 diff --git a/demo/fswavedecn.py b/demo/fswavedecn.py index 67a5aba90..987b73e5e 100644 --- a/demo/fswavedecn.py +++ b/demo/fswavedecn.py @@ -1,5 +1,6 @@ import numpy as np from matplotlib import pyplot as plt + import pywt img = pywt.data.camera().astype(float) diff --git a/demo/fswavedecn_mondrian.py b/demo/fswavedecn_mondrian.py index 5e95ef31f..725d9f16d 100644 --- a/demo/fswavedecn_mondrian.py +++ b/demo/fswavedecn_mondrian.py @@ -20,10 +20,10 @@ """ import numpy as np -import pywt - from matplotlib import pyplot as plt +import pywt + def mondrian(shape=(256, 256), nx=5, ny=8, seed=4): """ Piecewise-constant image (reminiscent of Dutch painter Piet Mondrian's @@ -69,7 +69,7 @@ def mondrian(shape=(256, 256), nx=5, ny=8, seed=4): img = mondrian() fig, axes = plt.subplots(1, 3) -imshow_kwargs = dict(cmap=plt.cm.gray, interpolation='nearest') +imshow_kwargs = {'cmap': plt.cm.gray, 'interpolation': 'nearest'} axes[0].imshow(img, **imshow_kwargs) axes[0].set_title('Anisotropic Image') axes[1].imshow(coeff_array_dwt != 0, **imshow_kwargs) diff --git a/demo/image_blender.py b/demo/image_blender.py index a30185e5f..da48410be 100644 --- a/demo/image_blender.py +++ b/demo/image_blender.py @@ -40,13 +40,14 @@ import optparse import os import sys + if os.name == 'nt': from time import clock # noqa else: from time import time as clock # noqa -from PIL import Image # PIL import numpy # http://www.scipy.org +from PIL import Image # PIL import pywt diff --git a/demo/mra2d.py b/demo/mra2d.py index 6358704a2..0490425bd 100644 --- a/demo/mra2d.py +++ b/demo/mra2d.py @@ -16,12 +16,12 @@ details = coeffs[1:] # Plot all coefficient subbands and the original -gridspec_kw = dict(hspace=0.1, wspace=0.1) -fontdict = dict(verticalalignment='center', horizontalalignment='center', - color='k') +gridspec_kw = {'hspace': 0.1, 'wspace': 0.1} +fontdict = {'verticalalignment': 'center', 'horizontalalignment': 'center', + 'color': 'k'} fig, axes = plt.subplots(len(details) + 1, 3, figsize=[5, 8], sharex=True, sharey=True, gridspec_kw=gridspec_kw) -imshow_kw = dict(interpolation='nearest', cmap=plt.cm.gray) +imshow_kw = {'interpolation': 'nearest', 'cmap': plt.cm.gray} for i, x in enumerate(details): axes[i][0].imshow(details[-i - 1]['ad'], **imshow_kw) diff --git a/demo/mra_vs_swt.py b/demo/mra_vs_swt.py index 581aff645..af4bfc42c 100644 --- a/demo/mra_vs_swt.py +++ b/demo/mra_vs_swt.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data diff --git a/demo/plot_demo_signals.py b/demo/plot_demo_signals.py index 6d5d6fee3..919b87af3 100644 --- a/demo/plot_demo_signals.py +++ b/demo/plot_demo_signals.py @@ -1,11 +1,9 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """Plot the set of 1D demo signals available in `pywt.data.demo_signal`.""" -import numpy as np - import matplotlib.pyplot as plt +import numpy as np import pywt diff --git a/demo/plot_wavelets.py b/demo/plot_wavelets.py index 67606b53b..c0948e99d 100644 --- a/demo/plot_wavelets.py +++ b/demo/plot_wavelets.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # Plot scaling and wavelet functions for db, sym, coif, bior and rbio families @@ -9,7 +8,6 @@ import pywt - plot_data = [('db', (4, 3)), ('sym', (4, 3)), ('coif', (3, 2))] diff --git a/demo/plot_wavelets_pyqtgraph.py b/demo/plot_wavelets_pyqtgraph.py index 184dec4d4..fa0c02c64 100644 --- a/demo/plot_wavelets_pyqtgraph.py +++ b/demo/plot_wavelets_pyqtgraph.py @@ -1,9 +1,9 @@ import sys -import pywt -from pyqtgraph.Qt import QtGui import pyqtgraph as pg +from pyqtgraph.Qt import QtGui +import pywt families = ['db', 'sym', 'coif', 'bior', 'rbio'] diff --git a/demo/swt2.py b/demo/swt2.py index a3b205a38..fb29fc474 100644 --- a/demo/swt2.py +++ b/demo/swt2.py @@ -1,12 +1,10 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import matplotlib.pyplot as plt import pywt import pywt.data - arr = pywt.data.aero() plt.imshow(arr, interpolation="nearest", cmap=plt.cm.gray) diff --git a/demo/swt_variance.py b/demo/swt_variance.py index 9fb52afef..799dd1a99 100644 --- a/demo/swt_variance.py +++ b/demo/swt_variance.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data @@ -51,7 +51,7 @@ # create a plot of the variance as a function of level plt.figure(figsize=(8, 6)) -fontdict = dict(fontsize=16, fontweight='bold') +fontdict = {'fontsize': 16, 'fontweight': 'bold'} plt.plot(level, detail_variances[::-1], 'k.') plt.xlabel("Decomposition level", fontdict=fontdict) plt.ylabel("Variance", fontdict=fontdict) diff --git a/demo/waveinfo.py b/demo/waveinfo.py index 5e047c741..fcf8171a0 100644 --- a/demo/waveinfo.py +++ b/demo/waveinfo.py @@ -1,12 +1,11 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import sys import matplotlib.pyplot as plt import numpy as np -import pywt +import pywt usage = """ Usage: diff --git a/demo/wp_2d.py b/demo/wp_2d.py index ff679e666..f75f9e1cc 100644 --- a/demo/wp_2d.py +++ b/demo/wp_2d.py @@ -1,12 +1,10 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np -from pywt import WaveletPacket2D import pywt.data - +from pywt import WaveletPacket2D arr = pywt.data.aero() diff --git a/demo/wp_nd.py b/demo/wp_nd.py index 74a927413..921f4d321 100644 --- a/demo/wp_nd.py +++ b/demo/wp_nd.py @@ -1,12 +1,11 @@ #!/usr/bin/env python # Note: This demo is a repeat of wp_2d, but using WaveletPacketND instead -import numpy as np import matplotlib.pyplot as plt +import numpy as np -from pywt import WaveletPacketND import pywt.data - +from pywt import WaveletPacketND arr = pywt.data.aero() diff --git a/demo/wp_scalogram.py b/demo/wp_scalogram.py index 6334d462e..5df9afede 100644 --- a/demo/wp_scalogram.py +++ b/demo/wp_scalogram.py @@ -1,12 +1,10 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt - x = np.linspace(0, 1, num=512) data = np.sin(250 * np.pi * x**2) diff --git a/demo/wp_visualize_coeffs_distribution.py b/demo/wp_visualize_coeffs_distribution.py index d5af2faa6..29bfede01 100644 --- a/demo/wp_visualize_coeffs_distribution.py +++ b/demo/wp_visualize_coeffs_distribution.py @@ -1,14 +1,12 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os -import numpy as np import matplotlib.pyplot as plt +import numpy as np -from pywt import WaveletPacket import pywt.data - +from pywt import WaveletPacket ecg = pywt.data.ecg() diff --git a/doc/paper/paper.md b/doc/paper/paper.md index 670366057..50d467691 100644 --- a/doc/paper/paper.md +++ b/doc/paper/paper.md @@ -1,5 +1,5 @@ --- -title: 'PyWavelets: A Python package for wavelet analysis' +title: "PyWavelets: A Python package for wavelet analysis" tags: - Python - wavelets @@ -24,18 +24,18 @@ authors: orcid: 0000-0003-1984-2323 affiliation: 6 affiliations: - - name: Department of Radiology, Cincinnati Children's Hospital Medical Center, Cincinnati, OH, USA - index: 1 - - name: Department of Radiology, University of Cincinnati School of Medicine, Cincinnati, OH, USA - index: 2 - - name: Scion, 49 Sala Street, Private Bag 3020, Rotorua 3046, New Zealand - index: 3 - - name: FPInnovations, 2665 East Mall, Vancouver, BC V6T 1Z4, Canada - index: 4 - - name: Department of Biochemistry, University of Cambridge, Old Addenbrookes Site, 80 Tennis Court Road, Cambridge, CB2 1GA, United Kingdom - index: 5 - - name: None - index: 6 + - name: Department of Radiology, Cincinnati Children's Hospital Medical Center, Cincinnati, OH, USA + index: 1 + - name: Department of Radiology, University of Cincinnati School of Medicine, Cincinnati, OH, USA + index: 2 + - name: Scion, 49 Sala Street, Private Bag 3020, Rotorua 3046, New Zealand + index: 3 + - name: FPInnovations, 2665 East Mall, Vancouver, BC V6T 1Z4, Canada + index: 4 + - name: Department of Biochemistry, University of Cambridge, Old Addenbrookes Site, 80 Tennis Court Road, Cambridge, CB2 1GA, United Kingdom + index: 5 + - name: None + index: 6 date: 24 August 2018 bibliography: paper.bib @@ -53,7 +53,7 @@ key to the good performance of wavelets in applications such as data compression and denoising. For example, the wavelet transform is a key component of the JPEG 2000 image compression standard. -``PyWavelets`` is a Python package implementing a number of n-dimensional +`PyWavelets` is a Python package implementing a number of n-dimensional discrete wavelet transforms as well as the 1D continuous wavelet transform. A wide variety of predefined wavelets are provided and it is possible for users to specify custom wavelet filter banks. All discrete wavelet transforms are @@ -62,7 +62,7 @@ up/downsampling convolutions are implemented in C for good performance. Cython [@cython] is used to wrap the C code and implement axis-specific 1D transformations based on the low-level C routines. All multi-dimensional transforms are implemented in Python via separable application of the 1D -transforms. The API for ``PyWavelets`` was designed to be similar to Matlab's +transforms. The API for `PyWavelets` was designed to be similar to Matlab's wavelet toolbox and functions such as the 1D, 2D and 3D discrete wavelet transforms are tested for accuracy vs. their Matlab counterparts. PyWavelets has additional functionality not common in other wavelet toolboxes such as @@ -71,7 +71,7 @@ data in either single or double precision. It is also possible to transform only a subset of axes and to vary the wavelet and signal boundary extension mode on a per-axis basis. -``PyWavelets`` was designed for use by scientists working within a range of +`PyWavelets` was designed for use by scientists working within a range of applications including time-series analysis, signal processing, image processing and medical imaging. It has already been adopted as a required or optional dependency by a number of other software projects. For example, @@ -79,7 +79,7 @@ it has enabled wavelet-based image denoising in scikit-image [@scikit-image]. The Operator Discretization Library (ODL) [@odl] uses PyWavelets to enable wavelet-based regularization in iterative inverse problems such as computed tomography image reconstruction. Another related package which is independent -of ``PyWavelets`` is Kymatio, which implements the wavelet scattering +of `PyWavelets` is Kymatio, which implements the wavelet scattering transform in 1D-3D [@kymatio]. The current implementation in Kymatio uses non-separable 2D and 3D wavelets defined in the frequency domain and is well suited to signal classification tasks, but does not have a simple inverse diff --git a/doc/release/1.0.2-notes.rst b/doc/release/1.0.2-notes.rst index 297aebd85..f2706c15e 100644 --- a/doc/release/1.0.2-notes.rst +++ b/doc/release/1.0.2-notes.rst @@ -70,5 +70,3 @@ The backports listed above correspond to the following PRs from the master branc - `#450 `__: handle mixed dtype coefficients correctly across inverse transforms - `#452 `__: bump minimum supported Cython version - `#462 `__: fix bug in iswtn for data of arbitrary shape when using user-specified axes - - diff --git a/doc/release/1.2.0-notes.rst b/doc/release/1.2.0-notes.rst index e1acfdf99..ef1d5349b 100644 --- a/doc/release/1.2.0-notes.rst +++ b/doc/release/1.2.0-notes.rst @@ -100,4 +100,3 @@ Pull requests for v1.2 * `#609 `__: MAINT: fix \`origin='image'\` calls that Matplotlib no longer... * `#610 `__: Update GitHub Actions workflow to build Python 3.10 wheels * `#611 `__: MAINT: fix doc build issues - diff --git a/doc/release/1.4.0-notes.rst b/doc/release/1.4.0-notes.rst index af55f18c5..a59c28496 100644 --- a/doc/release/1.4.0-notes.rst +++ b/doc/release/1.4.0-notes.rst @@ -12,7 +12,7 @@ There is one new utility function, `pywt.frequency2scale`, that can be used to determine CWT scale factors corresponding to a given (normalized) frequency. It is the inverse of the existing `pywt.scale2frequency`. -A detailed change log is provided below. +A detailed change log is provided below. Authors ======= diff --git a/doc/source/conf.py b/doc/source/conf.py index 42338cbd2..abf11c336 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # PyWavelets documentation build configuration file, created by # sphinx-quickstart on Sun Mar 14 10:46:18 2010. @@ -11,10 +10,10 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import re import datetime -import jinja2.filters +import re +import jinja2.filters import numpy as np # FIXME: doctests need the str/repr formatting used in Numpy < 1.14. @@ -62,6 +61,7 @@ # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. import pywt + version = re.sub(r'\.dev0+.*$', r'.dev', pywt.__version__) release = pywt.__version__ diff --git a/doc/source/dev/building_extension.rst b/doc/source/dev/building_extension.rst index ed7150fcf..7c8bd817b 100644 --- a/doc/source/dev/building_extension.rst +++ b/doc/source/dev/building_extension.rst @@ -43,4 +43,3 @@ Installing a regular release from PyPi A regular release can be installed with pip or easy_install:: pip install PyWavelets - diff --git a/doc/source/dev/conduct/code_of_conduct.rst b/doc/source/dev/conduct/code_of_conduct.rst index 63933c093..49d23d17f 100644 --- a/doc/source/dev/conduct/code_of_conduct.rst +++ b/doc/source/dev/conduct/code_of_conduct.rst @@ -173,4 +173,3 @@ The SciPy code of conduct was in turn inspired by the following documents: - `The Contributor Covenant `_ - `Jupyter Code of Conduct `_ - `Open Source Guides - Code of Conduct `_ - diff --git a/doc/source/pyplots/camera_approx_detail.py b/doc/source/pyplots/camera_approx_detail.py index ca8b97d65..513b290c8 100644 --- a/doc/source/pyplots/camera_approx_detail.py +++ b/doc/source/pyplots/camera_approx_detail.py @@ -1,10 +1,9 @@ -import numpy as np import matplotlib.pyplot as plt +import numpy as np import pywt import pywt.data - # Load image original = pywt.data.camera() diff --git a/doc/source/pyplots/cwt_scaling_demo.py b/doc/source/pyplots/cwt_scaling_demo.py index 154de97a8..cb3124c05 100644 --- a/doc/source/pyplots/cwt_scaling_demo.py +++ b/doc/source/pyplots/cwt_scaling_demo.py @@ -1,6 +1,7 @@ +import matplotlib.pyplot as plt import numpy as np + import pywt -import matplotlib.pyplot as plt wav = pywt.ContinuousWavelet('cmor1.5-1.0') @@ -23,7 +24,7 @@ j = np.floor( np.arange(scale * width + 1) / (scale * step)) if np.max(j) >= np.size(int_psi): - j = np.delete(j, np.where((j >= np.size(int_psi)))[0]) + j = np.delete(j, np.where(j >= np.size(int_psi))[0]) j = j.astype(np.int_) # normalize int_psi for easier plotting diff --git a/doc/source/pyplots/plot_2d_bases.py b/doc/source/pyplots/plot_2d_bases.py index 234703ad6..e0a7757bb 100644 --- a/doc/source/pyplots/plot_2d_bases.py +++ b/doc/source/pyplots/plot_2d_bases.py @@ -1,8 +1,14 @@ from itertools import product + import numpy as np from matplotlib import pyplot as plt -from pywt._doc_utils import (wavedec_keys, wavedec2_keys, draw_2d_wp_basis, - draw_2d_fswavedecn_basis) + +from pywt._doc_utils import ( + draw_2d_fswavedecn_basis, + draw_2d_wp_basis, + wavedec2_keys, + wavedec_keys, +) shape = (512, 512) diff --git a/doc/source/pyplots/plot_boundary_modes.py b/doc/source/pyplots/plot_boundary_modes.py index 940822f76..2f38d7aee 100644 --- a/doc/source/pyplots/plot_boundary_modes.py +++ b/doc/source/pyplots/plot_boundary_modes.py @@ -11,6 +11,7 @@ """ import numpy as np from matplotlib import pyplot as plt + from pywt._doc_utils import boundary_mode_subplot # synthetic test signal diff --git a/doc/source/pyplots/plot_mallat_2d.py b/doc/source/pyplots/plot_mallat_2d.py index ab01a1d5c..5485cd1e8 100644 --- a/doc/source/pyplots/plot_mallat_2d.py +++ b/doc/source/pyplots/plot_mallat_2d.py @@ -1,7 +1,8 @@ import numpy as np -import pywt from matplotlib import pyplot as plt -from pywt._doc_utils import wavedec2_keys, draw_2d_wp_basis + +import pywt +from pywt._doc_utils import draw_2d_wp_basis, wavedec2_keys x = pywt.data.camera().astype(np.float32) shape = x.shape @@ -10,7 +11,7 @@ label_levels = 3 # how many levels to explicitly label on the plots fig, axes = plt.subplots(2, 4, figsize=[14, 8]) -for level in range(0, max_lev + 1): +for level in range(max_lev + 1): if level == 0: # show the original image before decomposition axes[0, 0].set_axis_off() diff --git a/doc/source/pyplots/plot_thresholds.py b/doc/source/pyplots/plot_thresholds.py index 6b86fd5c8..886ab3640 100644 --- a/doc/source/pyplots/plot_thresholds.py +++ b/doc/source/pyplots/plot_thresholds.py @@ -1,5 +1,6 @@ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import pywt s = np.linspace(-4, 4, 1000) diff --git a/doc/source/ref/2d-dwt-and-idwt.rst b/doc/source/ref/2d-dwt-and-idwt.rst index 7628d761e..a1503344e 100644 --- a/doc/source/ref/2d-dwt-and-idwt.rst +++ b/doc/source/ref/2d-dwt-and-idwt.rst @@ -77,4 +77,3 @@ horizontal as follows:: | | axis 0 v - diff --git a/doc/source/ref/mra.rst b/doc/source/ref/mra.rst index 8570a9b91..40f3d3da0 100644 --- a/doc/source/ref/mra.rst +++ b/doc/source/ref/mra.rst @@ -40,4 +40,3 @@ Inverse Multilevel n-dimensional ``imran`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: imran - diff --git a/pywt/_c99_config.py.in b/pywt/_c99_config.py.in index 821f9d7d1..ad2dc41ce 100644 --- a/pywt/_c99_config.py.in +++ b/pywt/_c99_config.py.in @@ -1,4 +1,3 @@ # Autogenerated file containing compile-time definitions _have_c99_complex = @have_c99_complex@ - diff --git a/pywt/_cwt.py b/pywt/_cwt.py index 62d0e3da8..cad9b04c7 100644 --- a/pywt/_cwt.py +++ b/pywt/_cwt.py @@ -1,10 +1,13 @@ -from math import floor, ceil - -from ._extensions._pywt import (DiscreteContinuousWavelet, ContinuousWavelet, - Wavelet, _check_dtype) +from math import ceil, floor + +from ._extensions._pywt import ( + ContinuousWavelet, + DiscreteContinuousWavelet, + Wavelet, + _check_dtype, +) from ._functions import integrate_wavelet, scale2frequency - __all__ = ["cwt"] @@ -134,7 +137,7 @@ def cwt(data, scales, wavelet, sampling_period=1., method='conv', axis=-1): if method == 'fft': size_scale0 = -1 fft_data = None - elif not method == 'conv': + elif method != "conv": raise ValueError("method must be 'conv' or 'fft'") if data.ndim > 1: diff --git a/pywt/_doc_utils.py b/pywt/_doc_utils.py index ee906aeab..827d12c99 100644 --- a/pywt/_doc_utils.py +++ b/pywt/_doc_utils.py @@ -182,6 +182,6 @@ def boundary_mode_subplot(x, mode, ax, symw=True): step = len(x) rng = range(-2, 4) if mode in ['smooth', 'constant', 'zero']: - rng = range(0, 2) + rng = range(2) for rep in rng: ax.plot((left + rep * step) * o2, [xp.min() - .5, xp.max() + .5], 'k-') diff --git a/pywt/_dwt.py b/pywt/_dwt.py index 88bd2ca06..014796d50 100644 --- a/pywt/_dwt.py +++ b/pywt/_dwt.py @@ -3,14 +3,14 @@ import numpy as np from ._c99_config import _have_c99_complex -from ._extensions._pywt import Wavelet, Modes, _check_dtype, wavelist -from ._extensions._dwt import (dwt_single, dwt_axis, idwt_single, idwt_axis, - upcoef as _upcoef, downcoef as _downcoef, - dwt_max_level as _dwt_max_level, - dwt_coeff_len as _dwt_coeff_len) +from ._extensions._dwt import downcoef as _downcoef +from ._extensions._dwt import dwt_axis, dwt_single, idwt_axis, idwt_single +from ._extensions._dwt import dwt_coeff_len as _dwt_coeff_len +from ._extensions._dwt import dwt_max_level as _dwt_max_level +from ._extensions._dwt import upcoef as _upcoef +from ._extensions._pywt import Modes, Wavelet, _check_dtype, wavelist from ._utils import _as_wavelet - __all__ = ["dwt", "idwt", "downcoef", "upcoef", "dwt_max_level", "dwt_coeff_len", "pad"] @@ -66,9 +66,9 @@ def dwt_max_level(data_len, filter_len): filter_len = Wavelet(filter_len).dec_len else: raise ValueError( - ("'{}', is not a recognized discrete wavelet. A list of " + f"'{filter_len}', is not a recognized discrete wavelet. A list of " "supported wavelet names can be obtained via " - "pywt.wavelist(kind='discrete')").format(filter_len)) + "pywt.wavelist(kind='discrete')") elif not (isinstance(filter_len, Number) and filter_len % 1 == 0): raise ValueError( "filter_len must be an integer, discrete Wavelet object, or the " diff --git a/pywt/_extensions/_cwt.pyx b/pywt/_extensions/_cwt.pyx index 039943ff0..f4a8ca92d 100644 --- a/pywt/_extensions/_cwt.pyx +++ b/pywt/_extensions/_cwt.pyx @@ -122,4 +122,3 @@ cpdef cwt_psi_single(data_t[::1] data, ContinuousWavelet wavelet, size_t output_ with nogil: c_wt.float_cmor(&data[0], psi_r.data, psi_i.data, data_size, bandwidth_frequency, center_frequency) return (psi_r, psi_i) - diff --git a/pywt/_extensions/c/wavelets_coeffs.template.h b/pywt/_extensions/c/wavelets_coeffs.template.h index e45f4fae8..8f5853c1a 100644 --- a/pywt/_extensions/c/wavelets_coeffs.template.h +++ b/pywt/_extensions/c/wavelets_coeffs.template.h @@ -25,7 +25,7 @@ * ftp://phase.etl.go.jp/pub/phase/wavelet/index.html * * Compiled and verified by Olli Niemitalo. - * + * * Coefficients for Coiflets wavelets 1-17 * ----------------------------------------- * Computed by Kazuo Hatano, Aichi Institute of Technology. @@ -1696,7 +1696,7 @@ static const TYPE CAT(sym20_, TYPE)[40] = { // The coif wavelets have to be multiplied by sqrt(2) static const TYPE CAT(sqrt2_, TYPE) = 1.4142135623730951454746218587388284504413604736328125; - + static const TYPE CAT(coif1_, TYPE)[6] = { -5.142972847076845595317549230122688830344559947132656813651045e-02, 2.389297284707684559531754923012268883034455994713265681365104e-01, diff --git a/pywt/_extensions/c_wt.pxd b/pywt/_extensions/c_wt.pxd index f08387938..b0d33854b 100644 --- a/pywt/_extensions/c_wt.pxd +++ b/pywt/_extensions/c_wt.pxd @@ -204,4 +204,3 @@ cdef extern from "c/cwt.h": cdef void float_cmor(const float * const input, float * const output_r, float * const output_i, const size_t N, float FB, float FC) nogil - diff --git a/pywt/_extensions/wavelet.pxd b/pywt/_extensions/wavelet.pxd index e03825df7..5cffff088 100644 --- a/pywt/_extensions/wavelet.pxd +++ b/pywt/_extensions/wavelet.pxd @@ -75,6 +75,3 @@ cdef extern from "c/wavelets.h": cdef ContinuousWavelet* continuous_wavelet(WAVELET_NAME name, int type) cdef ContinuousWavelet* blank_continuous_wavelet() cdef void free_continuous_wavelet(ContinuousWavelet* wavelet) - - - diff --git a/pywt/_functions.py b/pywt/_functions.py index 57c0462b3..b2826d816 100644 --- a/pywt/_functions.py +++ b/pywt/_functions.py @@ -7,17 +7,15 @@ Other wavelet related functions. """ -from __future__ import division, print_function, absolute_import import warnings import numpy as np from numpy.fft import fft -from ._extensions._pywt import DiscreteContinuousWavelet, Wavelet, ContinuousWavelet +from ._extensions._pywt import ContinuousWavelet, DiscreteContinuousWavelet, Wavelet - -__all__ = ["integrate_wavelet", "central_frequency", +__all__ = ["integrate_wavelet", "central_frequency", "scale2frequency", "frequency2scale", "qmf", "orthogonal_filter_bank", "intwave", "centrfrq", "scal2frq", "orthfilt"] diff --git a/pywt/_mra.py b/pywt/_mra.py index e489746e8..a41431e34 100644 --- a/pywt/_mra.py +++ b/pywt/_mra.py @@ -2,8 +2,15 @@ import numpy as np -from ._multilevel import (_prep_axes_wavedecn, wavedec, wavedec2, wavedecn, - waverec, waverec2, waverecn) +from ._multilevel import ( + _prep_axes_wavedecn, + wavedec, + wavedec2, + wavedecn, + waverec, + waverec2, + waverecn, +) from ._swt import iswt, iswt2, iswtn, swt, swt2, swt_max_level, swtn from ._utils import _modes_per_axis, _wavelets_per_axis @@ -69,12 +76,12 @@ def mra(data, wavelet, level=None, axis=-1, transform='swt', if mode != 'periodization': raise ValueError( "transform swt only supports mode='periodization'") - kwargs = dict(wavelet=wavelet, axis=axis, norm=True) + kwargs = {"wavelet": wavelet, "axis": axis, "norm": True} forward = partial(swt, level=level, trim_approx=True, **kwargs) inverse = partial(iswt, **kwargs) is_swt = True elif transform == 'dwt': - kwargs = dict(wavelet=wavelet, mode=mode, axis=axis) + kwargs = {"wavelet": wavelet, "mode": mode, "axis": axis} forward = partial(wavedec, level=level, **kwargs) inverse = partial(waverec, **kwargs) is_swt = False @@ -201,11 +208,11 @@ def mra2(data, wavelet, level=None, axes=(-2, -1), transform='swt2', "transform swt only supports mode='periodization'") if level is None: level = min(swt_max_level(s) for s in data.shape) - kwargs = dict(wavelet=wavelet, axes=axes, norm=True) + kwargs = {"wavelet": wavelet, "axes": axes, "norm": True} forward = partial(swt2, level=level, trim_approx=True, **kwargs) inverse = partial(iswt2, **kwargs) elif transform == 'dwt2': - kwargs = dict(wavelet=wavelet, mode=mode, axes=axes) + kwargs = {"wavelet": wavelet, "mode": mode, "axes": axes} forward = partial(wavedec2, level=level, **kwargs) inverse = partial(waverec2, **kwargs) else: @@ -344,12 +351,12 @@ def mran(data, wavelet, level=None, axes=None, transform='swtn', "transform swt only supports mode='periodization'") if level is None: level = min(swt_max_level(s) for s in data.shape) - kwargs = dict(wavelet=wavelets, axes=axes, norm=True) + kwargs = {"wavelet": wavelets, "axes": axes, "norm": True} forward = partial(swtn, level=level, trim_approx=True, **kwargs) inverse = partial(iswtn, **kwargs) elif transform == 'dwtn': modes = _modes_per_axis(mode, axes) - kwargs = dict(wavelet=wavelets, mode=modes, axes=axes) + kwargs = {"wavelet": wavelets, "mode": modes, "axes": axes} forward = partial(wavedecn, level=level, **kwargs) inverse = partial(waverecn, **kwargs) else: diff --git a/pywt/_multidim.py b/pywt/_multidim.py index 23bd2e497..53f2ee1b9 100644 --- a/pywt/_multidim.py +++ b/pywt/_multidim.py @@ -7,7 +7,6 @@ 2D and nD Discrete Wavelet Transforms and Inverse Discrete Wavelet Transforms. """ -from __future__ import division, print_function, absolute_import from itertools import product @@ -15,8 +14,7 @@ from ._c99_config import _have_c99_complex from ._extensions._dwt import dwt_axis, idwt_axis -from ._utils import _wavelets_per_axis, _modes_per_axis - +from ._utils import _modes_per_axis, _wavelets_per_axis __all__ = ['dwt2', 'idwt2', 'dwtn', 'idwtn'] @@ -167,7 +165,7 @@ def dwtn(data, wavelet, mode='symmetric', axes=None): if not _have_c99_complex and np.iscomplexobj(data): real = dwtn(data.real, wavelet, mode, axes) imag = dwtn(data.imag, wavelet, mode, axes) - return dict((k, real[k] + 1j * imag[k]) for k in real.keys()) + return {k: real[k] + 1j * imag[k] for k in real} if data.dtype == np.dtype('object'): raise TypeError("Input must be a numeric array-like") @@ -197,26 +195,25 @@ def _fix_coeffs(coeffs): if missing_keys: raise ValueError( "The following detail coefficients were set to None:\n" - "{0}\n" + f"{missing_keys}\n" "For multilevel transforms, rather than setting\n" "\tcoeffs[key] = None\n" "use\n" - "\tcoeffs[key] = np.zeros_like(coeffs[key])\n".format( - missing_keys)) + "\tcoeffs[key] = np.zeros_like(coeffs[key])\n") invalid_keys = [k for k, v in coeffs.items() if not set(k) <= set('ad')] if invalid_keys: raise ValueError( "The following invalid keys were found in the detail " - "coefficient dictionary: {}.".format(invalid_keys)) + f"coefficient dictionary: {invalid_keys}.") - key_lengths = [len(k) for k in coeffs.keys()] + key_lengths = [len(k) for k in coeffs] if len(np.unique(key_lengths)) > 1: raise ValueError( "All detail coefficient names must have equal length.") - return dict((k, np.asarray(v)) for k, v in coeffs.items()) + return {k: np.asarray(v) for k, v in coeffs.items()} def idwtn(coeffs, wavelet, mode='symmetric', axes=None): @@ -251,23 +248,23 @@ def idwtn(coeffs, wavelet, mode='symmetric', axes=None): """ # drop the keys corresponding to value = None - coeffs = dict((k, v) for k, v in coeffs.items() if v is not None) + coeffs = {k: v for k, v in coeffs.items() if v is not None} # drop the keys corresponding to value = None - coeffs = dict((k, v) for k, v in coeffs.items() if v is not None) + coeffs = {k: v for k, v in coeffs.items() if v is not None} # Raise error for invalid key combinations coeffs = _fix_coeffs(coeffs) if (not _have_c99_complex and any(np.iscomplexobj(v) for v in coeffs.values())): - real_coeffs = dict((k, v.real) for k, v in coeffs.items()) - imag_coeffs = dict((k, v.imag) for k, v in coeffs.items()) + real_coeffs = {k: v.real for k, v in coeffs.items()} + imag_coeffs = {k: v.imag for k, v in coeffs.items()} return (idwtn(real_coeffs, wavelet, mode, axes) + 1j * idwtn(imag_coeffs, wavelet, mode, axes)) # key length matches the number of axes transformed - ndim_transform = max(len(key) for key in coeffs.keys()) + ndim_transform = max(len(key) for key in coeffs) try: coeff_shapes = (v.shape for k, v in coeffs.items() diff --git a/pywt/_multilevel.py b/pywt/_multilevel.py index 61476225a..68f3c3e0e 100644 --- a/pywt/_multilevel.py +++ b/pywt/_multilevel.py @@ -8,19 +8,19 @@ and Inverse Discrete Wavelet Transform. """ -from __future__ import division, print_function, absolute_import import numbers import warnings -from itertools import product from copy import copy +from itertools import product + import numpy as np -from ._extensions._pywt import Wavelet, Modes +from ._dwt import dwt, dwt_coeff_len, idwt from ._extensions._dwt import dwt_max_level -from ._dwt import dwt, idwt, dwt_coeff_len -from ._multidim import dwt2, idwt2, dwtn, idwtn, _fix_coeffs -from ._utils import _as_wavelet, _wavelets_per_axis, _modes_per_axis +from ._extensions._pywt import Modes, Wavelet +from ._multidim import _fix_coeffs, dwt2, dwtn, idwt2, idwtn +from ._utils import _as_wavelet, _modes_per_axis, _wavelets_per_axis __all__ = ['wavedec', 'waverec', 'wavedec2', 'waverec2', 'wavedecn', 'waverecn', 'coeffs_to_array', 'array_to_coeffs', 'ravel_coeffs', @@ -41,8 +41,8 @@ def _check_level(sizes, dec_lens, level): "Level value of %d is too low . Minimum level is 0." % level) elif level > max_level: warnings.warn( - ("Level value of {} is too high: all coefficients will experience " - "boundary effects.").format(level)) + f"Level value of {level} is too high: all coefficients will experience " + "boundary effects.") return level @@ -158,11 +158,11 @@ def waverec(coeffs, wavelet, mode='symmetric', axis=-1): for d in ds: if d is not None and not isinstance(d, np.ndarray): - raise ValueError(( - "Unexpected detail coefficient type: {}. Detail coefficients " + raise ValueError( + f"Unexpected detail coefficient type: {type(d)}. Detail coefficients " "must be arrays as returned by wavedec. If you are using " "pywt.array_to_coeffs or pywt.unravel_coeffs, please specify " - "output_format='wavedec'").format(type(d))) + "output_format='wavedec'") if (a is not None) and (d is not None): try: if a.shape[axis] == d.shape[axis] + 1: @@ -315,11 +315,11 @@ def waverec2(coeffs, wavelet, mode='symmetric', axes=(-2, -1)): for d in ds: if not isinstance(d, (list, tuple)) or len(d) != 3: - raise ValueError(( - "Unexpected detail coefficient type: {}. Detail coefficients " + raise ValueError( + f"Unexpected detail coefficient type: {type(d)}. Detail coefficients " "must be a 3-tuple of arrays as returned by wavedec2. If you " "are using pywt.array_to_coeffs or pywt.unravel_coeffs, " - "please specify output_format='wavedec2'").format(type(d))) + "please specify output_format='wavedec2'") d = tuple(np.asarray(coeff) if coeff is not None else None for coeff in d) d_shapes = (coeff.shape for coeff in d if coeff is not None) @@ -522,12 +522,12 @@ def waverecn(coeffs, wavelet, mode='symmetric', axes=None): a, ds = coeffs[0], coeffs[1:] # this dictionary check must be prior to the call to _fix_coeffs - if len(ds) > 0 and not all([isinstance(d, dict) for d in ds]): - raise ValueError(( - "Unexpected detail coefficient type: {}. Detail coefficients " + if len(ds) > 0 and not all(isinstance(d, dict) for d in ds): + raise ValueError( + f"Unexpected detail coefficient type: {type(ds[0])}. Detail coefficients " "must be a dictionary of arrays as returned by wavedecn. If " "you are using pywt.array_to_coeffs or pywt.unravel_coeffs, " - "please specify output_format='wavedecn'").format(type(ds[0]))) + "please specify output_format='wavedecn'") # Raise error for invalid key combinations ds = list(map(_fix_coeffs, ds)) @@ -588,7 +588,7 @@ def _coeffs_wavedec_to_wavedecn(coeffs): continue if coeffs[n].ndim != 1: raise ValueError("expected a 1D coefficient array") - coeffs[n] = dict(d=coeffs[n]) + coeffs[n] = {'d': coeffs[n]} return coeffs @@ -605,7 +605,7 @@ def _coeffs_wavedec2_to_wavedecn(coeffs): raise ValueError( "Expected numpy arrays of detail coefficients. Setting " "coefficients to None is not supported.") - coeffs[n] = dict(ad=ad, da=da, dd=dd) + coeffs[n] = {'ad': ad, 'da': da, 'dd': dd} return coeffs @@ -779,7 +779,7 @@ def coeffs_to_array(coeffs, padding=0, axes=None): raise ValueError("coeffs_to_array does not support missing " "coefficients.") d_shape = coeff_dict['d' * ndim_transform].shape - for key in coeff_dict.keys(): + for key in coeff_dict: d = coeff_dict[key] slice_array = [slice(None), ] * ndim for i, let in enumerate(key): @@ -1201,7 +1201,7 @@ def _check_fswavedecn_axes(data, axes): raise np.AxisError("Axis greater than data dimensions") -class FswavedecnResult(object): +class FswavedecnResult: """Object representing fully separable wavelet transform coefficients. Parameters @@ -1362,7 +1362,7 @@ def __setitem__(self, levels, x): "x does not match the shape of the requested coefficient") if x.dtype != current_dtype: warnings.warn("dtype mismatch: converting the provided array to" - "dtype {}".format(current_dtype)) + f"dtype {current_dtype}") self._coeffs[sl] = x def detail_keys(self): diff --git a/pywt/_pytest.py b/pywt/_pytest.py index cfc9f0590..a6af3acc4 100644 --- a/pywt/_pytest.py +++ b/pywt/_pytest.py @@ -1,11 +1,11 @@ """common test-related code.""" +import multiprocessing import os import sys -import multiprocessing + import numpy as np import pytest - __all__ = ['uses_matlab', # skip if pymatbridge and Matlab unavailable 'uses_futures', # skip if futures unavailable 'uses_pymatbridge', # skip if no PYWT_XSLOW environment variable diff --git a/pywt/_pytesttester.py b/pywt/_pytesttester.py index 3c3244b0a..6344fa8e3 100644 --- a/pywt/_pytesttester.py +++ b/pywt/_pytesttester.py @@ -24,10 +24,9 @@ includes the standard ``python runtests.py`` invocation. """ -from __future__ import division, absolute_import, print_function -import sys import os +import sys __all__ = ['PytestTester'] @@ -42,7 +41,7 @@ def _show_pywt_info(): print("Compiled without C99 complex support.") -class PytestTester(object): +class PytestTester: """ Pytest test runner. diff --git a/pywt/_swt.py b/pywt/_swt.py index ac00336f9..6f3cdb8b4 100644 --- a/pywt/_swt.py +++ b/pywt/_swt.py @@ -5,12 +5,13 @@ from ._c99_config import _have_c99_complex from ._extensions._dwt import idwt_single -from ._extensions._swt import swt_max_level, swt as _swt, swt_axis as _swt_axis -from ._extensions._pywt import Wavelet, Modes, _check_dtype +from ._extensions._pywt import Modes, Wavelet, _check_dtype +from ._extensions._swt import swt as _swt +from ._extensions._swt import swt_axis as _swt_axis +from ._extensions._swt import swt_max_level from ._multidim import idwt2, idwtn from ._utils import _as_wavelet, _wavelets_per_axis - __all__ = ["swt", "swt_max_level", 'iswt', 'swt2', 'iswt2', 'swtn', 'iswtn'] @@ -112,8 +113,8 @@ def swt(data, wavelet, level=None, start_level=0, axis=-1, if not _have_c99_complex and np.iscomplexobj(data): data = np.asarray(data) - kwargs = dict(wavelet=wavelet, level=level, start_level=start_level, - trim_approx=trim_approx, axis=axis, norm=norm) + kwargs = {"wavelet": wavelet, "level": level, "start_level": start_level, + "trim_approx": trim_approx, "axis": axis, "norm": norm} coeffs_real = swt(data.real, **kwargs) coeffs_imag = swt(data.imag, **kwargs) if not trim_approx: @@ -203,7 +204,7 @@ def iswt(coeffs, wavelet, norm=False, axis=-1): else: coeffs_real = [(ca.real, cd.real) for ca, cd in coeffs] coeffs_imag = [(ca.imag, cd.imag) for ca, cd in coeffs] - kwargs = dict(wavelet=wavelet, norm=norm) + kwargs = {"wavelet": wavelet, "norm": norm} y = iswt(coeffs_real, **kwargs) return y + 1j * iswt(coeffs_imag, **kwargs) @@ -451,7 +452,7 @@ def iswt2(coeffs, wavelet, norm=False, axes=(-2, -1)): for a, (h, v, d) in coeffs] coeffs_imag = [(a.imag, (h.imag, v.imag, d.imag)) for a, (h, v, d) in coeffs] - kwargs = dict(wavelet=wavelet, norm=norm) + kwargs = {"wavelet": wavelet, "norm": norm} y = iswt2(coeffs_real, **kwargs) return y + 1j * iswt2(coeffs_imag, **kwargs) @@ -614,8 +615,8 @@ def swtn(data, wavelet, level, start_level=0, axes=None, trim_approx=False, """ data = np.asarray(data) if not _have_c99_complex and np.iscomplexobj(data): - kwargs = dict(wavelet=wavelet, level=level, start_level=start_level, - trim_approx=trim_approx, axes=axes, norm=norm) + kwargs = {"wavelet": wavelet, "level": level, "start_level": start_level, + "trim_approx": trim_approx, "axes": axes, "norm": norm} real = swtn(data.real, **kwargs) imag = swtn(data.imag, **kwargs) if trim_approx: @@ -626,7 +627,7 @@ def swtn(data, wavelet, level, start_level=0, axes=None, trim_approx=False, offset = 0 for rdict, idict in zip(real[offset:], imag[offset:]): cplx.append( - dict((k, rdict[k] + 1j * idict[k]) for k in rdict.keys())) + {k: rdict[k] + 1j * idict[k] for k in rdict}) return cplx if data.dtype == np.dtype('object'): @@ -715,7 +716,7 @@ def iswtn(coeffs, wavelet, axes=None, norm=False): """ # key length matches the number of axes transformed - ndim_transform = max(len(key) for key in coeffs[-1].keys()) + ndim_transform = max(len(key) for key in coeffs[-1]) trim_approx = not isinstance(coeffs[0], dict) cA = coeffs[0] if trim_approx else coeffs[0]['a'*ndim_transform] @@ -729,7 +730,7 @@ def iswtn(coeffs, wavelet, axes=None, norm=False): coeffs_imag = [] coeffs_real += [{k: v.real for k, v in c.items()} for c in coeffs] coeffs_imag += [{k: v.imag for k, v in c.items()} for c in coeffs] - kwargs = dict(wavelet=wavelet, axes=axes, norm=norm) + kwargs = {"wavelet": wavelet, "axes": axes, "norm": norm} y = iswtn(coeffs_real, **kwargs) return y + 1j * iswtn(coeffs_imag, **kwargs) diff --git a/pywt/_thresholding.py b/pywt/_thresholding.py index 658d8e500..33af65b84 100644 --- a/pywt/_thresholding.py +++ b/pywt/_thresholding.py @@ -8,7 +8,6 @@ functions. """ -from __future__ import division, print_function, absolute_import import numpy as np __all__ = ['threshold', 'threshold_firm'] @@ -167,7 +166,7 @@ def threshold(data, value, mode='soft', substitute=0): # Make sure error is always identical by sorting keys keys = (f"'{key}'" for key in sorted(thresholding_options.keys())) - raise ValueError("The mode parameter only takes values from: {0}." + raise ValueError("The mode parameter only takes values from: {}." .format(', '.join(keys))) diff --git a/pywt/_utils.py b/pywt/_utils.py index 865b4ce0d..81d6e0c73 100644 --- a/pywt/_utils.py +++ b/pywt/_utils.py @@ -2,11 +2,16 @@ # # See COPYING for license details. import inspect -import numpy as np from collections.abc import Iterable -from ._extensions._pywt import (Wavelet, ContinuousWavelet, - DiscreteContinuousWavelet, Modes) +import numpy as np + +from ._extensions._pywt import ( + ContinuousWavelet, + DiscreteContinuousWavelet, + Modes, + Wavelet, +) def _as_wavelet(wavelet): @@ -49,9 +54,9 @@ def _wavelets_per_axis(wavelet, axes): wavelets = [_as_wavelet(wavelet[0]), ] * len(axes) else: if len(wavelet) != len(axes): - raise ValueError(( + raise ValueError( "The number of wavelets must match the number of axes " - "to be transformed.")) + "to be transformed.") wavelets = [_as_wavelet(w) for w in wavelet] else: raise ValueError("wavelet must be a str, Wavelet or iterable") @@ -85,8 +90,8 @@ def _modes_per_axis(modes, axes): else: # (potentially) unique wavelet per axis (e.g. for dual-tree DWT) if len(modes) != len(axes): - raise ValueError(("The number of modes must match the number " - "of axes to be transformed.")) + raise ValueError("The number of modes must match the number " + "of axes to be transformed.") modes = [Modes.from_object(mode) for mode in modes] else: raise ValueError("modes must be a str, Mode enum or iterable") diff --git a/pywt/_wavelet_packets.py b/pywt/_wavelet_packets.py index 64d1ceee5..57ebcb938 100644 --- a/pywt/_wavelet_packets.py +++ b/pywt/_wavelet_packets.py @@ -5,18 +5,18 @@ """1D and 2D Wavelet packet transform module.""" -from __future__ import division, print_function, absolute_import __all__ = ["BaseNode", "Node", "WaveletPacket", "Node2D", "WaveletPacket2D", "NodeND", "WaveletPacketND"] -from itertools import product from collections import OrderedDict +from itertools import product + import numpy as np +from ._dwt import dwt, dwt_max_level, idwt from ._extensions._pywt import Wavelet, _check_dtype -from ._dwt import dwt, idwt, dwt_max_level -from ._multidim import dwt2, idwt2, dwtn, idwtn +from ._multidim import dwt2, dwtn, idwt2, idwtn def get_graycode_order(level, x='a', y='d'): @@ -27,7 +27,7 @@ def get_graycode_order(level, x='a', y='d'): return graycode_order -class BaseNode(object): +class BaseNode: """ BaseNode for wavelet packet 1D and 2D tree nodes. @@ -109,8 +109,7 @@ def _delete_node(self, part): def _validate_node_name(self, part): if part not in self.PARTS: - raise ValueError("Subnode name must be in [%s], not '%s'." % - (', '.join("'%s'" % p for p in self.PARTS), part)) + raise ValueError("Subnode name must be in [{}], not '{}'.".format(', '.join("'%s'" % p for p in self.PARTS), part)) @property def path_tuple(self): @@ -332,10 +331,7 @@ def is_empty(self): @property def has_any_subnode(self): - for part in self.PARTS: - if self._get_node(part) is not None: # and not .is_empty - return True - return False + return any(self._get_node(part) is not None for part in self.PARTS) def get_leaf_nodes(self, decompose=False): """ @@ -584,7 +580,7 @@ class NodeND(BaseNode): """ def __init__(self, parent, data, node_name, ndim, ndim_transform): - super(NodeND, self).__init__(parent=parent, data=data, + super().__init__(parent=parent, data=data, node_name=node_name) self.PART_LEN = ndim_transform self.PARTS = OrderedDict() @@ -612,8 +608,7 @@ def _delete_node(self, part): def _validate_node_name(self, part): if part not in self.PARTS: raise ValueError( - "Subnode name must be in [%s], not '%s'." % - (', '.join("'%s'" % p for p in list(self.PARTS.keys())), part)) + "Subnode name must be in [{}], not '{}'.".format(', '.join("'%s'" % p for p in list(self.PARTS.keys())), part)) def _create_subnode(self, part, data=None, overwrite=True): return self._create_subnode_base(node_cls=NodeND, part=part, data=data, @@ -655,19 +650,19 @@ def _decompose(self): dwt2 : for 2D Discrete Wavelet Transform output coefficients. """ if self.is_empty: - coefs = {key: None for key in self.PARTS.keys()} + coefs = {key: None for key in self.PARTS} else: coefs = dwtn(self.data, self.wavelet, self.mode, axes=self.axes) for key, data in coefs.items(): self._create_subnode(key, data) - return (self._get_node(key) for key in self.PARTS.keys()) + return (self._get_node(key) for key in self.PARTS) def _reconstruct(self, update): - coeffs = {key: None for key in self.PARTS.keys()} + coeffs = {key: None for key in self.PARTS} nnodes = 0 - for key in self.PARTS.keys(): + for key in self.PARTS: node = self._get_node(key) if node is not None: nnodes += 1 @@ -707,7 +702,7 @@ class WaveletPacket(Node): """ def __init__(self, data, wavelet, mode='symmetric', maxlevel=None, axis=-1): - super(WaveletPacket, self).__init__(None, data, "") + super().__init__(None, data, "") if not isinstance(wavelet, Wavelet): wavelet = Wavelet(wavelet) @@ -744,7 +739,7 @@ def reconstruct(self, update=True): reconstruction values, also in subnodes. """ if self.has_any_subnode: - data = super(WaveletPacket, self).reconstruct(update) + data = super().reconstruct(update) if self.data_size is not None and (data.shape != self.data_size): data = data[[slice(sz) for sz in self.data_size]] if update: @@ -804,7 +799,7 @@ def collect(node): if order == "natural": return result elif order == "freq": - result = dict((node.path, node) for node in result) + result = {node.path: node for node in result} graycode_order = get_graycode_order(level) return [result[path] for path in graycode_order if path in result] else: @@ -833,7 +828,7 @@ class WaveletPacket2D(Node2D): """ def __init__(self, data, wavelet, mode='smooth', maxlevel=None, axes=(-2, -1)): - super(WaveletPacket2D, self).__init__(None, data, "") + super().__init__(None, data, "") if not isinstance(wavelet, Wavelet): wavelet = Wavelet(wavelet) @@ -870,7 +865,7 @@ def reconstruct(self, update=True): and its subnodes will be replaced with values from reconstruction. """ if self.has_any_subnode: - data = super(WaveletPacket2D, self).reconstruct(update) + data = super().reconstruct(update) if self.data_size is not None and (data.shape != self.data_size): data = data[[slice(sz) for sz in self.data_size]] if update: @@ -987,7 +982,7 @@ def __init__(self, data, wavelet, mode='smooth', maxlevel=None, else: ndim = len(axes) - super(WaveletPacketND, self).__init__(None, data, "", ndim, + super().__init__(None, data, "", ndim, ndim_transform) if not isinstance(wavelet, Wavelet): wavelet = Wavelet(wavelet) @@ -1018,7 +1013,7 @@ def reconstruct(self, update=True): and its subnodes will be replaced with values from reconstruction. """ if self.has_any_subnode: - data = super(WaveletPacketND, self).reconstruct(update) + data = super().reconstruct(update) if self.data_size is not None and (data.shape != self.data_size): data = data[[slice(sz) for sz in self.data_size]] if update: diff --git a/pywt/data/__init__.py b/pywt/data/__init__.py index 9344e3f60..052e784a5 100644 --- a/pywt/data/__init__.py +++ b/pywt/data/__init__.py @@ -1,2 +1,2 @@ -from ._readers import ascent, aero, ecg, camera, nino +from ._readers import aero, ascent, camera, ecg, nino from ._wavelab_signals import demo_signal diff --git a/pywt/data/_wavelab_signals.py b/pywt/data/_wavelab_signals.py index 3c41f2d74..6f86856b7 100644 --- a/pywt/data/_wavelab_signals.py +++ b/pywt/data/_wavelab_signals.py @@ -1,5 +1,3 @@ -# -*- coding:utf-8 -*- -from __future__ import division import numpy as np diff --git a/pywt/data/create_dat.py b/pywt/data/create_dat.py index f000fe4d6..4c9938553 100755 --- a/pywt/data/create_dat.py +++ b/pywt/data/create_dat.py @@ -13,7 +13,6 @@ Requires Scipy and PIL. """ -from __future__ import print_function import sys diff --git a/pywt/tests/data/generate_matlab_data.py b/pywt/tests/data/generate_matlab_data.py index a95abc83d..fc237c052 100644 --- a/pywt/tests/data/generate_matlab_data.py +++ b/pywt/tests/data/generate_matlab_data.py @@ -1,9 +1,9 @@ """ This script was used to generate dwt_matlabR2012a_result.npz by storing the outputs from Matlab R2012a. """ -from __future__ import division, print_function, absolute_import import numpy as np + import pywt try: @@ -17,7 +17,7 @@ _matlab_missing = True if _matlab_missing: - raise EnvironmentError("Can't generate matlab data files without MATLAB") + raise OSError("Can't generate matlab data files without MATLAB") size_set = 'reduced' diff --git a/pywt/tests/data/generate_matlab_data_cwt.py b/pywt/tests/data/generate_matlab_data_cwt.py index 05b6e42a0..e40f1126a 100644 --- a/pywt/tests/data/generate_matlab_data_cwt.py +++ b/pywt/tests/data/generate_matlab_data_cwt.py @@ -1,9 +1,9 @@ """ This script was used to generate dwt_matlabR2012a_result.npz by storing the outputs from Matlab R2012a. """ -from __future__ import division, print_function, absolute_import import numpy as np + import pywt try: @@ -17,7 +17,7 @@ _matlab_missing = True if _matlab_missing: - raise EnvironmentError("Can't generate matlab data files without MATLAB") + raise OSError("Can't generate matlab data files without MATLAB") size_set = 'reduced' diff --git a/pywt/tests/test__pywt.py b/pywt/tests/test__pywt.py index d17c7582c..7131084d4 100644 --- a/pywt/tests/test__pywt.py +++ b/pywt/tests/test__pywt.py @@ -1,9 +1,8 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import import numpy as np -from numpy.testing import assert_allclose, assert_, assert_raises +from numpy.testing import assert_, assert_allclose, assert_raises import pywt diff --git a/pywt/tests/test_concurrent.py b/pywt/tests/test_concurrent.py index 041171fd8..e6b38c9d4 100644 --- a/pywt/tests/test_concurrent.py +++ b/pywt/tests/test_concurrent.py @@ -3,15 +3,15 @@ concurrent.futures.ThreadPoolExecutor does not raise errors. """ -from __future__ import division, print_function, absolute_import import warnings -import numpy as np from functools import partial -from numpy.testing import assert_array_equal, assert_allclose -from pywt._pytest import uses_futures, futures, max_workers + +import numpy as np +from numpy.testing import assert_allclose, assert_array_equal import pywt +from pywt._pytest import futures, max_workers, uses_futures def _assert_all_coeffs_equal(coefs1, coefs2): diff --git a/pywt/tests/test_cwt_wavelets.py b/pywt/tests/test_cwt_wavelets.py index 97244f884..f7f64bcae 100644 --- a/pywt/tests/test_cwt_wavelets.py +++ b/pywt/tests/test_cwt_wavelets.py @@ -1,12 +1,18 @@ #!/usr/bin/env python import os -from itertools import product import pickle +from itertools import product -from numpy.testing import (assert_allclose, assert_warns, assert_almost_equal, - assert_raises, assert_equal) -import pytest import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_almost_equal, + assert_equal, + assert_raises, + assert_warns, +) + import pywt diff --git a/pywt/tests/test_data.py b/pywt/tests/test_data.py index c38ab0152..e1cf68fbc 100644 --- a/pywt/tests/test_data.py +++ b/pywt/tests/test_data.py @@ -1,6 +1,7 @@ import os + import numpy as np -from numpy.testing import assert_allclose, assert_raises, assert_ +from numpy.testing import assert_, assert_allclose, assert_raises import pywt.data diff --git a/pywt/tests/test_deprecations.py b/pywt/tests/test_deprecations.py index 5a6cbad9e..2b7d57bfb 100644 --- a/pywt/tests/test_deprecations.py +++ b/pywt/tests/test_deprecations.py @@ -1,7 +1,7 @@ import warnings import numpy as np -from numpy.testing import assert_warns, assert_array_equal +from numpy.testing import assert_array_equal, assert_warns import pywt diff --git a/pywt/tests/test_doc.py b/pywt/tests/test_doc.py index ac8c7bfb4..ea9bb3ee2 100644 --- a/pywt/tests/test_doc.py +++ b/pywt/tests/test_doc.py @@ -1,4 +1,3 @@ -from __future__ import division, print_function, absolute_import import doctest import glob diff --git a/pywt/tests/test_dwt_idwt.py b/pywt/tests/test_dwt_idwt.py index c3e80333f..c4a068fd5 100644 --- a/pywt/tests/test_dwt_idwt.py +++ b/pywt/tests/test_dwt_idwt.py @@ -1,9 +1,8 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import import numpy as np -from numpy.testing import (assert_allclose, assert_, assert_raises, - assert_array_equal) +from numpy.testing import assert_, assert_allclose, assert_array_equal, assert_raises + import pywt # Check that float32, float64, complex64, complex128 are preserved. @@ -196,7 +195,7 @@ def test_dwt_axis_arg(): assert_allclose(cA_, cA) assert_allclose(cD_, cD) -def test_dwt_axis_invalid_input(): +def test_dwt_axis_invalid_input(): x = np.ones((3,1)) assert_raises(ValueError, pywt.dwt, x, 'db2', 'reflect') diff --git a/pywt/tests/test_functions.py b/pywt/tests/test_functions.py index 5017d3ee1..03bc1ee4e 100644 --- a/pywt/tests/test_functions.py +++ b/pywt/tests/test_functions.py @@ -1,7 +1,6 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import -from numpy.testing import assert_almost_equal, assert_allclose +from numpy.testing import assert_allclose, assert_almost_equal import pywt diff --git a/pywt/tests/test_matlab_compatibility.py b/pywt/tests/test_matlab_compatibility.py index 5e26e5b40..9a79e6e15 100644 --- a/pywt/tests/test_matlab_compatibility.py +++ b/pywt/tests/test_matlab_compatibility.py @@ -3,15 +3,14 @@ accuracy against MathWorks Wavelet Toolbox. """ -from __future__ import division, print_function, absolute_import import numpy as np import pytest from numpy.testing import assert_ import pywt -from pywt._pytest import (uses_pymatbridge, uses_precomputed, size_set) from pywt._pytest import matlab_result_dict_dwt as matlab_result_dict +from pywt._pytest import size_set, uses_precomputed, uses_pymatbridge # list of mode names in pywt and matlab modes = [('zero', 'zpd'), @@ -121,7 +120,7 @@ def _load_matlab_result(data, wavelet, mmode): (md_key not in matlab_result_dict): raise KeyError( "Precompted Matlab result not found for wavelet: " - "{0}, mode: {1}, size: {2}".format(wavelet, mmode, N)) + f"{wavelet}, mode: {mmode}, size: {N}") ma = matlab_result_dict[ma_key] md = matlab_result_dict[md_key] return ma, md @@ -137,7 +136,7 @@ def _load_matlab_result_pywt_coeffs(data, wavelet, mmode): (md_key not in matlab_result_dict): raise KeyError( "Precompted Matlab result not found for wavelet: " - "{0}, mode: {1}, size: {2}".format(wavelet, mmode, N)) + f"{wavelet}, mode: {mmode}, size: {N}") ma = matlab_result_dict[ma_key] md = matlab_result_dict[md_key] return ma, md diff --git a/pywt/tests/test_matlab_compatibility_cwt.py b/pywt/tests/test_matlab_compatibility_cwt.py index 55dbcbe25..21d37c0a7 100644 --- a/pywt/tests/test_matlab_compatibility_cwt.py +++ b/pywt/tests/test_matlab_compatibility_cwt.py @@ -3,16 +3,20 @@ accuracy against MathWorks Wavelet Toolbox. """ -from __future__ import division, print_function, absolute_import import warnings + import numpy as np import pytest from numpy.testing import assert_ import pywt -from pywt._pytest import (uses_pymatbridge, uses_precomputed, size_set, - matlab_result_dict_cwt) +from pywt._pytest import ( + matlab_result_dict_cwt, + size_set, + uses_precomputed, + uses_pymatbridge, +) families = ('gaus', 'mexh', 'morl', 'cgau', 'shan', 'fbsp', 'cmor') wavelets = sum([pywt.wavelist(name) for name in families], []) @@ -126,7 +130,7 @@ def _load_matlab_result(data, wavelet, scales): if (coefs_key not in matlab_result_dict_cwt): raise KeyError( "Precompted Matlab result not found for wavelet: " - "{0}, mode: {1}, size: {2}".format(wavelet, scales, N)) + f"{wavelet}, mode: {scales}, size: {N}") coefs = matlab_result_dict_cwt[coefs_key] return coefs diff --git a/pywt/tests/test_modes.py b/pywt/tests/test_modes.py index 31ea95321..0af215f84 100644 --- a/pywt/tests/test_modes.py +++ b/pywt/tests/test_modes.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import import numpy as np -from numpy.testing import assert_raises, assert_equal, assert_allclose +from numpy.testing import assert_allclose, assert_equal, assert_raises import pywt diff --git a/pywt/tests/test_mra.py b/pywt/tests/test_mra.py index 055ac1fa7..76f330591 100644 --- a/pywt/tests/test_mra.py +++ b/pywt/tests/test_mra.py @@ -159,7 +159,7 @@ def test_mra2_axes(transform, axes, ndim, dtype): x = np.stack((x,) * 8, axis=-1) # out of range axis - if any([axis < -x.ndim or axis >= x.ndim for axis in axes]): + if any(axis < -x.ndim or axis >= x.ndim for axis in axes): with pytest.raises(np.AxisError): pywt.mra2(x, 'db1', transform=transform, axes=axes) return @@ -244,7 +244,7 @@ def test_mran_axes(axes, transform): x3d = np.stack((x,) * 8, axis=-1) # out of range axis - if any([axis < -x.ndim or axis >= x.ndim for axis in axes]): + if any(axis < -x.ndim or axis >= x.ndim for axis in axes): with pytest.raises(np.AxisError): pywt.mran(x, 'db1', transform='dwtn', axes=axes) return diff --git a/pywt/tests/test_multidim.py b/pywt/tests/test_multidim.py index bcf36c04d..eeaa680c0 100644 --- a/pywt/tests/test_multidim.py +++ b/pywt/tests/test_multidim.py @@ -1,12 +1,13 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import -import numpy as np from itertools import combinations -from numpy.testing import assert_allclose, assert_, assert_raises, assert_equal + +import numpy as np +from numpy.testing import assert_, assert_allclose, assert_equal, assert_raises import pywt + # Check that float32, float64, complex64, complex128 are preserved. # Other real types get converted to float64. # complex256 gets converted to complex128 @@ -27,7 +28,7 @@ def test_dwtn_input(): # Array-like must be accepted pywt.dwtn([1, 2, 3, 4], 'haar') # Others must not - data = dict() + data = {} assert_raises(TypeError, pywt.dwtn, data, 'haar') # Must be at least 1D assert_raises(ValueError, pywt.dwtn, 2, 'haar') @@ -83,7 +84,7 @@ def test_stride(): strided = np.ones((3, 12), dtype=data.dtype) strided[::-1, ::2] = data strided_dwtn = pywt.dwtn(strided[::-1, ::2], wavelet) - for key in expected.keys(): + for key in expected: assert_allclose(strided_dwtn[key], expected[key]) @@ -102,7 +103,7 @@ def test_byte_offset(): align=True)) padded[:] = data padded_dwtn = pywt.dwtn(padded['data'], wavelet) - for key in expected.keys(): + for key in expected: assert_allclose(padded_dwtn[key], expected[key]) @@ -188,7 +189,7 @@ def test_idwtn_missing(): def test_idwtn_all_coeffs_None(): - coefs = dict(aa=None, da=None, ad=None, dd=None) + coefs = {'aa': None, 'da': None, 'ad': None, 'dd': None} assert_raises(ValueError, pywt.idwtn, coefs, 'haar') @@ -253,15 +254,15 @@ def test_dwtn_axes(): [1, 4, 2, 8]]) data = data + 1j*data # test with complex data coefs = pywt.dwtn(data, 'haar', axes=(1,)) - expected_a = list(map(lambda x: pywt.dwt(x, 'haar')[0], data)) + expected_a = [pywt.dwt(x, 'haar')[0] for x in data] assert_equal(coefs['a'], expected_a) - expected_d = list(map(lambda x: pywt.dwt(x, 'haar')[1], data)) + expected_d = [pywt.dwt(x, 'haar')[1] for x in data] assert_equal(coefs['d'], expected_d) coefs = pywt.dwtn(data, 'haar', axes=(1, 1)) - expected_aa = list(map(lambda x: pywt.dwt(x, 'haar')[0], expected_a)) + expected_aa = [pywt.dwt(x, 'haar')[0] for x in expected_a] assert_equal(coefs['aa'], expected_aa) - expected_ad = list(map(lambda x: pywt.dwt(x, 'haar')[1], expected_a)) + expected_ad = [pywt.dwt(x, 'haar')[1] for x in expected_a] assert_equal(coefs['ad'], expected_ad) diff --git a/pywt/tests/test_multilevel.py b/pywt/tests/test_multilevel.py index 95fd68e19..cbfea564d 100644 --- a/pywt/tests/test_multilevel.py +++ b/pywt/tests/test_multilevel.py @@ -1,15 +1,24 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import import warnings from itertools import combinations + import numpy as np import pytest -from numpy.testing import (assert_almost_equal, assert_allclose, assert_, - assert_equal, assert_raises, assert_raises_regex, - assert_array_equal, assert_warns) +from numpy.testing import ( + assert_, + assert_allclose, + assert_almost_equal, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, + assert_warns, +) + import pywt + # Check that float32, float64, complex64, complex128 are preserved. # Other real types get converted to float64. # complex256 gets converted to complex128 @@ -415,7 +424,7 @@ def test_coeffs_to_array(): assert_raises(ValueError, pywt.coeffs_to_array, [a_coeffs, None]) # use an invalid key name in the coef dictionary - coeffs = [np.array([0]), dict(d=np.array([0]), c=np.array([0]))] + coeffs = [np.array([0]), {'d': np.array([0]), 'c': np.array([0])}] assert_raises(ValueError, pywt.coeffs_to_array, coeffs) diff --git a/pywt/tests/test_perfect_reconstruction.py b/pywt/tests/test_perfect_reconstruction.py index e57fa5532..102989213 100644 --- a/pywt/tests/test_perfect_reconstruction.py +++ b/pywt/tests/test_perfect_reconstruction.py @@ -4,7 +4,6 @@ Verify DWT perfect reconstruction. """ -from __future__ import division, print_function, absolute_import import numpy as np from numpy.testing import assert_ diff --git a/pywt/tests/test_swt.py b/pywt/tests/test_swt.py index 4e5efdfe0..3eaa9426d 100644 --- a/pywt/tests/test_swt.py +++ b/pywt/tests/test_swt.py @@ -1,14 +1,20 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import import warnings from copy import deepcopy from itertools import combinations, permutations + import numpy as np import pytest -from numpy.testing import (assert_allclose, assert_, assert_equal, - assert_raises, assert_array_equal, assert_warns) +from numpy.testing import ( + assert_, + assert_allclose, + assert_array_equal, + assert_equal, + assert_raises, + assert_warns, +) import pywt from pywt._extensions._swt import swt_axis diff --git a/pywt/tests/test_thresholding.py b/pywt/tests/test_thresholding.py index abe69fadf..8e1dc9406 100644 --- a/pywt/tests/test_thresholding.py +++ b/pywt/tests/test_thresholding.py @@ -1,10 +1,8 @@ -from __future__ import division, print_function, absolute_import import numpy as np -from numpy.testing import assert_allclose, assert_raises, assert_, assert_equal +from numpy.testing import assert_, assert_allclose, assert_equal, assert_raises import pywt - float_dtypes = [np.float32, np.float64, np.complex64, np.complex128] real_dtypes = [np.float32, np.float64] diff --git a/pywt/tests/test_wavelet.py b/pywt/tests/test_wavelet.py index e14c9227b..f678fb5d6 100644 --- a/pywt/tests/test_wavelet.py +++ b/pywt/tests/test_wavelet.py @@ -1,8 +1,9 @@ #!/usr/bin/env python import os import pickle + import numpy as np -from numpy.testing import assert_allclose, assert_ +from numpy.testing import assert_, assert_allclose import pywt @@ -152,7 +153,7 @@ def check_coefficients(wavelet): assert_(res < epsilon, msg=msg) -class _CustomHaarFilterBank(object): +class _CustomHaarFilterBank: @property def filter_bank(self): val = np.sqrt(2) / 2 diff --git a/pywt/tests/test_wp.py b/pywt/tests/test_wp.py index 06345a677..9bcd12302 100644 --- a/pywt/tests/test_wp.py +++ b/pywt/tests/test_wp.py @@ -4,8 +4,7 @@ import pickle import numpy as np -from numpy.testing import (assert_allclose, assert_, assert_raises, - assert_equal) +from numpy.testing import assert_, assert_allclose, assert_equal, assert_raises import pywt diff --git a/pywt/tests/test_wp2d.py b/pywt/tests/test_wp2d.py index cdeb3bc1b..b6f0b60d9 100644 --- a/pywt/tests/test_wp2d.py +++ b/pywt/tests/test_wp2d.py @@ -4,8 +4,7 @@ import pickle import numpy as np -from numpy.testing import (assert_allclose, assert_, assert_raises, - assert_equal) +from numpy.testing import assert_, assert_allclose, assert_equal, assert_raises import pywt diff --git a/pywt/tests/test_wpnd.py b/pywt/tests/test_wpnd.py index b8d775010..4473cb09f 100644 --- a/pywt/tests/test_wpnd.py +++ b/pywt/tests/test_wpnd.py @@ -1,13 +1,12 @@ #!/usr/bin/env python -from __future__ import division, print_function, absolute_import -from itertools import product -from functools import reduce import operator +from functools import reduce +from itertools import product + import numpy as np -from numpy.testing import (assert_allclose, assert_, assert_raises, - assert_equal) +from numpy.testing import assert_, assert_allclose, assert_equal, assert_raises import pywt diff --git a/util/authors.py b/util/authors.py index 861c553f8..85e2ca248 100755 --- a/util/authors.py +++ b/util/authors.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- encoding:utf-8 -*- """ git-authors [OPTIONS] REV1..REV2 @@ -11,12 +10,12 @@ """ # Author: Pauli Virtanen . This script is in the public domain. +import io import optparse -import re -import sys import os -import io +import re import subprocess +import sys stdout_b = sys.stdout.buffer MAILMAP_FILE = os.path.join(os.path.dirname(__file__), "..", ".mailmap") @@ -48,28 +47,28 @@ def analyze_line(line, names, disp=False): line = line.strip().decode('utf-8') # Check the commit author name - m = re.match(u'^@@@([^@]*)@@@', line) + m = re.match('^@@@([^@]*)@@@', line) if m: name = m.group(1) line = line[m.end():] name = NAME_MAP.get(name, name) if disp: if name not in names: - stdout_b.write(f" - Author: {name}\n".encode('utf-8')) + stdout_b.write(f" - Author: {name}\n".encode()) names.add(name) # Look for "thanks to" messages in the commit log m = re.search(r'([Tt]hanks to|[Cc]ourtesy of) ([A-Z][A-Za-z]*? [A-Z][A-Za-z]*? [A-Z][A-Za-z]*|[A-Z][A-Za-z]*? [A-Z]\. [A-Z][A-Za-z]*|[A-Z][A-Za-z ]*? [A-Z][A-Za-z]*|[a-z0-9]+)($|\.| )', line) if m: name = m.group(2) - if name not in (u'this',): + if name not in ('this',): if disp: stdout_b.write(f" - Log : {line.strip().encode('utf-8')}\n") name = NAME_MAP.get(name, name) names.add(name) line = line[m.end():].strip() - line = re.sub(r'^(and|, and|, ) ', u'Thanks to ', line) + line = re.sub(r'^(and|, and|, ) ', 'Thanks to ', line) analyze_line(line.encode('utf-8'), names) # Find all authors before the named range @@ -84,7 +83,7 @@ def analyze_line(line, names, disp=False): # Sort def name_key(fullname): - m = re.search(u' [a-z ]*[A-Za-z-]+$', fullname) + m = re.search(' [a-z ]*[A-Za-z-]+$', fullname) if m: forename = fullname[:m.start()].strip() surname = fullname[m.start():].strip() @@ -92,11 +91,11 @@ def name_key(fullname): forename = "" surname = fullname.strip() surname = surname.replace('\'', '') - if surname.startswith(u'van der '): + if surname.startswith('van der '): surname = surname[8:] - if surname.startswith(u'de '): + if surname.startswith('de '): surname = surname[3:] - if surname.startswith(u'von '): + if surname.startswith('von '): surname = surname[4:] return (surname.lower(), forename.lower()) @@ -106,9 +105,9 @@ def name_key(fullname): n_authors = list(new_authors) n_authors.sort(key=name_key) # Print some empty lines to separate - stdout_b.write(("\n\n").encode('utf-8')) + stdout_b.write(b"\n\n") for author in n_authors: - stdout_b.write(f"- {author}\n".encode('utf-8')) + stdout_b.write(f"- {author}\n".encode()) # return for early exit so we only print new authors return @@ -124,28 +123,28 @@ def name_key(fullname): for author in authors: if author in all_authors: - stdout_b.write(f"* {author}\n".encode('utf-8')) + stdout_b.write(f"* {author}\n".encode()) else: - stdout_b.write(f"* {author} +\n".encode('utf-8')) + stdout_b.write(f"* {author} +\n".encode()) stdout_b.write((""" A total of %(count)d people contributed to this release. People with a "+" by their names contributed a patch for the first time. This list of names is automatically generated, and may not be fully complete. -""" % dict(count=len(authors))).encode('utf-8')) +""" % {"count": len(authors)}).encode('utf-8')) - stdout_b.write(("\nNOTE: Check this list manually! It is automatically generated " - "and some names\n may be missing.\n").encode('utf-8')) + stdout_b.write(b"\nNOTE: Check this list manually! It is automatically generated " + b"and some names\n may be missing.\n") def load_name_map(filename): name_map = {} - with io.open(filename, 'r', encoding='utf-8') as f: + with open(filename, encoding='utf-8') as f: for line in f: line = line.strip() - if line.startswith(u"#") or not line: + if line.startswith("#") or not line: continue m = re.match(r'^(.*?)\s*<(.*?)>(.*?)\s*<(.*?)>\s*$', line) @@ -196,12 +195,12 @@ def __call__(self, command, *a, **kw): def pipe(self, command, *a, **kw): stdin = kw.pop('stdin', None) - p = self._call(command, a, dict(stdin=stdin, stdout=subprocess.PIPE), + p = self._call(command, a, {"stdin": stdin, "stdout": subprocess.PIPE}, call=False, **kw) return p.stdout def read(self, command, *a, **kw): - p = self._call(command, a, dict(stdout=subprocess.PIPE), + p = self._call(command, a, {"stdout": subprocess.PIPE}, call=False, **kw) out, err = p.communicate() if p.returncode != 0: @@ -213,8 +212,8 @@ def readlines(self, command, *a, **kw): return out.rstrip("\n").split("\n") def test(self, command, *a, **kw): - ret = self._call(command, a, dict(stdout=subprocess.PIPE, - stderr=subprocess.PIPE), + ret = self._call(command, a, {"stdout": subprocess.PIPE, + "stderr": subprocess.PIPE}, call=True, **kw) return (ret == 0) diff --git a/util/gh_lists.py b/util/gh_lists.py index 873d7c5f8..102d04a73 100755 --- a/util/gh_lists.py +++ b/util/gh_lists.py @@ -1,21 +1,18 @@ #!/usr/bin/env python3 -# -*- encoding:utf-8 -*- """ gh_lists.py MILESTONE Functions for Github API requests. """ +import argparse +import collections +import datetime +import json import os import re import sys -import json -import collections -import argparse -import datetime import time - -from urllib.request import urlopen, Request, HTTPError - +from urllib.request import HTTPError, Request, urlopen Issue = collections.namedtuple('Issue', ('id', 'title', 'url')) @@ -31,14 +28,14 @@ def main(): milestones = get_milestones(getter, args.project) if args.milestone not in milestones: msg = "Milestone {0} not available. Available milestones: {1}" - msg = msg.format(args.milestone, u", ".join(sorted(milestones))) + msg = msg.format(args.milestone, ", ".join(sorted(milestones))) p.error(msg) issues = get_issues(getter, args.project, args.milestone) issues.sort() finally: getter.save() - prs = [x for x in issues if u'/pull/' in x.url] + prs = [x for x in issues if '/pull/' in x.url] issues = [x for x in issues if x not in prs] def print_list(title, items): @@ -48,14 +45,14 @@ def print_list(title, items): print() for issue in items: - msg = u"* `#{0} <{1}>`__: {2}" + msg = "* `#{0} <{1}>`__: {2}" # sanitize whitespace, `, and * - title = re.sub(u"\\s+", u" ", issue.title.strip()) - title = title.replace(u'`', u'\\`').replace(u'*', u'\\*') + title = re.sub("\\s+", " ", issue.title.strip()) + title = title.replace('`', '\\`').replace('*', '\\*') if len(title) > 60: - remainder = re.sub(u"\\s.*$", u"...", title[60:]) + remainder = re.sub("\\s.*$", "...", title[60:]) if len(remainder) > 20: - remainder = title[:80] + u"..." + remainder = title[:80] + "..." else: title = title[:60] + remainder msg = msg.format(issue.id, issue.url, title) @@ -77,7 +74,7 @@ def get_milestones(getter, project): milestones = {} for ms in data: - milestones[ms[u'title']] = ms[u'number'] + milestones[ms['title']] = ms['number'] return milestones @@ -92,9 +89,9 @@ def get_issues(getter, project, milestone): issues = [] for issue_data in data: - issues.append(Issue(issue_data[u'number'], - issue_data[u'title'], - issue_data[u'html_url'])) + issues.append(Issue(issue_data['number'], + issue_data['title'], + issue_data['html_url'])) return issues @@ -106,7 +103,7 @@ def __init__(self, filename, getter): if os.path.isfile(filename): print(f"[gh_lists] using {filename} as cache (remove it if you want fresh data)", file=sys.stderr) - with open(filename, 'r', encoding='utf-8') as f: + with open(filename, encoding='utf-8') as f: self.cache = json.load(f) else: self.cache = {} @@ -175,7 +172,7 @@ def get(self, url): s = self.ratelimit_reset + 5 - time.time() if s <= 0: break - print("[gh_lists] rate limit exceeded: waiting until {0} ({1} s remaining)".format( + print("[gh_lists] rate limit exceeded: waiting until {} ({} s remaining)".format( datetime.datetime.fromtimestamp(self.ratelimit_reset).strftime('%Y-%m-%d %H:%M:%S'), int(s)), file=sys.stderr, flush=True) diff --git a/util/refguide_check.py b/util/refguide_check.py index f23b9d018..21750a48f 100755 --- a/util/refguide_check.py +++ b/util/refguide_check.py @@ -22,24 +22,24 @@ $ python refguide_check.py --check_docs optimize """ -from __future__ import print_function -import sys -import os -import re import copy -import inspect -import warnings import doctest -import tempfile +import glob +import inspect import io -import docutils.core -from docutils.parsers.rst import directives +import os +import re import shutil -import glob -from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, IGNORE_EXCEPTION_DETAIL +import sys +import tempfile +import warnings from argparse import ArgumentParser +from doctest import ELLIPSIS, IGNORE_EXCEPTION_DETAIL, NORMALIZE_WHITESPACE + +import docutils.core import numpy as np +from docutils.parsers.rst import directives # FIXME: doctests need the str/repr formatting used in Numpy < 1.14. try: @@ -50,6 +50,7 @@ # sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'doc', # 'sphinxext')) from numpydoc.docscrape_sphinx import get_doc_object + # Remove sphinx directives that don't run without Sphinx environment directives._directives.pop('versionadded', None) directives._directives.pop('versionchanged', None) @@ -68,7 +69,7 @@ # these names are known to fail doctesting and we like to keep it that way # e.g. sometimes pseudocode is acceptable etc -DOCTEST_SKIPLIST = set([]) +DOCTEST_SKIPLIST = set() # these names are not required to be present in ALL despite being in # autosummary:: listing @@ -246,12 +247,12 @@ def validate_rst_syntax(text, name, dots=True): output_dot('E') return False, f"ERROR: {name}: no documentation" - ok_unknown_items = set([ + ok_unknown_items = { 'mod', 'currentmodule', 'autosummary', 'data', 'obj', 'versionadded', 'versionchanged', 'module', 'class', 'ref', 'func', 'toctree', 'moduleauthor', 'sectionauthor', 'codeauthor', 'eq', - ]) + } # Run through docutils error_stream = io.StringIO() @@ -263,16 +264,16 @@ def resolve(name, is_label=False): docutils.core.publish_doctree( text, token, - settings_overrides = dict(halt_level=5, - traceback=True, - default_reference_context='title-reference', - default_role='emphasis', - link_base='', - resolve_name=resolve, - stylesheet_path='', - raw_enabled=0, - file_insertion_enabled=0, - warning_stream=error_stream)) + settings_overrides = {'halt_level': 5, + 'traceback': True, + 'default_reference_context': 'title-reference', + 'default_role': 'emphasis', + 'link_base': '', + 'resolve_name': resolve, + 'stylesheet_path': '', + 'raw_enabled': 0, + 'file_insertion_enabled': 0, + 'warning_stream': error_stream}) # Print errors, disregarding unimportant ones error_msg = error_stream.getvalue() @@ -357,8 +358,8 @@ def check_rest(module, names, dots=True): m = re.search("([\x00-\x09\x0b-\x1f])", text) if m: - msg = ("Docstring contains a non-printable character %r! " - "Maybe forgot r\"\"\"?" % (m.group(1),)) + msg = (f"Docstring contains a non-printable character {m.group(1)!r}! " + "Maybe forgot r\"\"\"?") results.append((full_name, False, msg)) continue @@ -542,7 +543,7 @@ def _run_doctests(tests, full_name, verbose, doctest_warnings): def out(msg): output.append(msg) - class MyStderr(object): + class MyStderr: """Redirect stderr to the current stdout""" def write(self, msg): if doctest_warnings: @@ -677,10 +678,10 @@ def check_doctests_testfile(fname, verbose, ns=None, full_name = fname text = open(fname).read() - PSEUDOCODE = set(['some_function', 'some_module', 'import example', + PSEUDOCODE = {'some_function', 'some_module', 'import example', 'ctypes.CDLL', # likely need compiling, skip it 'integrate.nquad(func,' # ctypes integrate tutotial - ]) + } # split the text into "blocks" and try to detect and omit pseudocode blocks. parser = doctest.DocTestParser() diff --git a/util/version_utils.py b/util/version_utils.py index dab8b92a8..81d119e75 100644 --- a/util/version_utils.py +++ b/util/version_utils.py @@ -1,7 +1,6 @@ +import argparse import os import subprocess -import argparse - MAJOR = 1 MINOR = 5