@@ -639,9 +639,10 @@ def test_time_vector(self, tsystem, fun, squeeze, matarrayout):
639639 if hasattr (tsystem , 't' ):
640640 # tout should always match t, which has shape (n, )
641641 np .testing .assert_allclose (tout , tsystem .t )
642- if squeeze is False or sys .outputs > 1 :
642+
643+ if squeeze is False or not sys .issiso ():
643644 assert yout .shape [0 ] == sys .outputs
644- assert yout .shape [1 ] == tout .shape [0 ]
645+ assert yout .shape [- 1 ] == tout .shape [0 ]
645646 else :
646647 assert yout .shape == tout .shape
647648
@@ -725,21 +726,22 @@ def test_time_series_data_convention_2D(self, siso_ss1):
725726
726727 @pytest .mark .usefixtures ("editsdefaults" )
727728 @pytest .mark .parametrize ("fcn" , [ct .ss , ct .tf , ct .ss2io ])
728- @pytest .mark .parametrize ("nstate, nout, ninp, squeeze, shape" , [
729- [1 , 1 , 1 , None , (8 ,)],
730- [2 , 1 , 1 , True , (8 ,)],
731- [3 , 1 , 1 , False , (1 , 8 )],
732- [3 , 2 , 1 , None , (2 , 8 )],
733- [4 , 2 , 1 , True , (2 , 8 )],
734- [5 , 2 , 1 , False , (2 , 8 )],
735- [3 , 1 , 2 , None , (1 , 8 )],
736- [4 , 1 , 2 , True , (8 ,)],
737- [5 , 1 , 2 , False , (1 , 8 )],
738- [4 , 2 , 2 , None , (2 , 8 )],
739- [5 , 2 , 2 , True , (2 , 8 )],
740- [6 , 2 , 2 , False , (2 , 8 )],
729+ @pytest .mark .parametrize ("nstate, nout, ninp, squeeze, shape1, shape2" , [
730+ # state out in squeeze in/out out-only
731+ [1 , 1 , 1 , None , (8 ,), (8 ,)],
732+ [2 , 1 , 1 , True , (8 ,), (8 ,)],
733+ [3 , 1 , 1 , False , (1 , 1 , 8 ), (1 , 8 )],
734+ [3 , 2 , 1 , None , (2 , 1 , 8 ), (2 , 8 )],
735+ [4 , 2 , 1 , True , (2 , 8 ), (2 , 8 )],
736+ [5 , 2 , 1 , False , (2 , 1 , 8 ), (2 , 8 )],
737+ [3 , 1 , 2 , None , (1 , 2 , 8 ), (1 , 8 )],
738+ [4 , 1 , 2 , True , (2 , 8 ), (8 ,)],
739+ [5 , 1 , 2 , False , (1 , 2 , 8 ), (1 , 8 )],
740+ [4 , 2 , 2 , None , (2 , 2 , 8 ), (2 , 8 )],
741+ [5 , 2 , 2 , True , (2 , 2 , 8 ), (2 , 8 )],
742+ [6 , 2 , 2 , False , (2 , 2 , 8 ), (2 , 8 )],
741743 ])
742- def test_squeeze (self , fcn , nstate , nout , ninp , squeeze , shape ):
744+ def test_squeeze (self , fcn , nstate , nout , ninp , squeeze , shape1 , shape2 ):
743745 # Figure out if we have SciPy 1+
744746 scipy0 = StrictVersion (sp .__version__ ) < '1.0'
745747
@@ -750,27 +752,56 @@ def test_squeeze(self, fcn, nstate, nout, ninp, squeeze, shape):
750752 else :
751753 sys = fcn (ct .rss (nstate , nout , ninp , strictly_proper = True ))
752754
753- # Keep track of expect users warnings
754- warntype = UserWarning if sys .inputs > 1 else None
755-
756755 # Generate the time and input vectors
757756 tvec = np .linspace (0 , 1 , 8 )
758757 uvec = np .dot (
759758 np .ones ((sys .inputs , 1 )),
760759 np .reshape (np .sin (tvec ), (1 , 8 )))
761760
761+ #
762762 # Pass squeeze argument and make sure the shape is correct
763- with pytest .warns (warntype , match = "Converting MIMO system" ):
764- _ , yvec = ct .impulse_response (sys , tvec , squeeze = squeeze )
765- assert yvec .shape == shape
763+ #
764+ # For responses that are indexed by the input, check against shape1
765+ # For responses that have no/fixed input, check against shape2
766+ #
766767
767- _ , yvec = ct .initial_response (sys , tvec , 1 , squeeze = squeeze )
768- assert yvec .shape == shape
768+ # Impulse response
769+ if isinstance (sys , StateSpace ):
770+ # Check the states as well
771+ _ , yvec , xvec = ct .impulse_response (
772+ sys , tvec , squeeze = squeeze , return_x = True )
773+ if sys .issiso () and squeeze is not False :
774+ assert xvec .shape == (sys .states , 8 )
775+ else :
776+ assert xvec .shape == (sys .states , sys .inputs , 8 )
777+ else :
778+ _ , yvec = ct .impulse_response (sys , tvec , squeeze = squeeze )
779+ assert yvec .shape == shape1
769780
770- with pytest .warns (warntype , match = "Converting MIMO system" ):
781+ # Step response
782+ if isinstance (sys , StateSpace ):
783+ # Check the states as well
784+ _ , yvec , xvec = ct .step_response (
785+ sys , tvec , squeeze = squeeze , return_x = True )
786+ if sys .issiso () and squeeze is not False :
787+ assert xvec .shape == (sys .states , 8 )
788+ else :
789+ assert xvec .shape == (sys .states , sys .inputs , 8 )
790+ else :
771791 _ , yvec = ct .step_response (sys , tvec , squeeze = squeeze )
772- assert yvec .shape == shape
792+ assert yvec .shape == shape1
793+
794+ # Initial response (only indexed by output)
795+ if isinstance (sys , StateSpace ):
796+ # Check the states as well
797+ _ , yvec , xvec = ct .initial_response (
798+ sys , tvec , 1 , squeeze = squeeze , return_x = True )
799+ assert xvec .shape == (sys .states , 8 )
800+ else :
801+ _ , yvec = ct .initial_response (sys , tvec , 1 , squeeze = squeeze )
802+ assert yvec .shape == shape2
773803
804+ # Forced response (only indexed by output)
774805 if isinstance (sys , StateSpace ):
775806 # Check the states as well
776807 _ , yvec , xvec = ct .forced_response (
@@ -779,52 +810,54 @@ def test_squeeze(self, fcn, nstate, nout, ninp, squeeze, shape):
779810 else :
780811 # Just check the input/output response
781812 _ , yvec = ct .forced_response (sys , tvec , uvec , 0 , squeeze = squeeze )
782- assert yvec .shape == shape
813+ assert yvec .shape == shape2
783814
784815 # Test cases where we choose a subset of inputs and outputs
785816 _ , yvec = ct .step_response (
786817 sys , tvec , input = ninp - 1 , output = nout - 1 , squeeze = squeeze )
787- # Possible code if we implemenet a squeeze='siso' option
788818 if squeeze is False :
789819 # Shape should be unsqueezed
790- assert yvec .shape == (1 , 8 )
820+ assert yvec .shape == (1 , 1 , 8 )
791821 else :
792822 # Shape should be squeezed
793823 assert yvec .shape == (8 , )
794824
795- # For InputOutputSystems, also test input_output_response
825+ # For InputOutputSystems, also test input/output response
796826 if isinstance (sys , ct .InputOutputSystem ) and not scipy0 :
797827 _ , yvec = ct .input_output_response (sys , tvec , uvec , squeeze = squeeze )
798- assert yvec .shape == shape
828+ assert yvec .shape == shape2
799829
800830 #
801831 # Changing config.default to False should return 3D frequency response
802832 #
803833 ct .config .set_defaults ('control' , squeeze_time_response = False )
804834
805- with pytest . warns ( warntype , match = "Converting MIMO system" ):
806- _ , yvec = ct . impulse_response ( sys , tvec )
807- assert yvec .shape == (sys .outputs , 8 )
835+ _ , yvec = ct . impulse_response ( sys , tvec )
836+ if squeeze is not True or sys . inputs > 1 or sys . outputs > 1 :
837+ assert yvec .shape == (sys .outputs , sys . inputs , 8 )
808838
809- _ , yvec = ct .initial_response (sys , tvec , 1 )
810- assert yvec .shape == (sys .outputs , 8 )
839+ _ , yvec = ct .step_response (sys , tvec )
840+ if squeeze is not True or sys .inputs > 1 or sys .outputs > 1 :
841+ assert yvec .shape == (sys .outputs , sys .inputs , 8 )
811842
812- with pytest . warns ( warntype , match = "Converting MIMO system" ):
813- _ , yvec = ct . step_response ( sys , tvec )
814- assert yvec .shape == (sys .outputs , 8 )
843+ _ , yvec = ct . initial_response ( sys , tvec , 1 )
844+ if squeeze is not True or sys . outputs > 1 :
845+ assert yvec .shape == (sys .outputs , 8 )
815846
816847 if isinstance (sys , ct .StateSpace ):
817848 _ , yvec , xvec = ct .forced_response (
818849 sys , tvec , uvec , 0 , return_x = True )
819850 assert xvec .shape == (sys .states , 8 )
820851 else :
821852 _ , yvec = ct .forced_response (sys , tvec , uvec , 0 )
822- assert yvec .shape == (sys .outputs , 8 )
853+ if squeeze is not True or sys .outputs > 1 :
854+ assert yvec .shape == (sys .outputs , 8 )
823855
824856 # For InputOutputSystems, also test input_output_response
825857 if isinstance (sys , ct .InputOutputSystem ) and not scipy0 :
826858 _ , yvec = ct .input_output_response (sys , tvec , uvec )
827- assert yvec .shape == (sys .noutputs , 8 )
859+ if squeeze is not True or sys .outputs > 1 :
860+ assert yvec .shape == (sys .outputs , 8 )
828861
829862 @pytest .mark .parametrize ("fcn" , [ct .ss , ct .tf , ct .ss2io ])
830863 def test_squeeze_exception (self , fcn ):
0 commit comments