Skip to content

Commit 0dae798

Browse files
committed
tweak max_curve_magnitude + add start point
1 parent e80343d commit 0dae798

2 files changed

Lines changed: 49 additions & 12 deletions

File tree

control/freqplot.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -518,15 +518,17 @@ def gen_zero_centered_series(val_min, val_max, period):
518518

519519
# Default values for module parameter variables
520520
_nyquist_defaults = {
521-
'nyquist.primary_style': ['-', '-.'], # style for primary curve
522-
'nyquist.mirror_style': ['--', ':'], # style for mirror curve
523-
'nyquist.arrows': 2,
524-
'nyquist.arrow_size': 8,
525-
'nyquist.indent_radius': 1e-6, # indentation radius
521+
'nyquist.primary_style': ['-', '-.'], # style for primary curve
522+
'nyquist.mirror_style': ['--', ':'], # style for mirror curve
523+
'nyquist.arrows': 2, # number of arrors around curve
524+
'nyquist.arrow_size': 8, # pixel size for arrows
525+
'nyquist.indent_radius': 1e-4, # indentation radius
526526
'nyquist.indent_direction': 'right', # indentation direction
527527
'nyquist.indent_points': 50, # number of points to insert
528-
'nyquist.max_curve_magnitude': 20,
529-
'nyquist.max_curve_offset': 0.02, # percent offset of curves
528+
'nyquist.max_curve_magnitude': 20, # clip large values
529+
'nyquist.max_curve_offset': 0.02, # offset of primary/mirror
530+
'nyquist.start_marker': 'o', # marker at start of curve
531+
'nyquist.start_marker_size': 4, # size of the maker
530532
}
531533

532534

@@ -617,8 +619,9 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
617619
are at or near the imaginary axis.
618620
619621
indent_radius : float, optional
620-
Amount to indent the Nyquist contour around poles that are at or near
621-
the imaginary axis.
622+
Amount to indent the Nyquist contour around poles on or near the
623+
imaginary axis. Portions of the Nyquist plot corresponding to indented
624+
portions of the contour are plotted using a different line style.
622625
623626
max_curve_magnitude : float, optional
624627
Restrict the maximum magnitude of the Nyquist plot to this value.
@@ -637,13 +640,22 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
637640
`False` then omit completely. Default linestyle (['--', '-.']) is
638641
determined by config.defaults['nyquist.mirror_style'].
639642
640-
primary_style : [str, str]
643+
primary_style : [str, str], optional
641644
Linestyles for primary image of the Nyquist curve. The first element
642645
is used for unscaled portions of the Nyquist curve, the second
643646
element is used for scaled portions that are scaled (using
644647
max_curve_magnitude). Default linestyle (['-', ':']) is determined by
645648
config.defaults['nyquist.mirror_style'].
646649
650+
start_marker : str, optional
651+
Matplotlib marker to use to mark the starting point of the Nyquist
652+
plot. Defaults value is 'o' and can be set using
653+
config.defaults['nyquist.start_marker'].
654+
655+
start_marker_size : float, optional
656+
Start marker size (in display coordinates). Default value is
657+
4 and can be set using config.defaults['nyquist.start_marker_size'].
658+
647659
warn_nyquist : bool, optional
648660
If set to 'False', turn off warnings about frequencies above Nyquist.
649661
@@ -712,6 +724,10 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
712724
'nyquist', 'max_curve_magnitude', kwargs, _nyquist_defaults, pop=True)
713725
max_curve_offset = config._get_param(
714726
'nyquist', 'max_curve_offset', kwargs, _nyquist_defaults, pop=True)
727+
start_marker = config._get_param(
728+
'nyquist', 'start_marker', kwargs, _nyquist_defaults, pop=True)
729+
start_marker_size = config._get_param(
730+
'nyquist', 'start_marker_size', kwargs, _nyquist_defaults, pop=True)
715731

716732
# Set line styles for the curves
717733
def _parse_linestyle(style_name, allow_false=False):
@@ -847,6 +863,7 @@ def _parse_linestyle(style_name, allow_false=False):
847863
start_freq, p.imag + indent_radius, indent_points)),
848864
splane_contour[last_point:]))
849865

866+
# Indent points that are too close to a pole
850867
for i, s in enumerate(splane_contour):
851868
# Find the nearest pole
852869
p = splane_poles[(np.abs(splane_poles - s)).argmin()]
@@ -928,13 +945,21 @@ def _parse_linestyle(style_name, allow_false=False):
928945
'simple', head_width=arrow_size, head_length=arrow_size)
929946

930947
# Find the different portions of the curve (with scaled pts marked)
931-
reg_mask = abs(resp) > max_curve_magnitude
948+
reg_mask = np.logical_or(
949+
np.abs(resp) > max_curve_magnitude,
950+
contour.real != 0)
951+
# reg_mask = np.logical_or(
952+
# np.abs(resp.real) > max_curve_magnitude,
953+
# np.abs(resp.imag) > max_curve_magnitude)
954+
932955
scale_mask = ~reg_mask \
933956
& np.concatenate((~reg_mask[1:], ~reg_mask[-1:])) \
934957
& np.concatenate((~reg_mask[0:1], ~reg_mask[:-1]))
935958

936959
# Rescale the points with large magnitude
937-
resp[reg_mask] /= (np.abs(resp[reg_mask]) / max_curve_magnitude)
960+
rescale = np.logical_and(
961+
reg_mask, abs(resp) > max_curve_magnitude)
962+
resp[rescale] *= max_curve_magnitude / abs(resp[rescale])
938963

939964
# Plot the regular portions of the curve (and grab the color)
940965
x_reg = np.ma.masked_where(reg_mask, resp.real)
@@ -985,6 +1010,11 @@ def _parse_linestyle(style_name, allow_false=False):
9851010
_add_arrows_to_line2D(
9861011
ax, p[0], arrow_pos, arrowstyle=arrow_style, dir=-1)
9871012

1013+
# Mark the start of the curve
1014+
if start_marker:
1015+
plt.plot(resp[0].real, resp[0].imag, start_marker,
1016+
color=c, markersize=start_marker_size)
1017+
9881018
# Mark the -1 point
9891019
plt.plot([-1], [0], 'r+')
9901020

control/tests/nyquist_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,13 @@ def test_linestyle_checks():
360360
test_nyquist_indent_do(indentsys)
361361
test_nyquist_indent_left(indentsys)
362362

363+
# Generate a figuring showing effects of different parameters
364+
sys = 3 * (s+6)**2 / (s * (s**2 + 1e-4 * s + 1))
365+
plt.figure()
366+
ct.nyquist_plot(sys)
367+
ct.nyquist_plot(sys, max_curve_magnitude=15)
368+
ct.nyquist_plot(sys, indent_radius=1e-6, max_curve_magnitude=25)
369+
363370
print("Unusual Nyquist plot")
364371
sys = ct.tf([1], [1, 3, 2]) * ct.tf([1], [1, 0, 1])
365372
plt.figure()

0 commit comments

Comments
 (0)