From efb79a73cfceba437073cb1d7d2458ac81603c89 Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sun, 28 Mar 2021 21:32:25 +0200 Subject: [PATCH 1/3] activate previously unreached test code --- control/tests/lti_test.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/control/tests/lti_test.py b/control/tests/lti_test.py index 1bf633e84..b18c21774 100644 --- a/control/tests/lti_test.py +++ b/control/tests/lti_test.py @@ -6,8 +6,8 @@ import control as ct from control import c2d, tf, tf2ss, NonlinearIOSystem -from control.lti import (LTI, common_timebase, damp, dcgain, isctime, isdtime, - issiso, pole, timebaseEqual, zero) +from control.lti import (LTI, common_timebase, evalfr, damp, dcgain, isctime, + isdtime, issiso, pole, timebaseEqual, zero) from control.tests.conftest import slycotonly from control.exception import slycot_check @@ -243,13 +243,17 @@ def test_squeeze_exceptions(self, fcn): with pytest.raises(ValueError, match="unknown squeeze value"): sys.frequency_response([1], squeeze=1) - sys([1], squeeze='siso') - evalfr(sys, [1], squeeze='siso') + with pytest.raises(ValueError, match="unknown squeeze value"): + sys([1j], squeeze='siso') + with pytest.raises(ValueError, match="unknown squeeze value"): + evalfr(sys, [1j], squeeze='siso') with pytest.raises(ValueError, match="must be 1D"): sys.frequency_response([[0.1, 1], [1, 10]]) - sys([[0.1, 1], [1, 10]]) - evalfr(sys, [[0.1, 1], [1, 10]]) + with pytest.raises(ValueError, match="must be 1D"): + sys([[0.1j, 1j], [1j, 10j]]) + with pytest.raises(ValueError, match="must be 1D"): + evalfr(sys, [[0.1j, 1j], [1j, 10j]]) with pytest.warns(DeprecationWarning, match="LTI `inputs`"): ninputs = sys.inputs From cdba09aaa46d672a9bc08f0e4ec9b62d7bd4648c Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sun, 28 Mar 2021 21:36:26 +0200 Subject: [PATCH 2/3] test ndarray and python native omegas for test_squeeze --- control/tests/lti_test.py | 41 +++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/control/tests/lti_test.py b/control/tests/lti_test.py index b18c21774..d4d5ec786 100644 --- a/control/tests/lti_test.py +++ b/control/tests/lti_test.py @@ -179,11 +179,20 @@ def test_isdtime(self, objfun, arg, dt, ref, strictref): [1, 1, 2, [0.1, 1, 10], None, (1, 2, 3)], # MISO [2, 1, 2, [0.1, 1, 10], True, (2, 3)], [3, 1, 2, [0.1, 1, 10], False, (1, 2, 3)], + [1, 1, 2, 0.1, None, (1, 2)], + [1, 1, 2, 0.1, True, (2,)], + [1, 1, 2, 0.1, False, (1, 2)], [1, 2, 2, [0.1, 1, 10], None, (2, 2, 3)], # MIMO [2, 2, 2, [0.1, 1, 10], True, (2, 2, 3)], - [3, 2, 2, [0.1, 1, 10], False, (2, 2, 3)] + [3, 2, 2, [0.1, 1, 10], False, (2, 2, 3)], + [1, 2, 2, 0.1, None, (2, 2)], + [2, 2, 2, 0.1, True, (2, 2)], + [3, 2, 2, 0.1, False, (2, 2)], ]) - def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape): + @pytest.mark.parametrize("omega_type", ["numpy", "native"]) + def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape, + omega_type): + """Test correct behavior of frequencey response squeeze parameter.""" # Create the system to be tested if fcn == ct.frd: sys = fcn(ct.rss(nstate, nout, ninp), [1e-2, 1e-1, 1, 1e1, 1e2]) @@ -193,15 +202,23 @@ def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape): else: sys = fcn(ct.rss(nstate, nout, ninp)) - # Convert the frequency list to an array for easy of use - isscalar = not hasattr(omega, '__len__') - omega = np.array(omega) + if omega_type == "numpy": + omega = np.asarray(omega) + isscalar = omega.ndim == 0 + # keep the ndarray type even for scalars + s = np.asarray(omega * 1j) + else: + isscalar = not hasattr(omega, '__len__') + if isscalar: + s = omega*1J + else: + s = [w*1J for w in omega] # Call the transfer function directly and make sure shape is correct - assert sys(omega * 1j, squeeze=squeeze).shape == shape + assert sys(s, squeeze=squeeze).shape == shape # Make sure that evalfr also works as expected - assert ct.evalfr(sys, omega * 1j, squeeze=squeeze).shape == shape + assert ct.evalfr(sys, s, squeeze=squeeze).shape == shape # Check frequency response mag, phase, _ = sys.frequency_response(omega, squeeze=squeeze) @@ -216,7 +233,7 @@ def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape): # Make sure the default shape lines up with squeeze=None case if squeeze is None: - assert sys(omega * 1j).shape == shape + assert sys(s).shape == shape # Changing config.default to False should return 3D frequency response ct.config.set_defaults('control', squeeze_frequency_response=False) @@ -224,14 +241,14 @@ def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape): if isscalar: assert mag.shape == (sys.noutputs, sys.ninputs, 1) assert phase.shape == (sys.noutputs, sys.ninputs, 1) - assert sys(omega * 1j).shape == (sys.noutputs, sys.ninputs) - assert ct.evalfr(sys, omega * 1j).shape == (sys.noutputs, sys.ninputs) + assert sys(s).shape == (sys.noutputs, sys.ninputs) + assert ct.evalfr(sys, s).shape == (sys.noutputs, sys.ninputs) else: assert mag.shape == (sys.noutputs, sys.ninputs, len(omega)) assert phase.shape == (sys.noutputs, sys.ninputs, len(omega)) - assert sys(omega * 1j).shape == \ + assert sys(s).shape == \ (sys.noutputs, sys.ninputs, len(omega)) - assert ct.evalfr(sys, omega * 1j).shape == \ + assert ct.evalfr(sys, s).shape == \ (sys.noutputs, sys.ninputs, len(omega)) @pytest.mark.parametrize("fcn", [ct.ss, ct.tf, ct.frd, ct.ss2io]) From 56461462f489c0779f3f24528d131b543596373e Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sun, 28 Mar 2021 21:55:38 +0200 Subject: [PATCH 3/3] ndarray.ndim==0 is a scalar --- control/lti.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control/lti.py b/control/lti.py index 01d04e020..52f6b2e72 100644 --- a/control/lti.py +++ b/control/lti.py @@ -665,7 +665,7 @@ def _process_frequency_response(sys, omega, out, squeeze=None): if squeeze is None: squeeze = config.defaults['control.squeeze_frequency_response'] - if not hasattr(omega, '__len__'): + if np.asarray(omega).ndim < 1: # received a scalar x, squeeze down the array along last dim out = np.squeeze(out, axis=2) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy