Add unit tests to increase code coverage · python-control/python-control@e61ac53

@@ -8,6 +8,7 @@

88991010

from control import StateSpace, forced_response, impulse_response, tf, rss, c2d, TimeResponseData

11+

from control.exception import ControlArgument, ControlDimension

1112

from control.tests.conftest import slycotonly

1213

from control.modelsimp import balred, hsvd, markov, modred

1314

@@ -32,7 +33,7 @@ def testHSVD(self):

3233

assert not isinstance(hsv, np.matrix)

33343435

def testMarkovSignature(self):

35-

U = np.array([[1., 1., 1., 1., 1.]])

36+

U = np.array([[1., 1., 1., 1., 1., 1., 1.]])

3637

Y = U

3738

response = TimeResponseData(time=np.arange(U.shape[-1]),

3839

outputs=Y,

@@ -41,27 +42,40 @@ def testMarkovSignature(self):

4142

input_labels='u',

4243

)

434444-

# Basic usage

45+

# setup

4546

m = 3

4647

Htrue = np.array([1., 0., 0.])

48+

Htrue_l = np.array([1., 0., 0., 0., 0., 0., 0.])

474948-

H = markov(Y, U, m=m, transpose=False)

49-

np.testing.assert_array_almost_equal(H, Htrue)

50+

# test not enough input arguments

51+

with pytest.raises(ControlArgument):

52+

H = markov(Y)

53+

with pytest.raises(ControlArgument):

54+

H = markov()

505551-

response.transpose=False

52-

H = markov(response, m=m)

53-

np.testing.assert_array_almost_equal(H, Htrue)

56+

# to many positional arguments

57+

with pytest.raises(ControlArgument):

58+

H = markov(Y,U,m,1)

59+

with pytest.raises(ControlArgument):

60+

H = markov(response,m,1)

546155-

# Make sure that transposed data also works

56-

H = markov(Y.T, U.T, m, transpose=True)

57-

np.testing.assert_array_almost_equal(H, np.transpose(Htrue))

62+

# to many positional arguments

63+

with pytest.raises(ControlDimension):

64+

U2 = np.hstack([U,U])

65+

H = markov(Y,U2,m)

586659-

response.transpose=True

60-

H = markov(response, m)

61-

np.testing.assert_array_almost_equal(H, np.transpose(Htrue))

62-

response.transpose=False

67+

# not enough data

68+

with pytest.warns(Warning):

69+

H = markov(Y,U,8)

70+71+

# Basic Usage, m=l

72+

H = markov(Y, U)

73+

np.testing.assert_array_almost_equal(H, Htrue_l)

637464-

# Generate Markov parameters without any arguments

75+

H = markov(response)

76+

np.testing.assert_array_almost_equal(H, Htrue_l)

77+78+

# Basic Usage, m

6579

H = markov(Y, U, m)

6680

np.testing.assert_array_almost_equal(H, Htrue)

6781

@@ -74,6 +88,20 @@ def testMarkovSignature(self):

7488

H = markov(response, m=m)

7589

np.testing.assert_array_almost_equal(H, Htrue)

769091+

response.transpose=False

92+

H = markov(response, m=m)

93+

np.testing.assert_array_almost_equal(H, Htrue)

94+95+

# Make sure that transposed data also works, siso

96+

HT = markov(Y.T, U.T, m, transpose=True)

97+

np.testing.assert_array_almost_equal(HT, np.transpose(Htrue))

98+99+

response.transpose = True

100+

HT = markov(response, m)

101+

np.testing.assert_array_almost_equal(HT, np.transpose(Htrue))

102+

response.transpose=False

103+104+77105

# Test example from docstring

78106

# TODO: There is a problem here, last markov parameter does not fit

79107

# the approximation error could be to big

@@ -114,16 +142,41 @@ def testMarkovSignature(self):

114142

dt = 0.25

115143

sysd = sys.sample(dt, method='zoh')

116144117-

t = np.arange(0,100,dt)

118-

u = np.random.randn(sysd.B.shape[-1], len(t))

119-

response = forced_response(sysd, U=u)

145+

T = np.arange(0,100,dt)

146+

U = np.random.randn(sysd.B.shape[-1], len(T))

147+

response = forced_response(sysd, U=U)

148+

Y = response.outputs

120149121150

m = 100

122-

H = markov(response, m, dt=dt)

123151

_, Htrue = impulse_response(sysd, T=dt*(m-1))

124152153+154+

# test array_like

155+

H = markov(Y, U, m, dt=dt)

125156

np.testing.assert_array_almost_equal(H, Htrue)

126157158+

# test array_like, truncate

159+

H = markov(Y, U, m, dt=dt, truncate=True)

160+

np.testing.assert_array_almost_equal(H, Htrue)

161+162+

# test array_like, transpose

163+

HT = markov(Y.T, U.T, m, dt=dt, transpose=True)

164+

np.testing.assert_array_almost_equal(HT, np.transpose(Htrue))

165+166+

# test response data

167+

H = markov(response, m, dt=dt)

168+

np.testing.assert_array_almost_equal(H, Htrue)

169+170+

# test response data

171+

H = markov(response, m, dt=dt, truncate=True)

172+

np.testing.assert_array_almost_equal(H, Htrue)

173+174+

# test response data, transpose

175+

response.transpose = True

176+

HT = markov(response, m, dt=dt)

177+

np.testing.assert_array_almost_equal(HT, np.transpose(Htrue))

178+179+127180

# Make sure markov() returns the right answer

128181

@pytest.mark.parametrize("k, m, n",

129182

[(2, 2, 2),

@@ -168,14 +221,14 @@ def testMarkovResults(self, k, m, n):

168221

ir_true = impulse_response(Hd,T)

169222

Mtrue_scaled = ir_true[1][:m]

170223171-

T, Y = forced_response(Hd, T, U, squeeze=True)

172-

Mcomp = markov(Y, U, m, dt=True)

173-

Mcomp_scaled = markov(Y, U, m, dt=Ts)

174-175224

# Compare to results from markov()

176225

# experimentally determined probability to get non matching results

177226

# with rtot=1e-6 and atol=1e-8 due to numerical errors

178227

# for k=5, m=n=10: 0.015 %

228+

T, Y = forced_response(Hd, T, U, squeeze=True)

229+

Mcomp = markov(Y, U, m, dt=True)

230+

Mcomp_scaled = markov(Y, U, m, dt=Ts)

231+179232

np.testing.assert_allclose(Mtrue, Mcomp, rtol=1e-6, atol=1e-8)

180233

np.testing.assert_allclose(Mtrue_scaled, Mcomp_scaled, rtol=1e-6, atol=1e-8)

181234