@@ -714,41 +714,53 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
714714 if np .any (omega_sys * sys .dt > np .pi ) and warn_nyquist :
715715 warnings .warn ("evaluation above Nyquist frequency" )
716716
717- # Transform frequencies to continuous domain
718- contour = np .exp (1j * omega * sys .dt )
719- else :
720- contour = 1j * omega_sys
717+ # do indentations in s-plane where it is more convenient
718+ splane_contour = 1j * omega_sys
721719
722720 # Bend the contour around any poles on/near the imaginary axis
721+ # TODO: smarter indent radius that depends on dcgain of system
722+ # and timebase of discrete system.
723723 if isinstance (sys , (StateSpace , TransferFunction )) \
724- and sys .isctime () and indent_direction != 'none' :
725- poles = sys .pole ()
726- if contour [1 ].imag > indent_radius \
727- and 0. in poles and not omega_range_given :
724+ and indent_direction != 'none' :
725+ if sys .isctime ():
726+ splane_poles = sys .pole ()
727+ else :
728+ # map z-plane poles to s-plane, ignoring any at the origin
729+ # because we don't need to indent for them
730+ zplane_poles = sys .pole ()
731+ zplane_poles = zplane_poles [~ np .isclose (abs (zplane_poles ), 0. )]
732+ splane_poles = np .log (zplane_poles )/ sys .dt
733+
734+ if splane_contour [1 ].imag > indent_radius \
735+ and np .any (np .isclose (abs (splane_poles ), 0 )) \
736+ and not omega_range_given :
728737 # add some points for quarter circle around poles at origin
729- contour = np .concatenate (
738+ splane_contour = np .concatenate (
730739 (1j * np .linspace (0. , indent_radius , 50 ),
731- contour [1 :]))
732- for i , s in enumerate (contour ):
740+ splane_contour [1 :]))
741+ for i , s in enumerate (splane_contour ):
733742 # Find the nearest pole
734- p = poles [(np .abs (poles - s )).argmin ()]
735-
743+ p = splane_poles [(np .abs (splane_poles - s )).argmin ()]
736744 # See if we need to indent around it
737745 if abs (s - p ) < indent_radius :
738- if p .real < 0 or \
739- ( p . real == 0 and indent_direction == 'right' ):
746+ if p .real < 0 or ( np . isclose ( p . real , 0 ) \
747+ and indent_direction == 'right' ):
740748 # Indent to the right
741- contour [i ] += \
749+ splane_contour [i ] += \
742750 np .sqrt (indent_radius ** 2 - (s - p ).imag ** 2 )
743- elif p .real > 0 or \
744- ( p . real == 0 and indent_direction == 'left' ):
751+ elif p .real > 0 or ( np . isclose ( p . real , 0 ) \
752+ and indent_direction == 'left' ):
745753 # Indent to the left
746- contour [i ] -= \
754+ splane_contour [i ] -= \
747755 np .sqrt (indent_radius ** 2 - (s - p ).imag ** 2 )
748756 else :
749757 ValueError ("unknown value for indent_direction" )
750758
751- # TODO: add code to indent around discrete poles on unit circle
759+ # change contour to z-plane if necessary
760+ if sys .isctime ():
761+ contour = splane_contour
762+ else :
763+ contour = np .exp (splane_contour * sys .dt )
752764
753765 # Compute the primary curve
754766 resp = sys (contour )
0 commit comments