diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 386f01d..ab3381c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,9 +18,9 @@ jobs:
package:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v7
- name: Set up Python
- uses: actions/setup-python@v6
+ uses: actions/setup-python@v7
with:
python-version: '3.10'
- name: Install dependencies
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index cfe4336..4570f90 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -38,10 +38,10 @@ jobs:
OPENBLAS_NUM_THREADS: "1"
PYTHONUNBUFFERED: "1"
steps:
- - uses: actions/setup-python@v6
+ - uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v7
- uses: pyvista/setup-headless-display-action@main
with:
qt: true
@@ -81,7 +81,7 @@ jobs:
MKL_NUM_THREADS: '1'
PYTHONUNBUFFERED: '1'
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v7
- uses: pyvista/setup-headless-display-action@main
with:
qt: true
@@ -115,10 +115,10 @@ jobs:
OPENBLAS_NUM_THREADS: "1"
PYTHONUNBUFFERED: "1"
steps:
- - uses: actions/setup-python@v6
+ - uses: actions/setup-python@v7
with:
python-version: "3.10"
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v7
- uses: pyvista/setup-headless-display-action@main
with:
qt: true
@@ -126,17 +126,14 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
- pip install --upgrade --upgrade-strategy eager .[test]
+ pip install -e . --no-deps
+ pip install -r tools/requirements_old.txt
- name: Display versions and environment information
run: |
echo $TZ
date
- python --version
which python
- - run: |
- pip install -e . --no-deps
- pip install -r tools/requirements_old.txt
- - run: python -c "import pybispectra; import mne; print(f'PyBispectra {pybispectra.__version__}\n'); mne.sys_info()"
+ python -c "import pybispectra; import mne; print(f'PyBispectra {pybispectra.__version__}\n'); mne.sys_info()"
- name: Download testing data
run: python -c "from pybispectra.utils import DATASETS, get_example_data_paths; (get_example_data_paths(data) for data in DATASETS.keys())"
- name: Run pytest
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f7aef92..1c5f94e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,7 +1,7 @@
repos:
# ruff PyBispectra
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.15.8
+ rev: v0.16.0
hooks:
- id: ruff
name: ruff lint pybispectra
@@ -10,7 +10,7 @@ repos:
# ruff examples
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.15.8
+ rev: v0.16.0
hooks:
- id: ruff
name: ruff lint examples
@@ -19,7 +19,7 @@ repos:
# codespell
- repo: https://github.com/codespell-project/codespell
- rev: v2.4.2
+ rev: v2.4.3
hooks:
- id: codespell
additional_dependencies:
diff --git a/changelog.md b/changelog.md
index 65cc04b..0311962 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,6 +8,13 @@ No changes.
## [Version 1.3](https://pybispectra.readthedocs.io/1.3/)
+### Version 1.3.2
+
+##### Dependencies
+- Dropped max supported Python version being pinned.
+
+
+
### Version 1.3.1
##### Dependencies
diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css
index 7b67808..d4d7a90 100644
--- a/docs/source/_static/css/custom.css
+++ b/docs/source/_static/css/custom.css
@@ -6,6 +6,29 @@ ul {
text-align: left
}
+/* widen main content area */
+.bd-page-width {
+ max-width: 100rem;
+}
+
+/* make versionadded smaller and inline with param name */
+/* don't do for deprecated / versionchanged; they have extra info (too long to fit) */
+div.versionadded>p {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.versionadded {
+ margin: 0;
+ margin-left: 0.5rem;
+ display: inline-block;
+}
+
+/* when FF supports :has(), change to → dd > p:has(+div.versionadded) */
+dd>p {
+ display: inline;
+}
+
@media (max-width: 1199.98px) {
.bd-header .navbar-header-items__start {
flex-shrink: 1;
diff --git a/docs/source/_static/versions.json b/docs/source/_static/versions.json
index e947050..ec275f0 100644
--- a/docs/source/_static/versions.json
+++ b/docs/source/_static/versions.json
@@ -6,7 +6,7 @@
},
{
"name": "1.3 (stable)",
- "version": "1.3.1",
+ "version": "1.3.2",
"url": "https://pybispectra.readthedocs.io/1.3/"
},
{
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 7a20a04..5a1ac63 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -16,7 +16,7 @@
project = "PyBispectra"
copyright = "2023-2026, Thomas S. Binns"
author = "Thomas S. Binns"
-release = "1.3.1"
+release = "1.3.2"
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
diff --git a/docs/source/installation.rst b/docs/source/installation.rst
index 8ea8185..04ee5e6 100644
--- a/docs/source/installation.rst
+++ b/docs/source/installation.rst
@@ -7,6 +7,10 @@ for version ≥ 1.2.2.
PyBispectra requires Python ≥ 3.10.
+
+Package installation
+--------------------
+
To install PyBispectra, activate the desired environment or project in which you want
the package, then install it using `pip `_:
@@ -34,13 +38,29 @@ or `pixi `_:
|
+.. dropdown:: Compatibility for newly released Python versions
+ :icon: alert
+ :color: info
+
+ If you encounter issues installing PyBispectra in environments with newly released Python versions, this may be due to a lack of compatible ``numba`` releases, one of PyBispectra's core dependencies.
+
+ ``numba`` is not always immediately compatible with new Python versions, and there may be a delay of several weeks before a compatible version is released.
+
+ You can find the supported Python versions for ``numba`` in this `table `_.
+
+ If a compatible ``numba`` release is available for your environment's Python version and you are still encountering installation issues, please report this on the `PyBispectra issue page `_.
+
.. dropdown:: Compatibility with Python ≥ 3.14 on macOS Intel systems
+ :icon: alert
+ :color: info
- Support for macOS Intel systems is limited to Python < 3.14 due to wheel availability limitations for `llvmlite`, which can lead to installation issues using ``pip`` and ``uv``.
+ Due to wheel availability limitations for ``llvmlite`` on macOS Intel systems with Python ≥ 3.14, installation issues can arise when using ``pip`` and ``uv``.
- If you have a macOS Intel system and need to use Python ≥ 3.14, consider using ``conda`` or ``pixi`` for installation.
+ If you have a macOS Intel system and need to use Python ≥ 3.14, consider using ``conda`` or ``pixi`` for an easier installation.
-|
+
+Creating an environment or project for installation
+---------------------------------------------------
If you need to create an environment or project in which to install PyBispectra, you can
do so using `venv `_,
@@ -48,7 +68,7 @@ do so using `venv `_,
`conda `_.
With ``venv``
--------------
+~~~~~~~~~~~~~
In a shell with Python available, navigate to your project location and create the
environment:
@@ -66,7 +86,7 @@ then install the package:
pip install pybispectra
With ``uv``
------------
+~~~~~~~~~~~
In a shell with ``uv`` available, navigate to your project location and create the
environment:
@@ -84,7 +104,7 @@ then install the package:
uv pip install pybispectra
With ``pixi``
--------------
+~~~~~~~~~~~~~
In a shell with ``pixi`` available, run the following commands:
@@ -95,7 +115,7 @@ In a shell with ``pixi`` available, run the following commands:
pixi add pybispectra
With ``conda``
---------------
+~~~~~~~~~~~~~~
In a shell with ``conda`` available, run the following commands:
diff --git a/environment.yml b/environment.yml
index ffc93b9..631712f 100644
--- a/environment.yml
+++ b/environment.yml
@@ -2,7 +2,7 @@ name: pybispectra
channels:
- conda-forge
dependencies:
- - python>=3.10,<3.15
+ - python>=3.10
- joblib>=1.2
- matplotlib>=3.6
- mne-base>=1.7
diff --git a/examples/plot_compute_time_resolved.py b/examples/plot_compute_time_resolved.py
index ba9cd46..7759b03 100644
--- a/examples/plot_compute_time_resolved.py
+++ b/examples/plot_compute_time_resolved.py
@@ -18,7 +18,7 @@
from matplotlib import pyplot as plt
from numpy.random import RandomState
-from pybispectra import WaveShape, get_example_data_paths, compute_tfr
+from pybispectra import WaveShape, compute_tfr, get_example_data_paths
########################################################################################
# Background
diff --git a/pyproject.toml b/pyproject.toml
index bcdbd81..2b80b9f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,7 +16,7 @@ dynamic = [
] # check tools/hatch_build.py for details
name = "pybispectra"
readme = "README.md"
-version = "1.3.1"
+version = "1.3.2"
[project.optional-dependencies]
dev = ["pybispectra[doc]", "pybispectra[lint]", "pybispectra[test]"]
@@ -126,7 +126,11 @@ ignore_roles = [
report_level = "WARNING"
[tool.ruff]
-extend-exclude = ["docs", "examples/compute_*.py"]
+extend-exclude = [
+ "docs",
+ "examples/compute_*.py",
+ "src/pybispectra/utils/_docs.py",
+]
line-length = 88
[tool.ruff.lint.per-file-ignores]
diff --git a/src/pybispectra/__init__.py b/src/pybispectra/__init__.py
index 9cd9656..1a66d0f 100644
--- a/src/pybispectra/__init__.py
+++ b/src/pybispectra/__init__.py
@@ -1,6 +1,6 @@
"""Initialisation of the PyBispectra package."""
-__version__ = "1.3.1"
+__version__ = "1.3.2"
from .cfc import AAC, PAC, PPC
from .general import Bispectrum, Threenorm
diff --git a/src/pybispectra/cfc/aac.py b/src/pybispectra/cfc/aac.py
index 9335d8c..5067b9f 100644
--- a/src/pybispectra/cfc/aac.py
+++ b/src/pybispectra/cfc/aac.py
@@ -7,9 +7,9 @@
from pybispectra.utils._defaults import _precision
from pybispectra.utils._process import _ProcessFreqBase
from pybispectra.utils._utils import (
+ _compute_in_parallel,
_compute_pearsonr_2d,
_fast_find_first,
- _compute_in_parallel,
)
@@ -61,7 +61,7 @@ class AAC(_ProcessFreqBase):
verbose : bool
Whether or not to report the progress of the processing.
- """ # noqa: E501
+ """
_data_precision: type = _precision.real # Real-valued TFR power
@@ -72,9 +72,9 @@ class AAC(_ProcessFreqBase):
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_jobs: int = 1,
) -> None:
r"""Compute AAC, averaged over epochs.
diff --git a/src/pybispectra/cfc/pac.py b/src/pybispectra/cfc/pac.py
index 937b69c..feaab72 100644
--- a/src/pybispectra/cfc/pac.py
+++ b/src/pybispectra/cfc/pac.py
@@ -80,9 +80,9 @@ class PAC(_ProcessBispectrum):
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
antisym: bool | tuple[bool] = False,
norm: bool | tuple[bool] = False,
n_jobs: int = 1,
@@ -181,7 +181,7 @@ def compute(
References
----------
.. footbibliography::
- """ # noqa: E501
+ """
self._reset_attrs()
self._sort_metrics(antisym, norm)
diff --git a/src/pybispectra/cfc/ppc.py b/src/pybispectra/cfc/ppc.py
index b09f280..361eab2 100644
--- a/src/pybispectra/cfc/ppc.py
+++ b/src/pybispectra/cfc/ppc.py
@@ -6,7 +6,7 @@
from pybispectra.utils import ResultsCFC
from pybispectra.utils._defaults import _precision
from pybispectra.utils._process import _ProcessFreqBase
-from pybispectra.utils._utils import _fast_find_first, _compute_in_parallel
+from pybispectra.utils._utils import _compute_in_parallel, _fast_find_first
class PPC(_ProcessFreqBase):
@@ -73,9 +73,9 @@ class PPC(_ProcessFreqBase):
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_jobs: int = 1,
) -> None:
r"""Compute PPC, averaged over epochs.
diff --git a/src/pybispectra/general/general.py b/src/pybispectra/general/general.py
index 98d3be8..fdbacc2 100644
--- a/src/pybispectra/general/general.py
+++ b/src/pybispectra/general/general.py
@@ -22,16 +22,14 @@ class _General(_ProcessBispectrum):
def _sort_indices(self, indices: tuple[tuple[int]] | None) -> None:
"""Sort kmn channel indices inputs."""
if indices is None:
- indices = tuple(
- [
- tuple(np.tile(range(self._n_chans), self._n_chans**2).tolist()),
- tuple(
- np.repeat(
- np.tile(range(self._n_chans), self._n_chans), self._n_chans
- ).tolist()
- ),
- tuple(np.repeat(range(self._n_chans), self._n_chans**2).tolist()),
- ]
+ indices = (
+ tuple(np.tile(range(self._n_chans), self._n_chans**2).tolist()),
+ tuple(
+ np.repeat(
+ np.tile(range(self._n_chans), self._n_chans), self._n_chans
+ ).tolist()
+ ),
+ tuple(np.repeat(range(self._n_chans), self._n_chans**2).tolist()),
)
if not isinstance(indices, tuple):
raise TypeError("`indices` must be a tuple.")
@@ -118,9 +116,9 @@ class Bispectrum(_General):
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_jobs: int = 1,
) -> None:
r"""Compute the bispectrum, averaged over epochs.
@@ -167,7 +165,7 @@ def compute(
.. warning::
For values of ``f1s`` higher than ``f2s`` or where ``f2s + f1s`` exceeds the
Nyquist frequency, a :obj:`numpy.nan` value is returned.
- """ # noqa: E501
+ """
self._reset_attrs()
self._sort_indices(indices)
@@ -305,9 +303,9 @@ class Threenorm(_General):
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_jobs: int = 1,
) -> None:
r"""Compute the threenorm, averaged over epochs.
diff --git a/src/pybispectra/tde/tde.py b/src/pybispectra/tde/tde.py
index 748cfff..bfffea5 100644
--- a/src/pybispectra/tde/tde.py
+++ b/src/pybispectra/tde/tde.py
@@ -1,7 +1,8 @@
"""Tools for handling TDE analysis."""
+from collections.abc import Callable
from copy import deepcopy
-from typing import Callable
+from typing import ClassVar
import numpy as np
from numba import njit
@@ -10,7 +11,7 @@
from pybispectra.utils import ResultsTDE
from pybispectra.utils._defaults import _precision
from pybispectra.utils._process import _ProcessBispectrum
-from pybispectra.utils._utils import _compute_in_parallel, _number_like, _int_like
+from pybispectra.utils._utils import _compute_in_parallel, _int_like, _number_like
class TDE(_ProcessBispectrum):
@@ -97,7 +98,7 @@ class TDE(_ProcessBispectrum):
_tde_iv_nosym: np.ndarray = None
_tde_iv_antisym: np.ndarray = None
- _kmn: dict = {
+ _kmn: ClassVar[dict] = {
"xxx": (0, 0, 0),
"yyy": (1, 1, 1),
"xyx": (0, 1, 0),
@@ -109,9 +110,9 @@ def __init__(
self,
data: np.ndarray,
freqs: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
verbose: bool = True,
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, freqs, sampling_freq, times=None, verbose=verbose)
self._sort_fft_coeffs()
@@ -130,8 +131,8 @@ def _sort_fft_coeffs(self) -> None:
def compute(
self,
indices: tuple[tuple[int]] | None = None,
- fmin: int | float | tuple[int | float] = 0.0,
- fmax: int | float | tuple[int | float] = np.inf,
+ fmin: float | tuple[float] = 0.0,
+ fmax: float | tuple[float] = np.inf,
antisym: bool | tuple[bool] = False,
method: int | tuple[int] = 1,
n_jobs: int = 1,
@@ -284,9 +285,7 @@ def _reset_attrs(self) -> None:
self._xyz = None
def _sort_freq_bands(
- self,
- fmin: int | float | tuple[int | float],
- fmax: int | float | tuple[int | float],
+ self, fmin: float | tuple[float], fmax: float | tuple[float]
) -> None:
"""Sort inputs for the frequency bounds."""
if not isinstance(fmin, _number_like + (tuple,)):
diff --git a/src/pybispectra/utils/_defaults.py b/src/pybispectra/utils/_defaults.py
index fc35a9b..14156cf 100644
--- a/src/pybispectra/utils/_defaults.py
+++ b/src/pybispectra/utils/_defaults.py
@@ -9,7 +9,7 @@ class _Precision:
Double precision (i.e., float64 and complex128) used by default.
"""
- def __init__(self) -> None: # noqa: D107
+ def __init__(self) -> None:
self.type = "double"
self.real = np.float64
self.complex = np.complex128
diff --git a/src/pybispectra/utils/_plot.py b/src/pybispectra/utils/_plot.py
index e7eb70d..c28a3e9 100644
--- a/src/pybispectra/utils/_plot.py
+++ b/src/pybispectra/utils/_plot.py
@@ -44,8 +44,8 @@ def _sort_plot_inputs(
nodes: int | tuple[int] | None,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
) -> tuple[int]:
"""Sort the plotting inputs.
@@ -142,7 +142,7 @@ def _sort_freq_inputs(
return f1s, f2s, f1_idcs, f2_idcs
def _sort_time_inputs(
- self, times: tuple[int | float] | None
+ self, times: tuple[float] | None
) -> tuple[np.ndarray | None, np.ndarray | None]:
"""Sort `times` input.
@@ -234,7 +234,7 @@ def __init__(
f2s: np.ndarray,
times: np.ndarray | None,
name: str,
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, indices, name)
self.f1s = f1s.copy()
@@ -244,13 +244,13 @@ def __init__(
def plot(
self,
nodes: int | tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 5.0,
- minor_tick_intervals: int | float = 1.0,
+ major_tick_intervals: float = 5.0,
+ minor_tick_intervals: float = 1.0,
plot_absolute: bool = False,
mirror_cbar_range: bool = True,
cbar_range_abs: tuple[float] | list[tuple[float]] | None = None,
@@ -400,13 +400,13 @@ def plot(
def _sort_plot_inputs(
self,
nodes: int | tuple[int] | None,
- f1s: tuple[int | float] | None,
- f2s: tuple[int | float] | None,
- times: tuple[int | float] | None,
+ f1s: tuple[float] | None,
+ f2s: tuple[float] | None,
+ times: tuple[float] | None,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
plot_absolute: bool,
mirror_cbar_range: bool,
cbar_range_abs: tuple[float] | list[tuple[float]] | None,
@@ -469,8 +469,9 @@ def _sort_plot_inputs(
cbar_range_phase,
]
cbar_names = ["abs", "real", "imag", "phase"]
- cbar_idx = 0
- for cbar_range, cbar_name in zip(cbar_ranges, cbar_names):
+ for cbar_idx, (cbar_range, cbar_name) in enumerate(
+ zip(cbar_ranges, cbar_names)
+ ):
if not isinstance(cbar_range, (list, tuple, type(None))):
raise TypeError(
f"`cbar_range_{cbar_name}` must be a list, tuple, or None."
@@ -490,7 +491,6 @@ def _sort_plot_inputs(
f"Limits in `cbar_range_{cbar_name}` must have length of 2."
)
cbar_ranges[cbar_idx] = cbar_range
- cbar_idx += 1
return (nodes, f1s, f2s, f1_idcs, f2_idcs, times, time_idcs, cbar_ranges)
@@ -555,8 +555,8 @@ def _plot_results(
time_idcs: np.ndarray | None,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
plot_absolute: bool,
mirror_cbar_range: bool,
cbar_ranges: list[list[tuple[float | None]]],
@@ -711,8 +711,8 @@ def _plot_results(
def _set_axis_ticks(
self,
axis: plt.Axes,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
) -> None:
"""Set major and minor tick intervals of x- and y-axes."""
axis.xaxis.set_major_locator(plt.MultipleLocator(major_tick_intervals))
@@ -757,7 +757,7 @@ def __init__(
f2s: np.ndarray,
times: np.ndarray | None,
name: str,
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, indices, name)
self.f1s = f1s.copy()
@@ -767,13 +767,13 @@ def __init__(
def plot(
self,
nodes: int | tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 5.0,
- minor_tick_intervals: int | float = 1.0,
+ major_tick_intervals: float = 5.0,
+ minor_tick_intervals: float = 1.0,
cbar_range: tuple[float] | list[tuple[float]] | None = None,
show: bool = True,
) -> tuple[list[Figure], list[np.ndarray]]:
@@ -836,7 +836,7 @@ def plot(
-----
``n_rows`` and ``n_cols`` of ``1`` will plot the results for each node on a new
figure.
- """ # noqa: E501
+ """
nodes, f1s, f2s, f1_idcs, f2_idcs, times, time_idcs, cbar_range = (
self._sort_plot_inputs(
nodes,
@@ -876,13 +876,13 @@ def plot(
def _sort_plot_inputs(
self,
nodes: int | tuple[int] | None,
- f1s: tuple[int | float] | None,
- f2s: tuple[int | float] | None,
- times: tuple[int | float] | None,
+ f1s: tuple[float] | None,
+ f2s: tuple[float] | None,
+ times: tuple[float] | None,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
cbar_range: tuple[float] | list[tuple[float]] | None,
) -> tuple[
tuple[int],
@@ -956,8 +956,8 @@ def _plot_results(
time_idcs: np.ndarray | None,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
cbar_range: list[tuple[float | None]],
) -> tuple[list[Figure], list[np.ndarray]]:
"""Plot results on the relevant figures/subplots."""
@@ -1043,8 +1043,8 @@ def _plot_results(
def _set_axis_ticks(
self,
axis: plt.Axes,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
) -> None:
"""Set major and minor tick intervals of x- and y-axes."""
axis.xaxis.set_major_locator(plt.MultipleLocator(major_tick_intervals))
@@ -1086,7 +1086,7 @@ def __init__(
freq_bands: tuple[tuple[float]] | None,
times: np.ndarray,
name: str,
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, indices, name)
self.tau = tau
@@ -1102,11 +1102,11 @@ def plot(
self,
nodes: int | tuple[int] | None = None,
freq_bands: int | tuple[int] | None = None,
- times: tuple[int | float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 500.0,
- minor_tick_intervals: int | float = 100.0,
+ major_tick_intervals: float = 500.0,
+ minor_tick_intervals: float = 100.0,
show: bool = True,
) -> tuple[list[Figure], list[np.ndarray]]:
"""Plot the results.
@@ -1189,7 +1189,7 @@ def _sort_plot_inputs(
self,
nodes: int | tuple[int] | None,
freq_bands: int | tuple[int] | None,
- times: tuple[int | float] | None,
+ times: tuple[float] | None,
n_rows: int,
n_cols: int,
major_tick_intervals: float,
@@ -1290,8 +1290,8 @@ def _plot_results(
time_idcs: np.ndarray,
n_rows: int,
n_cols: int,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
) -> tuple[list[Figure], list[np.ndarray]]:
"""Plot results on the relevant figures/subplots."""
fig_i = 0
@@ -1385,8 +1385,8 @@ def _mark_delay(
def _set_axis_ticks(
self,
axis: plt.Axes,
- major_tick_intervals: int | float,
- minor_tick_intervals: int | float,
+ major_tick_intervals: float,
+ minor_tick_intervals: float,
) -> None:
"""Set major and minor tick intervals of the x-axis."""
axis.xaxis.set_major_locator(plt.MultipleLocator(major_tick_intervals))
diff --git a/src/pybispectra/utils/_process.py b/src/pybispectra/utils/_process.py
index ddc49f2..6a66dc5 100644
--- a/src/pybispectra/utils/_process.py
+++ b/src/pybispectra/utils/_process.py
@@ -39,7 +39,7 @@ def __init__(
self,
data: np.ndarray,
freqs: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
times: np.ndarray | None = None,
verbose: bool = True,
) -> None:
@@ -49,7 +49,7 @@ def _sort_init_inputs(
self,
data: np.ndarray,
freqs: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
times: np.ndarray | None,
verbose: bool,
) -> None:
@@ -135,11 +135,9 @@ def _sort_init_inputs(
def _sort_indices(self, indices: tuple[tuple[int]] | None) -> None:
"""Sort seed-target indices inputs."""
if indices is None:
- indices = tuple(
- [
- tuple(np.tile(range(self._n_chans), self._n_chans).tolist()),
- tuple(np.repeat(range(self._n_chans), self._n_chans).tolist()),
- ]
+ indices = (
+ tuple(np.tile(range(self._n_chans), self._n_chans).tolist()),
+ tuple(np.repeat(range(self._n_chans), self._n_chans).tolist()),
)
if not isinstance(indices, tuple):
raise TypeError("`indices` must be a tuple.")
@@ -167,9 +165,7 @@ def _sort_indices(self, indices: tuple[tuple[int]] | None) -> None:
self._n_cons = len(seeds)
- def _sort_freqs(
- self, f1s: tuple[int | float] | None, f2s: tuple[int | float] | None
- ) -> None:
+ def _sort_freqs(self, f1s: tuple[float] | None, f2s: tuple[float] | None) -> None:
"""Sort frequency inputs."""
check_f1s = True
check_f2s = True
@@ -208,15 +204,14 @@ def _sort_freqs(
)
self._f2s = self.freqs[f2_idcs]
- if self.verbose:
- if self._f1s.max() >= self._f2s.min():
- warn(
- "At least one value in `f1s` is >= a value in `f2s`. The "
- "corresponding result(s) will have a value of NaN.",
- UserWarning,
- )
+ if self.verbose and self._f1s.max() >= self._f2s.min():
+ warn(
+ "At least one value in `f1s` is >= a value in `f2s`. The corresponding "
+ "result(s) will have a value of NaN.",
+ UserWarning,
+ )
- def _sort_tmin_tmax(self, times: tuple[int | float] | None) -> None:
+ def _sort_tmin_tmax(self, times: tuple[float] | None) -> None:
"""Sort time range inputs."""
if times is None:
times = (-np.inf, np.inf)
@@ -308,34 +303,33 @@ def _sort_indices(self, indices: tuple[tuple[int]]) -> None:
"""Sort seed-target indices inputs."""
super()._sort_indices(indices)
- if self.verbose:
- if self._return_antisym and (
+ if (
+ self.verbose
+ and self._return_antisym
+ and (
any(seed == target for seed, target in zip(self._seeds, self._targets))
- ):
- warn(
- "The seed and target for at least one connection is the same "
- "channel. The corresponding antisymmetrised result(s) will be "
- "NaN-valued.",
- UserWarning,
- )
+ )
+ ):
+ warn(
+ "The seed and target for at least one connection is the same channel. "
+ "The corresponding antisymmetrised result(s) will be NaN-valued.",
+ UserWarning,
+ )
- def _sort_freqs(
- self, f1s: tuple[int | float] | None, f2s: tuple[int | float] | None
- ) -> None:
+ def _sort_freqs(self, f1s: tuple[float] | None, f2s: tuple[float] | None) -> None:
"""Sort frequency inputs."""
super()._sort_freqs(f1s, f2s)
- if self.verbose:
- if any(
- hfreq + lfreq not in self.freqs
- for hfreq in self._f2s
- for lfreq in self._f1s
- ):
- warn(
- "At least one value of `f2s` + `f1s` is not present in the "
- "frequencies. The corresponding result(s) will be NaN-valued.",
- UserWarning,
- )
+ if self.verbose and any(
+ hfreq + lfreq not in self.freqs
+ for hfreq in self._f2s
+ for lfreq in self._f1s
+ ):
+ warn(
+ "At least one value of `f2s` + `f1s` is not present in the "
+ "frequencies. The corresponding result(s) will be NaN-valued.",
+ UserWarning,
+ )
@njit
diff --git a/src/pybispectra/utils/_utils.py b/src/pybispectra/utils/_utils.py
index d455351..f1eedb3 100644
--- a/src/pybispectra/utils/_utils.py
+++ b/src/pybispectra/utils/_utils.py
@@ -8,7 +8,6 @@
from pybispectra.utils._defaults import _precision
-
# Aliases for type checking
_int_like = (int, np.integer)
_float_like = (float, np.floating)
@@ -109,7 +108,7 @@ def _get_block_indices(block_i: int, limit: int, n_jobs: int) -> np.ndarray:
@njit
def _fast_find_first(
- vector: np.ndarray, value: int | float, start_idx: int = 0
+ vector: np.ndarray, value: float, start_idx: int = 0
) -> int: # pragma: no cover
"""Quickly find the first index of a value in a 1D array using Numba.
diff --git a/src/pybispectra/utils/ged.py b/src/pybispectra/utils/ged.py
index b04db4c..9131313 100644
--- a/src/pybispectra/utils/ged.py
+++ b/src/pybispectra/utils/ged.py
@@ -1,14 +1,15 @@
"""Tools for performing generalised eigendecompositions."""
-from packaging.version import Version
from multiprocessing import cpu_count
from warnings import warn
import numpy as np
import scipy as sp
-from mne import Info, __version__ as mne_version
+from mne import Info
+from mne import __version__ as mne_version
from mne.decoding import SSD
from mne.time_frequency import csd_array_fourier, csd_array_multitaper
+from packaging.version import Version
from pybispectra.utils._defaults import _precision
from pybispectra.utils._utils import _create_mne_info, _int_like, _number_like
@@ -168,9 +169,9 @@ class SpatioSpectralFilter:
def __init__(
self,
data: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
verbose: bool = True,
- ) -> None: # noqa: D107
+ ) -> None:
self.verbose = verbose
self._sort_init_inputs(data, sampling_freq)
@@ -193,9 +194,9 @@ def _sort_init_inputs(self, data: np.ndarray, sampling_freq: float) -> None:
def _sort_freq_bounds(
self,
- signal_bounds: tuple[int | float],
- noise_bounds: tuple[int | float],
- signal_noise_gap: int | float,
+ signal_bounds: tuple[float],
+ noise_bounds: tuple[float],
+ signal_noise_gap: float,
) -> None:
"""Sort frequency bound inputs."""
if not isinstance(signal_bounds, tuple) or not all(
@@ -307,9 +308,9 @@ def _sort_csd_method(self, csd_method: str) -> None:
def fit_ssd(
self,
- signal_bounds: tuple[int | float],
- noise_bounds: tuple[int | float],
- signal_noise_gap: int | float = 1.0,
+ signal_bounds: tuple[float],
+ noise_bounds: tuple[float],
+ signal_noise_gap: float = 1.0,
bandpass_filter: bool = False,
indices: tuple[int] | None = None,
rank: int | None = None,
@@ -373,9 +374,9 @@ def fit_ssd(
def _create_mne_filt_params(
self,
- signal_bounds: tuple[int | float],
- noise_bounds: tuple[int | float],
- signal_noise_gap: int | float,
+ signal_bounds: tuple[float],
+ noise_bounds: tuple[float],
+ signal_noise_gap: float,
) -> tuple[dict, dict]:
"""Create filter parameters for use with MNE's SSD implementation.
@@ -452,14 +453,14 @@ def _compute_ssd(
def fit_hpmax(
self,
- signal_bounds: tuple[int | float],
- noise_bounds: tuple[int | float],
+ signal_bounds: tuple[float],
+ noise_bounds: tuple[float],
n_harmonics: int = -1,
indices: tuple[int] | None = None,
rank: int | None = None,
csd_method: str = "multitaper",
n_fft: int | None = None,
- mt_bandwidth: int | float = 5.0,
+ mt_bandwidth: float = 5.0,
mt_adaptive: bool = True,
mt_low_bias: bool = True,
n_jobs: int = 1,
@@ -563,7 +564,7 @@ def _compute_csd(
self,
csd_method: str,
n_fft: int | None,
- mt_bandwidth: int | float,
+ mt_bandwidth: float,
mt_adaptive: bool,
mt_low_bias: bool,
n_jobs: int,
@@ -837,7 +838,7 @@ def fit_transform_hpmax(self, *args: tuple, **kwargs: dict) -> np.ndarray:
return self.transform()
def get_transformed_data(
- self, min_ratio: int | float = -np.inf, copy: bool = True
+ self, min_ratio: float = -np.inf, copy: bool = True
) -> np.ndarray:
"""Return the transformed data.
diff --git a/src/pybispectra/utils/results.py b/src/pybispectra/utils/results.py
index 8cf3569..184fdd6 100644
--- a/src/pybispectra/utils/results.py
+++ b/src/pybispectra/utils/results.py
@@ -5,9 +5,9 @@
import numpy as np
from matplotlib.figure import Figure
+from pybispectra.utils._defaults import _precision
from pybispectra.utils._plot import _PlotCFC, _PlotGeneral, _PlotTDE, _PlotWaveShape
from pybispectra.utils._utils import _int_like
-from pybispectra.utils._defaults import _precision
class _ResultsBase(ABC):
@@ -316,7 +316,7 @@ def __init__(
f2s: np.ndarray,
times: np.ndarray | None = None,
name: str = "CFC",
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, (3, 4), name)
self._sort_init_inputs(indices, f1s, f2s, times)
@@ -368,13 +368,13 @@ def _get_compact_results_child(self) -> tuple[np.ndarray, tuple[tuple[int]]]:
def plot(
self,
nodes: int | tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 5.0,
- minor_tick_intervals: int | float = 1.0,
+ major_tick_intervals: float = 5.0,
+ minor_tick_intervals: float = 1.0,
cbar_range: tuple[float] | list[tuple[float]] | None = None,
show: bool = True,
) -> tuple[list[Figure], list[np.ndarray]]:
@@ -509,9 +509,9 @@ class ResultsTDE(_ResultsBase):
tau : ~numpy.ndarray, shape of [nodes, frequency_bands]
Estimated time delay (in ms) for each connection and frequency band.
- """ # noqa: E501
+ """
- freq_bands: tuple[tuple[int | float]] = None
+ freq_bands: tuple[tuple[float]] = None
_n_fbands: int = None
def __repr__(self) -> str:
@@ -535,9 +535,9 @@ def __init__(
data: np.ndarray,
indices: tuple[tuple[int]],
times: np.ndarray,
- freq_bands: tuple[tuple[int | float]] | None = None,
+ freq_bands: tuple[tuple[float]] | None = None,
name: str = "TDE",
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, (3,), name)
self._sort_init_inputs(indices, times, freq_bands)
@@ -553,10 +553,7 @@ def __init__(
)
def _sort_init_inputs(
- self,
- indices: tuple[tuple[int]],
- times: np.ndarray,
- freq_bands: tuple[int | float],
+ self, indices: tuple[tuple[int]], times: np.ndarray, freq_bands: tuple[float]
) -> None:
"""Sort inputs to the object."""
super()._sort_indices_seeds_targets(indices)
@@ -575,7 +572,7 @@ def _sort_times(self, times: np.ndarray) -> None:
self.times = times
- def _sort_freq_bands(self, freq_bands: tuple[tuple[int | float]]) -> None:
+ def _sort_freq_bands(self, freq_bands: tuple[tuple[float]]) -> None:
"""Sort ``freq_bands`` input."""
if freq_bands is not None:
if not isinstance(freq_bands, tuple):
@@ -621,11 +618,11 @@ def plot(
self,
nodes: int | tuple[int] | None = None,
freq_bands: int | tuple[int] | None = None,
- times: tuple[int | float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 500.0,
- minor_tick_intervals: int | float = 100.0,
+ major_tick_intervals: float = 500.0,
+ minor_tick_intervals: float = 100.0,
show: bool = True,
) -> tuple[list[Figure], list[np.ndarray]]:
"""Plot the results.
@@ -780,7 +777,7 @@ def __init__(
f2s: np.ndarray,
times: np.ndarray | None = None,
name: str = "Waveshape",
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, (3, 4), name)
self._sort_init_inputs(indices, f1s, f2s, times)
@@ -831,13 +828,13 @@ def get_results(self, copy: bool = True) -> np.ndarray:
def plot(
self,
nodes: int | tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 5.0,
- minor_tick_intervals: int | float = 1.0,
+ major_tick_intervals: float = 5.0,
+ minor_tick_intervals: float = 1.0,
plot_absolute: bool = False,
mirror_cbar_range: bool = True,
cbar_range_abs: tuple[float] | list[tuple[float]] | None = None,
@@ -1048,7 +1045,7 @@ def __init__(
f2s: np.ndarray,
times: np.ndarray | None = None,
name: str = "General",
- ) -> None: # noqa: D107
+ ) -> None:
super().__init__(data, (3, 4), name)
self._sort_init_inputs(indices, f1s, f2s, times)
@@ -1145,13 +1142,13 @@ def _get_compact_results_child(self) -> tuple[np.ndarray, tuple[tuple[int]]]:
def plot(
self,
nodes: int | tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
n_rows: int = 1,
n_cols: int = 1,
- major_tick_intervals: int | float = 5.0,
- minor_tick_intervals: int | float = 1.0,
+ major_tick_intervals: float = 5.0,
+ minor_tick_intervals: float = 1.0,
plot_absolute: bool = False,
mirror_cbar_range: bool = True,
cbar_range_abs: tuple[float] | list[tuple[float]] | None = None,
@@ -1254,7 +1251,7 @@ def plot(
-----
``n_rows`` and ``n_cols`` of ``1`` will plot the results for each node on a new
figure.
- """ # noqa: E501
+ """
figures, axes = self._plotting.plot(
nodes=nodes,
f1s=f1s,
diff --git a/src/pybispectra/utils/utils.py b/src/pybispectra/utils/utils.py
index aa7635b..0ba7134 100644
--- a/src/pybispectra/utils/utils.py
+++ b/src/pybispectra/utils/utils.py
@@ -1,13 +1,14 @@
"""Public tools for handling data and processing results."""
+from collections.abc import Callable
from multiprocessing import cpu_count
-from typing import Callable
-from packaging.version import Version
-import pooch
import numpy as np
+import pooch
import scipy as sp
-from mne import time_frequency, __version__ as mne_version
+from mne import __version__ as mne_version
+from mne import time_frequency
+from packaging.version import Version
from pybispectra import __version__ as version
from pybispectra.utils._defaults import _precision
@@ -16,7 +17,7 @@
def compute_fft(
data: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
n_points: int | None = None,
window: str = "hanning",
n_jobs: int = 1,
@@ -100,7 +101,7 @@ def compute_fft(
def _compute_fft_input_checks(
data: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
n_points: int | None,
window: str,
n_jobs: int,
@@ -156,13 +157,13 @@ def _compute_fft_input_checks(
def compute_tfr(
data: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
freqs: np.ndarray,
tfr_mode: str = "morlet",
- n_cycles: np.ndarray | int | float = 7.0,
+ n_cycles: np.ndarray | float = 7.0,
zero_mean_wavelets: bool | None = None,
use_fft: bool = True,
- multitaper_time_bandwidth: int | float = 4.0,
+ multitaper_time_bandwidth: float = 4.0,
output: str = "power",
n_jobs: int = 1,
verbose: bool = True,
@@ -206,10 +207,10 @@ def compute_tfr(
output : ``"power"`` | ``"complex"`` (default ``"power"``)
Type of TFR output to return.
+ .. versionadded:: 1.3
.. note::
If ``output = "complex"`` and ``tfr_mode = "multitaper"``, returning weights
for each taper requires MNE version 1.10 or higher.
- .. versionadded:: 1.3
n_jobs : int (default ``1``)
Number of jobs to run in parallel. If ``-1``, all available CPUs are used.
@@ -290,13 +291,13 @@ def compute_tfr(
def _compute_tfr_input_checks(
data: np.ndarray,
- sampling_freq: int | float,
+ sampling_freq: float,
freqs: np.ndarray,
tfr_mode: str,
- n_cycles: np.ndarray | int | float,
+ n_cycles: np.ndarray | float,
zero_mean_wavelets: bool | None,
use_fft: bool,
- multitaper_time_bandwidth: int | float,
+ multitaper_time_bandwidth: float,
output: str,
n_jobs: int,
verbose: bool,
@@ -362,9 +363,10 @@ def _compute_tfr_input_checks(
if not isinstance(use_fft, bool):
raise TypeError("`use_fft` must be a bool.")
- if tfr_mode == "multitaper":
- if not isinstance(multitaper_time_bandwidth, _number_like):
- raise TypeError("`multitaper_time_bandwidth` must be an int or a float.")
+ if tfr_mode == "multitaper" and not isinstance(
+ multitaper_time_bandwidth, _number_like
+ ):
+ raise TypeError("`multitaper_time_bandwidth` must be an int or a float.")
outputs = ["power", "complex"]
if not isinstance(output, str):
@@ -394,7 +396,7 @@ def _compute_tfr_input_checks(
return tfr_func, return_weights, n_jobs
-def compute_rank(data: np.ndarray, sv_tol: int | float = 1e-5) -> int:
+def compute_rank(data: np.ndarray, sv_tol: float = 1e-5) -> int:
"""Compute the minimum rank of data from non-zero singular values.
Parameters
@@ -536,7 +538,7 @@ def get_example_data_paths(name: str, verbose: bool = False) -> str:
If the file is not found in the local cache (see :func:`pooch.os_cache` for the
location), it will be downloaded automatically.
"""
- if name not in DATASETS.keys():
+ if name not in DATASETS:
raise ValueError(f"`name` must be one of: {list(DATASETS.keys())}")
return _pooch.fetch(fname=DATASETS[name], progressbar=verbose)
diff --git a/src/pybispectra/waveshape/waveshape.py b/src/pybispectra/waveshape/waveshape.py
index 61bd186..79a9641 100644
--- a/src/pybispectra/waveshape/waveshape.py
+++ b/src/pybispectra/waveshape/waveshape.py
@@ -8,8 +8,8 @@
_compute_threenorm,
_ProcessBispectrum,
)
-from pybispectra.utils.results import ResultsWaveShape
from pybispectra.utils._utils import _compute_in_parallel, _int_like
+from pybispectra.utils.results import ResultsWaveShape
np.seterr(divide="ignore", invalid="ignore") # no warning for NaN division
@@ -78,7 +78,7 @@ class WaveShape(_ProcessBispectrum):
References
----------
.. footbibliography::
- """ # noqa: E501
+ """
_return_nonorm = False
_return_threenorm = False
@@ -86,9 +86,9 @@ class WaveShape(_ProcessBispectrum):
def compute(
self,
indices: tuple[int] | None = None,
- f1s: tuple[int | float] | None = None,
- f2s: tuple[int | float] | None = None,
- times: tuple[int | float] | None = None,
+ f1s: tuple[float] | None = None,
+ f2s: tuple[float] | None = None,
+ times: tuple[float] | None = None,
norm: bool | tuple[bool] = True,
n_jobs: int = 1,
) -> None:
diff --git a/tools/hatch_build.py b/tools/hatch_build.py
index a49c51e..aac907a 100644
--- a/tools/hatch_build.py
+++ b/tools/hatch_build.py
@@ -16,8 +16,6 @@ def update(self, metadata):
requires_python = ">=3.10"
if is_macos_intel:
requires_python += ", <3.14"
- else:
- requires_python += ", <3.15"
metadata["requires-python"] = requires_python
# dependencies