Skip to content

setpoint_events

setpoint_events ¤

SetpointChangeEvents ¤

SetpointChangeEvents(
    dataframe: DataFrame,
    setpoint_uuid: str,
    *,
    event_uuid: str = "eng:setpoint_change",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Detect step/ramp changes on a setpoint signal and compute follow-up KPIs like time-to-settle and overshoot based on an actual (process) value.

Schema assumptions (columns): - uuid, sequence_number, systime, plctime, is_delta - value_integer, value_string, value_double, value_bool, value_bytes

Example

import pandas as pd from ts_shape import SetpointChangeEvents df = pd.DataFrame({ ... "systime": pd.date_range("2025-01-01 08:00", periods=4, freq="10min"), ... "uuid": "oven:setpoint", ... "value_double": [50.0, 50.0, 60.0, 60.0], ... }) steps = SetpointChangeEvents(df, "oven:setpoint").detect_setpoint_steps(min_delta=5.0) steps[["start", "prev_level", "new_level", "magnitude"]] start prev_level new_level magnitude 0 2025-01-01 08:20:00 50.0 60.0 10.0

detect_setpoint_steps ¤

detect_setpoint_steps(
    min_delta: float,
    min_hold: str = "0s",
    filter_noise: bool = False,
    noise_threshold: float = 0.01,
) -> pd.DataFrame

Point events at times where the setpoint changes by >= min_delta and the new level holds for at least min_hold (no subsequent change within that time).

Parameters:

Name Type Description Default
min_delta float

Minimum magnitude of change to detect

required
min_hold str

Minimum duration the new level must hold

'0s'
filter_noise bool

If True, filter out changes smaller than noise_threshold

False
noise_threshold float

Threshold for noise filtering (absolute value)

0.01

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (== start), duration_seconds

DataFrame

(0.0), uuid, source_uuid, is_delta, change_type='step', magnitude,

DataFrame

prev_level, new_level.

detect_setpoint_ramps ¤

detect_setpoint_ramps(
    min_rate: float, min_duration: str = "0s"
) -> pd.DataFrame

Interval events where |dS/dt| >= min_rate for at least min_duration.

Parameters:

Name Type Description Default
min_rate float

Minimum absolute setpoint rate of change, in setpoint units per second, for a sample-to-sample step to count as ramping.

required
min_duration str

Minimum time from the first to the last ramping sample of a contiguous run (pandas offset string). Default "0s".

'0s'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end, duration_seconds, uuid,

DataFrame

source_uuid, is_delta, change_type='ramp', avg_rate, delta.

detect_setpoint_changes ¤

detect_setpoint_changes(
    *,
    min_delta: float = 0.0,
    min_rate: float | None = None,
    min_hold: str = "0s",
    min_duration: str = "0s"
) -> pd.DataFrame

Unified setpoint change table (steps + ramps) with standardized columns.

Parameters:

Name Type Description Default
min_delta float

Minimum step magnitude, passed to :meth:detect_setpoint_steps.

0.0
min_rate float | None

Minimum ramp rate in setpoint units per second, passed to :meth:detect_setpoint_ramps. None skips ramp detection.

None
min_hold str

Minimum time a new step level must hold, passed to :meth:detect_setpoint_steps.

'0s'
min_duration str

Minimum ramp duration, passed to :meth:detect_setpoint_ramps.

'0s'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end, duration_seconds, uuid,

DataFrame

source_uuid, is_delta, change_type, magnitude, prev_level,

DataFrame

new_level, avg_rate, delta.

time_to_settle ¤

time_to_settle(
    actual_uuid: str,
    *,
    tol: float = 0.0,
    settle_pct: float | None = None,
    hold: str = "0s",
    lookahead: str = "10min"
) -> pd.DataFrame

For each setpoint change (any change), compute the settling time: the time after which the actual signal enters the ±tolerance band around the new setpoint and stays inside it until the end of the evaluation window (Ogata, Modern Control Engineering, settling time t_s). The first entry into the band is not the settling time: an underdamped response crosses the band on every swing long before it settles.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
tol float

Absolute tolerance, used when settle_pct is None.

0.0
settle_pct float | None

Tolerance as a fraction of the step magnitude (e.g. 0.02 for 2%). When given it wins over tol; passing both emits a UserWarning.

None
hold str

Minimum duration the final inside-band run must last before the window ends for the settle to count as confirmed (settled).

'0s'
lookahead str

Evaluation window after each change. It also ends at the next (later) setpoint change, after which the process follows a different setpoint. The response must be inside the band at the window's last sample to have settled.

'10min'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, t_settle_seconds (seconds from the change to the start

DataFrame

of the final inside-band run; None when the response is

DataFrame

outside the band at the end of the window), settled_within_window

DataFrame

(True when the response is inside the band at the end of the

DataFrame

window, so a settling time exists) and settled

DataFrame

(settled_within_window and the final inside-band run lasts at

DataFrame

least hold).

overshoot_metrics ¤

overshoot_metrics(
    actual_uuid: str, *, window: str = "10min"
) -> pd.DataFrame

For each change, compute peak overshoot, undershoot, and oscillation metrics relative to the new setpoint within a lookahead window.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual (process value) signal.

required
window str

Lookahead window after each setpoint change in which the peak, undershoot and oscillations are measured (pandas offset string).

'10min'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, overshoot_abs, overshoot_pct, overshoot_ratio,

DataFrame

t_peak_seconds, undershoot_abs, undershoot_pct, undershoot_ratio,

DataFrame

t_undershoot_seconds, oscillation_count, oscillation_amplitude.

DataFrame

overshoot_pct is the peak overshoot in percent of the step

DataFrame

magnitude (0-100+, Ogata's maximum percent overshoot M_p);

DataFrame

overshoot_ratio is the same quantity as a fraction (0-1+).

DataFrame

undershoot_pct / undershoot_ratio are the swing back past

DataFrame

the new setpoint after it is first reached, in the same two units.

time_to_settle_derivative ¤

time_to_settle_derivative(
    actual_uuid: str,
    *,
    rate_threshold: float = 0.01,
    lookahead: str = "10min",
    hold: str = "0s"
) -> pd.DataFrame

Detect settling based on rate of change (derivative) falling below threshold. More sensitive to when the process has truly stopped moving.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
rate_threshold float

Maximum absolute rate of change to consider settled

0.01
lookahead str

Maximum time window to search for settling

'10min'
hold str

Minimum duration the rate must stay below threshold

'0s'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, t_settle_seconds, settled, final_rate.

rise_time ¤

rise_time(
    actual_uuid: str,
    *,
    start_pct: float = 0.1,
    end_pct: float = 0.9,
    lookahead: str = "10min"
) -> pd.DataFrame

Compute rise time: time for actual to go from start_pct to end_pct of the setpoint change. Typically measured from 10% to 90% of the final value.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
start_pct float

Starting percentage of change (e.g., 0.1 for 10%)

0.1
end_pct float

Ending percentage of change (e.g., 0.9 for 90%)

0.9
lookahead str

Maximum time window to search

'10min'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, rise_time_seconds, reached_end.

decay_rate ¤

decay_rate(
    actual_uuid: str,
    *,
    lookahead: str = "10min",
    min_points: int = 5
) -> pd.DataFrame

Estimate exponential decay rate of the settling behavior. Fits error(t) = A * exp(-lambda * t) and returns lambda.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
lookahead str

Time window for analysis

'10min'
min_points int

Minimum number of points required for fitting

5

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, decay_rate_lambda, fit_quality_r2.

oscillation_frequency ¤

oscillation_frequency(
    actual_uuid: str,
    *,
    window: str = "10min",
    min_oscillations: int = 2
) -> pd.DataFrame

Estimate the frequency of oscillations during settling. Counts zero crossings and estimates period.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
window str

Time window for analysis

'10min'
min_oscillations int

Minimum number of oscillations to compute frequency

2

Returns:

Type Description
DataFrame

DataFrame with columns: start, end (start + the lookahead window),

DataFrame

duration_seconds, uuid, source_uuid (","),

DataFrame

is_delta, oscillation_freq_hz, period_seconds.

control_quality_metrics ¤

control_quality_metrics(
    actual_uuid: str,
    *,
    tol: float = 0.0,
    settle_pct: float | None = None,
    hold: str = "0s",
    lookahead: str = "10min",
    rate_threshold: float = 0.01
) -> pd.DataFrame

Comprehensive control quality metrics combining multiple performance indicators.

Computes all available metrics for each setpoint change and returns them in a single DataFrame. This includes: settling time, rise time, overshoot, undershoot, oscillations, and decay characteristics. The change table and the response windows are gathered once and shared by all of them.

Parameters:

Name Type Description Default
actual_uuid str

UUID of the actual/process value signal

required
tol float

Absolute tolerance for settling, used when settle_pct is None.

0.0
settle_pct float | None

Settling tolerance as a fraction of the step magnitude. When given it wins over tol; passing both emits a UserWarning.

None
hold str

Minimum duration to confirm settling

'0s'
lookahead str

Time window for all analyses

'10min'
rate_threshold float

Rate threshold for derivative-based settling

0.01

Returns:

Type Description
DataFrame

DataFrame with comprehensive metrics including:

DataFrame
  • start, end (start + lookahead), duration_seconds, uuid, source_uuid (","), is_delta
DataFrame
  • t_settle_seconds, settled, settled_within_window (from time_to_settle)
DataFrame
  • t_settle_derivative_seconds (from time_to_settle_derivative)
DataFrame
  • rise_time_seconds (from rise_time)
DataFrame
  • overshoot_abs, overshoot_pct (percent), overshoot_ratio (fraction) (from overshoot_metrics)
DataFrame
  • undershoot_abs, undershoot_pct (percent), undershoot_ratio
DataFrame
  • oscillation_count, oscillation_amplitude, oscillation_freq_hz
DataFrame
  • decay_rate_lambda, fit_quality_r2
DataFrame
  • steady_state_error (final error in window)