Skip to content

Commit 35061d3

Browse files
authored
Merge pull request #1563 from scipy/signal._ltisys/improvements
2 parents bfcc562 + f5afd5e commit 35061d3

2 files changed

Lines changed: 205 additions & 55 deletions

File tree

scipy-stubs/signal/_ltisys.pyi

Lines changed: 189 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -230,20 +230,20 @@ class dlti(LinearTimeInvariant[_ZerosT_co, _PolesT_co, _DTT_co], Generic[_ZerosT
230230
) -> TransferFunctionDiscrete[_Float, _DTT_co]: ...
231231
@overload
232232
def __new__(
233-
cls, zeros: onp.ToFloat1D, poles: onp.ToFloat2D, gain: onp.ToFloat1D, /, *, dt: _DTT_co = ...
233+
cls, zeros: onp.ToFloat1D, poles: onp.ToFloat1D, gain: onp.ToFloat, /, *, dt: _DTT_co = ...
234234
) -> ZerosPolesGainDiscrete[_Float, _Float, _DTT_co]: ...
235235
@overload
236236
def __new__(
237-
cls, zeros: onp.ToComplex1D, poles: onp.ToComplex1D, gain: onp.ToFloat1D, /, *, dt: _DTT_co = ...
238-
) -> ZerosPolesGainDiscrete[_Inexact, _Float, _DTT_co]: ...
237+
cls, zeros: onp.ToComplex1D, poles: onp.ToComplex1D, gain: onp.ToFloat, /, *, dt: _DTT_co = ...
238+
) -> ZerosPolesGainDiscrete[Any, _Float, _DTT_co]: ...
239239
@overload
240240
def __new__(
241241
cls, A: _ToFloat012D, B: _ToFloat012D, C: _ToFloat012D, D: _ToFloat012D, /, *, dt: _DTT_co = ...
242242
) -> StateSpaceDiscrete[_Float, _Float, _DTT_co]: ...
243243
@overload
244244
def __new__(
245245
cls, A: _ToComplex012D, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /, *, dt: _DTT_co = ...
246-
) -> StateSpaceDiscrete[_Inexact, _Float, _DTT_co]: ...
246+
) -> StateSpaceDiscrete[Any, _Float, _DTT_co]: ...
247247

248248
#
249249
def __init__(self, /, *system: *tuple[()], dt: _DTT_co) -> None: ...
@@ -270,10 +270,50 @@ class TransferFunction(LinearTimeInvariant[_PolesT_co, _PolesT_co, _DTT_co], Gen
270270
@overload
271271
def __new__(cls, system: lti[_PolesT, _PolesT], /) -> TransferFunctionContinuous[_PolesT]: ... # pyrefly:ignore[bad-override]
272272
@overload
273-
def __new__(cls, system: dlti[_PolesT, _PolesT, _DTT], /) -> TransferFunctionDiscrete[_PolesT, _DTT]: ...
273+
def __new__(
274+
cls,
275+
num: onp.ToArray1D[float, npc.integer | npc.floating64] | onp.ToArray2D[float, npc.integer | npc.floating64],
276+
den: onp.ToFloat1D,
277+
/,
278+
) -> TransferFunctionContinuous[np.float64]: ...
279+
@overload
280+
def __new__(
281+
cls, num: onp.ToFloat1D | onp.ToFloat2D, den: onp.ToArray1D[float, npc.integer | npc.floating64], /
282+
) -> TransferFunctionContinuous[np.float64]: ...
283+
@overload
284+
def __new__(
285+
cls, num: onp.ToJustFloat32_1D | onp.ToJustFloat32_2D, den: onp.ToFloat32_1D, /
286+
) -> TransferFunctionContinuous[np.float32]: ...
287+
@overload
288+
def __new__(
289+
cls, num: onp.ToFloat32_1D | onp.ToFloat32_2D, den: onp.ToJustFloat32_1D, /
290+
) -> TransferFunctionContinuous[np.float32]: ...
274291
@overload
275292
def __new__(cls, num: _ToFloat12D, den: onp.ToFloat1D, /) -> TransferFunctionContinuous[_Float]: ...
276293
@overload
294+
def __new__(cls, system: dlti[_PolesT, _PolesT, _DTT], /) -> TransferFunctionDiscrete[_PolesT, _DTT]: ...
295+
@overload
296+
def __new__(
297+
cls,
298+
num: onp.ToArray1D[float, npc.integer | npc.floating64] | onp.ToArray2D[float, npc.integer | npc.floating64],
299+
den: onp.ToFloat1D,
300+
/,
301+
*,
302+
dt: _DTT,
303+
) -> TransferFunctionDiscrete[np.float64, _DTT]: ...
304+
@overload
305+
def __new__(
306+
cls, num: onp.ToFloat1D | onp.ToFloat2D, den: onp.ToArray1D[float, npc.integer | npc.floating64], /, *, dt: _DTT
307+
) -> TransferFunctionDiscrete[np.float64, _DTT]: ...
308+
@overload
309+
def __new__(
310+
cls, num: onp.ToJustFloat32_1D | onp.ToJustFloat32_2D, den: onp.ToFloat32_1D, /, *, dt: _DTT
311+
) -> TransferFunctionDiscrete[np.float32, _DTT]: ...
312+
@overload
313+
def __new__(
314+
cls, num: onp.ToFloat32_1D | onp.ToFloat32_2D, den: onp.ToJustFloat32_1D, /, *, dt: _DTT
315+
) -> TransferFunctionDiscrete[np.float32, _DTT]: ...
316+
@overload
277317
def __new__(cls, num: _ToFloat12D, den: onp.ToFloat1D, /, *, dt: _DTT) -> TransferFunctionDiscrete[_Float, _DTT]: ...
278318

279319
#
@@ -337,20 +377,56 @@ class ZerosPolesGain(LinearTimeInvariant[_ZerosT_co, _PolesT_co, _DTT_co], Gener
337377
) -> ZerosPolesGainDiscrete[_ZerosT_co, _PolesT_co, _DTT_co]: ...
338378
@overload
339379
def __new__(
340-
cls, zeros: _ToFloat12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /
341-
) -> ZerosPolesGainContinuous[_Float, _Float]: ...
380+
cls,
381+
zeros: onp.ToArray1D[float, npc.integer | npc.floating64] | onp.ToArray2D[float, npc.integer | npc.floating64],
382+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
383+
gain: onp.ToFloat,
384+
/,
385+
) -> ZerosPolesGainContinuous[np.float64, np.float64]: ...
342386
@overload
343387
def __new__(
344-
cls, zeros: _ToComplex12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /
345-
) -> ZerosPolesGainContinuous[_Inexact, _Float]: ...
388+
cls,
389+
zeros: onp.ToArray1D[float, npc.integer | npc.floating64] | onp.ToArray2D[float, npc.integer | npc.floating64],
390+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
391+
gain: onp.ToFloat,
392+
/,
393+
*,
394+
dt: _DTT,
395+
) -> ZerosPolesGainDiscrete[np.float64, np.float64, _DTT]: ...
396+
@overload
397+
def __new__(
398+
cls, zeros: _ToFloat12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /
399+
) -> ZerosPolesGainContinuous[_Float, _Float]: ...
346400
@overload
347401
def __new__(
348402
cls, zeros: _ToFloat12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /, *, dt: _DTT
349403
) -> ZerosPolesGainDiscrete[_Float, _Float, _DTT]: ...
350404
@overload
405+
def __new__(
406+
cls,
407+
zeros: onp.ToJustComplex128_1D | onp.ToJustComplex128_2D,
408+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
409+
gain: onp.ToFloat,
410+
/,
411+
) -> ZerosPolesGainContinuous[np.complex128, np.float64]: ...
412+
@overload
413+
def __new__(
414+
cls,
415+
zeros: onp.ToJustComplex128_1D | onp.ToJustComplex128_2D,
416+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
417+
gain: onp.ToFloat,
418+
/,
419+
*,
420+
dt: _DTT,
421+
) -> ZerosPolesGainDiscrete[np.complex128, np.float64, _DTT]: ...
422+
@overload
423+
def __new__(
424+
cls, zeros: _ToComplex12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /
425+
) -> ZerosPolesGainContinuous[Any, _Float]: ...
426+
@overload
351427
def __new__(
352428
cls, zeros: _ToComplex12D, poles: onp.ToFloat1D, gain: onp.ToFloat, /, *, dt: _DTT
353-
) -> ZerosPolesGainDiscrete[_Inexact, _Float, _DTT]: ...
429+
) -> ZerosPolesGainDiscrete[Any, _Float, _DTT]: ...
354430

355431
#
356432
@overload
@@ -408,6 +484,16 @@ class ZerosPolesGainDiscrete(
408484
@overload
409485
def __init__(self, system: ZerosPolesGain[_ZerosT_co, _PolesT_co, _DTT_co], /) -> None: ...
410486
@overload
487+
def __init__(
488+
self: ZerosPolesGainDiscrete[np.float64, np.float64, _DTT],
489+
zeros: onp.ToArray1D[float, npc.integer | npc.floating64] | onp.ToArray2D[float, npc.integer | npc.floating64],
490+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
491+
gain: onp.ToFloat,
492+
/,
493+
*,
494+
dt: _DTT = ...,
495+
) -> None: ...
496+
@overload
411497
def __init__(
412498
self: ZerosPolesGainDiscrete[_Float, _Float, _DTT],
413499
zeros: _ToFloat12D,
@@ -419,7 +505,17 @@ class ZerosPolesGainDiscrete(
419505
) -> None: ...
420506
@overload
421507
def __init__(
422-
self: ZerosPolesGainDiscrete[_Inexact, _Float, _DTT],
508+
self: ZerosPolesGainDiscrete[np.complex128, np.float64, _DTT],
509+
zeros: onp.ToJustComplex128_1D | onp.ToJustComplex128_2D,
510+
poles: onp.ToArray1D[float, npc.integer | npc.floating64],
511+
gain: onp.ToFloat,
512+
/,
513+
*,
514+
dt: _DTT = ...,
515+
) -> None: ...
516+
@overload
517+
def __init__(
518+
self: ZerosPolesGainDiscrete[Any, _Float, _DTT],
423519
zeros: _ToComplex12D,
424520
poles: onp.ToFloat1D,
425521
gain: onp.ToFloat,
@@ -445,25 +541,59 @@ class StateSpace(LinearTimeInvariant[_ZerosT_co, _PolesT_co, _DTT_co], Generic[_
445541
def __new__(cls, system: dlti[_ZerosT_co, _PolesT_co, _DTT_co], /) -> StateSpaceDiscrete[_ZerosT_co, _PolesT_co, _DTT_co]: ...
446542
@overload
447543
def __new__(
448-
cls, A: _ToFloat012D, B: _ToFloat012D, C: _ToFloat012D, D: _ToFloat012D, /
449-
) -> StateSpaceContinuous[_Float, _Float]: ...
544+
cls, A: onp.ToArrayND[float, npc.integer | npc.floating64], B: _ToFloat012D, C: _ToFloat012D, D: _ToFloat012D, /
545+
) -> StateSpaceContinuous[np.float64, np.float64]: ...
450546
@overload
451547
def __new__(
452-
cls, A: _ToComplex012D, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /
453-
) -> StateSpaceContinuous[_Inexact, _Float]: ...
548+
cls,
549+
A: onp.ToArrayND[float, npc.integer | npc.floating64],
550+
B: _ToFloat012D,
551+
C: _ToFloat012D,
552+
D: _ToFloat012D,
553+
/,
554+
*,
555+
dt: _DTT,
556+
) -> StateSpaceDiscrete[np.float64, np.float64, _DTT]: ...
557+
@overload
558+
def __new__(
559+
cls, A: _ToFloat012D, B: _ToFloat012D, C: _ToFloat012D, D: _ToFloat012D, /
560+
) -> StateSpaceContinuous[_Float, _Float]: ...
454561
@overload
455562
def __new__(
456563
cls, A: _ToFloat012D, B: _ToFloat012D, C: _ToFloat012D, D: _ToFloat012D, /, *, dt: _DTT
457564
) -> StateSpaceDiscrete[_Float, _Float, _DTT]: ...
458565
@overload
566+
def __new__(
567+
cls, A: onp.ToJustComplex128_ND, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /
568+
) -> StateSpaceContinuous[np.complex128, np.float64]: ...
569+
@overload
570+
def __new__(
571+
cls, A: onp.ToJustComplex128_ND, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /, *, dt: _DTT
572+
) -> StateSpaceDiscrete[np.complex128, np.float64, _DTT]: ...
573+
@overload
574+
def __new__(
575+
cls, A: _ToComplex012D, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /
576+
) -> StateSpaceContinuous[Any, _Float]: ...
577+
@overload
459578
def __new__(
460579
cls, A: _ToComplex012D, B: _ToComplex012D, C: _ToComplex012D, D: _ToComplex012D, /, *, dt: _DTT
461-
) -> StateSpaceDiscrete[_Inexact, _Float, _DTT]: ...
580+
) -> StateSpaceDiscrete[Any, _Float, _DTT]: ...
462581

463582
#
464583
@overload
465584
def __init__(self, system: StateSpace[_ZerosT_co, _PolesT_co, _DTT_co], /) -> None: ...
466585
@overload
586+
def __init__(
587+
self: StateSpace[np.float64, np.float64],
588+
A: onp.ToArrayND[float, npc.integer | npc.floating64],
589+
B: _ToFloat012D,
590+
C: _ToFloat012D,
591+
D: _ToFloat012D,
592+
/,
593+
*,
594+
dt: _DTT_co = ...,
595+
) -> None: ...
596+
@overload
467597
def __init__(
468598
self: StateSpace[_Float, _Float],
469599
A: _ToFloat012D,
@@ -476,7 +606,18 @@ class StateSpace(LinearTimeInvariant[_ZerosT_co, _PolesT_co, _DTT_co], Generic[_
476606
) -> None: ...
477607
@overload
478608
def __init__(
479-
self: StateSpace[_Inexact, _Float],
609+
self: StateSpace[np.complex128, np.float64],
610+
A: onp.ToJustComplex128_ND,
611+
B: _ToComplex012D,
612+
C: _ToComplex012D,
613+
D: _ToComplex012D,
614+
/,
615+
*,
616+
dt: _DTT_co = ...,
617+
) -> None: ...
618+
@overload
619+
def __init__(
620+
self: StateSpace[Any, _Float],
480621
A: _ToComplex012D,
481622
B: _ToComplex012D,
482623
C: _ToComplex012D,
@@ -542,23 +683,45 @@ class StateSpaceDiscrete(
542683
@overload
543684
def __init__(self, system: StateSpace[_ZerosT_co, _PolesT_co, _DTT_co], /) -> None: ...
544685
@overload
686+
def __init__(
687+
self: StateSpaceDiscrete[np.float64, np.float64, _DTT],
688+
A: onp.ToArrayND[float, npc.integer | npc.floating64],
689+
B: _ToFloat012D,
690+
C: _ToFloat012D,
691+
D: _ToFloat012D,
692+
/,
693+
*,
694+
dt: _DTT = ...,
695+
) -> None: ...
696+
@overload
545697
def __init__(
546698
self: StateSpaceDiscrete[_Float, _Float, _DTT],
547-
A: onp.ToFloat2D,
548-
B: onp.ToFloat2D,
549-
C: onp.ToFloat2D,
550-
D: onp.ToFloat2D,
699+
A: _ToFloat012D,
700+
B: _ToFloat012D,
701+
C: _ToFloat012D,
702+
D: _ToFloat012D,
551703
/,
552704
*,
553705
dt: _DTT = ...,
554706
) -> None: ...
555707
@overload
556708
def __init__(
557-
self: StateSpaceDiscrete[_Inexact, _Float, _DTT],
558-
A: onp.ToComplex2D,
559-
B: onp.ToComplex2D,
560-
C: onp.ToComplex2D,
561-
D: onp.ToComplex2D,
709+
self: StateSpaceDiscrete[np.complex128, np.float64, _DTT],
710+
A: onp.ToJustComplex128_ND,
711+
B: _ToComplex012D,
712+
C: _ToComplex012D,
713+
D: _ToComplex012D,
714+
/,
715+
*,
716+
dt: _DTT = ...,
717+
) -> None: ...
718+
@overload
719+
def __init__(
720+
self: StateSpaceDiscrete[Any, _Float, _DTT],
721+
A: _ToComplex012D,
722+
B: _ToComplex012D,
723+
C: _ToComplex012D,
724+
D: _ToComplex012D,
562725
/,
563726
*,
564727
dt: _DTT = ...,

tests/signal/test_ltisys.pyi

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -114,43 +114,30 @@ _to_ss_disc_c128: tuple[
114114
# TransferFunction
115115
assert_type(TransferFunction(_tf_cont_f32), TransferFunctionContinuous[np.float32]) # type: ignore[assert-type]
116116
assert_type(TransferFunction(_tf_disc_f32), TransferFunctionDiscrete[np.float32, float]) # type: ignore[assert-type]
117-
assert_type(TransferFunction(_f64_1d, _f64_1d), TransferFunctionContinuous[np.float32 | np.float64]) # type: ignore[assert-type]
118-
assert_type(TransferFunction(_f64_1d, _f64_1d, dt=0.1), TransferFunctionDiscrete[np.float32 | np.float64, float]) # type: ignore[assert-type]
117+
assert_type(TransferFunction(_f32_1d, _f32_1d), TransferFunctionContinuous[np.float32]) # type: ignore[assert-type]
118+
assert_type(TransferFunction(_f32_1d, _f64_1d), TransferFunctionContinuous[np.float64]) # type: ignore[assert-type]
119+
assert_type(TransferFunction(_f64_1d, _f32_1d), TransferFunctionContinuous[np.float64]) # type: ignore[assert-type]
120+
assert_type(TransferFunction(_f64_1d, _f64_1d), TransferFunctionContinuous[np.float64]) # type: ignore[assert-type]
121+
assert_type(TransferFunction(_f32_1d, _f32_1d, dt=0.1), TransferFunctionDiscrete[np.float32, float]) # type: ignore[assert-type]
122+
assert_type(TransferFunction(_f32_1d, _f64_1d, dt=0.1), TransferFunctionDiscrete[np.float64, float]) # type: ignore[assert-type]
123+
assert_type(TransferFunction(_f64_1d, _f32_1d, dt=0.1), TransferFunctionDiscrete[np.float64, float]) # type: ignore[assert-type]
124+
assert_type(TransferFunction(_f64_1d, _f64_1d, dt=0.1), TransferFunctionDiscrete[np.float64, float]) # type: ignore[assert-type]
119125

120126
# ZerosPolesGain
121127
assert_type(ZerosPolesGain(_zpk_cont_f32), ZerosPolesGainContinuous[np.float32, np.float32]) # type: ignore[assert-type]
122128
assert_type(ZerosPolesGain(_zpk_disc_f32), ZerosPolesGainDiscrete[np.float32, np.float32, float]) # type: ignore[assert-type]
123-
assert_type(ZerosPolesGain(_f64_1d, _f64_1d, 5), ZerosPolesGainContinuous[np.float32 | np.float64, np.float32 | np.float64]) # type: ignore[assert-type]
124-
assert_type( # type: ignore[assert-type]
125-
ZerosPolesGain(_c128_1d, _f64_1d, 5),
126-
ZerosPolesGainContinuous[np.float32 | np.float64 | np.complex64 | np.complex128, np.float32 | np.float64],
127-
)
128-
assert_type( # type: ignore[assert-type]
129-
ZerosPolesGain(_f64_1d, _f64_1d, 5, dt=0.1), ZerosPolesGainDiscrete[np.float32 | np.float64, np.float32 | np.float64, float]
130-
)
131-
assert_type( # type: ignore[assert-type]
132-
ZerosPolesGain(_c128_1d, _f64_1d, 5, dt=0.1),
133-
ZerosPolesGainDiscrete[np.float32 | np.float64 | np.complex64 | np.complex128, np.float32 | np.float64, float],
134-
)
129+
assert_type(ZerosPolesGain(_f64_1d, _f64_1d, 5), ZerosPolesGainContinuous[np.float64, np.float64]) # type: ignore[assert-type]
130+
assert_type(ZerosPolesGain(_c128_1d, _f64_1d, 5), ZerosPolesGainContinuous[np.complex128, np.float64]) # type: ignore[assert-type]
131+
assert_type(ZerosPolesGain(_f64_1d, _f64_1d, 5, dt=0.1), ZerosPolesGainDiscrete[np.float64, np.float64, float]) # type: ignore[assert-type]
132+
assert_type(ZerosPolesGain(_c128_1d, _f64_1d, 5, dt=0.1), ZerosPolesGainDiscrete[np.complex128, np.float64, float]) # type: ignore[assert-type]
135133

136134
# StateSpace
137135
assert_type(StateSpace(_ss_cont_f32), StateSpaceContinuous[np.float32, np.float32]) # type: ignore[assert-type]
138136
assert_type(StateSpace(_ss_disc_f32), StateSpaceDiscrete[np.float32, np.float32, float]) # type: ignore[assert-type]
139-
assert_type( # type: ignore[assert-type]
140-
StateSpace(_f64_2d, _f64_2d, _f64_2d, _f64_2d), StateSpaceContinuous[np.float32 | np.float64, np.float32 | np.float64]
141-
)
142-
assert_type( # type: ignore[assert-type]
143-
StateSpace(_c128_2d, _c128_2d, _c128_2d, _c128_2d),
144-
StateSpaceContinuous[np.float32 | np.float64 | np.complex64 | np.complex128, np.float32 | np.float64],
145-
)
146-
assert_type( # type: ignore[assert-type]
147-
StateSpace(_f64_2d, _f64_2d, _f64_2d, _f64_2d, dt=0.1),
148-
StateSpaceDiscrete[np.float32 | np.float64, np.float32 | np.float64, float],
149-
)
150-
assert_type( # type: ignore[assert-type]
151-
StateSpace(_c128_2d, _c128_2d, _c128_2d, _c128_2d, dt=0.1),
152-
StateSpaceDiscrete[np.float32 | np.float64 | np.complex64 | np.complex128, np.float32 | np.float64, float],
153-
)
137+
assert_type(StateSpace(_f64_2d, _f64_2d, _f64_2d, _f64_2d), StateSpaceContinuous[np.float64, np.float64]) # type: ignore[assert-type]
138+
assert_type(StateSpace(_c128_2d, _c128_2d, _c128_2d, _c128_2d), StateSpaceContinuous[np.complex128, np.float64]) # type: ignore[assert-type]
139+
assert_type(StateSpace(_f64_2d, _f64_2d, _f64_2d, _f64_2d, dt=0.1), StateSpaceDiscrete[np.float64, np.float64, float]) # type: ignore[assert-type]
140+
assert_type(StateSpace(_c128_2d, _c128_2d, _c128_2d, _c128_2d, dt=0.1), StateSpaceDiscrete[np.complex128, np.float64, float]) # type: ignore[assert-type]
154141

155142
###
156143
# lsim (same as impulse and step)

0 commit comments

Comments
 (0)