@@ -22,9 +22,9 @@ def _sys_condition(system, feedback):
2222 num = system [0 ]
2323 den = system [1 ]
2424 # Convolve numerator or denominator as needed
25- if str ( type ( num )) == tuple :
25+ if isinstance ( num , tuple ) :
2626 num = convolve (num ) # Convolve terms in numerator
27- if str ( type ( den )) == tuple :
27+ if isinstance ( den , tuple ) :
2828 den = convolve (den ) # Convolve terms in denominator
2929 if feedback : # If asked to add the numerator to the denominator
3030 ld = len (den ) # Length of denominator
@@ -99,11 +99,21 @@ def bode(system, mn=0.001, mx=1000, npts=100, title="", xlim=False, ylim=False,
9999
100100 # Condition min and max freq terms
101101 degrees = False
102- if freqaxis .lower ().find ("deg" ) != - 1 : # degrees requested
102+ # Backwards-compatible: historically "deg" here behaved like "Hz"
103+ if freqaxis .lower ().find ("hz" ) != - 1 or freqaxis .lower ().find ("deg" ) != - 1 :
103104 degrees = True
104- # Scale Degrees to Radians for calculation
105+ # Scale Hz to rad/sec for calculation
105106 mn = 2 * _np .pi * mn
106107 mx = 2 * _np .pi * mx
108+
109+ # Prevent invalid log10 values
110+ if mn <= 0 :
111+ mn = 1e-12
112+ if mx <= 0 :
113+ mx = 1e-12
114+ if mx <= mn :
115+ raise ValueError ("mx must be greater than mn" )
116+
107117 mn = _np .log10 (mn ) # find the _exponent value
108118 mx = _np .log10 (mx ) # find the _exponent value
109119
@@ -113,14 +123,14 @@ def bode(system, mn=0.001, mx=1000, npts=100, title="", xlim=False, ylim=False,
113123 # Calculate the bode system
114124 w , mag , ang = _sig .bode (system , wover )
115125
116- def _plot (plot_title , y_label ):
126+ def _plot (plot_title , y_label , ydata ):
117127 _plt .title (plot_title )
118128 _plt .ylabel (y_label )
119- if degrees : # Plot in degrees
120- _plt .plot (w / (2 * _np .pi ), ang )
129+ if degrees : # Plot in Hz
130+ _plt .plot (w / (2 * _np .pi ), ydata )
121131 _plt .xlabel ("Frequency (Hz)" )
122132 else : # Plot in radians
123- _plt .plot (w , ang )
133+ _plt .plot (w , ydata )
124134 _plt .xlabel ("Frequency (rad/sec)" )
125135 _plt .xscale ("log" )
126136 _plt .grid (which = "both" )
@@ -129,12 +139,12 @@ def _plot(plot_title, y_label):
129139 if ylim :
130140 _plt .ylim (ylim )
131141 if sv :
132- _plt .savefig (title + ".png" )
142+ _plt .savefig (plot_title + ".png" )
133143
134144 # Plot Magnitude
135145 if magnitude :
136146 magTitle = "Magnitude " + title
137- _plot (magTitle , "Magnitude (DB)" )
147+ _plot (magTitle , "Magnitude (DB)" , mag )
138148 if disp3db :
139149 _plt .axhline (- 3 )
140150 if lowcut is not None :
@@ -144,7 +154,7 @@ def _plot(plot_title, y_label):
144154 # Plot Angle
145155 if angle :
146156 angTitle = "Angle " + title
147- _plot (angTitle , "Angle (degrees)" )
157+ _plot (angTitle , "Angle (degrees)" , ang )
148158 _plt .show ()
149159
150160
@@ -200,8 +210,14 @@ def sbode(f, NN=1000, title="", xlim=False, ylim=False, mn=0, mx=1000,
200210 angle: bool, optional
201211 Control argument to enable plotting of angle, default=True
202212 """
203- W = _np .linspace (mn , mx , NN )
204- H = _np .zeros (NN , dtype = _np .complex )
213+ # Avoid log(0) on semilog plots
214+ if mn <= 0 :
215+ mn_plot = 1e-12
216+ else :
217+ mn_plot = mn
218+
219+ W = _np .linspace (mn_plot , mx , NN )
220+ H = _np .zeros (NN , dtype = complex )
205221
206222 for n in range (0 , NN ):
207223 s = 1j * W [n ]
@@ -278,17 +294,23 @@ def zbode(f, dt=0.01, NN=1000, title="", mn=0, mx=2 * _pi, xlim=False, ylim=Fals
278294 angle: bool, optional
279295 Control argument to enable plotting of angle, default=True
280296 """
281- phi = _np .linspace (mn , mx , NN )
297+ # Avoid log(0) on semilog plots
298+ if mn <= 0 :
299+ mn_plot = 1e-12
300+ else :
301+ mn_plot = mn
302+
303+ phi = _np .linspace (mn_plot , mx , NN )
282304
283- H = _np .zeros (NN , dtype = _np . complex )
305+ H = _np .zeros (NN , dtype = complex )
284306 for n in range (0 , NN ):
285307 z = _exp (1j * phi [n ])
286308 if approx is not False and callable (approx ):
287309 # Approximated Z-Domain
288310 s = approx (z , dt ) # Pass current z-value and dt
289311 H [n ] = f (s )
290312 else : # Z-Domain Transfer Function Provided
291- H [n ] = dt * f (z )
313+ H [n ] = f (z )
292314
293315 if magnitude :
294316 _plt .semilogx ((180 / _pi ) * phi , 20 * _np .log10 (abs (H )), 'k' )
0 commit comments