Utilities Package

The utilities package provides essential control design utilities, mathematical tools, and data processing functions for process control applications.

Note

This is part of the modern modular structure of SPROCLIB.

Submodules

Control Utils

Control Utilities for SPROCLIB

This module provides utility functions specifically for control system design, tuning, and performance evaluation.

Author: Thorsten Gressling <gressling@paramus.ai> License: MIT License

sproclib.utilities.control_utils.tune_pid(model_params, method='ziegler_nichols', controller_type='PID')[source]

Automatic PID tuning using empirical rules.

Parameters:
  • model_params (Dict[str, float]) – Process model parameters

  • method (str) – Tuning method (‘ziegler_nichols’, ‘amigo’, ‘lambda_tuning’)

  • controller_type (str) – Controller type (‘P’, ‘PI’, ‘PID’)

Returns:

Dictionary with PID parameters

Return type:

Dict[str, float]

sproclib.utilities.control_utils.simulate_process(model, t_span, x0, u_profile, method='RK45', max_step=None)[source]

Simulate a process model with given input profile.

Parameters:
  • model (Callable) – Function f(t, x, u) returning dx/dt

  • t_span (Tuple[float, float]) – Time span (start, end)

  • x0 (<MagicMock id='130137676745760'>) – Initial conditions

  • u_profile (Callable[[float], <MagicMock id='130137678233088'>]) – Function u(t) returning inputs

  • method (str) – Integration method

  • max_step (float | None) – Maximum step size

Returns:

Dictionary with simulation results

Return type:

Dict[str, <MagicMock id=’130137678230736’>]

sproclib.utilities.control_utils.calculate_ise(t, error)[source]

Calculate Integral of Squared Error (ISE).

Parameters:
  • t (<MagicMock id='130137680248320'>) – Time array

  • error (<MagicMock id='130137678825856'>) – Error signal array

Returns:

ISE value

Return type:

float

sproclib.utilities.control_utils.calculate_iae(t, error)[source]

Calculate Integral of Absolute Error (IAE).

Parameters:
  • t (<MagicMock id='130137678826192'>) – Time array

  • error (<MagicMock id='130137676745088'>) – Error signal array

Returns:

IAE value

Return type:

float

sproclib.utilities.control_utils.calculate_itae(t, error)[source]

Calculate Integral of Time-weighted Absolute Error (ITAE).

Parameters:
  • t (<MagicMock id='130137676744752'>) – Time array

  • error (<MagicMock id='130137676744416'>) – Error signal array

Returns:

ITAE value

Return type:

float

sproclib.utilities.control_utils.design_lead_lag(zero, pole, gain=1.0)[source]

Design lead-lag compensator transfer function.

Parameters:
  • zero (float) – Zero location

  • pole (float) – Pole location

  • gain (float) – DC gain

Returns:

Tuple of (numerator, denominator) coefficients

Return type:

Tuple[<MagicMock id=’130137676744080’>, <MagicMock id=’130137676743744’>]

sproclib.utilities.control_utils.root_locus_design(plant_num, plant_den, desired_poles)[source]

Design controller using root locus method.

Parameters:
  • plant_num (<MagicMock id='130137676746768'>) – Plant numerator coefficients

  • plant_den (<MagicMock id='130137676747104'>) – Plant denominator coefficients

  • desired_poles (List[complex]) – Desired closed-loop pole locations

Returns:

Dictionary with controller design results

Return type:

Dict[str, Any]

sproclib.utilities.control_utils.frequency_domain_design(plant_num, plant_den, gain_margin_db=6.0, phase_margin_deg=45.0)[source]

Design controller using frequency domain specifications.

Parameters:
  • plant_num (<MagicMock id='130137676747440'>) – Plant numerator coefficients

  • plant_den (<MagicMock id='130137676747776'>) – Plant denominator coefficients

  • gain_margin_db (float) – Desired gain margin [dB]

  • phase_margin_deg (float) – Desired phase margin [degrees]

Returns:

Dictionary with controller design results

Return type:

Dict[str, Any]

sproclib.utilities.control_utils.step_response_test(data, step_time=None)[source]

Analyze step response test data.

Parameters:
  • data (Dict[str, <MagicMock id='130137676748112'>]) – Dictionary with ‘t’ and ‘y’ arrays

  • step_time (float | None) – Time when step was applied

Returns:

Dictionary with step response characteristics

Return type:

Dict[str, float]

sproclib.utilities.control_utils.linearize(model_func, x_ss, u_ss, epsilon=1e-06)[source]

Linearize a nonlinear model around an operating point.

Parameters:
  • model_func (Callable) – Function f(x, u) returning dx/dt

  • x_ss (<MagicMock id='130137676749120'>) – Steady-state states

  • u_ss (<MagicMock id='130137676749456'>) – Steady-state inputs

  • epsilon (float) – Perturbation size for finite differences

Returns:

A, B matrices for linear model dx/dt = A*x + B*u

Return type:

Tuple[<MagicMock id=’130137676749792’>, <MagicMock id=’130137676750128’>]

sproclib.utilities.control_utils.disturbance_rejection(plant_tf, controller_tf, disturbance_type='step', w=None)[source]

Analyze disturbance rejection performance.

Parameters:
  • plant_tf (Tuple[<MagicMock id='130137676751808'>, <MagicMock id='130137676752144'>]) – Plant transfer function (num, den)

  • controller_tf (Tuple[<MagicMock id='130137676753824'>, <MagicMock id='130137676754160'>]) – Controller transfer function (num, den)

  • disturbance_type (str) – Type of disturbance (‘step’, ‘ramp’, ‘frequency’)

  • w (<MagicMock id='130137676755840'> | None) – Frequency vector for analysis

Returns:

Dictionary with disturbance rejection analysis

Return type:

Dict[str, Any]

sproclib.utilities.control_utils.model_predictive_control(A, B, Q, R, prediction_horizon=10, control_horizon=None)[source]

Basic Model Predictive Control formulation.

Parameters:
  • A (<MagicMock id='130137676756848'>) – State-space matrices

  • B (<MagicMock id='130137676757184'>) – State-space matrices

  • Q (<MagicMock id='130137676757520'>) – State and input weighting matrices

  • R (<MagicMock id='130137676757856'>) – State and input weighting matrices

  • prediction_horizon (int) – Prediction horizon N

  • control_horizon (int | None) – Control horizon M (default: same as prediction horizon)

Returns:

Dictionary with MPC formulation matrices

Return type:

Dict[str, Any]

Math Utils

Math Utilities for SPROCLIB

This module provides mathematical utility functions for process control including signal processing, numerical methods, and mathematical operations.

Author: Thorsten Gressling <gressling@paramus.ai> License: MIT License

sproclib.utilities.math_utils.step_response(system, t=None, t_final=10.0, input_magnitude=1.0)[source]

Calculate step response of a system.

Parameters:
  • system – Transfer function object or (num, den) tuple

  • t (<MagicMock id='130137679723360'> | None) – Time vector (optional)

  • t_final (float) – Final time if t not provided

  • input_magnitude (float) – Step magnitude

Returns:

Dictionary with ‘t’ and ‘y’ arrays

Return type:

Dict[str, <MagicMock id=’130137678217296’>]

sproclib.utilities.math_utils.bode_plot(system, w=None, plot=True, title='Bode Plot')[source]

Generate Bode plot for frequency response analysis.

Parameters:
  • system – Transfer function object or (num, den) tuple

  • w (<MagicMock id='130137678218304'> | None) – Frequency vector (optional)

  • plot (bool) – Whether to create plot

  • title (str) – Plot title

Returns:

Dictionary with frequency, magnitude, and phase data

Return type:

Dict[str, <MagicMock id=’130137678219312’>]

sproclib.utilities.math_utils.linearize(model_func, x_ss, u_ss, epsilon=1e-06)[source]

Linearize a nonlinear model around an operating point.

Parameters:
  • model_func – Function f(x, u) returning dx/dt

  • x_ss (<MagicMock id='130137679722352'>) – Steady-state states

  • u_ss (<MagicMock id='130137679722016'>) – Steady-state inputs

  • epsilon (float) – Perturbation size for finite differences

Returns:

A, B matrices for linear model dx/dt = A*x + B*u

Return type:

Tuple[<MagicMock id=’130137679721680’>, <MagicMock id=’130137679721344’>]

sproclib.utilities.math_utils.stability_check(A)[source]

Check if a linear system is stable.

Parameters:

A (<MagicMock id='130137678220656'>) – State matrix

Returns:

True if stable, False otherwise

Return type:

bool

sproclib.utilities.math_utils.routh_hurwitz(coeffs)[source]

Routh-Hurwitz stability criterion.

Parameters:

coeffs (<MagicMock id='130137678220992'>) – Characteristic polynomial coefficients

Returns:

Dictionary with stability analysis

Return type:

Dict[str, Any]

sproclib.utilities.math_utils.frequency_response(num, den, w)[source]

Calculate frequency response.

Parameters:
  • num (<MagicMock id='130137678221328'>) – Numerator coefficients

  • den (<MagicMock id='130137678221664'>) – Denominator coefficients

  • w (<MagicMock id='130137678222000'>) – Frequency vector

Returns:

Magnitude and phase arrays

Return type:

Tuple[<MagicMock id=’130137678222336’>, <MagicMock id=’130137678222672’>]

Data Utils

Data Utilities for SPROCLIB

This module provides data processing utilities for process control including filtering, resampling, and data analysis functions.

Author: Thorsten Gressling <gressling@paramus.ai> License: MIT License

sproclib.utilities.data_utils.filter_data(data, filter_type='lowpass', cutoff=0.1, order=2, method='butterworth')[source]

Filter time series data.

Parameters:
  • data (<MagicMock id='130137678226704'>) – Input data array

  • filter_type (str) – Type of filter (‘lowpass’, ‘highpass’, ‘bandpass’)

  • cutoff (float) – Cutoff frequency (normalized)

  • order (int) – Filter order

  • method (str) – Filter method (‘butterworth’, ‘chebyshev’, ‘bessel’)

Returns:

Filtered data array

Return type:

<MagicMock id=’130137678227040’>

sproclib.utilities.data_utils.resample_data(t, data, new_dt, method='linear')[source]

Resample time series data.

Parameters:
  • t (<MagicMock id='130137678227376'>) – Original time array

  • data (<MagicMock id='130137678227712'>) – Original data array

  • new_dt (float) – New sampling interval

  • method (str) – Interpolation method

Returns:

New time array and resampled data

Return type:

Tuple[<MagicMock id=’130137678228048’>, <MagicMock id=’130137678228384’>]

sproclib.utilities.data_utils.detect_outliers(data, method='iqr', threshold=1.5)[source]

Detect outliers in data.

Parameters:
  • data (<MagicMock id='130137678230064'>) – Input data array

  • method (str) – Detection method (‘iqr’, ‘zscore’, ‘modified_zscore’)

  • threshold (float) – Threshold for outlier detection

Returns:

Boolean array indicating outliers

Return type:

<MagicMock id=’130137678226368’>

sproclib.utilities.data_utils.smooth_data(data, window_size=5, method='moving_average')[source]

Smooth data using various methods.

Parameters:
  • data (<MagicMock id='130137678226032'>) – Input data array

  • window_size (int) – Size of smoothing window

  • method (str) – Smoothing method (‘moving_average’, ‘savgol’, ‘exponential’)

Returns:

Smoothed data array

Return type:

<MagicMock id=’130137678225696’>

sproclib.utilities.data_utils.calculate_statistics(data)[source]

Calculate basic statistics for data.

Parameters:

data (<MagicMock id='130137678225360'>) – Input data array

Returns:

Dictionary with statistical measures

Return type:

Dict[str, float]

sproclib.utilities.data_utils.calculate_skewness(data)[source]

Calculate skewness of data.

Parameters:

data (<MagicMock id='130137678225024'>)

Return type:

float

sproclib.utilities.data_utils.calculate_kurtosis(data)[source]

Calculate kurtosis of data.

Parameters:

data (<MagicMock id='130137678224688'>)

Return type:

float

Quick Usage

PID Controller Tuning:

from utilities.control_utils import tune_pid

# Define process model parameters
model_params = {
    'K': 2.0,    # Process gain
    'tau': 5.0,  # Time constant
    'theta': 1.0 # Dead time
}

# Auto-tune PID controller
pid_params = tune_pid(
    model_params,
    method='ziegler_nichols',
    controller_type='PID'
)

print(f"Kp = {pid_params['Kp']:.3f}")
print(f"Ki = {pid_params['Ki']:.3f}")
print(f"Kd = {pid_params['Kd']:.3f}")

Process Linearization:

from utilities.control_utils import linearize
import numpy as np

# Define nonlinear model
def reactor_model(x, u):
    T, Ca = x
    Tc = u[0]
    # Reactor dynamics
    dT_dt = 0.1 * (Tc - T) + 0.5 * Ca
    dCa_dt = -0.2 * Ca * np.exp(-1000/T)
    return np.array([dT_dt, dCa_dt])

# Linearize around operating point
x_ss = np.array([350, 2.0])  # Temperature, Concentration
u_ss = np.array([340])       # Coolant temperature

A, B = linearize(reactor_model, x_ss, u_ss)
print("State matrix A:")
print(A)
print("Input matrix B:")
print(B)

Mathematical Utilities:

from utilities.math_utils import numerical_derivative, integrate_ode

# Numerical differentiation
def f(x):
    return x**3 + 2*x**2 - 5*x + 1

df_dx = numerical_derivative(f, x=2.0, method='central')
print(f"df/dx at x=2: {df_dx}")

Data Processing:

from utilities.data_utils import filter_data, resample_data
import numpy as np

# Generate noisy data
t = np.linspace(0, 10, 1000)
signal = np.sin(t) + 0.1 * np.random.randn(len(t))

# Filter data
filtered = filter_data(signal, filter_type='lowpass', cutoff=0.1)

# Resample data
t_new, signal_new = resample_data(t, filtered, new_rate=0.1)