Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0226404
Add some relevant files and venvs to ignore
agriyakhetarpal Feb 20, 2024
a05ab89
Clarify + assert correct Python version lower bounds
agriyakhetarpal Feb 20, 2024
0580579
Add workflow for testing WASM distribution
agriyakhetarpal Feb 20, 2024
a2ed067
For now, skip tests that use `concurrent.futures`
agriyakhetarpal Feb 20, 2024
198fc92
Enable coloured output for GitHub Actions
agriyakhetarpal Feb 21, 2024
80ae120
Use different check for Emscripten Python interpreter
agriyakhetarpal Feb 21, 2024
7687665
Rename `ImportError` error message for `batch_processing` module
agriyakhetarpal Feb 21, 2024
9941e05
Try fixing bad file descriptors via `os.path.abspath`
agriyakhetarpal Feb 21, 2024
7f95d65
Revisit NumPy-style `IS_WASM` check
agriyakhetarpal Feb 21, 2024
cd69215
Fix `os` module kwargs error
agriyakhetarpal Feb 21, 2024
0249892
Revert "Fix `os` module kwargs error"
agriyakhetarpal Feb 21, 2024
f20d088
Revert "Try fixing bad file descriptors via `os.path.abspath`"
agriyakhetarpal Feb 21, 2024
90d13d0
Hope to fix a few `mra_roundtrip` data tests
agriyakhetarpal Feb 21, 2024
15b6eae
Try loading data files via conversion to abspath
agriyakhetarpal Feb 21, 2024
bc67ce7
Some more path-abspath trickery
agriyakhetarpal Feb 21, 2024
3b743b5
TST: fix test condition for Pyodide
rgommers Feb 21, 2024
f2d8a9c
TST: ensure file handles get closed
rgommers Feb 21, 2024
d5008f7
use importlib.resources instead of `__file__`
rgommers Feb 21, 2024
a4ab51e
try caching data loading
rgommers Feb 21, 2024
f69782e
Git-ignore pytest cache directory tree
agriyakhetarpal Feb 22, 2024
2e0e490
Remove incorrect boolean statement provided to `except` clause
agriyakhetarpal Feb 22, 2024
ef078b0
Rewrite `.npy` file paths as `.npz` archives
agriyakhetarpal Feb 22, 2024
7633198
Convert ecg to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
b031e4a
Convert sst_nino3 to NumPy compressed archive
agriyakhetarpal Feb 22, 2024
ae1d470
Properly skip tests for WASM and wherever threading isn't available
agriyakhetarpal Feb 22, 2024
fa3a852
Clean up conditions to be met to skip tests
agriyakhetarpal Feb 22, 2024
0343b6d
Use better job name to reflect Pyodide build
agriyakhetarpal Feb 22, 2024
dedac16
Remove workflow run contexts, i.e., run on pushes and PRs
agriyakhetarpal Feb 22, 2024
7315b43
import `importlib.resources`, mark `/pywt/data/` as constant
agriyakhetarpal Feb 22, 2024
4a962c9
Remove unneeded `@uses_futures` decorator
agriyakhetarpal Feb 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/emscripten.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
name: Test Pyodide build for PyWavelets

on:
push:
branches:
- master
- v1.**
pull_request:
branches:
- master
- v1.**

env:
FORCE_COLOR: 3

jobs:
build_wasm_emscripten:
name: Build PyWavelets for Pyodide
runs-on: ubuntu-latest
# Uncomment the following line to test changes on a fork
# if: github.repository == 'PyWavelets/pywt'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.11
id: setup-python
uses: actions/setup-python@v2
with:
python-version: '3.11.2'

- name: Install prerequisites
run: |
python -m pip install pyodide-build "pydantic<2"
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV

- name: Set up Emscripten toolchain
uses: mymindstorm/setup-emscripten@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache

- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: '18'

- name: Build PyWavelets
run: |
pyodide build

- name: Install and test wheel
run: |
pyodide venv .venv-pyodide
source .venv-pyodide/bin/activate
pip install dist/*.whl
pushd demo
pip install matplotlib pytest
python -c "import pywt; print(pywt.__version__)"
pytest --pyargs pywt
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,8 @@ __pycache__
*.py[co]
*.pyd
*.so
.DS_Store
.pytest_cache/

# Packages
*.egg
Expand DownExpand Up@@ -32,6 +34,12 @@ cythonize.dat
pywt/version.py
build.log

# Virtual environments
.env/
env/
venv/
.venv/

# asv files
asv/env
asv/html
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,7 +65,7 @@ For more usage examples see the `demo`_ directory in the source package.
Installation
------------

PyWavelets supports `Python`_ >=3.7, and is only dependent on `NumPy`_
PyWavelets supports `Python`_ >=3.9, and is only dependent on `NumPy`_
(supported versions are currently ``>= 1.14.6``). To pass all of the tests,
`Matplotlib`_ is also required. `SciPy`_ is also an optional dependency. When
present, FFT-based continuous wavelet transforms will use FFTs from SciPy
Expand Down
3 changes: 1 addition & 2 deletions demo/batch_processing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,7 @@
from concurrent import futures
except ImportError:
raise ImportError(
"This demo requires concurrent.futures. It can be installed for "
"for python 2.x via: pip install futures")
"This demo requires concurrent.futures. If you are on WebAssembly, this is not available.")

import numpy as np
from numpy.testing import assert_array_equal
Expand Down
16 changes: 11 additions & 5 deletions pywt/_pytest.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
"""common test-related code."""
import os
import sys
import platform
import multiprocessing
import numpy as np
import pytest
Expand All@@ -18,15 +19,18 @@
]

try:
if sys.version_info[0] == 2:
import futures
else:
from concurrent import futures
from concurrent import futures
max_workers = multiprocessing.cpu_count()
futures_available = True
except ImportError:
futures_available = False
futures = None
max_workers = 1

# Check if running on Emscripten/WASM, and skip tests that require concurrency.
# Relevant issue: https://github.com/pyodide/pyodide/issues/237
IS_WASM = (sys.platform == "emscripten") or (platform.machine() in ["wasm32", "wasm64"])


# check if pymatbridge + MATLAB tests should be run
matlab_result_dict_dwt = None
Expand DownExpand Up@@ -57,7 +61,9 @@
matlab_result_dict_dwt = np.load(matlab_data_file_dwt)

uses_futures = pytest.mark.skipif(
not futures_available, reason='futures not available')
not futures_available or IS_WASM,
reason='futures is not available, or running via Pyodide/WASM.')
# not futures_available, reason='futures not available')
uses_matlab = pytest.mark.skipif(
matlab_missing, reason='pymatbridge and/or Matlab not available')
uses_pymatbridge = pytest.mark.skipif(
Expand Down
35 changes: 25 additions & 10 deletions pywt/data/_readers.py
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
import functools
import importlib.resources
import os

import numpy as np


_DATADIR = importlib.resources.files('pywt.data')


@functools.cache
def ascent():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -36,11 +42,13 @@ def ascent():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'ascent.npz')
ascent = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('ascent.npz')) as f:
ascent = np.load(f)['data']

return ascent


@functools.cache
def aero():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -71,11 +79,13 @@ def aero():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'aero.npz')
aero = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('aero.npz')) as f:
aero = np.load(f)['data']

return aero


@functools.cache
def camera():
"""
Get an 8-bit grayscale bit-depth, 512 x 512 derived image for
Expand DownExpand Up@@ -117,11 +127,13 @@ def camera():
>>> plt.show() # doctest: +SKIP

"""
fname = os.path.join(os.path.dirname(__file__), 'camera.npz')
camera = np.load(fname)['data']
with importlib.resources.as_file(_DATADIR.joinpath('camera.npz')) as f:
camera = np.load(f)['data']

return camera


@functools.cache
def ecg():
"""
Get 1024 points of an ECG timeseries.
Expand All@@ -147,11 +159,13 @@ def ecg():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'ecg.npy')
ecg = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('ecg.npz')) as f:
ecg = np.load(f)['data']

return ecg


@functools.cache
def nino():
"""
This data contains the averaged monthly sea surface temperature in degrees
Expand DownExpand Up@@ -183,8 +197,9 @@ def nino():
[<matplotlib.lines.Line2D object at ...>]
>>> plt.show() # doctest: +SKIP
"""
fname = os.path.join(os.path.dirname(__file__), 'sst_nino3.npy')
sst_csv = np.load(fname)
with importlib.resources.as_file(_DATADIR.joinpath('sst_nino3.npz')) as f:
sst_csv = np.load(f)['data']

# sst_csv = pd.read_csv("http://www.cpc.ncep.noaa.gov/data/indices/ersst4.nino.mth.81-10.ascii", sep=' ', skipinitialspace=True)
# take only full years
n = int(np.floor(sst_csv.shape[0]/12.)*12.)
Expand Down
Binary file renamedpywt/data/ecg.npy → pywt/data/ecg.npz
Binary file not shown.
Binary file not shown.
4 changes: 3 additions & 1 deletion pywt/tests/test_concurrent.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
import warnings
import numpy as np
from functools import partial

import pytest
from numpy.testing import assert_array_equal, assert_allclose
from pywt._pytest import uses_futures, futures, max_workers

from pywt._pytest import uses_futures, futures, max_workers
import pywt


Expand Down