[Scipy-svn] r6367 - in trunk: doc/release doc/source scipy/signal scipy/signal/tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Sun May 2 19:19:59 EDT 2010
Author: warren.weckesser
Date: 2010-05-02 18:19:59 -0500 (Sun, 02 May 2010)
New Revision: 6367
Modified:
trunk/doc/release/0.8.0-notes.rst
trunk/doc/source/signal.rst
trunk/scipy/signal/info.py
trunk/scipy/signal/ltisys.py
trunk/scipy/signal/tests/test_ltisys.py
Log:
ENH: signal: Added the function step2 to compute the step response of a linear system using lsim2 (which used odeint).
Modified: trunk/doc/release/0.8.0-notes.rst
===================================================================
--- trunk/doc/release/0.8.0-notes.rst 2010-05-02 02:20:45 UTC (rev 6366)
+++ trunk/doc/release/0.8.0-notes.rst 2010-05-02 23:19:59 UTC (rev 6367)
@@ -85,9 +85,9 @@
Additions and modification to LTI functions (scipy.signal)
----------------------------------------------------------
-* The function `impulse2` was added to `scipy.signal`. It uses the ODE
- solver `scipy.integrate.odeint` to compute the impulse response of
- a system.
+* The functions `impulse2` and `step2` were added to `scipy.signal`.
+ They use the function `scipy.signal.lsim2` to compute the impulse and
+ step response of a system, respectively.
* The function `scipy.signal.lsim2` was changed to pass any additional
keyword arguments to the ODE solver.
Modified: trunk/doc/source/signal.rst
===================================================================
--- trunk/doc/source/signal.rst 2010-05-02 02:20:45 UTC (rev 6366)
+++ trunk/doc/source/signal.rst 2010-05-02 23:19:59 UTC (rev 6367)
@@ -103,6 +103,7 @@
impulse
impulse2
step
+ step2
LTI Reresentations
==================
Modified: trunk/scipy/signal/info.py
===================================================================
--- trunk/scipy/signal/info.py 2010-05-02 02:20:45 UTC (rev 6366)
+++ trunk/scipy/signal/info.py 2010-05-02 23:19:59 UTC (rev 6367)
@@ -70,8 +70,9 @@
lsim -- continuous-time simulation of output to linear system.
lsim2 -- like lsim, but `scipy.integrate.odeint` is used.
impulse -- impulse response of linear, time-invariant (LTI) system.
- impulse2 -- like impulse2, but `scipy.integrate.odeint` is used.
+ impulse2 -- like impulse, but `scipy.integrate.odeint` is used.
step -- step response of continous-time LTI system.
+ step2 -- like step, but `scipy.integrate.odeint` is used.
LTI Reresentations:
Modified: trunk/scipy/signal/ltisys.py
===================================================================
--- trunk/scipy/signal/ltisys.py 2010-05-02 02:20:45 UTC (rev 6366)
+++ trunk/scipy/signal/ltisys.py 2010-05-02 23:19:59 UTC (rev 6367)
@@ -495,8 +495,9 @@
def _default_response_times(A, n):
"""Compute a reasonable set of time samples for the response time.
- This function is used by impulse(), impulse2() and step() to compute
- the response time when the `T` argument to the function is None.
+ This function is used by impulse(), impulse2(), step() and step2()
+ to compute the response time when the `T` argument to the function
+ is None.
Parameters
----------
@@ -595,7 +596,7 @@
**kwargs :
Additional keyword arguments are passed on the function
`scipy.signal.lsim2`, which in turn passes them on to
- :func:`scipy.integrate.odeint`. See the documation for
+ :func:`scipy.integrate.odeint`. See the documentation for
:func:`scipy.integrate.odeint` for information about these
arguments.
@@ -661,6 +662,9 @@
yout : 1D ndarray
Step response of system.
+ See also
+ --------
+ scipy.signal.step2
"""
if isinstance(system, lti):
sys = system
@@ -673,3 +677,58 @@
U = ones(T.shape, sys.A.dtype)
vals = lsim(sys, U, T, X0=X0)
return vals[0], vals[1]
+
+def step2(system, X0=None, T=None, N=None, **kwargs):
+ """Step response of continuous-time system.
+
+ This function is functionally the same as `scipy.signal.step`, but
+ it uses the function `scipy.ltisys.lsim2` to compute the step
+ response.
+
+ Parameters
+ ----------
+ system : an instance of the LTI class or a tuple describing the system.
+ The following gives the number of elements in the tuple and
+ the interpretation.
+ 2 (num, den)
+ 3 (zeros, poles, gain)
+ 4 (A, B, C, D)
+ X0 : array_like, optional
+ Initial state-vector (default is zero).
+ T : array_like, optional
+ Time points (computed if not given).
+ N : int
+ Number of time points to compute if `T` is not given.
+ **kwargs :
+ Additional keyword arguments are passed on the function
+ `scipy.signal.lsim2`, which in turn passes them on to
+ :func:`scipy.integrate.odeint`. See the documentation for
+ :func:`scipy.integrate.odeint` for information about these
+ arguments.
+
+ Returns
+ -------
+ T : 1D ndarray
+ Output time points.
+ yout : 1D ndarray
+ Step response of system.
+
+ See also
+ --------
+ scipy.signal.step
+
+ Notes
+ -----
+ .. versionadded:: 0.8.0
+ """
+ if isinstance(system, lti):
+ sys = system
+ else:
+ sys = lti(*system)
+ if N is None:
+ N = 100
+ if T is None:
+ T = _default_response_times(sys.A, N)
+ U = ones(T.shape, sys.A.dtype)
+ vals = lsim2(sys, U, T, X0=X0, **kwargs)
+ return vals[0], vals[1]
Modified: trunk/scipy/signal/tests/test_ltisys.py
===================================================================
--- trunk/scipy/signal/tests/test_ltisys.py 2010-05-02 02:20:45 UTC (rev 6366)
+++ trunk/scipy/signal/tests/test_ltisys.py 2010-05-02 23:19:59 UTC (rev 6367)
@@ -1,8 +1,9 @@
import numpy as np
from numpy.testing import assert_almost_equal, assert_equal, run_module_suite
-from scipy.signal.ltisys import ss2tf, lsim2, impulse2, lti
+from scipy.signal.ltisys import ss2tf, lsim2, impulse2, step2, lti
+
class TestSS2TF:
def tst_matrix_shapes(self, p, q, r):
ss2tf(np.zeros((p, p)),
@@ -148,5 +149,65 @@
expected_y = tout * np.exp(-tout)
assert_almost_equal(y, expected_y)
+class Test_step2(object):
+
+ def test_01(self):
+ # First order system: x'(t) + x(t) = u(t)
+ # Exact step response is x(t) = 1 - exp(-t).
+ system = ([1.0],[1.0,1.0])
+ tout, y = step2(system)
+ expected_y = 1.0 - np.exp(-tout)
+ assert_almost_equal(y, expected_y)
+
+ def test_02(self):
+ """Specify the desired time values for the output."""
+
+ # First order system: x'(t) + x(t) = u(t)
+ # Exact step response is x(t) = 1 - exp(-t).
+ system = ([1.0],[1.0,1.0])
+ n = 21
+ t = np.linspace(0, 2.0, n)
+ tout, y = step2(system, T=t)
+ assert_equal(tout.shape, (n,))
+ assert_almost_equal(tout, t)
+ expected_y = 1 - np.exp(-t)
+ assert_almost_equal(y, expected_y)
+
+ def test_03(self):
+ """Specify an initial condition as a scalar."""
+
+ # First order system: x'(t) + x(t) = u(t), x(0)=3.0
+ # Exact step response is x(t) = 1 + 2*exp(-t).
+ system = ([1.0],[1.0,1.0])
+ tout, y = step2(system, X0=3.0)
+ expected_y = 1 + 2.0*np.exp(-tout)
+ assert_almost_equal(y, expected_y)
+
+ def test_04(self):
+ """Specify an initial condition as a list."""
+
+ # First order system: x'(t) + x(t) = u(t), x(0)=3.0
+ # Exact step response is x(t) = 1 + 2*exp(-t).
+ system = ([1.0],[1.0,1.0])
+ tout, y = step2(system, X0=[3.0])
+ expected_y = 1 + 2.0*np.exp(-tout)
+ assert_almost_equal(y, expected_y)
+
+ def test_05(self):
+ # Simple integrator: x'(t) = u(t)
+ # Exact step response is x(t) = t.
+ system = ([1.0],[1.0,0.0])
+ tout, y = step2(system, atol=1e-10, rtol=1e-8)
+ expected_y = tout
+ assert_almost_equal(y, expected_y)
+
+ def test_06(self):
+ # Second order system with a repeated root: x''(t) + 2*x(t) + x(t) = u(t)
+ # The exact step response is 1 - (1 + t)*exp(-t).
+ system = ([1.0], [1.0, 2.0, 1.0])
+ tout, y = step2(system, atol=1e-10, rtol=1e-8)
+ expected_y = 1 - (1 + tout) * np.exp(-tout)
+ assert_almost_equal(y, expected_y)
+
if __name__ == "__main__":
run_module_suite()
More information about the Scipy-svn
mailing list