diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ae2f98af..57f8d2a2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -14,7 +14,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"] steps: - uses: actions/checkout@v7 diff --git a/meegkit/asr.py b/meegkit/asr.py index 2009b90a..54fe2b09 100755 --- a/meegkit/asr.py +++ b/meegkit/asr.py @@ -4,8 +4,7 @@ import numpy as np import pyriemann from pyriemann.geometry.mean import gmean as mean_covariance -from scipy import linalg, signal -from statsmodels.robust.scale import mad +from scipy import linalg, signal, stats from .utils import block_covariance, nonlinear_eigenspace from .utils.asr import ( @@ -407,7 +406,7 @@ def clean_windows(X, sfreq, max_bad_chans=0.2, zthresholds=[-3.5, 5], # extra meegkit-specific criterion: drop windows whose across-channel # z-scores are nearly flat (very low MAD or std) - bad_by_mad = mad(wz, c=1, axis=0) < .1 + bad_by_mad = stats.median_abs_deviation(wz, axis=0) < .1 bad_by_std = np.std(wz, axis=0) < .1 mask3 = np.logical_or(bad_by_mad, bad_by_std) diff --git a/requirements.txt b/requirements.txt index 878c0097..6286662b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,5 +5,4 @@ scikit-learn pandas joblib tqdm -statsmodels pyriemann>=0.12 diff --git a/tests/test_freethreading.py b/tests/test_freethreading.py new file mode 100644 index 00000000..dffc8197 --- /dev/null +++ b/tests/test_freethreading.py @@ -0,0 +1,22 @@ +import subprocess +import sys +import sysconfig + +import pytest + +pytestmark = pytest.mark.skipif( + not sysconfig.get_config_var("Py_GIL_DISABLED"), + reason="requires a free-threaded CPython build", +) + + +def test_import_does_not_reenable_gil(): + # test dependencies (such as pytest extensions) could re-enable the GIL + # without making the library non-freethreaded so we need to run this in + # its own subprocess. + proc = subprocess.run( + [sys.executable, "-c", "import sys, meegkit; assert not sys._is_gil_enabled()"], + capture_output=True, + text=True, + ) + assert proc.returncode == 0, proc.stderr