Main Utilities¶
Be sure to check out Tutorials for example usages of these utilities!
Complementary Filter Synthesis¶
Optimal complementary filter synthesis using \(\mathcal{H}_\infty\) methods.
-
class
kontrol.
ComplementaryFilter
(noise1=None, noise2=None, weight1=None, weight2=None, filter1=None, filter2=None, f=None)¶ Bases:
object
Complementary filter synthesis class.
Parameters: - noise1 (TransferFunction) – Sensor noise 1 transfer function model. A transfer function that has magnitude response matching the amplitude spectral density of noise 1.
- noise2 (TransferFunction) – Sensor noise 2 transfer function model. A transfer function that has magnitude response matching the amplitude spectral density of noise 2.
- weight1 (TransferFunction, optional) – Weighting function 1. Frequency dependent specification for noise 1. Defaults None.
- weight2 (TransferFunction, optional) – Weighting function 2. Frequency dependent specification for noise 2. Defaults None.
- filter1 (TransferFunction, optional) – The complementary filter for noise 1. Defaults None.
- filter2 (TransferFunction, optional) – The complementary filter for noise 2. Defaults None.
- f (array, optional) – The frequency axis in Hz for evaluating the super sensor noise. Defaults None.
-
h2synthesis
()¶ Complementary filter synthesis that minimizes the \(\mathcal{H}_2\)-norm of the super sensor noise. The noise must be specified before using this method.
-
hinfsynthesis
()¶ Complementary filter synthesis that minimizes the \(\mathcal{H}_\infty\)-norm of the super sensor noise. The noise must be specified before using this method.
Notes
This is a utility class for complementary filter synthesis, sensor noise estimation and analysis. To use synthesis methods, specify
noise1
andnoise2
as the transfer function modesl for the sensor noises, and specifyweight1
andweight2
as the frequency dependent specification for the two sensor noises.References
[1] T. T. L. Tsang, T. G. F. Li, T. Dehaeze, C. Collette. Optimal Sensor Fusion Method for Active Vibration Isolation Systems in Ground-Based Gravitational-Wave Detectors. https://arxiv.org/pdf/2111.14355.pdf -
f
¶ The frequency axis in Hz.
-
filter1
¶ First complementary filter.
-
filter2
¶ Second complementary filter.
-
h2synthesis
(clean_filter=True, **kwargs) Synthesize complementary filters using H2 synthesis.
Returns: - filter1 (TransferFunction) – The complementary filter filtering noise 1.
- filter2 (TransferFunction) – The complementary filter filtering noise 2.
- clean_filter (boolean, optional) – Remove small outlier coefficients from filters. Defaults True.
- **kwargs – Keyword arguments passed to kontrol.TransferFunction.clean()
-
hinfsynthesis
(clean_filter=True, **kwargs) Synthesize complementary filters using H-inifinity synthesis.
Returns: - filter1 (TransferFunction) – The complementary filter filtering noise 1.
- filter2 (TransferFunction) – The complementary filter filtering noise 2.
- clean_filter (boolean, optional) – Remove small outlier coefficients from filters. Defaults True.
- **kwargs – Keyword arguments passed to kontrol.TransferFunction.clean()
-
noise1
¶ Transfer function model of sensor noise 1.
-
noise2
¶ Transfer function model of sensor noise 2.
-
noise_super
(f=None, noise1=None, noise2=None, filter1=None, filter2=None)¶ Compute and return predicted the ASD of the super sensor noise
- f : array, optional
- The frequency axis in Hz. Use self.f if None. Defaults None.
- noise1 : array, optional
- The amplitude spectral density of noise 1. Use self.noise1 and self.f to estimate if None. Defaults None.
- noise2 : array, optional
- The amplitude spectral density of noise 2. Use self.noise1 and self.f to estimate if None. Defaults None.
- filter1 : TransferFunction, optional
- The complementary filter for filtering noise1 Use self.filter1 if not specified. Defaults None
- filter2 : TransferFunction, optional
- The complementary filter for filtering noise1 Use self.filter2 if not specified. Defaults None
Returns: The amplitude spectral density of the super sensor noise. Return type: array
Frequency Series Class¶
Frequency domain and transfer function data modeling
-
class
kontrol.
FrequencySeries
(f, x)¶ Bases:
object
Frequency series class
-
f
¶ Frequency axis
Type: array
-
x
¶ Frequency series data.
Type: array
-
x_empirical
¶ Frequency series of the empirical model.
Type: array or None
-
model_empirical
¶ The model function whose first argument is the frequency axis and the rest being an arbitrary number of model parameters to be fit.
Type: func(f, a, b, c, ..) -> array or None
-
args_empirical_model
¶ The optimized arguments passed to the model_empirical.
Type: array or None
-
f_zpk
¶ The frequency axis used during ZPK fitting.
Type: array or None
-
x_zpk
¶ The frequency series data used during ZPK fitting. Note: this is a complex array.
Type: array or None
-
tf_zpk
¶ The transfer function the best fit the data using ZPK model.
Type: control.xferfcn.TransferFunction or None
-
args_zpk_model
¶ A 1-D list of zeros, poles, and gain. Zeros and poles are in unit of Hz.
Type: array or None
-
f_tf
¶ The frequency series data used during transfer function fitting.
Type: array or None
-
x_tf
¶ The frequency series data used during transfer function fitting. Note: this is a complex array.
Type: array or None
-
tf
¶ The modeled transfer function.
Type: control.xferfcn.TransferFunction or None
-
args_tf_model
¶ A 1-D list of numerator and denominator coefficients, from higher order to lower order.
Type: array or None
-
fit_empirical
(model, x0=None, error_func=<function log_mse>, error_func_kwargs={}, optimizer=<function minimize>, optimizer_kwargs={})¶ Fit frequency series data with an empirical model. (Local optimize)
Parameters: - model (func(f, a, b, c, ..) -> array) – The model function whose first argument is the frequency axis and the rest being an arbitrary number of model parameters to be fit.
- x0 (array, optional) – The initial parameters for fitting. Defaults None. If None, defaults to np.ones()
- error_func (func(x1: array, x2: array) -> float) – The function that evaluate the error between arrays x1 and x2. Defaults to kontrol.core.math.log_mse, which evaluates the logarithmic mean square error.
- error_func_kwargs (dict, optional) – Keyword arguments passed to the error function. Use this to specify weighting function {“weight”: weight_func}. Defaults to {}.
- optimizer (func, optional) – The optimization function which has the signature func(func, args, bounds, **kw) -> scipy.optimize.OptimizeResult. Defaults to scipy.optimize.minimize.
- optimizer_kwargs (dict, optional) – Keyword arguments passed to the optimization function. Defaults {} but will set to {“method”: “Powell”, “x0”=x0} if optimizer is default.
Returns: res – The result of the fitting (optimization)
Return type: scipy.optimize.OptimizeResult
-
fit_tf
(x0=None, log_var=True, error_func=<function log_mse>, error_func_kwargs={}, optimizer=<function minimize>, optimizer_kwargs={})¶ Fit frequency series with a transfer function model
Parameters: - x0 (array or None, optional) – The initial parameters defining the initial transfer function. A 1-D list of numerator and denominator coefficients, from higher order to lower order. Defaults None. If None, will use the result from the ZPK fitting.
- log_var (boolean, optional) – Optimize the log of variables instead. Useful for variables that have very large dynamic range Defaults True.
- error_func (func(x1: array, x2: array) -> float, optional) – The function that evaluate the error between arrays x1 and x2. Defaults to kontrol.core.math.log_mse, which evaluates the logarithmic mean square error.
- error_func_kwargs (dict, optional) – Keyword arguments passed to the error function. Use this to specify weighting function {“weight”: weight_func}. Defaults to {}.
- optimizer (func, optional) – The optimization function which has the signature func(func, args, bounds, **kw) -> scipy.optimize.OptimizeResult. Defaults to scipy.optimize.minimize.
- optimizer_kwargs (dict, optional) – Keyword arguments passed to the optimization function. Defaults {} but will set to {“method”: “Powell”, “x0”: x0} if optimizer is default.
Returns: res – The result of the optimization.
Return type: scipy.optimize.OptimizerResult
Note
Only use this after using fit_zpk().
-
fit_zpk
(order, fit='x_empirical', padding=False, padding_order=1.0, error_func=<function log_mse>, error_func_kwargs={}, optimizer=<function differential_evolution>, optimizer_kwargs={})¶ Fit frequency series with a zpk model.
Parameters: - order (int) – The order of the ZPK model to be used.
- fit (str, optional) – Choose the data to be fit, choose from [“x”, “x_empirical”].
- padding (boolean, optional) – Pad the data by continuous white noise. Defaults False.
- padding_order (float, optional) – The number of decades to be padded on both sides of the series. Defaults to 1.
- error_func (func(x1: array, x2: array) -> float) – The function that evaluate the error between arrays x1 and x2. Defaults to kontrol.core.math.log_mse, which evaluates the logarithmic mean square error.
- error_func_kwargs (dict, optional) – Keyword arguments passed to the error function. Use this to specify weighting function {“weight”: weight_func}. Defaults to {}.
- optimizer (func, optional) – The optimization function which has the signature func(func, args, bounds, **kw) -> scipy.optimize.OptimizeResult. Defaults to scipy.optimize.differential_evolution.
- optimizer_kwargs (dict, optional) – Keyword arguments passed to the optimization function. Defaults {} but will set to {“workers”: -1, “updating”:”deferred”} if optimizer is default.
Returns: res – The result of the optimization.
Return type: scipy.optimize.OptimizerResult
Note
For now, we support models with equal number of zeros and poles only.
Best use with log-space frequency series or after using fit_empirical().
-
Sensors and Actuators Utilities¶
Sensing Matrix Classes¶
Sensing matrix and diagonalization.
-
class
kontrol.
SensingMatrix
(matrix, coupling_matrix=None, *args, **kwargs)¶ Bases:
kontrol.sensact.matrix.Matrix
Base class for sensing matrices
-
diagonalize
(coupling_matrix=None)¶ Diagonalize the sensing matrix, given a coupling matrix.
Parameters: coupling_matrix (array, optional.) – The coupling matrix. If None, self.coupling_matrix will be used. Default None. Returns: The new sensing matrix. Return type: array Notes
The coupling matrix has (i, j) elements as coupling ratios x_i/x_j. For example, consider the 2-sensor configuration: I have a coupled sensing readout \(x_{1,\mathrm{coupled}}\) that reads \(x_{1,\mathrm{coupled}}=x_1 + 0.1x_2\). and, I have another coupled sensing readout \(x_{2,\mathrm{coupled}}\) that reads \(x_{2,\mathrm{coupled}}=-0.2x_1 + x_2\). Then, the coupling matrix is
\[\begin{split}\begin{bmatrix} 1 & 0.1\\ -0.2 & 1 \end{bmatrix}.\end{split}\]
-
Optical Lever Sensing Matrices¶
Sensing matrices for optical levers in KAGRA.
-
class
kontrol.
OpticalLeverSensingMatrix
(*args, **kwargs)¶ Bases:
kontrol.sensact.matrix.SensingMatrix
Optical lever sensing matrix base class.
This is a sensing matrix that maps tilt-sensing QPD and length-sensing QPD (placed behind a lens) readouts to the suspended optics’ longitudinal, pitch, and yaw displacements.
Parameters: - r_h (float) – Lever arm from the optics to the tilt-sensing QPD plane on the horizontal plane (amplifying yaw).
- r_v (float) – Lever arm from the optics to the tilt-sensing QPD plane on the vertical plane (amplifying pitch).
- alpha_h (float) – Angle of incidence on the horizontal plane.
- alpha_v (float) – Angle of incidence on the vertical plane.
- r_lens_h (float, optional) – Lever arm from optics to the lens on the horizontal plane. Defaults None. Specify if it exists.
- r_lens_v (float, optional) – Lever arm from optics to the lens on the vertical plane. Defaults None. Specify if it exists.
- d_h (float, optional) – Horizontal distance from the lens to the length-sensing QPD. Defaults None.
- d_v (float, optional) – Vertical distance from the lens to the length-sensing QPD. Defaults None.
- delta_x (float, optional) – Horizontal miscentering of the beam spot at the optics plane.
- delta_y (float, optional) – Vertical miscentering of the beam spot at the optics plane.
- phi_tilt (float, optional) – Angle from the tilt-sensing QPD frame to the yaw-pitch frame. Defaults None.
- phi_len (float, optional) – Angle from the length-sensing QPD frame to the yaw-pitch frame. Defaults None.
- f_h (float, optional,) – Focal length of the lens projected to the horizontal plane.
Defaults
np.inf
(no lens). - f_v (float, optional,) – Focal length of the lens projected to the vertical plane.
Defaults
np.inf
(no lens). - format (str, optional) –
Format of the sensing matrix. Choose from
- ”OPLEV2EUL”: Default sensing matrix from KAGRA MEDM screen
- with input (TILT_PIT, TILT_YAW, LEN_PIT, LEN_YAW), and output (longitudinal, pitch and yaw).
”xy”: Matrix as shown in [1]_.
- coupling_matrix (array, optional) – The coupling matrix. Default None.
Notes
We’re using equation (29) from [1]_.
\[\begin{split}\begin{pmatrix} x_L\\ \theta_P\\ \theta_Y \end{pmatrix} = \mathbf{C}_\mathrm{miscenter} \mathbf{C}_\mathrm{align} \mathbf{C}_\mathrm{rotation} \begin{pmatrix} x_\mathrm{tilt}\\ y_\mathrm{tilt}\\ x_\mathrm{len}\\ y_\mathrm{len} \end{pmatrix},\end{split}\]where \(x_L\) is the longitudinal displacement of the optics, \(\theta_P\) is the pitch angular displacement of the optics, \(\theta_Y\) is the yaw angular displacement of the optics, \(x_\mathrm{tilt}\) is the horizontal displacement of the beam spot at the tilt-sensing QPD plane, \(y_\mathrm{tilt}\) is the vertical displacement of the beam spot at the tilt-sensing QPD plane, \(x_\mathrm{len}\) is the horizontal displacement of the beam spot at the length-sensing QPD plane, \(y_\mathrm{len}\) is the vertical displacement of the beam spot at the length-sensing QPD plane,
\[\begin{split}\mathbf{C}_\mathrm{rotation} = \begin{bmatrix} \cos\phi_\mathrm{tilt} & \sin\phi_\mathrm{tilt} & 0 & 0\\ -\sin\phi_\mathrm{tilt} & \cos\phi_\mathrm{tilt} & 0 & 0\\ 0 & 0 & \cos\phi_\mathrm{len} & \sin\phi_\mathrm{len}\\ 0 & 0 & -\sin\phi_\mathrm{len} & \cos\phi_\mathrm{len} \end{bmatrix},\end{split}\]\[\begin{split}\mathbf{C}_\mathrm{align} = \begin{bmatrix} 2\sin\alpha_h & 0 & 2r_h\\ 2\sin\alpha_v & 2r_v & 0\\ 2\sin\alpha_h\left(1-\frac{d_h}{f_h}\right) & 0 & 2\left[\left(1-\frac{d_h}{f_h}\right)r_{\mathrm{lens},h} + d_h\right]\\ 2\sin\alpha_v\left(1-\frac{d_v}{f_v}\right) & 2\left[\left(1-\frac{d_v}{f_v}\right)r_{\mathrm{lens},v} + d_v\right] & 0\\ \end{bmatrix}^{+},\end{split}\]\[\begin{split}\mathbf{C}_\mathrm{miscenter} = \begin{bmatrix} 1 & \delta_y & \delta_x\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}^{-1},\end{split}\]\(\phi_\mathrm{tilt}\) is the angle between the tilt-sensing QPD and the yaw-pitch frame, \(\phi_\mathrm{len}\) is the angle between the length-sensing QPD and the yaw-pitch frame, \(r_h\) is the lever arm on the horzontal plane, \(r_v\) is the lever arm on the vertical plane, \(\alpha_h\) is the angle of incidence on the horizontal plane, \(\alpha_v\) is the angle of incidence on the vertical plane, \(r_{\mathrm{lens}, h}\) is the lever arm between the optics and the lens on the horizontal plane, \(r_{\mathrm{lens}, v}\) is the lever arm between the optics and the lens on the vertical plane, \(d_h\) is the distance between the lens and the length-sensing QPD on the horizontal plane, \(d_v\) is the distance between lens and the length-sensing QPD on the vertical plane, and \(f\) is the focal length of the convex lens.
References
[1] Tsang Terrence Tak Lun, Sensing Matrices for Optical Levers of the KAGRA Main Optics, https://github.com/terrencetec/kagra-optical-lever. -
alpha_h
¶ Angle of incidence on the horizontal plane.
-
alpha_v
¶ Angle of incidence on the vertical plane.
-
d_h
¶ Horizontal distance from the lens to the length-sensing QPD.
-
d_v
¶ Vertical distance from the lens to the length-sensing QPD.
-
delta_x
¶ Horizontal miscentering of the beam spot at the optics plane.
-
delta_y
¶ Horizontal miscentering of the beam spot at the optics plane.
-
f_h
¶ Focal length of the convex lens projected on the horizontal plane.
-
f_v
¶ Focal length of the convex lens projected on the vertical plane.
-
format
¶ Format of the sensing matrix.
- Choose from
- “OPLEV2EUL”: Default sensing matrix from KAGRA MEDM screen
- with input (TILT_PIT, TILT_YAW, LEN_PIT, LEN_YAW), and output (longitudinal, pitch and yaw).
“xy”: Matrix as shown in [1]_.
References
[1] Tsang Terrence Tak Lun, Sensing Matrices for Optical Levers of the KAGRA Main Optics, https://github.com/terrencetec/kagra-optical-lever.
-
phi_len
¶ Angle from the length-sensing QPD frame to the yaw-pitch frame.
-
phi_tilt
¶ Angle from the tilt-sensing QPD frame to the yaw-pitch frame.
-
r_h
¶ Lever arm from optics to tilt-sensing QPD on the horizontal plane.
-
r_lens_h
¶ Lever arm from optics to the lens on the horizontal plane.
-
r_lens_v
¶ Lever arm from optics to the lens on the vertical plane.
-
r_v
¶ Lever arm from optics to tilt-sensing QPD on the vertical plane.
-
update_matrices_decorator
()¶ Update matrices and self upon setting new parameters.
Horizontal Optical Lever Sensing Matrices¶
Sensing matrices for horizontal optical levers (Type-A, Type-Bp) in KAGRA.
-
class
kontrol.
HorizontalOpticalLeverSensingMatrix
(*args, **kwargs)¶ Bases:
kontrol.sensact.optical_lever.OpticalLeverSensingMatrix
Horizontal optical lever sensing matrix.
Parameters: - r (float) – Lever arm.
- alpha_h (float) – Angle of incidence on the horizontal plane.
- r_lens (float, optional) – Lever arm from the optics to the convex lens. Default 0.
- f (float, optional) – Focal length of the convex lens. Default np.inf.
- alpha_v (float, optional) – Angle of incidence on the vertical plane. Default 0.
- phi_tilt (float, optional) – Angle from the tilt-sensing QPD frame to the yaw-pitch frame. Default 0.
- phi_len (float, optional) – Angle from the length-sensing QPD frame to the yaw-pitch frame. Default 0.
- delta_x (float, optional) – Horizontal miscentering of the beam spot at the optics plane. Default 0.
- delta_y (float, optional) – Vertical miscentering of the beam spot at the optics plane. Default 0.
- delta_d (float, optional) – Misplacement of the length-sensing QPD. Default 0.
- format (str, optional) –
Format of the sensing matrix. Choose from
- ”OPLEV2EUL”: Default sensing matrix from KAGRA MEDM screen
- with input (TILT_PIT, TILT_YAW, LEN_PIT, LEN_YAW), and output (longitudinal, pitch and yaw).
”xy”: Matrix as shown in [1]_.
- coupling_matrix (array, optional) – The coupling matrix. Default None.
- *args – Variable length arguments passed to OpticalLeverSensingMatrix.
- **kwargs – Keyword arguments passed to OpticalLeverSensingMatrix.
-
delta_d
¶ Misplacement of the length-sensing QPD.
-
f
¶ Focal length of the convex lens.
-
r
¶ Lever arm.
-
r_lens
¶ Lever arm from the optics to the convex lens.
Vertical Optical Lever Sensing Matrices¶
Sensing matrices for vertical optical levers (Type-B) in KAGRA.
-
class
kontrol.
VerticalOpticalLeverSensingMatrix
(*args, **kwargs)¶ Bases:
kontrol.sensact.optical_lever.OpticalLeverSensingMatrix
Vertical optical lever sensing matrix.
Parameters: - r (float) – Lever arm.
- alpha_v (float) – Angle of incidence on the vertical plane.
- r_lens (float, optional) – Lever arm from the optics to the convex lens. Default 0.
- f (float, optional) – Focal length of the convex lens. Default np.inf.
- alpha_h (float, optional) – Angle of incidence on the horizontal plane. Default 0.
- phi_tilt (float, optional) – Angle from the tilt-sensing QPD frame to the yaw-pitch frame. Default 0.
- phi_len (float, optional) – Angle from the length-sensing QPD frame to the yaw-pitch frame. Default 0.
- delta_x (float, optional) – Horizontal miscentering of the beam spot at the optics plane. Default 0.
- delta_y (float, optional) – Vertical miscentering of the beam spot at the optics plane. Default 0.
- delta_d (float, optional) – Misplacement of the length-sensing QPD. Default 0.
- format (str, optional) –
Format of the sensing matrix. Choose from
- ”OPLEV2EUL”: Default sensing matrix from KAGRA MEDM screen
- with input (TILT_PIT, TILT_YAW, LEN_PIT, LEN_YAW), and output (longitudinal, pitch and yaw).
”xy”: Matrix as shown in [1]_.
- coupling_matrix (array, optional) – The coupling matrix. Default None.
- *args – Variable length arguments passed to OpticalLeverSensingMatrix.
- **kwargs – Keyword arguments passed to OpticalLeverSensingMatrix.
-
delta_d
¶ Misplacement of the length-sensing QPD.
-
f
¶ Focal length of the convex lens.
-
r
¶ Lever arm.
-
r_lens
¶ Lever arm from the optics to the convex lens.
Sensor Calibration Functions¶
Functions for calibrating sensor readouts.
Calibration library for calibrating sensors from sensors measurements
-
kontrol.sensact.calibration.
calibrate
(xdata, ydata, method='linear', **kwargs)¶ Fit the measurement data and returns the slope of the fit.
Parameters: - xdata (array) – The independent variable, e.g. the displacement of the sensor.
- ydata (array) – The dependent variable, e.g. the sensor readout.
- method (str, optional) –
- The method of the fit.
- Choose from [“linear”, “erf”].
- ”linear”: use
kontrol.sensact.calibration.calibrate_linear()
- ”erf”: use
kontrol.sensact.calibration.calibrate_erf()
- **kwargs – Keyword arguments passed to the calibration methods.
Returns: - slope (float) – The slope of the fitted straight line.
- intercept (float) – The y-intercept of the fitted straight line.
- linear_range (float, optional) – The range of y where the sensor considered linear.
-
kontrol.sensact.calibration.
calibrate_erf
(xdata, ydata, nonlinearity=5, return_linear_range=False, return_model=False)¶ Fit an error function and return the 1st-order slope and intercept.
Parameters: - xdata (array) – The independent variable, e.g. the displacement of the sensor.
- ydata (array) – The dependent variable, e.g. the sensor readout.
- nonlinearity (float, optional) – The specification of non-linearity (%). Defined by the maximum deviation of the full_range. Default 5.
- return_linear_range (boolean, optional) – If True, return the linear range of ydata.
- return_model (boolean, optional) – Return a kontrol.curvefit.model.Model object with the fitted parameters.
Returns: - slope (float) – The slope of the fitted straight line.
- intercept (float) – The \(y\)-intercept of the fitted straight line.
- linear_range (float, optional) – The range of x where the sensor considered linear.
Notes
Credits to Kouseki Miyo, the inventor of this method.
We fit the following function
\[f(x; a, m, x_0, y_0) = a\,\mathrm{erf}(m(x-x_0)) + y_0\,\,\]where \(a, m, x_0, y_0\) are some parameters to be found. The \(\mathrm{erf}(x)\) function is defined as
\[\mathrm{erf}(x) = \frac{2}{\sqrt{\pi}}\int_0^x\,e^{-x^2}\,dx\,.\]If we taylor expand the exponential function and take the first-order approximation of the \(\mathrm{erf}(x)\) function, we get
\[\mathrm{erf}(x) \approx \frac{2am}{\sqrt{\pi}}(x-x_0) + y_0\,.\]So the (inverse) calibration factor is \(\frac{2am}{\sqrt{\pi}}\), and the \(y\)-intercept is \(\frac{2am}{\sqrt{\pi}}x_0 + y_0\).
-
kontrol.sensact.calibration.
calibrate_linear
(xdata, ydata, nonlinearity=5, full_range=None, start_index=None, return_linear_range=False, return_model=False)¶ Fit a straight line to the data and returns the slope and intercept
This functions recursively fits a straight line to chosen data points and terminates when no linear data point remains. It starts from 3 points closest to the middle of the full-range. After fitting a straight line to the 3 points, other data points that are within the linearity specification will be included to the dataset and this dataset will be use for the next fit. The process repeats until no data points can be added anymore.
Parameters: - xdata (array) – The independent variable, e.g. the displacement of the sensor.
- ydata (array) – The dependent variable, e.g. the sensor readout.
- nonlinearity (float, optional) – The specification of non-linearity (%). Defined by the maximum deviation of the full_range. Default 5.
- full_range (float, optional) – The full output range of the sensor.
If not specified, it will be chosen to be
max(ydata) - min(ydata)
- start_index (int, optional) – The index of the data point to start with.
If not specified, it will be chosen to be index of the
ydata
closest to(max(ydata) + min(ydata))/2
. - return_linear_range (boolean, optional) – If True, return the linear range of ydata.
- return_model (boolean, optional) – Return a kontrol.curvefit.model.Model object with the fitted parameters.
Returns: - slope (float) – The slope of the fitted straight line.
- intercept (float) – The y-intercept of the fitted straight line.
- linear_range (float, optional) – The range of x where the sensor considered linear.
- model (kontrol.curvefit.model.Model) – The fitted model.
Spectral Analysis Functions¶
Spectral analysis related functions library.
Spectral analysis related function library.
-
kontrol.core.spectral.
asd2rms
(asd, f=None, df=1.0, return_series=True)¶ Calculate root-mean-squared value from amplitude spectral density
Parameters: - asd (array) – The amplitude spectral density
- f (array, optional) – The frequency axis.
Defaults
None
. - df (float, optional) – The frequency spacing. Defaults 1.
- return_series (bool, optional) – Returns the RMS as a frequency series, where each value is the integrated RMS from highest frequency. If False, returns a single RMS value for the whole spectrum. Defaults True.
Returns: - array – The integrated RMS series, if
return_series==True
. - float – The integrated RMS value, if
return_series==False
.
Notes
The integrated RMS series is defined as
\[x_\mathrm{RMS}(f) = \int_\infty^{f}\,x(f')^2\,df'\,,\]where \(x(f)\) is the amplitude spectral density.
When
return_series
is False, only \(x_\mathrm{RMS}(0)\) is returned.
-
kontrol.core.spectral.
asd2ts
(asd, f=None, fs=None, t=None, window=None, zero_mean=True)¶ Simulate time series from amplitude spectral density
Parameters: - asd (array) – The amplitude spectral density.
- f (array, optional) – The frequency axis of the amplitude spectral density.
This is used to calculate the sampling frequency.
If
fs
is not specified,f
must be specified. DefaultsNone
. - fs (float, optional) – The sampling frequency in Hz.
If
f
is specified, the last element off
will be treated as the Nyquist frequency so the double of it would be the sampling frequency. DefaultsNone
. - t (array, optional) – The desired time axis for the time series.
If
t
is specified, then the time series will be interpolated usingnumpy.interp()
assuming that the time series is periodic. DefaultNone
. - window (array, optional) – The FFT window used to compute the amplitude spectral density.
Defaults
None
. - zero_mean (boolean, optional) – Returns a time series with zero mean.
Defaults
True
.
Returns: - t (array) – Time axis.
- time_series (array) – The time series
Notes
Using a custom time axis is not recommended as interpolation leads to distortion of the signal. To extend the signal in time, it’s recommended to repeat the original time series instead.
-
kontrol.core.spectral.
pad_above_maxima
(series, pad_index=-1, **kwargs)¶ Pad series above local maxima
Parameters: - series (array) – The series to be padded.
- pad_index (int, optional) – The index of the local maxima. Defaults to -1.
- **kwargs – Keyword arguments passed to scipy.signal.argrelmin()
Returns: series_padded – The padded series
Return type: array
-
kontrol.core.spectral.
pad_above_minima
(series, pad_index=-1, **kwargs)¶ Pad series above local minima
Parameters: - series (array) – The series to be padded.
- pad_index (int, optional) – The index of the local minima. Defaults to -1.
- **kwargs – Keyword arguments passed to scipy.signal.argrelmin()
Returns: series_padded – The padded series
Return type: array
-
kontrol.core.spectral.
pad_below_maxima
(series, pad_index=0, **kwargs)¶ Pad series below local maxima
Parameters: - series (array) – The series to be padded.
- pad_index (int, optional) – The index of the local maxima. Defaults to 0.
- **kwargs – Keyword arguments passed to scipy.signal.argrelmin()
Returns: series_padded – The padded series
Return type: array
-
kontrol.core.spectral.
pad_below_minima
(series, pad_index=0, **kwargs)¶ Pad series below local minima
Parameters: - series (array) – The series to be padded.
- pad_index (int, optional) – The index of the local minima. Defaults to 0.
- **kwargs – Keyword arguments passed to scipy.signal.argrelmin()
Returns: series_padded – The padded series
Return type: array
-
kontrol.core.spectral.
three_channel_correlation
(psd1, psd2=None, psd3=None, csd12=None, csd13=None, csd21=None, csd23=None, csd31=None, csd32=None, returnall=True)¶ Noise estimation from three sensors’ readouts.
Parameters: - psd1 (array) – The power spectral density of the readout of the first sensor.
- psd2 (array, optional) – The power spectral density of the readout of the second sensor.
Defaults
None
. - psd3 (array, optional) – The power spectral density of the readout of the third sensor.
Defaults
None
. - csd12 (array, optional) – Cross power spectral density between readout 1 and 2.
If not specified, this will be estimated as
psd1*psd2/csd21
. DefaultNone
. - csd13 (array, optional) – Cross power spectral density between readout 1 and 3.
If not specified, this will be estimated as
psd1*psd3/csd31
. DefaultNone
. - csd21 (array, optional) – Cross power spectral density between readout 2 and 1.
If not specified, this will be estimated as
psd2*psd1/csd12
. DefaultNone
. - csd23 (array, optional) – Cross power spectral density between readout 2 and 3.
If not specified, this will be estimated as
psd2*psd3/csd32
. DefaultNone
. - csd31 (array, optional) – Cross power spectral density between readout 3 and 1.
If not specified, this will be estimated as
psd1*psd3/csd13
. DefaultNone
. - csd32 (array, optional) – Cross power spectral density between readout 3 and 1.
If not specified, this will be estimated as
psd3*psd2/csd23
. DefaultNone
. - returnall (boolean, optional) – If
True
, return all three noise estimations. IfFalse
, return noise estimation of first sensor only. Defaults True.
Returns: - noise1 (array) – Power spectral density of the estimated noise in psd1.
- noise2 (array, optional) – Power spectral density of the estimated noise in psd2.
Returns only if
returnall==True
- noise3 (array, optional) – Power spectral density of the estimated noise in psd3.
Returns only if
returnall==True
Notes
The PSD of the noise in psd1 is then computed as
\[P_{n_1n_1}(f) = \left\lvert P_{x_1x_1}(f) - \frac{P_{x_1x_3}(f)}{P_{x_2x_3}(f)}P_{x_2x_1}\right\vert\,,\]If
returnall
isTrue
, at leastpsd1
,psd2
,psd3
, (csd13
orcsd31
), (csd23
orcsd32
), and (csd12
andcsd21
) must be provided.References
[2] R. Sleeman, A. Wettum, and J. Trampert. Three-channel correlation analysis: A new technique to measure instrumental noise of digitizers and seismic sensors. Bulletin of the Seismological Society of America, 96:258–271, 2006.
-
kontrol.core.spectral.
two_channel_correlation
(psd, coh)¶ Noise estimation from two identical sensors’ readouts.
Parameters: - psd (array) – The power spectral density of the readout of the sensor
- coh (array) – The coherence between readout of the sensor and another identical sensor.
Returns: noise – Power spectral density of the estimated noise.
Return type: array
Notes
The PSD of the noise is computed as
\[P_{nn}(f) = P_{x_1x_1}(f)\left(1-C_{x_1x_2}(f)^{\frac{1}{2}}\right)\,,\]where \(P_{x_1x_1}(f)\) is the power spectral density of the readout and \(C_{x_1x_2}(f)\) is the coherence between the two sensor readouts.
References
[1] Aaron Barzilai, Tom VanZandt, and Tom Kenny. Technique for measurement of the noise of a sensor in the presence of large background signals. Review of Scientific Instruments, 69:2767–2772, 07 1998.
Foton Utilities¶
KAGRA/LIGO Foton related utilities.
KAGRA/LIGO Foton related utilities.
-
kontrol.core.foton.
foton2tf
(foton_string)¶ Convert a Foton string to TransferFunction
Parameters: foton_string (str) – The Foton string, e.g. zpk([0], [1; 1], 1, “n”). Returns: tf – The transfer function. Return type: TransferFunction
-
kontrol.core.foton.
notch
(frequency, q, depth, significant_figures=6)¶ Returns the foton expression of a notch filter.
Parameters: - frequency (float) – The notch frequency (Hz).
- q (float) – The quality factor.
- depth (float) – The depth of the notch filter (magnitude).
- significant_figures (int, optional) – Number of significant figures to print out. Defaults to 6.
Returns: The foton representation of this notch filter.
Return type: str
-
kontrol.core.foton.
rpoly2tf
(foton_string)¶ Converts rpoly Foton strings to TransferFunction
Parameters: foton_string (str) – The rpoly Foton string. E.g. rpoly([1; 2; 3], [2; 3; 4], 5)
-
kontrol.core.foton.
tf2foton
(tf, expression='zpk', root_location='s', significant_figures=6, itol=1e-25, epsilon=1e-25)¶ Convert a single transfer function to foton expression.
Parameters: - tf (TransferFunction) – The transfer function object.
- expression (str, optional) – Format of the foton expression. Choose from [“zpk”, “rpoly”]. Defaults to “zpk”.
- root_location (str, optional) – Root location of the zeros and poles for expression==”zpk”. Choose from [“s”, “f”, “n”]. “s”: roots in s-plane, i.e. zpk([…], […], …, “s”). “f”: roots in frequency plane, i.e. zpk([…], [,,,], …, “f”). “n”: roots in frequency plane but negated and gains are normalized, i.e. real parts are positive zpk([…], […], …, “n”). Defaults to “s”.
- significant_figures (int, optional) – Number of significant figures to print out. Defaults to 6.
- itol (float, optional) – Treating complex roots as real roots if the ratio of the imaginary part and the real part is smaller than this tolerance Defaults to 1e-25.
- epsilon (float, optional) – Small number to add to denominator to prevent division error. Defaults to 1e-25.
Returns: foton_expression – The foton expression in selected format.
Return type: str
-
kontrol.core.foton.
tf2rpoly
(tf, significant_figures=6)¶ Convert a transfer function to foton rpoly expression.
Parameters: - tf (TransferFunction) – The transfer function object
- significant_figures (int, optional) – Number of significant figures to print out. Defaults to 6.
Returns: Foton express in foton rpoly expression.
Return type: str
Notes
Only works for transfer functions with less than 20 orders.
-
kontrol.core.foton.
tf2zpk
(tf, root_location='s', significant_figures=6, itol=1e-25, epsilon=1e-25)¶ Convert a single transfer function to foton zpk expression.
Parameters: - tf (TransferFunction) – The transfer function object.
- root_location (str, optional) – Root location of the zeros and poles. Choose from [“s”, “f”, “n”]. “s”: roots in s-plane, i.e. zpk([…], […], …, “s”). “f”: roots in frequency plane, i.e. zpk([…], [,,,], …, “f”). “n”: roots in frequency plane but negated and gains are normalized, i.e. real parts are positive zpk([…], […], …, “n”). Defaults to “s”.
- significant_figures (int, optional) – Number of significant figures to print out. Defaults to 6.
- itol (float, optional) – Treating complex roots as real roots if the ratio of the imaginary part and the real part is smaller than this tolerance Defaults to 1e-25.
- epsilon (float, optional) – Small number to add to denominator to prevent division error. Defaults to 1e-25.
Returns: The foton zpk expression in selected format.
Return type: str
Notes
Only works for transfer functions with less than 20 orders.
-
kontrol.core.foton.
zpk2tf
(foton_string)¶ Convert a Foton ZPK string to TransferFunction
- foton_string : str
- The Foton ZPK string, e.g. zpk([0], [1; 1], 1, “n”).
Returns: tf – The transfer function. Return type: TransferFunction
Curve Fitting¶
Curve fitting
Curve fitting class¶
Base class for general curve fitting.
-
class
kontrol.curvefit.
CurveFit
(xdata=None, ydata=None, model=None, model_kwargs=None, cost=None, optimizer=None, optimizer_kwargs=None)¶ Bases:
object
Base class for curve fitting
Parameters: - xdata (array, ydata: array) -> float) – The independent variable data / data on the x axis. Defaults to None.
- ydata (array or None, optional) – The dependent variable data / data on the y axis. Defaults to None.
- model (func(x: array, args: array, **kwargs) -> array, or None, optional) – The model used to fit the data.
args
in model is an array of parameters that define the model. Defaults to None - model_kwargs (dict or None, optional) – Keyword arguments passed to the model. Defaults to None.
- cost (kontrol.curvefit.Cost or func(args, model, xdata, ydata) -> array) – Cost function.
- xdata – The cost function to be used to fit the data. First argument is a list of parameters that will be passed to the model. This must be pickleable if multiprocessing is to be used. Defaults to None.
- optimizer (func(func, **kwargs) -> OptimizeResult, or None, optional) – The optimization algorithm use for minimizing the cost function.
- optimizer_kwargs (dict or None, optional) – Keyword arguments passed to the optimizer function. Defaults to None.
-
cost
¶ The cost function to be used to fit the data.
-
fit
(model_kwargs=None, cost_kwargs=None, optimizer_kwargs=None)¶ Fit the data
Sets self.optimized_args and self.optimize_result.
Parameters: - model_kwargs (dict or None, optional) – Overriding keyword arguments in self.model_kwargs. Defaults to None.
- cost_kwargs (dict or None, optional) – Overriding keyword arguments in self.cost_kwargs. Defaults to None.
- optimizer_kwargs (dict or None, optional) – Overriding keyword argumetns in self.optimizer_kwargs. Defaults to None.
Returns: Return type: scipy.optimizer.OptimizeResult
-
model
¶ The model used to fit the data.
-
model_kwargs
¶ Keyword arguments passed to the model.
-
optimize_result
¶ Optimization Result
-
optimized_args
¶ The optimized arguments
-
optimizer
¶ The optimizer function to be used to fit the data.
-
optimizer_kwargs
¶ Keyword arguments passed to the optimizer function.
-
prefit
()¶ Something to do before fitting.
-
xdata
¶ The independent variable data.
-
ydata
¶ The dependent variable data
-
yfit
¶ The fitted y values
Transfer function fitting class¶
Curve fitting class for transfer function fitting.
-
class
kontrol.curvefit.
TransferFunctionFit
(xdata=None, ydata=None, model=None, model_kwargs=None, cost=None, weight=None, error_func_kwargs=None, optimizer=None, optimizer_kwargs=None, options=None, x0=None)¶ Bases:
kontrol.curvefit.curvefit.CurveFit
Transfer function fitting class
This class is basically a
CurveFit
class with default cost functions and optimizer that is designed for fitting a transfer function. By default, the error function iskontrol.curvefit.error_func.tf_error()
. The default optimizer isscipy.optimize.minimize( ...,method="Nelder-Mead",...)
, withoptions = {"adaptive": True, "maxiter": N*1000}
, whereN
is the number of variables. All of these can be overridden if specified.Parameters: - xdata (
array
orNone
, optional) – Independent variable data. Defaults toNone
. - ydata (
array
orNone
, optional) – Transfer function frequency response in complex numbers. Defaults toNone
. - model (
func(x: ``array
, args:array
, **kwargs)`` ->array
, orNone
, optional) – The model used to fit the data.args
in model is anarray
of parameters that define the model. Defaults toNone
- model_kwargs (
dict
orNone
, optional) – Keyword arguments passed to the model. Defaults toNone
. - cost (
kontrol.curvefit.Cost
orfunc(args, model, xdata, ydata)
->array
, optional) – Cost function. The cost function to be used to fit the data. First argument is a list of parameters that will be passed to the model. This must be pickleable if multiprocessing is to be used. Defaults toNone
. - weight (
array
orNone
, optional) – Weighting function. DefaultsNone
. - error_func_kwargs (
dict
orNone
, optional) – Keyword arguments the will be passed toerror_func
, which is passed to the construct the cost function. Defaults toNone
. - optimizer (
func(func, **kwargs)
->OptimizeResult
, orNone
, optional) – The optimization algorithm use for minimizing the cost function. - optimizer_kwargs (
dict
orNone
, optional) – Keyword arguments passed to the optimizer function. Defaults toNone
. - options (
dict
orNone
, optional) – The option arguments passed to theoptimizer
- x0 (
array
, optional) – Inital guess. Defaults to None.
-
options
¶ Option arguments passed to optimizer
-
weight
¶ Weighting function
-
x0
¶ Initial guess
- xdata (
Models for Curve Fitting¶
These classes are designed to use with kontrol.curvefit
-
class
kontrol.curvefit.model.
Model
(args=None, nargs=None, log_args=False)¶ Bases:
object
Model base class for curve fitting
-
args
¶ Model parameters
-
nargs
¶ Number of model parameters
-
-
class
kontrol.curvefit.model.
TransferFunctionModel
(nzero, npole, args=None, log_args=False)¶ Bases:
kontrol.curvefit.model.model.Model
Transfer function model class defined by numerator and denominator
Parameters: - nzero (int) – Number of zeros.
- npole (int) – Number of poles.
- args (array or None, optional.) – The model parameters. Structured as follows: [b_n, b_n-1,…, b_1, b_0, a_m, a_m-1,…, a_1, a_0], where b and a are the coefficients of the numerator and denominator respectively, ordered from higher-order to lower-order. Defaults to None.
-
tf
¶ The last evaluted transfer function.
Type: kontrol.TransferFunction
Notes
The transfer function model is defined as
\[G(s, b_n, b_{n-1},..., b_1, b_0, a_m, a_{m-1},..., a_1, a_0) = \frac{\sum_{i=0}^{n} b_i s^i}{\sum_{j=0}^{m} a_j s^j}\]-
den
¶ Denominator array
-
npole
¶ Number of zeros
-
num
¶ Numerator array
-
nzero
¶ Number of zeros
-
tf
The Transfer Function object.
-
class
kontrol.curvefit.model.
DampedOscillator
(args=None)¶ Bases:
kontrol.curvefit.model.transfer_function_model.TransferFunctionModel
Transfer function model for a damped oscillator.
Parameters: args (array or None, optional.) – The model parameters with three numbers. Structured as follows: args = [k, fn, q]
, wherek
is the DC gain of the transfer function,fn
is the resonance frequency in Hz, andq
is the Q-factor. Defaults to None.Notes
The model is definded as
\[G(s; k, \omega_n, q) = k\frac{\omega_n^2}{s^2 + \frac{\omega_n}{q}s + \omega_n^2}\]where \(k\) is the DC gain of the transfer function, \(\omega_n\) is the resonance frequency of the oscillator, and \(q\) is the Q-factor if the damped oscillator.
-
args
¶ Model parameters
-
damped_oscillator_args
¶ The model parameters with three numbers [k, fn, q]
-
fn
¶ Resonance frequency
-
gain
¶ DC gain
-
q
¶ Q factor
-
-
class
kontrol.curvefit.model.
SimpleZPK
(nzero, npole, args=None, log_args=False)¶ Bases:
kontrol.curvefit.model.model.Model
ZPK model with simple poles and zeros.
Parameters: - nzero (int) – Number of simple zeros.
- npole (int) – Number of simple poles.
- args (array, optional) – The model parameters defined as
args = [z1, z2,..., p1, p2,..., k]
wherez
are the locations of the zeros in Hz,p
are the locations of the pole in Hz, andk
is the static gain, - log_args (boolean, optional) – If true, model parameters passed to the model are assumed to be passed through a log10() function. So, when the real parameters will be assumed to be 10**args instead. Defaults to False.
-
zero
¶ List of zeros.
Type: array
-
pole
¶ List of poles.
Type: array
-
gain
¶ Static gain.
Type: float
-
tf
¶ The transfer function representation of this ZPK model
Type: kontrol.TranserFunction
Notes
The simple ZPK model is defined as
\[G(s; z_1, z_2,..., p_1, p_2, ..., k) = k\frac{\prod_i(\frac{s}{2\pi z_i}+1)}{\prod_j(\frac{s}{2\pi p_j}+1)}\]-
args
¶ Model parameters in ZPK [z1, z2,…, p1, p2,…, k] format
-
gain
Static gain
-
npole
¶ Number of complex pole pairs
-
nzero
¶ Number of simple zeros
-
pole
List of poles
-
tf
Returns a TransferFunction object of this ZPK model
-
zero
List of zeros
-
class
kontrol.curvefit.model.
ComplexZPK
(nzero_pairs, npole_pairs, args=None, log_args=False)¶ Bases:
kontrol.curvefit.model.model.Model
ZPK model with complex poles and zeros.
Parameters: - nzero_pairs (int) – Number of complex zero pairs.
- npole_pairs (int) – Number of complex pole pairs.
- args (array, optional) – The model parameters defined as
args = [f1, q1, f2, q2,..., fi, qi,..., fn, qn, k]
, wheref
are resonance frequencies of the complex zero/pole pairs,q
are the quality factors, andk
is the static gain,i
is the number of complex zero pairs, andn-i
is the number of of complex pole pairs. - log_args (boolean, optional) – If true, model parameters passed to the model are assumed to be passed through a log10() function. So, when the real parameters will be assumed to be 10**args instead. Defaults to False.
-
fn_zero
¶ List of resonance frequencies of the complex zeros.
Type: array
-
fn_pole
¶ List of resonance frequencies of the complex poles.
Type: array
-
q_zero
¶ List of Q-factors of the complex zeros.
Type: array
-
q_pole
¶ List of Q-factors of the complex poles.
Type: array
Notes
The complex ZPK model is defined by:
\[G(s; f_i, q_i,k) =k\frac{\prod_i(\frac{s^2}{(2\pi f_i)^2} + \frac{1}{2\pi f_i q_i}s + 1)} {\prod_j(\frac{s^2}{(2\pi f_j)^2} + \frac{1}{2\pi f_j q_j}s + 1)}\]-
args
¶ Model parameters in ZPK [f1, q1, f2, q2,…, fn, qn, k] format
-
fn_pole
List of resonance frequencies of complex poles.
-
fn_zero
List of resonance frequencies of complex zeros.
-
gain
¶ Static gain.
-
npole_pairs
¶ Number of complex pole pairs
-
nzero_pairs
¶ Number of complex zero pairs
-
q_pole
List of quality factors of the complex poles
-
q_zero
List of quality factors of the complex zeros
-
tf
¶ Returns a TransferFunction object of this ZPK model
-
class
kontrol.curvefit.model.
StraightLine
(args=None)¶ Bases:
kontrol.curvefit.model.model.Model
Simply a straight line.
Parameters: args (array, optional) – The model parameters structued as: [slope, y-intercept]. Defaults to None. -
slope
¶ The slope of the line.
Type: float
-
intercept
¶ The y-intercept of the line.
Type: float
Notes
The straight line is defined as
\[y(x; m, c) = mx + c\,,\]where \(m\) is the slope and \(c\) is the y-intercept.
-
intercept
The y-intercept of the line
-
slope
The slope of the line
-
-
class
kontrol.curvefit.model.
Erf
(args=None)¶ Bases:
kontrol.curvefit.model.model.Model
The error function erf(x)
Parameters: args (array, optional) – The model parameters structured as [amplitude, slope, x0, y0]. Defaults to None. Notes
The function is defined as
\[f(x; a, m, x_0, y_0) = a\,\mathrm{erf}(m(x-x_0)) + y_0\,,\]where \(\mathrm{erf}(x)\) is the error function [1]_, \(a\) is the peak to peak amplitude, \(m\) is the slope at the inflection point, \(x_0\) is the \(x\) offset , and \(y_0\) is the \(y\) offset.
References
[1] https://en.wikipedia.org/wiki/Error_function -
amplitude
¶ Peak to Peak amplitude of the error function.
-
slope
¶ Slope at the inflection point.
-
x_offset
¶ x offset
-
y_offset
¶ y offset
-
Control Regulator Design¶
Functions for algorithmic design of control regulators
Feedback Control¶
Algorithmic designs for feedback control regulators.
-
kontrol.regulator.feedback.
add_integral_control
(plant, regulator=None, integrator_ugf=None, integrator_time_constant=None, **kwargs)¶ Match and returns an integral gain.
This function finds an integral gain such that the UGF of the integral control matches that of the specified regulator. If
integrator_ugf
orintegrator_time_constant
is specified instead, these will be matched instead.Parameters: - plant (TransferFunction) – The transfer function representation of the system to be feedback controlled.
- regulator (TransferFunction, optional) – The pre-regulator
Use
kontrol.regulator.feedback.proportional_derivative()
orkontrol.regulator.feedback.critical_damping()
to make one for oscillator-like systems. - integrator_ugf (float, optional) – The unity gain frequency (Hz) of the integral control.
This is the inverse of the integration time constant.
If
integrator_time_constant is not None
, then this value will be ignored. If set to None, it’ll be set to match the first UGF of the derivative control. Defaults to None. - integrator_time_constant (float, optional,) – The integration time constant (s) for integral control.
Setting this will override the
integrator_ugf
argument. Defaults to None.
Returns: ki – The integral control gain.
Return type: float
-
kontrol.regulator.feedback.
add_proportional_control
(plant, regulator=None, dcgain=None, **kwargs)¶ Match and returns proportional gain.
This function finds a proportional gain such that the proportional control UGF matches the first UGF of the specified regulator (typically a derivative control regulator). If
dcgain
is specified, the DC gain is matched instead.Parameters: - plant (TransferFunction) – The transfer function representation of the system to be feedback controlled. The plant must contain at least one pair of complex poles.
- regulator (TransferFunction, optional) – The pre-regulator.
If not specified, then
dcgain
must be specified. Defaults to None. - dcgain (float, optional) – The desired DC gain of the open-loop transfer function. If not specified, the portional gain is tuned such that the portional control’s first UGF matches that of the derivative control. Defaults to None.
Returns: kp – The proportional control gain.
Return type: float
-
kontrol.regulator.feedback.
critical_damp_calculated
(plant, nmode=1, **kwargs)¶ Find dominant mode and returns the approximate critical regulator.
Parameters: - plant (TransferFunction) – The transfer function representation of the system to be feedback controlled. The plant must contain at least one pair of complex poles.
- nmode (int, optional) – The ``nmode``th dominant mode to be damped. This number must be less than the number of modes in the plant. Defaults 1.
Returns: kd – The derivative gain for critically damping the dominant mode.
Return type: float
Notes
The plant must contain at least one complex pole pair. The plant must have a non-zero DC gain.
The critical regulator is approximated by
\[K(s) \approx \frac{2}{\omega_n K_\mathrm{DC}}\,,\]where \(\omega_n\) is the resonance frequency of the dominant mode and \(K_\mathrm{DC}\) is the sum of DC gains of the mode and that of the other higher-frequency modes..
-
kontrol.regulator.feedback.
critical_damp_optimize
(plant, gain_step=1.1, ktol=1e-06, **kwargs)¶ Optimize derivative damping gain and returns the critical regulator
Parameters: - plant (TransferFunction) – The transfer function representation of the system to be feedback controlled. The plant must contain at least one pair of complex poles.
- gain_step (float, optional) – The multiplicative factor of the gain for finding the gain upper bound. It must be greater than 1. Defaults to 1.1.
- ktol (float, optional) – The tolerance for the convergence condition. The convergence condition is (kd_max-kd_min)/kd_min > ktol. It must be greater than 0. Defaults to 1e-6.
Returns: kd – The derivative gain for critically damping the dominant mode.
Return type: float
Notes
Update on 2021-12-04: Use carefully. It only critically damps the mode that has the highest peak when multiplied by an differentiator. Note for myself: only 2 complex poles can become simple poles for plants with second-order rolloff.
Only works with plants that contain at least one complex pole pair. Works best with plants that only contain complex zeros/poles. If it returns unreasonably high gain, try lowering
gain_step
.The algorithm goes as follows.
1. Find the minimum damping gain
k_min
such that the open-loop transfer functionk_min*s*plant
has maxmimum gain at unity gain frequency.- Iterate
i
:k_i=k_min*i*gain_step
for i=1,2,3…
3. Terminate when
1/(1+k_i*s*plant)
has less complex pole pairs than theplant
itself, i.e. one mode has been overdamped. Then, definek_max=k_i
.4. Iterate: Define
k_mid
as the logarithmic mean ofk_max
andk_min
. If1/(1+k_mid*s*plant)
has less complex pole pairs thanplant
, i.e. overdamps, then setk_max=k_mid
. Otherwise, setk_min=k_mid
.- Terminate when
(k_max - k_min)/k_min < ktol
, i.e. converges.
-
kontrol.regulator.feedback.
critical_damping
(plant, method='calculated', **kwargs)¶ Returns the critical damping derivative control gain.
This functions calls
kontrol.regulator.feedback.critical_damp_calculated()
orkontrol.regulator.feedback.cricical_damp_optimized()
and returns the derivative control gain.Parameters: - plant (TransferFunction) – The transfer function representation of the system to be feedback controlled. The plant must contain at least one pair of complex poles.
- method (str, optional) –
The method to be used for setting the gain. Choose from [“optimized”, “calculated”].
”optimized”: the gain is optimized until the dominant complex pole pairs become two simple poles.
”calculated”: the gain is set to \(2/\omega_n/K_{DC}\), where \(\omega_n\) is the resonance frequency in rad/s of the mode to be damped, and \(K_{DC}\) is the sum of DC gains of the mode and that of the other high-frequency modes.
Both method assumes that the plant has at least one pair of complex poles.
Defaults to “calculated”.
- **kwargs (dict) –
Method specific keyword arguments.
See:
- ”optimized”: kontrol.regulator.feedback.critical_damp_optimized
- ”calculated”: kontrol.regulator.feedback.critical_damp_calculated
Returns: kd – The derivative gain for critically damping the dominant mode.
Return type: float
-
kontrol.regulator.feedback.
mode_composition
(wn, q, k)¶ Create a plant composed of many modes.
Parameters: - wn (array) –
- (rad/s) (Frequencies) –
- q (array) – Q factors.
- k (array) – Dcgains of the modes.
Returns: The composed plant.
Return type:
-
kontrol.regulator.feedback.
mode_decomposition
(plant)¶ Returns a list of single mode transfer functions
Parameters: plant (TransferFunction) – The transfer function with at list one pair of complex poles. Returns: - wn (array) – Frequencies (rad/s).
- q (array) – Q factors.
- k (array) – Dcgains of the modes.
Regulator for Oscillatory Systems¶
Control regulators designs for oscillator-like systems
-
kontrol.regulator.oscillator.
pid
(plant, regulator_type='PID', dcgain=None, integrator_ugf=None, integrator_time_constant=None, return_gain=False, **kwargs)¶ PID-like controller design for oscillator-like systems
Parameters: - plant (TransferFunction) – The transfer function of the system that needs to be controlled.
- regulator_type (str, optional) – The type of the contorl regulator.
Choose from
{"PID", "PD", "PI", "I", "D"}
for proportional-integral-derivative, proportional-derivative, proportional-integral, or derivative (velocity) control respectively. Defaults to “PID”. - dcgain (float, optional) – The DC gain of the OLTF of the proportional control.
If set to None, it will be set automatically
depending on the type of the controller.
If
regulator_type=="PI"
, then dcgain will be set such that the proportional control UGF matches that of the integral control. Ifregulator_type=="PD" or "PID"
, then the dcgain will be set such that it matches the UGF of the derivative control. Defaults to None. - integrator_ugf (float, optional) – The unity gain frequency (Hz) of the integral control.
This is the inverse of the integration time constant.
If
integrator_time_constant is not None
, then this value will be ignored. If set to None, it’ll be set to match the UGF of the derivative control. Forregulator_type=="I"
, this must be specified. Defaults to None. - integrator_time_constant (float, optional,) – The integration time constant (s) for integral control.
Setting this will override the
integrator_ugf
argument. Defaults to None. - return_gain (boolean, optional) – Return the PID gain instead.
Returns: - regulator (TransferFunction, optional) – The regulator.
Return only if return_gain is
False
. - kp (float, optional) – Proportional gain. Return only if return_gain is ``True’’.
- ki (float, optional) – Integral gain.
Return only if return_gain is
True
. - kd (float, optional) – Derivative gain.
Return only if return_gain is
True
.
Post Filtering¶
Functions for designing post-regulator filters
-
kontrol.regulator.post_filter.
post_low_pass
(plant, regulator, post_filter=None, ignore_ugf_above=None, decades_after_ugf=1, phase_margin=45, f_start=None, f_step=1.1, low_pass=None, mtol=1e-06, small_number=1e-06, oscillatory=True, **kwargs)¶ Add low-pass filter after regulator.
This function lowers/increase the the cutoff frequency of a low-pass filter until the phase margin at a dedicated ugf crosses the specified phase margin. Then, runs a bisection algorithm to poolish the cutoff frequency until the phase margin converges relative to the specified tolerance.
Parameters: - plant (TransferFunction) – The transfer function of the system that needs to be controlled.
- regulator (TransferFunction) – The regulator.
- post_filter (TransferFunction, optional) – Any post filters that will be applied on top of the regulator. Defaults None.
- ignore_ugf_above (float, optional) – Ignore unity gain frequencies higher than
ignore_ugf_above
(Hz). If not specified, defaults to 1 decade higher than the last UGF. This value can be overrided by the argumentdecades_after_ugf
Note that there’s no guarantee that the UGF will be lower than this. The priority is to match the target phase margin. Defaults to None. - decades_after_ugf (float, optional) – Set ignore_ugf_above some decades higher than the UGF of the OLTF ignore_ugf_above is None. Defaults to 1.
- phase_margin (float, optional,) – The target phase margin (Degrees). Defaults to 45.
- f_start (float, optional,) – The cutoff frequency to start iterating with.
If not specified, defaults to some decades higher than the
highest UGF. “Some decade” is set by
decades_after_ugf
. Defaults None. - f_step (float, optional,) – The gain that is used to multiply (or divide) the cutoff frequency during a coarse search. Defaults 1.1
- low_pass (func(cutoff, order) -> TransferFunction, optional) – The low-pass filter.
If not specified,
kontrol.regulator.predefined.lowpass()
with order 2 will be used. Defaults to None. - mtol (float, optional) – Tolerance for convergence of phase margin. Defaults to 1e-6.
- small_number (float, optional) – A small number as a delta f to detect whether the gain is a rising or lowering edge at the unity gain frequency. Defaults to 1e-6.
- oscillatory (boolean, optional) – Use the first mode of the oscillatory system to evaluate the phase margins to avoid having UGFs at steep phase slopes. The benefit of using this is to have a conservative phase margin estimate. The phase response of the first mode is the lower bound of the phase response. If False, use the plant itself to calculate phase margins. If the plant does not contain any complex poles, this option will be overridden to False. Defaults True.
- **kwargs – Keyword arguments passed to
low_pass
.
Returns: The low-pass filter.
Return type:
-
kontrol.regulator.post_filter.
post_notch
(plant, regulator=None, post_filter=None, target_gain=None, notch_peaks_above=None, phase_margin=45, notch=None, **kwargs)¶ Returns a list of notch filters that suppress resonance peaks.
This functions finds the resonances peak of the plant/OLTF above certain frequencies and returns a list of notch filters that suppress these peaks to the target gains.
Parameters: - plant (TransferFunction) – The transfer function of the system that needs to be controlled.
- regulator (TransferFunction, optional) – The regulator. Defaults to None.
- post_filter (TransferFunction, optional) – Any post filters that will be applied on top of the regulator. Defaults None.
- target_gain (float, optional) – The target open-loop gain for the suppressed peak. To ensure a stable system, a value of less than 1 is recommended. If not specified, the notch will fully suppress the peak. Default None.
- phase_margin (float, optional) – The target phase margin. Defaults to 45.
- notch_peaks_above (float, optional) – Notch modes that has freqeuncies above
notch_peaks_above
. If not specified, defaults to the highest unity gain frequency that is abovephase_margin
Defaults to None. - notch (func(frequency, q, depth) -> TransferFunction, optional) – The notch filter.
If not specified,
kontrol.Notch()
will be used. Defaults to None. - **kwargs – Keyword arguments passed to notch().
Returns: A list of notch filters.
Return type: list of TransferFunction
Notes
This operation does not guarantee stability. It only finds resonances peaking out of the unity gain above some unity gain frequency and make notch filters to suppress them to a target gain level lower than the unity gain. The stability of the notched OLTF is not checked whatsoever.
Predefined Filters¶
Predefined regulator library.
-
kontrol.regulator.predefined.
low_pass
(cutoff, order=1, **kwargs)¶ Simple low-pass filter
Parameters: - cutoff (float) – Cutoff frequency (Hz)
- order (int, optional) – The order of the filter. Defaults to be 1.
- **kwargs – Keyword arguments holder. Not passed to anywhere.
Returns: The low-pass filter.
Return type: Notes
The low-pass filter is defined as
\[L(s) = \left(\frac{2\pi f_c}{s+2\pi f_c}\right)^n\,,\]where \(f_c\) is the cutoff frequency (Hz), \(n\) is the order of the filter.
-
kontrol.regulator.predefined.
notch
(frequency, q, depth=None, depth_db=None, **kwargs)¶ Notch filter defined in Foton.
Parameters: - frequency (float) – The notch frequency (Hz).
- q (float) – The quality factor.
- depth (float, optional) – The depth of the notch filter (magnitude).
If not specified,
depth_db
will be used. Defaults None. - depth_db (float, optional) – The depth of the notch filter (decibel).
If not specified,
depth
will be used instead. Defaults None.
Returns: The notch filter
Return type: Notes
The notch filter is defined by Foton, as
\[N(s) = \frac{s^2 + (2\pi f_n)/(dQ/2)s + (2\pi f_n)^2} {s^2 + (2\pi f_n)/(Q/2)s + (2\pi f_n)^2}\,,\]where \(f_n\) is the notch frequency, \(q\) is the quality factor , and \(d\) is the depth.
-
kontrol.regulator.predefined.
pid
(kp=0, ki=0, kd=0)¶ Alias of proportional_integral_derivative()
-
kontrol.regulator.predefined.
proportional_integral_derivative
(kp=0, ki=0, kd=0)¶ PID control build on proportional_derivative().
Parameters: - kp (float, optional) – The proportional control gain. Defaults to 0.
- ki (float, optional) – The integral control gain. Defaults to 0.
- kd (float, optional) – Defaults to 0.
Returns: The PID controller.
Return type: Notes
The PID controller is defined as
\[K_\mathrm{PID}(s) = K_p + K_i/s + K_d s\,.\]
Dynamic Mode Decomposition¶
Dynamic mode decomposition algorithm
Dynamic mode decomposition main class¶
Dynamic mode decomposition class
-
class
kontrol.dmd.dmd.
DMD
(snapshot_1, snapshot_2=None, truncation_value=None, dt=1, run=False)¶ Bases:
object
Dynamic mode decomposition class
Parameters: - snapshot_1 (array) – The 2-D snapshot array.
- snapshot_2 (array, optional) – The 2-D snapshot array at next time step.
If not provided,
snapshot_1[:, :-1]
becomes snapshot_1 andsnapshot_2[:, 1:]
becomessnapshot_2
. Defaults None. - truncation_value (float, optional) – The truncation value (order/rank) of the system. Defaults None.
- dt (float, optional) – The time difference between two snapshots. Defaults 1.
- run (bool, optional) – Run dynamic mode decomposition upon construction. Computes DMD modes, Reduced-order model, etc. truncation_value must be specified for this to work. Defaults False.
-
snapshot_1
¶ The 2-D snapshot matrix
Type: array
-
snapshot_2
¶ The 2-D snapshot matrix at next time step.
Type: array
-
truncation_value
¶ The truncation value (order/rank) of the system.
Type: int
-
dt
¶ The time difference between two snapshots.
Type: float
-
u
¶ The left singular vector of the snapshot_1 matrix.
Type: array
-
vh
¶ The right singular vector (conjugate-transposed) of the snapshot_1 matrix.
Type: array
-
sigma
¶ The singular values of the snapshot_1 matrix
Type: array
-
u_truncated
¶ The truncated left singular vector of the snapshot_1 matrix.
Type: array
-
vh_truncated
¶ The truncated right singular vector (conjugate-transposed) of the snapshot_1 matrix.
Type: array
-
sigma_truncated
¶ The truncated singular values of the snapshot_1 matrix
Type: array
-
A_reduced
¶ The reduced-order model of the dynamics.
Type: array
-
w_reduced
¶ The eigenvalues of the reduced-order model.
Type: array
-
v_reduced
¶ The eigenvectors of the reduced-order model.
Type: array
-
dmd_modes
¶ The DMD modes.
Type: array
-
complex_frequencies
¶ The complex frequencies of the modes.
Type: array
-
v_constant
¶ The constant vector of the time dynamics, determined by initial conditions.
Type: array
-
time_dynamics
¶ The time dynamics of the ODE solution.
Type: array
-
prediction
¶ The predicted time series.
Type: array
-
A_reduced
Reduced-order model
-
complex_frequencies
Complex frequencies
-
compute_complex_frequencies
(dt=None)¶ Compute the complex frequencies
Parameters: dt (float, optional) – The time spacing between snapshots. Specified as self.dt or in constructor option. Defaults 1. Returns: complex_frequencies – Array of complex frequencies Return type: array
-
compute_dmd_modes
()¶ Compute the DMD modes
Returns: dmd_modes – The DMD modes. Return type: array
-
compute_reduced_model
()¶ Compute the reduced-order model
Returns: A_reduced – Matrix representing the reduced-order model. Return type: array
-
dt
Time difference between the snapshots
-
eig_reduced_model
()¶ Eigen decomposition of the reduced-order model
Returns: - w_reduced (array) – The list of eigenvalues.
- v_reduced (array) – Eigenvalues as columns.
-
low_rank_approximation
(truncation_value=None)¶ Truncate the svd.
- truncation_value : int, optional
- The truncation value (order/rank) of the system. Specify as self.truncation_value or via the constuctor option. Defaults None.
Returns: - u_truncated (array) – Truncated unitary matrix having left singular vectors as columns.
- sigma_truncated (array) – Truncated singular values.
- vh_truncated (array) – Truncated unitary matrix having right singular vectors as rows.
-
predict
(t, t_constant=None, i_constant=0)¶ Predict the future states given a time array
Parameters: - t (array) – The time array
- t_constant (float, optional) – Time at which the constant vector is calculated.
Defaults to be
t[0]
if not given. - i_constant (int, optional) – Index of the
snapshot_1
at which the constant vector is calculated. Defaults 0.
Returns: prediction – Predicted states.
Return type: array
Notes
The constant vector is the vector that evolves and is evaluated using the initial/boundary values. Set
t_constant
andi_constant
to where the prediction of the time series begins.
-
prediction
The ODE solution
-
run
()¶ Run the DMD algorithm, compute dmd modes and complex frequencies
-
sigma
Singular values
-
sigma_truncated
Singular values truncated
-
snapshot_1
Snapshot 1
-
snapshot_2
Snapshot 1
-
svd
()¶ Decompose the snapshot 1
Returns: - u (array) – Unitary matrix having left singular vectors as columns.
- sigma (array) – The singular values.
- vh (array) – Unitary matrix having right singular vectors as rows.
-
time_dynamics
Time dynamics of the ODE solution
-
truncation_value
Truncation value (order/rank) of the system
-
u
Left singular vectors
-
u_truncated
Left singular vectors (truncated)
-
v_constant
Constant vector of the ODE solution
-
vh
Right singular vectors
-
vh_truncated
Right singular vectors (truncated)
Dynamic mode decomposition utilities¶
Utility functions for Dymanic Mode Decomposition.
-
kontrol.dmd.utils.
auto_truncate
(sigma, threshold=0.99)¶ Automatically get truncation value
Parameters: - sigma (array) – Singular values. Arranged from large to small values.
- threshold (float, optional) – Only include singular values so their sum is
threshold
of the original sum. Defaults 0.99.
Returns: truncation_value – Amount of singular values that are required to reach the threshold sum.
Return type: int
-
kontrol.dmd.utils.
hankel
(array, order)¶ Hankelize an array
Parameters: - array (array) – Array with rows as channels and columns as samples
- order (int) – The number of rows of the hankelized matrix.
Returns: hankel_array – The hankelized array
Return type: array
Examples