4848from .ctrlutil import unwrap
4949from .bdalg import feedback
5050from .margins import stability_margins
51+ from .config import defaults
5152
5253__all__ = ['bode_plot' , 'nyquist_plot' , 'gangof4_plot' ,
5354 'bode' , 'nyquist' , 'gangof4' ]
6263# Bode plot
6364
6465
65- def bode_plot (syslist , omega = None , dB = None , Hz = None , deg = None ,
66- Plot = True , omega_limits = None , omega_num = None , margins = None , * args , ** kwargs ):
67- """
68- Bode plot for a system
66+ def bode_plot (syslist , omega = None ,
67+ Plot = True , omega_limits = None , omega_num = None ,
68+ margins = None , * args , ** kwargs ):
69+ """ Bode plot for a system
6970
7071 Plots a Bode plot for the system over a (optional) frequency range.
7172
@@ -76,18 +77,21 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,
7677 omega : list
7778 List of frequencies in rad/sec to be used for frequency response
7879 dB : boolean
79- If True, plot result in dB
80+ If True, plot result in dB. Defaults to config.defaults['bode.dB'].
8081 Hz : boolean
81- If True, plot frequency in Hz (omega must be provided in rad/sec)
82+ If True, plot frequency in Hz (omega must be provided in rad/sec).
83+ Defaults to config.defaults['bode.Hz']
8284 deg : boolean
83- If True, plot phase in degrees (else radians)
85+ If True, plot phase in degrees (else radians). Defaults to
86+ config.defaults['bode.deg']
8487 Plot : boolean
8588 If True, plot magnitude and phase
8689 omega_limits: tuple, list, ... of two values
8790 Limits of the to generate frequency vector.
8891 If Hz=True the limits are in Hz otherwise in rad/s.
8992 omega_num: int
90- number of samples
93+ Number of samples to plot. Defaults to
94+ config.defaults['freqplot.number_of_samples'].
9195 margins : boolean
9296 If True, plot gain and phase margin
9397 \*args, \**kwargs:
@@ -102,6 +106,12 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,
102106 omega : array (list if len(syslist) > 1)
103107 frequency in rad/sec
104108
109+ Other Parameters
110+ ----------------
111+ grid : bool
112+ If True, plot grid lines on gain and phase plots. Default is set by
113+ config.defaults['bode.grid'].
114+
105115 Notes
106116 -----
107117 1. Alternatively, you may use the lower-level method (mag, phase, freq)
@@ -117,15 +127,13 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,
117127 --------
118128 >>> sys = ss("1. -2; 3. -4", "5.; 7", "6. 8", "9.")
119129 >>> mag, phase, omega = bode(sys)
130+
120131 """
121- # Set default values for options
122- from . import config
123- if dB is None :
124- dB = config .bode_dB
125- if deg is None :
126- deg = config .bode_deg
127- if Hz is None :
128- Hz = config .bode_Hz
132+ # Set default values for options (and pop from list to allow use in plots)
133+ dB = kwargs .pop ('dB' , defaults .get ('bode.dB' , False ))
134+ deg = kwargs .pop ('deg' , defaults .get ('bode.deg' , True ))
135+ Hz = kwargs .pop ('Hz' , defaults .get ('bode.Hz' , False ))
136+ grid = kwargs .pop ('grid' , defaults .get ('bode.grid' , True ))
129137
130138 # If argument was a singleton, turn it into a list
131139 if not getattr (syslist , '__iter__' , False ):
@@ -235,7 +243,7 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,
235243 color = pltline [0 ].get_color ())
236244
237245 # Add a grid to the plot + labeling
238- ax_mag .grid (False if margins else True , which = 'both' )
246+ ax_mag .grid (grid and not margins , which = 'both' )
239247 ax_mag .set_ylabel ("Magnitude (dB)" if dB else "Magnitude" )
240248
241249 # Phase plot
@@ -377,7 +385,7 @@ def gen_zero_centered_series(val_min, val_max, period):
377385 ylim [1 ],
378386 math .pi / 12. ),
379387 minor = True )
380- ax_phase .grid (False if margins else True , which = 'both' )
388+ ax_phase .grid (grid and not margins , which = 'both' )
381389 # ax_mag.grid(which='minor', alpha=0.3)
382390 # ax_mag.grid(which='major', alpha=0.9)
383391 # ax_phase.grid(which='minor', alpha=0.3)
@@ -592,7 +600,7 @@ def gangof4_plot(P, C, omega=None):
592600
593601# Compute reasonable defaults for axes
594602def default_frequency_range (syslist , Hz = None , number_of_samples = None ,
595- feature_periphery_decade = None ):
603+ feature_periphery_decades = None ):
596604 """Compute a reasonable default frequency range for frequency
597605 domain plots.
598606
@@ -603,24 +611,18 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None,
603611 ----------
604612 syslist : list of LTI
605613 List of linear input/output systems (single system is OK)
606-
607614 Hz : bool
608615 If True, the limits (first and last value) of the frequencies
609616 are set to full decades in Hz so it fits plotting with logarithmic
610617 scale in Hz otherwise in rad/s. Omega is always returned in rad/sec.
611-
612618 number_of_samples : int, optional
613- Number of samples to generate. Defaults to ``numpy.logspace`` default
614- value.
615-
616- feature_periphery_decade : float, optional
619+ Number of samples to generate. The default value is read from
620+ ``config.defaults['freqplot.number_of_samples']. If None, then the
621+ default from `numpy.logspace` is used.
622+ feature_periphery_decades : float, optional
617623 Defines how many decades shall be included in the frequency range on
618- both sides of features (poles, zeros).
619-
620- Example: If there is a feature, e.g. a pole, at 1 Hz and
621- feature_periphery_decade=1., then the range of frequencies shall span
622- 0.1 .. 10 Hz. The default value is read from
623- ``config.bode_feature_periphery_decade``.
624+ both sides of features (poles, zeros). The default value is read from
625+ ``config.defaults['freqplot.feature_periphery_decades']``.
624626
625627 Returns
626628 -------
@@ -643,9 +645,10 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None,
643645 # Set default values for options
644646 from . import config
645647 if number_of_samples is None :
646- number_of_samples = config .bode_number_of_samples
647- if feature_periphery_decade is None :
648- feature_periphery_decade = config .bode_feature_periphery_decade
648+ number_of_samples = config .defaults ['freqplot.number_of_samples' ]
649+ if feature_periphery_decades is None :
650+ feature_periphery_decades = \
651+ config .defaults ['freqplot.feature_periphery_decades' ]
649652
650653 # Find the list of all poles and zeros in the systems
651654 features = np .array (())
@@ -693,14 +696,14 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None,
693696 if Hz :
694697 features /= 2. * math .pi
695698 features = np .log10 (features )
696- lsp_min = np .floor (np .min (features ) - feature_periphery_decade )
697- lsp_max = np .ceil (np .max (features ) + feature_periphery_decade )
699+ lsp_min = np .floor (np .min (features ) - feature_periphery_decades )
700+ lsp_max = np .ceil (np .max (features ) + feature_periphery_decades )
698701 lsp_min += np .log10 (2. * math .pi )
699702 lsp_max += np .log10 (2. * math .pi )
700703 else :
701704 features = np .log10 (features )
702- lsp_min = np .floor (np .min (features ) - feature_periphery_decade )
703- lsp_max = np .ceil (np .max (features ) + feature_periphery_decade )
705+ lsp_min = np .floor (np .min (features ) - feature_periphery_decades )
706+ lsp_max = np .ceil (np .max (features ) + feature_periphery_decades )
704707 if freq_interesting :
705708 lsp_min = min (lsp_min , np .log10 (min (freq_interesting )))
706709 lsp_max = max (lsp_max , np .log10 (max (freq_interesting )))
0 commit comments