From 12dd0a80cd92b3705e43d67773c64c53b8290c6d Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 30 Dec 2024 11:52:42 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20`signal`:=20complete=20`=5Ffir?= =?UTF-8?q?=5Ffilter=5Fdesign.*`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scipy-stubs/signal/_arraytools.pyi | 14 ++- scipy-stubs/signal/_fir_filter_design.pyi | 142 +++++++++++++++------- 2 files changed, 113 insertions(+), 43 deletions(-) diff --git a/scipy-stubs/signal/_arraytools.pyi b/scipy-stubs/signal/_arraytools.pyi index 299be237..e54219db 100644 --- a/scipy-stubs/signal/_arraytools.pyi +++ b/scipy-stubs/signal/_arraytools.pyi @@ -1,4 +1,4 @@ -from typing import TypeVar +from typing import Literal, TypeAlias, TypeVar, overload import numpy as np import optype as op @@ -6,6 +6,10 @@ import optype.numpy as onp _SCT = TypeVar("_SCT", bound=np.generic) +_Truthy: TypeAlias = Literal[True, 1] + +### + def axis_slice( a: onp.ArrayND[_SCT], start: op.CanIndex | None = None, @@ -14,7 +18,15 @@ def axis_slice( axis: op.CanIndex = -1, ) -> onp.ArrayND[_SCT]: ... def axis_reverse(a: onp.ArrayND[_SCT], axis: op.CanIndex = -1) -> onp.ArrayND[_SCT]: ... + +# def odd_ext(x: onp.ArrayND[_SCT], n: onp.ToInt, axis: op.CanIndex = -1) -> onp.ArrayND[_SCT]: ... def even_ext(x: onp.ArrayND[_SCT], n: onp.ToInt, axis: op.CanIndex = -1) -> onp.ArrayND[_SCT]: ... def const_ext(x: onp.ArrayND[_SCT], n: onp.ToInt, axis: op.CanIndex = -1) -> onp.ArrayND[_SCT]: ... def zero_ext(x: onp.ArrayND[_SCT], n: onp.ToInt, axis: op.CanIndex = -1) -> onp.ArrayND[_SCT]: ... + +# +@overload +def _validate_fs(fs: None, allow_none: _Truthy = True) -> None: ... +@overload +def _validate_fs(fs: onp.ToFloat, allow_none: onp.ToBool = True) -> float: ... diff --git a/scipy-stubs/signal/_fir_filter_design.pyi b/scipy-stubs/signal/_fir_filter_design.pyi index 80cef211..8faee08e 100644 --- a/scipy-stubs/signal/_fir_filter_design.pyi +++ b/scipy-stubs/signal/_fir_filter_design.pyi @@ -1,55 +1,113 @@ -from typing import Literal +from typing import Literal, TypeAlias, overload +from typing_extensions import TypeVar -from scipy._typing import Untyped, UntypedArray +import numpy as np +import optype as op +import optype.numpy as onp +import optype.numpy.compat as npc +from .windows._windows import _ToWindow __all__ = ["firls", "firwin", "firwin2", "kaiser_atten", "kaiser_beta", "kaiserord", "minimum_phase", "remez"] -def kaiser_beta(a: Untyped) -> Untyped: ... -def kaiser_atten(numtaps: int, width: float | None) -> Untyped: ... -def kaiserord(ripple: Untyped, width: float | None) -> Untyped: ... +### + +_InexactT_py = TypeVar("_InexactT_py", bound=complex) +_InexactT_np = TypeVar("_InexactT_np", bound=npc.inexact) + +_IIRFilterType: TypeAlias = Literal["bandpass", "lowpass", "highpass", "bandstop"] +_RemezFilterType: TypeAlias = Literal["bandpass", "differentiator", "hilbert"] +_LinearPhaseFIRMethod: TypeAlias = Literal["homomorphic", "hilbert"] + +### + +# +def kaiser_beta(a: onp.ToFloat) -> float: ... +def kaiserord(ripple: onp.ToFloat, width: onp.ToFloat) -> tuple[int, float]: ... + +# +@overload +def kaiser_atten(numtaps: _InexactT_py, width: _InexactT_py) -> _InexactT_py: ... +@overload +def kaiser_atten(numtaps: _InexactT_np | float, width: _InexactT_np) -> _InexactT_np: ... +@overload +def kaiser_atten(numtaps: npc.integer, width: npc.integer | float) -> np.float64: ... +@overload +def kaiser_atten(numtaps: npc.integer | float, width: npc.integer) -> np.float64: ... + +# +@overload +def firwin( + numtaps: onp.ToJustInt, + cutoff: onp.ToFloat64 | onp.ToFloat64_1D, + *, + width: onp.ToFloat64 | None = None, + window: _ToWindow = "hamming", + pass_zero: _IIRFilterType | bool = True, + scale: op.CanBool = True, + fs: onp.ToFloat64 | None = None, +) -> onp.Array1D[np.float64]: ... +@overload def firwin( - numtaps: int, - cutoff: Untyped, + numtaps: onp.ToJustInt, + cutoff: onp.ToFloat | onp.ToFloat1D, *, - width: Untyped | None = None, - window: str = "hamming", - pass_zero: Literal["bandpass", "lowpass", "highpass", "bandstop"] | bool = True, - scale: bool = True, - fs: float | None = None, -) -> Untyped: ... + width: onp.ToFloat | None = None, + window: _ToWindow = "hamming", + pass_zero: _IIRFilterType | bool = True, + scale: op.CanBool = True, + fs: onp.ToFloat | None = None, +) -> onp.Array1D[np.float64 | np.longdouble]: ... + +# def firwin2( - numtaps: int, - freq: Untyped, - gain: Untyped, + numtaps: onp.ToJustInt, + freq: onp.ToFloat1D, + gain: onp.ToFloat1D, *, - nfreqs: Untyped | None = None, - window: str = "hamming", - antisymmetric: bool = False, - fs: float | None = None, -) -> Untyped: ... -def remez( - numtaps: int, - bands: Untyped, - desired: Untyped, + nfreqs: onp.ToJustInt | None = None, + window: _ToWindow = "hamming", + antisymmetric: op.CanBool = False, + fs: onp.ToFloat | None = None, +) -> onp.Array1D[np.float64]: ... + +# +@overload +def firls( + numtaps: onp.ToJustInt, + bands: onp.ToFloat1D, + desired: onp.ToFloat1D, *, - weight: Untyped | None = None, - type: str = "bandpass", - maxiter: int = 25, - grid_density: int = 16, - fs: float | None = None, -) -> Untyped: ... + weight: onp.ToFloat1D | None = None, + fs: onp.ToFloat | None = None, +) -> onp.Array1D[np.float64]: ... +@overload def firls( - numtaps: int, - bands: Untyped, - desired: Untyped, + numtaps: onp.ToJustInt, + bands: onp.ToFloat2D, + desired: onp.ToFloat2D, *, - weight: Untyped | None = None, - fs: float | None = None, -) -> Untyped: ... + weight: onp.ToFloat1D | None = None, + fs: onp.ToFloat | None = None, +) -> onp.Array1D[np.float64]: ... + +# +def remez( + numtaps: onp.ToJustInt, + bands: onp.ToFloat1D, + desired: onp.ToFloat1D, + *, + weight: onp.ToFloat1D | None = None, + type: _RemezFilterType = "bandpass", + maxiter: onp.ToJustInt = 25, + grid_density: onp.ToJustInt = 16, + fs: onp.ToFloat | None = None, +) -> onp.Array1D[np.float64]: ... + +# def minimum_phase( - h: UntypedArray, - method: Literal["homomorphic", "hilbert"] = "homomorphic", - n_fft: int | None = None, + h: onp.ToFloat1D, + method: _LinearPhaseFIRMethod = "homomorphic", + n_fft: onp.ToJustInt | None = None, *, - half: bool = True, -) -> UntypedArray: ... + half: op.CanBool = True, +) -> onp.Array1D[np.float64]: ... From bccdf1a131cf654d242c8c3bdfa484a4cc77371c Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 30 Dec 2024 12:04:12 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8=20`signal`:=20complete=20`=5Fmax?= =?UTF-8?q?=5Flen=5Fseq[=5Finner].*`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scipy-stubs/signal/_max_len_seq.pyi | 17 +++++++++++------ scipy-stubs/signal/_max_len_seq_inner.pyi | 11 +++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/scipy-stubs/signal/_max_len_seq.pyi b/scipy-stubs/signal/_max_len_seq.pyi index 2a880828..9761c7f5 100644 --- a/scipy-stubs/signal/_max_len_seq.pyi +++ b/scipy-stubs/signal/_max_len_seq.pyi @@ -1,10 +1,15 @@ -from scipy._typing import Untyped, UntypedArray +from typing import Final + +import numpy as np +import optype.numpy as onp __all__ = ["max_len_seq"] +_mls_taps: Final[dict[int, list[int]]] = ... + def max_len_seq( - nbits: int, - state: Untyped | None = None, - length: int | None = None, - taps: Untyped | None = None, -) -> tuple[UntypedArray, UntypedArray]: ... + nbits: onp.ToJustInt, + state: onp.ToInt1D | None = None, + length: onp.ToJustInt | None = None, + taps: onp.ToJustInt1D | None = None, +) -> tuple[onp.Array1D[np.int8], onp.Array1D[np.int8]]: ... diff --git a/scipy-stubs/signal/_max_len_seq_inner.pyi b/scipy-stubs/signal/_max_len_seq_inner.pyi index 9a71f9bf..e5279c95 100644 --- a/scipy-stubs/signal/_max_len_seq_inner.pyi +++ b/scipy-stubs/signal/_max_len_seq_inner.pyi @@ -1 +1,12 @@ +import numpy as np +import optype.numpy as onp + __pythran__: tuple[str, str] = ... + +def _max_len_seq_inner( + taps: onp.Array1D[np.intp], + state: onp.Array1D[np.int8], + nbits: int | np.intp, + length: int | np.intp, + out: onp.Array1D[np.int8], +) -> onp.Array1D[np.int8]: ...