8080
8181
8282def bode_plot (syslist , omega = None ,
83- Plot = True , omega_limits = None , omega_num = None ,
83+ plot = True , omega_limits = None , omega_num = None ,
8484 margins = None , * args , ** kwargs ):
8585 """Bode plot for a system
8686
@@ -100,7 +100,7 @@ def bode_plot(syslist, omega=None,
100100 deg : bool
101101 If True, plot phase in degrees (else radians). Default value (True)
102102 config.defaults['bode.deg']
103- Plot : bool
103+ plot : bool
104104 If True (default), plot magnitude and phase
105105 omega_limits: tuple, list, ... of two values
106106 Limits of the to generate frequency vector.
@@ -110,9 +110,9 @@ def bode_plot(syslist, omega=None,
110110 config.defaults['freqplot.number_of_samples'].
111111 margins : bool
112112 If True, plot gain and phase margin.
113- *args
114- Additional arguments for :func: `matplotlib.plot` (color, linestyle, etc)
115- **kwargs:
113+ *args : `matplotlib` plot positional properties, optional
114+ Additional arguments for `matplotlib` plots (color, linestyle, etc)
115+ **kwargs : `matplotlib` plot keyword properties, optional
116116 Additional keywords (passed to `matplotlib`)
117117
118118 Returns
@@ -153,12 +153,20 @@ def bode_plot(syslist, omega=None,
153153 # Make a copy of the kwargs dictonary since we will modify it
154154 kwargs = dict (kwargs )
155155
156+ # Check to see if legacy 'Plot' keyword was used
157+ if 'Plot' in kwargs :
158+ import warnings
159+ warnings .warn ("'Plot' keyword is deprecated in bode_plot; use 'plot'" ,
160+ FutureWarning )
161+ # Map 'Plot' keyword to 'plot' keyword
162+ plot = kwargs .pop ('Plot' )
163+
156164 # Get values for params (and pop from list to allow keyword use in plot)
157165 dB = config ._get_param ('bode' , 'dB' , kwargs , _bode_defaults , pop = True )
158166 deg = config ._get_param ('bode' , 'deg' , kwargs , _bode_defaults , pop = True )
159167 Hz = config ._get_param ('bode' , 'Hz' , kwargs , _bode_defaults , pop = True )
160168 grid = config ._get_param ('bode' , 'grid' , kwargs , _bode_defaults , pop = True )
161- Plot = config ._get_param ('bode' , 'grid' , Plot , True )
169+ plot = config ._get_param ('bode' , 'grid' , plot , True )
162170 margins = config ._get_param ('bode' , 'margins' , margins , False )
163171
164172 # If argument was a singleton, turn it into a list
@@ -211,7 +219,7 @@ def bode_plot(syslist, omega=None,
211219 # Get the dimensions of the current axis, which we will divide up
212220 # TODO: Not current implemented; just use subplot for now
213221
214- if Plot :
222+ if plot :
215223 nyquistfrq_plot = None
216224 if Hz :
217225 omega_plot = omega_sys / (2. * math .pi )
@@ -429,12 +437,13 @@ def gen_zero_centered_series(val_min, val_max, period):
429437 else :
430438 return mags , phases , omegas
431439
440+
432441#
433442# Nyquist plot
434443#
435444
436- def nyquist_plot (syslist , omega = None , Plot = True ,
437- labelFreq = 0 , arrowhead_length = 0.1 , arrowhead_width = 0.1 ,
445+ def nyquist_plot (syslist , omega = None , plot = True , label_freq = 0 ,
446+ arrowhead_length = 0.1 , arrowhead_width = 0.1 ,
438447 color = None , * args , ** kwargs ):
439448 """
440449 Nyquist plot for a system
@@ -451,13 +460,13 @@ def nyquist_plot(syslist, omega=None, Plot=True,
451460 If True, plot magnitude
452461 color : string
453462 Used to specify the color of the plot
454- labelFreq : int
463+ label_freq : int
455464 Label every nth frequency on the plot
456465 arrowhead_width : arrow head width
457466 arrowhead_length : arrow head length
458- *args
459- Additional arguments for :func: `matplotlib.plot` (color, linestyle, etc)
460- **kwargs:
467+ *args : `matplotlib` plot positional properties, optional
468+ Additional arguments for `matplotlib` plots (color, linestyle, etc)
469+ **kwargs : `matplotlib` plot keyword properties, optional
461470 Additional keywords (passed to `matplotlib`)
462471
463472 Returns
@@ -475,6 +484,22 @@ def nyquist_plot(syslist, omega=None, Plot=True,
475484 >>> real, imag, freq = nyquist_plot(sys)
476485
477486 """
487+ # Check to see if legacy 'Plot' keyword was used
488+ if 'Plot' in kwargs :
489+ import warnings
490+ warnings .warn ("'Plot' keyword is deprecated in nyquist_plot; "
491+ "use 'plot'" , FutureWarning )
492+ # Map 'Plot' keyword to 'plot' keyword
493+ plot = kwargs .pop ('Plot' )
494+
495+ # Check to see if legacy 'labelFreq' keyword was used
496+ if 'labelFreq' in kwargs :
497+ import warnings
498+ warnings .warn ("'labelFreq' keyword is deprecated in nyquist_plot; "
499+ "use 'label_freq'" , FutureWarning )
500+ # Map 'labelFreq' keyword to 'label_freq' keyword
501+ label_freq = kwargs .pop ('labelFreq' )
502+
478503 # If argument was a singleton, turn it into a list
479504 if not getattr (syslist , '__iter__' , False ):
480505 syslist = (syslist ,)
@@ -507,7 +532,7 @@ def nyquist_plot(syslist, omega=None, Plot=True,
507532 x = sp .multiply (mag , sp .cos (phase ))
508533 y = sp .multiply (mag , sp .sin (phase ))
509534
510- if Plot :
535+ if plot :
511536 # Plot the primary curve and mirror image
512537 p = plt .plot (x , y , '-' , color = color , * args , ** kwargs )
513538 c = p [0 ].get_color ()
@@ -527,8 +552,8 @@ def nyquist_plot(syslist, omega=None, Plot=True,
527552 plt .plot ([- 1 ], [0 ], 'r+' )
528553
529554 # Label the frequencies of the points
530- if labelFreq :
531- ind = slice (None , None , labelFreq )
555+ if label_freq :
556+ ind = slice (None , None , label_freq )
532557 for xpt , ypt , omegapt in zip (x [ind ], y [ind ], omega [ind ]):
533558 # Convert to Hz
534559 f = omegapt / (2 * sp .pi )
@@ -550,14 +575,15 @@ def nyquist_plot(syslist, omega=None, Plot=True,
550575 str (int (np .round (f / 1000 ** pow1000 , 0 ))) + ' ' +
551576 prefix + 'Hz' )
552577
553- if Plot :
578+ if plot :
554579 ax = plt .gca ()
555580 ax .set_xlabel ("Real axis" )
556581 ax .set_ylabel ("Imaginary axis" )
557582 ax .grid (color = "lightgray" )
558583
559584 return x , y , omega
560585
586+
561587#
562588# Gang of Four plot
563589#
@@ -575,6 +601,8 @@ def gangof4_plot(P, C, omega=None, **kwargs):
575601 Linear input/output systems (process and control)
576602 omega : array
577603 Range of frequencies (list or bounds) in rad/sec
604+ **kwargs : `matplotlib` plot keyword properties, optional
605+ Additional keywords (passed to `matplotlib`)
578606
579607 Returns
580608 -------
@@ -590,16 +618,16 @@ def gangof4_plot(P, C, omega=None, **kwargs):
590618 Hz = config ._get_param ('bode' , 'Hz' , kwargs , _bode_defaults , pop = True )
591619 grid = config ._get_param ('bode' , 'grid' , kwargs , _bode_defaults , pop = True )
592620
593- # Select a default range if none is provided
594- # TODO: This needs to be made more intelligent
595- if omega is None :
596- omega = default_frequency_range ((P , C ))
597-
598621 # Compute the senstivity functions
599622 L = P * C
600623 S = feedback (1 , L )
601624 T = L * S
602625
626+ # Select a default range if none is provided
627+ # TODO: This needs to be made more intelligent
628+ if omega is None :
629+ omega = default_frequency_range ((P , C , S ))
630+
603631 # Set up the axes with labels so that multiple calls to
604632 # gangof4_plot will superimpose the data. See details in bode_plot.
605633 plot_axes = {'t' : None , 's' : None , 'ps' : None , 'cs' : None }
@@ -628,36 +656,49 @@ def gangof4_plot(P, C, omega=None, **kwargs):
628656 # TODO: Need to add in the mag = 1 lines
629657 mag_tmp , phase_tmp , omega = S .freqresp (omega )
630658 mag = np .squeeze (mag_tmp )
631- plot_axes ['s' ].loglog (omega_plot , 20 * np .log10 (mag ) if dB else mag )
632- plot_axes ['s' ].set_ylabel ("$|S|$" )
659+ if dB :
660+ plot_axes ['s' ].semilogx (omega_plot , 20 * np .log10 (mag ), ** kwargs )
661+ else :
662+ plot_axes ['s' ].loglog (omega_plot , mag , ** kwargs )
663+ plot_axes ['s' ].set_ylabel ("$|S|$" + " (dB)" if dB else "" )
633664 plot_axes ['s' ].tick_params (labelbottom = False )
634665 plot_axes ['s' ].grid (grid , which = 'both' )
635666
636667 mag_tmp , phase_tmp , omega = (P * S ).freqresp (omega )
637668 mag = np .squeeze (mag_tmp )
638- plot_axes ['ps' ].loglog (omega_plot , 20 * np .log10 (mag ) if dB else mag )
669+ if dB :
670+ plot_axes ['ps' ].semilogx (omega_plot , 20 * np .log10 (mag ), ** kwargs )
671+ else :
672+ plot_axes ['ps' ].loglog (omega_plot , mag , ** kwargs )
639673 plot_axes ['ps' ].tick_params (labelbottom = False )
640- plot_axes ['ps' ].set_ylabel ("$|PS|$" )
674+ plot_axes ['ps' ].set_ylabel ("$|PS|$" + " (dB)" if dB else "" )
641675 plot_axes ['ps' ].grid (grid , which = 'both' )
642676
643677 mag_tmp , phase_tmp , omega = (C * S ).freqresp (omega )
644678 mag = np .squeeze (mag_tmp )
645- plot_axes ['cs' ].loglog (omega_plot , 20 * np .log10 (mag ) if dB else mag )
679+ if dB :
680+ plot_axes ['cs' ].semilogx (omega_plot , 20 * np .log10 (mag ), ** kwargs )
681+ else :
682+ plot_axes ['cs' ].loglog (omega_plot , mag , ** kwargs )
646683 plot_axes ['cs' ].set_xlabel (
647684 "Frequency (Hz)" if Hz else "Frequency (rad/sec)" )
648- plot_axes ['cs' ].set_ylabel ("$|CS|$" )
685+ plot_axes ['cs' ].set_ylabel ("$|CS|$" + " (dB)" if dB else "" )
649686 plot_axes ['cs' ].grid (grid , which = 'both' )
650687
651688 mag_tmp , phase_tmp , omega = T .freqresp (omega )
652689 mag = np .squeeze (mag_tmp )
653- plot_axes ['t' ].loglog (omega_plot , 20 * np .log10 (mag ) if dB else mag )
690+ if dB :
691+ plot_axes ['t' ].semilogx (omega_plot , 20 * np .log10 (mag ), ** kwargs )
692+ else :
693+ plot_axes ['t' ].loglog (omega_plot , mag , ** kwargs )
654694 plot_axes ['t' ].set_xlabel (
655695 "Frequency (Hz)" if Hz else "Frequency (rad/sec)" )
656- plot_axes ['t' ].set_ylabel ("$|T|$" )
696+ plot_axes ['t' ].set_ylabel ("$|T|$" + " (dB)" if dB else "" )
657697 plot_axes ['t' ].grid (grid , which = 'both' )
658698
659699 plt .tight_layout ()
660700
701+
661702#
662703# Utility functions
663704#
@@ -754,7 +795,7 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None,
754795 # TODO
755796 raise NotImplementedError (
756797 "type of system in not implemented now" )
757- except :
798+ except NotImplementedError :
758799 pass
759800
760801 # Make sure there is at least one point in the range
@@ -787,15 +828,17 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None,
787828 omega = sp .logspace (lsp_min , lsp_max , endpoint = True )
788829 return omega
789830
831+
790832#
791- # KLD 5/23/11: Two functions to create nice looking labels
833+ # Utility functions to create nice looking labels (KLD 5/23/11)
792834#
793835
794836def get_pow1000 (num ):
795837 """Determine exponent for which significand of a number is within the
796838 range [1, 1000).
797839 """
798- # Based on algorithm from http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg14433.html, accessed 2010/11/7
840+ # Based on algorithm from http://www.mail-archive.com/
841+ # matplotlib-users@lists.sourceforge.net/msg14433.html, accessed 2010/11/7
799842 # by Jason Heeris 2009/11/18
800843 from decimal import Decimal
801844 from math import floor
0 commit comments