Merge pull request #125 from murrayrm/doc-update · python-control/python-control@32f13bc

@@ -78,11 +78,11 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

7878

If True, plot phase in degrees (else radians)

7979

Plot : boolean

8080

If True, plot magnitude and phase

81-

omega_limits: tuple, list, ... of two values

81+

omega_limits: tuple, list, ... of two values

8282

Limits of the to generate frequency vector.

8383

If Hz=True the limits are in Hz otherwise in rad/s.

8484

omega_num: int

85-

number of samples

85+

number of samples

8686

*args, **kwargs:

8787

Additional options to matplotlib (color, linestyle, etc)

8888

@@ -120,7 +120,7 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

120120

# If argument was a singleton, turn it into a list

121121

if (not getattr(syslist, '__iter__', False)):

122122

syslist = (syslist,)

123-123+124124

if omega is None:

125125

if omega_limits is None:

126126

# Select a default range if none is provided

@@ -133,7 +133,7 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

133133

omega = sp.logspace(np.log10(omega_limits[0]), np.log10(omega_limits[1]), num=omega_num, endpoint=True)

134134

else:

135135

omega = sp.logspace(np.log10(omega_limits[0]), np.log10(omega_limits[1]), endpoint=True)

136-136+137137

mags, phases, omegas, nyquistfrqs = [], [], [], []

138138

for sys in syslist:

139139

if (sys.inputs > 1 or sys.outputs > 1):

@@ -142,8 +142,8 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

142142

else:

143143

omega_sys = np.array(omega)

144144

if sys.isdtime(True):

145-

nyquistfrq = 2. * np.pi * 1. / sys.dt / 2.

146-

omega_sys = omega_sys[omega_sys < nyquistfrq]

145+

nyquistfrq = 2. * np.pi * 1. / sys.dt / 2.

146+

omega_sys = omega_sys[omega_sys < nyquistfrq]

147147

# TODO: What distance to the Nyquist frequency is appropriate?

148148

else:

149149

nyquistfrq = None

@@ -179,7 +179,7 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

179179

plt.hold(True);

180180

if nyquistfrq_plot:

181181

ax_mag.axvline(nyquistfrq_plot, color=pltline[0].get_color())

182-182+183183

# Add a grid to the plot + labeling

184184

ax_mag.grid(True, which='both')

185185

ax_mag.set_ylabel("Magnitude (dB)" if dB else "Magnitude")

@@ -194,30 +194,31 @@ def bode_plot(syslist, omega=None, dB=None, Hz=None, deg=None,

194194

ax_phase.hold(True);

195195

if nyquistfrq_plot:

196196

ax_phase.axvline(nyquistfrq_plot, color=pltline[0].get_color())

197-197+198198

# Add a grid to the plot + labeling

199-

ax_phase.set_ylabel("Phase (deg)" if deg else "Phase (rad)")

199+

ax_phase.set_ylabel("Phase (deg)" if deg else "Phase (rad)")

200+200201

def genZeroCenteredSeries(val_min, val_max, period):

201202

v1 = np.ceil(val_min / period - 0.2)

202203

v2 = np.floor(val_max / period + 0.2)

203-

return np.arange(v1, v2 + 1) * period

204+

return np.arange(v1, v2 + 1) * period

204205

if deg:

205206

ylim = ax_phase.get_ylim()

206-

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], 45.))

207-

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], 15.), minor=True)

207+

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], 45.))

208+

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], 15.), minor=True)

208209

else:

209210

ylim = ax_phase.get_ylim()

210-

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], np.pi / 4.))

211+

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], np.pi / 4.))

211212

ax_phase.set_yticks(genZeroCenteredSeries(ylim[0], ylim[1], np.pi / 12.), minor=True)

212213

ax_phase.grid(True, which='both')

213-

# ax_mag.grid(which='minor', alpha=0.3)

214+

# ax_mag.grid(which='minor', alpha=0.3)

214215

# ax_mag.grid(which='major', alpha=0.9)

215-

# ax_phase.grid(which='minor', alpha=0.3)

216-

# ax_phase.grid(which='major', alpha=0.9)

217-216+

# ax_phase.grid(which='minor', alpha=0.3)

217+

# ax_phase.grid(which='major', alpha=0.9)

218+218219

# Label the frequency axis

219-

ax_phase.set_xlabel("Frequency (Hz)" if Hz else "Frequency (rad/sec)")

220-220+

ax_phase.set_xlabel("Frequency (Hz)" if Hz else "Frequency (rad/sec)")

221+221222

if len(syslist) == 1:

222223

return mags[0], phases[0], omegas[0]

223224

else:

@@ -314,7 +315,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',

314315

# instead of 1.0, and this would otherwise be

315316

# truncated to 0.

316317

plt.text(xpt, ypt,

317-

' ' + str(int(np.round(f / 1000 ** pow1000, 0))) +

318+

' ' + str(int(np.round(f / 1000 ** pow1000, 0))) +

318319

' ' + prefix + 'Hz')

319320

return x, y, omega

320321

@@ -394,18 +395,18 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None, feature_pe

394395

syslist : list of LTI

395396

List of linear input/output systems (single system is OK)

396397

Hz: boolean

397-

If True, the limits (first and last value) of the frequencies

398-

are set to full decades in Hz so it fits plotting with logarithmic

398+

If True, the limits (first and last value) of the frequencies

399+

are set to full decades in Hz so it fits plotting with logarithmic

399400

scale in Hz otherwise in rad/s. Omega is always returned in rad/sec.

400401

number_of_samples: int

401402

Number of samples to generate

402403

feature_periphery_decade: float

403-

Defines how many decades shall be included in the frequency range on

404-

both sides of features (poles, zeros).

404+

Defines how many decades shall be included in the frequency range on

405+

both sides of features (poles, zeros).

405406

Example: If there is a feature, e.g. a pole, at 1Hz and feature_periphery_decade=1.

406-

then the range of frequencies shall span 0.1 .. 10 Hz.

407+

then the range of frequencies shall span 0.1 .. 10 Hz.

407408

The default value is read from config.bode_feature_periphery_decade.

408-409+409410

Returns

410411

-------

411412

omega : array

@@ -425,14 +426,14 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None, feature_pe

425426426427

# Set default values for options

427428

from . import config

428-

if (number_of_samples is None):

429+

if (number_of_samples is None):

429430

number_of_samples = config.bode_number_of_samples

430-

if (feature_periphery_decade is None):

431-

feature_periphery_decade = config.bode_feature_periphery_decade

431+

if (feature_periphery_decade is None):

432+

feature_periphery_decade = config.bode_feature_periphery_decade

432433433434

# Find the list of all poles and zeros in the systems

434435

features = np.array(())

435-

freq_interesting = []

436+

freq_interesting = []

436437437438

# detect if single sys passed by checking if it is sequence-like

438439

if (not getattr(syslist, '__iter__', False)):

@@ -443,34 +444,34 @@ def default_frequency_range(syslist, Hz=None, number_of_samples=None, feature_pe

443444

# Add new features to the list

444445

if sys.isctime():

445446

features_ = np.concatenate((np.abs(sys.pole()),

446-

np.abs(sys.zero())))

447+

np.abs(sys.zero())))

447448

# Get rid of poles and zeros at the origin

448449

features_ = features_[features_ != 0.0];

449450

features = np.concatenate((features, features_))

450451

elif sys.isdtime(strict=True):

451452

fn = np.pi * 1. / sys.dt

452-

# TODO: What distance to the Nyquist frequency is appropriate?

453+

# TODO: What distance to the Nyquist frequency is appropriate?

453454

freq_interesting.append(fn * 0.9)

454455455456

features_ = np.concatenate((sys.pole(),

456-

sys.zero()))

457-

# Get rid of poles and zeros

457+

sys.zero()))

458+

# Get rid of poles and zeros

458459

# * at the origin and real <= 0 & imag==0: log!

459460

# * at 1.: would result in omega=0. (logaritmic plot!)

460461

features_ = features_[(features_.imag != 0.0) | (features_.real > 0.)]

461462

features_ = features_[np.bitwise_not((features_.imag == 0.0) & (np.abs(features_.real - 1.0) < 1.e-10))]

462463

# TODO: improve

463464

features__ = np.abs(np.log(features_) / (1.j * sys.dt))

464-

features = np.concatenate((features, features__))

465+

features = np.concatenate((features, features__))

465466

else:

466467

# TODO

467-

raise NotImplementedError('type of system in not implemented now')

468+

raise NotImplementedError('type of system in not implemented now')

468469

except:

469470

pass

470471471472472473

# Make sure there is at least one point in the range

473-

if (features.shape[0] == 0):

474+

if (features.shape[0] == 0):

474475

features = np.array([1.]);

475476476477

if Hz: