@@ -522,6 +522,7 @@ def gen_zero_centered_series(val_min, val_max, period):
522522 'nyquist.mirror_style' : ['--' , ':' ], # style for mirror curve
523523 'nyquist.arrows' : 2 , # number of arrors around curve
524524 'nyquist.arrow_size' : 8 , # pixel size for arrows
525+ 'nyquist.encirclement_threshold' : 0.05 , # warning threshold
525526 'nyquist.indent_radius' : 1e-4 , # indentation radius
526527 'nyquist.indent_direction' : 'right' , # indentation direction
527528 'nyquist.indent_points' : 50 , # number of points to insert
@@ -610,6 +611,11 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
610611 arrow_style : matplotlib.patches.ArrowStyle, optional
611612 Define style used for Nyquist curve arrows (overrides `arrow_size`).
612613
614+ encirclement_threshold : float, optional
615+ Define the threshold for generating a warning if the number of net
616+ encirclements is a non-integer value. Default value is 0.05 and can
617+ be set using config.defaults['nyquist.encirclement_threshold'].
618+
613619 indent_direction : str, optional
614620 For poles on the imaginary axis, set the direction of indentation to
615621 be 'right' (default), 'left', or 'none'.
@@ -716,6 +722,9 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
716722 arrow_style = config ._get_param ('nyquist' , 'arrow_style' , kwargs , None )
717723 indent_radius = config ._get_param (
718724 'nyquist' , 'indent_radius' , kwargs , _nyquist_defaults , pop = True )
725+ encirclement_threshold = config ._get_param (
726+ 'nyquist' , 'encirclement_threshold' , kwargs ,
727+ _nyquist_defaults , pop = True )
719728 indent_direction = config ._get_param (
720729 'nyquist' , 'indent_direction' , kwargs , _nyquist_defaults , pop = True )
721730 indent_points = config ._get_param (
@@ -749,8 +758,11 @@ def _parse_linestyle(style_name, allow_false=False):
749758 if not hasattr (syslist , '__iter__' ):
750759 syslist = (syslist ,)
751760
761+ # Determine the range of frequencies to use, based on args/features
752762 omega , omega_range_given = _determine_omega_vector (
753763 syslist , omega , omega_limits , omega_num )
764+
765+ # If omega was not specified explicitly, start at omega = 0
754766 if not omega_range_given :
755767 if omega_num_given :
756768 # Just reset the starting point
@@ -851,6 +863,7 @@ def _parse_linestyle(style_name, allow_false=False):
851863 first_point = 0
852864 start_freq = 0
853865
866+ # Find the frequencies after the pole frequency
854867 above_points = np .argwhere (
855868 splane_contour .imag - abs (p .imag ) > indent_radius )
856869 last_point = above_points [0 ].item ()
@@ -899,7 +912,15 @@ def _parse_linestyle(style_name, allow_false=False):
899912
900913 # Compute CW encirclements of -1 by integrating the (unwrapped) angle
901914 phase = - unwrap (np .angle (resp + 1 ))
902- count = int (np .round (np .sum (np .diff (phase )) / np .pi , 0 ))
915+ encirclements = np .sum (np .diff (phase )) / np .pi
916+ count = int (np .round (encirclements , 0 ))
917+
918+ # Let the user know if the count might not make sense
919+ if abs (encirclements - count ) > encirclement_threshold :
920+ warnings .warn (
921+ "number of encirclements was a non-integer value; this can"
922+ " happen is contour is not closed, possibly based on a"
923+ " frequency range that does not include zero." )
903924
904925 #
905926 # Make sure that the enciriclements match the Nyquist criterion
@@ -1533,6 +1554,7 @@ def _determine_omega_vector(syslist, omega_in, omega_limits, omega_num,
15331554 num = omega_num , endpoint = True )
15341555 else :
15351556 omega_out = np .copy (omega_in )
1557+
15361558 return omega_out , omega_range_given
15371559
15381560
0 commit comments