Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
other = _convertToFRD(other, omega=self.omega)
# Check that the input-output sizes are consistent.
if self.inputs != other.outputs:
raise ValueError(
"H = G1*G2: input-output size mismatch: "
"G1 has %i input(s), G2 has %i output(s)." %
(self.inputs, other.outputs))
inputs = other.inputs
outputs = self.outputs
fresp = empty((outputs, inputs, len(self.omega)),
dtype=self.fresp.dtype)
for i in range(len(self.omega)):
fresp[:, :, i] = dot(self.fresp[:, :, i], other.fresp[:, :, i])
return FRD(fresp, self.omega,
smooth=(self.ifunc is not None) and
(other.ifunc is not None))
def __truediv__(self, other):
"""Divide two LTI objects."""
if isinstance(other, (int, float, complex, np.number)):
return FRD(self.fresp * (1/other), self.omega,
smooth=(self.ifunc is not None))
else:
other = _convertToFRD(other, omega=self.omega)
if (self.inputs > 1 or self.outputs > 1 or
other.inputs > 1 or other.outputs > 1):
raise NotImplementedError(
"FRD.__truediv__ is currently only implemented for SISO "
"systems.")
return FRD(self.fresp/other.fresp, self.omega,
smooth=(self.ifunc is not None) and
(other.ifunc is not None))
omega.sort()
if len(omega) == len(sys.omega) and \
(abs(omega - sys.omega) < FRD.epsw).all():
# frequencies match, and system was already frd; simply use
return sys
raise NotImplementedError(
"Frequency ranges of FRD do not match, conversion not implemented")
elif isinstance(sys, LTI):
omega.sort()
fresp = empty((sys.outputs, sys.inputs, len(omega)), dtype=complex)
for k, w in enumerate(omega):
fresp[:, :, k] = sys._evalfr(w)
return FRD(fresp, omega, smooth=True)
elif isinstance(sys, (int, float, complex, np.number)):
fresp = ones((outputs, inputs, len(omega)), dtype=float)*sys
return FRD(fresp, omega, smooth=True)
# try converting constant matrices
try:
sys = array(sys)
outputs, inputs = sys.shape
fresp = empty((outputs, inputs, len(omega)), dtype=float)
for i in range(outputs):
for j in range(inputs):
fresp[i, j, :] = sys[i, j]
return FRD(fresp, omega, smooth=True)
except Exception:
pass
warn("Frequency points do not match; expect "
"truncation and interpolation.")
# Convert the second argument to a frequency response function.
# or re-base the frd to the current omega (if needed)
other = _convertToFRD(other, omega=self.omega)
# Check that the input-output sizes are consistent.
if self.inputs != other.inputs:
raise ValueError("The first summand has %i input(s), but the \
second has %i." % (self.inputs, other.inputs))
if self.outputs != other.outputs:
raise ValueError("The first summand has %i output(s), but the \
second has %i." % (self.outputs, other.outputs))
return FRD(self.fresp + other.fresp, other.omega)
def __neg__(self):
"""Negate a transfer function."""
return FRD(-self.fresp, self.omega)
return sys
raise NotImplementedError(
"Frequency ranges of FRD do not match, conversion not implemented")
elif isinstance(sys, LTI):
omega.sort()
fresp = empty((sys.outputs, sys.inputs, len(omega)), dtype=complex)
for k, w in enumerate(omega):
fresp[:, :, k] = sys._evalfr(w)
return FRD(fresp, omega, smooth=True)
elif isinstance(sys, (int, float, complex, np.number)):
fresp = ones((outputs, inputs, len(omega)), dtype=float)*sys
return FRD(fresp, omega, smooth=True)
# try converting constant matrices
try:
sys = array(sys)
outputs, inputs = sys.shape
fresp = empty((outputs, inputs, len(omega)), dtype=float)
for i in range(outputs):
for j in range(inputs):
fresp[i, j, :] = sys[i, j]
return FRD(fresp, omega, smooth=True)
except Exception:
pass
raise TypeError('''Can't convert given type "%s" to FRD system.''' %
sys.__class__)
def __mul__(self, other):
"""Multiply two LTI objects (serial connection)."""
# Convert the second argument to a transfer function.
if isinstance(other, (int, float, complex, np.number)):
return FRD(self.fresp * other, self.omega,
smooth=(self.ifunc is not None))
else:
other = _convertToFRD(other, omega=self.omega)
# Check that the input-output sizes are consistent.
if self.inputs != other.outputs:
raise ValueError(
"H = G1*G2: input-output size mismatch: "
"G1 has %i input(s), G2 has %i output(s)." %
(self.inputs, other.outputs))
inputs = other.inputs
outputs = self.outputs
fresp = empty((outputs, inputs, len(self.omega)),
dtype=self.fresp.dtype)
for i in range(len(self.omega)):
def __pow__(self, other):
if not type(other) == int:
raise ValueError("Exponent must be an integer")
if other == 0:
return FRD(ones(self.fresp.shape), self.omega,
smooth=(self.ifunc is not None)) # unity
if other > 0:
return self * (self**(other-1))
if other < 0:
return (FRD(ones(self.fresp.shape), self.omega) / self) * \
(self**(other+1))
# Check that the input-output sizes are consistent.
if self.outputs != other.inputs:
raise ValueError(
"H = G1*G2: input-output size mismatch: "
"G1 has %i input(s), G2 has %i output(s)." %
(other.inputs, self.outputs))
inputs = self.inputs
outputs = other.outputs
fresp = empty((outputs, inputs, len(self.omega)),
dtype=self.fresp.dtype)
for i in range(len(self.omega)):
fresp[:, :, i] = dot(other.fresp[:, :, i], self.fresp[:, :, i])
return FRD(fresp, self.omega,
smooth=(self.ifunc is not None) and
(other.ifunc is not None))
)
return FRD(fresp, other.omega, smooth=(self.ifunc is not None))
#
# Allow FRD as an alias for the FrequencyResponseData class
#
# Note: This class was initially given the name "FRD", but this caused
# problems with documentation on MacOS platforms, since files were generated
# for control.frd and control.FRD, which are not differentiated on most MacOS
# filesystems, which are case insensitive. Renaming the FRD class to be
# FrequenceResponseData and then assigning FRD to point to the same object
# fixes this problem.
#
FRD = FrequencyResponseData
def _convertToFRD(sys, omega, inputs=1, outputs=1):
"""Convert a system to frequency response data form (if needed).
If sys is already an frd, and its frequency range matches or
overlaps the range given in omega then it is returned. If sys is
another LTI object or a transfer function, then it is converted to
a frequency response data at the specified omega. If sys is a
scalar, then the number of inputs and outputs can be specified
manually, as in:
>>> frd = _convertToFRD(3., omega) # Assumes inputs = outputs = 1
>>> frd = _convertToFRD(1., omegs, inputs=3, outputs=2)
In the latter example, sys's matrix transfer function is [[1., 1., 1.]