Skip to content

Index

maintenance ¤

Maintenance Events

Detectors for maintenance-related patterns: degradation trends, failure prediction, reliability (MTBF / MTTR / Weibull) and vibration analysis for predictive maintenance on manufacturing/industrial IoT time series data.

  • AssetHealthIndexEvents: Fuse several degradation signals into one asset health index, weighted by failure-mode criticality.
  • health_index: Weighted 0-100 asset score per evaluation window.
  • health_events: Point events on warning/critical threshold crossings.
  • signal_contributions: Per-signal share of the asset's health loss.
  • maintenance_forecast: Days until the index reaches a critical level.

  • DegradationDetectionEvents: Detect trend degradation, variance increases, level shifts, and compute composite health scores.

  • detect_trend_degradation: Rolling linear regression slope detection.
  • detect_variance_increase: Rolling variance vs baseline comparison.
  • detect_level_shift: CUSUM-like permanent mean shift detection.
  • health_score: Composite 0-100 score from drift, variance, and trend.

  • FailurePredictionEvents: Predict remaining useful life and escalating failure patterns.

  • remaining_useful_life: Linear extrapolation to failure threshold.
  • detect_exceedance_pattern: Rolling threshold exceedance frequency.
  • time_to_threshold: Rate-of-change based threshold ETA.

  • ReliabilityEvents: Reliability KPIs from a failure-state signal.

  • failure_events: One interval per failure with repair and operating time.
  • mtbf_mttr: MTBF (common and ISO 22400), MTTR, availability, failure rate.
  • weibull_fit: Censored Weibull life model (beta, eta, MTTF, B10).
  • reliability_at: Reliability and hazard ahead, optionally given the age.

  • VibrationAnalysisEvents: Vibration signal analysis for rotating equipment.

  • detect_rms_exceedance: Rolling RMS vs baseline threshold.
  • detect_amplitude_growth: Peak-to-peak amplitude tracking.
  • bearing_health_indicators: Kurtosis and crest factor per window.

AssetHealthIndexEvents ¤

AssetHealthIndexEvents(
    dataframe: DataFrame,
    asset_id: str,
    signals: Mapping[str, str | Mapping[str, Any]],
    *,
    event_uuid: str = "maint:asset_health",
    value_column: str = "value_double",
    time_column: str = "systime",
    uuid_column: str = "uuid"
)

Bases: Base

Maintenance: multi-signal asset health fusion.

Each asset is described by a mapping of signal UUID to a failure mode (and optionally a weight)::

AssetHealthIndexEvents(
    df,
    asset_id="press-01",
    signals={
        "vib:press-01": "bearing",
        "temp:press-01": {"failure_mode": "thermal", "weight": 2.0},
        "curr:press-01": {"failure_mode": "electrical"},
    },
)

A bare string is shorthand for {"failure_mode": <str>, "weight": 1.0}. Weights express failure-mode criticality: a thermal runaway that scraps the tool should outweigh a slow bearing drift.

Methods: - health_index: fused 0-100 asset score per window. - health_events: point events when the index crosses warning/critical. - signal_contributions: per-signal breakdown of the health loss. - maintenance_forecast: days until the index reaches a critical level.

Initialize the asset health index.

Parameters:

Name Type Description Default
dataframe DataFrame

Timeseries frame holding every configured signal.

required
asset_id str

Identifier of the asset the signals belong to. It is emitted as source_uuid so the event log binds the rows to one asset object.

required
signals Mapping[str, str | Mapping[str, Any]]

Mapping of signal UUID to failure mode (string) or to a {"failure_mode": str, "weight": float} mapping.

required
event_uuid str

UUID stamped on emitted events.

'maint:asset_health'
value_column str

Column holding the numeric readings.

'value_double'
time_column str

Timestamp column.

'systime'
uuid_column str

Column identifying the signal.

'uuid'

Raises:

Type Description
ValueError

If signals is empty or a weight is not positive.

health_index ¤

health_index(
    *, window: str = "1h", baseline_window: str = "24h"
) -> pd.DataFrame

Fuse the configured signals into one asset health score per window.

A signal with no data in a window is skipped rather than scored as zero; confidence_level reports the share of the configured weight that was actually available, so a score computed from one of four signals is visibly weaker evidence than a score from all four.

Parameters:

Name Type Description Default
window str

Evaluation window (e.g. '1h', '1D').

'1h'
baseline_window str

Opening period of each signal used as its healthy reference for drift and variance.

'24h'

Returns:

Type Description
DataFrame

Summary-shape DataFrame: start, end, duration_seconds,

DataFrame

uuid, source_uuid, asset_id, asset_health_score,

DataFrame

dominant_failure_mode, worst_signal_uuid,

DataFrame

signals_available, signals_expected, confidence_level,

DataFrame

sample_count.

health_events ¤

health_events(
    *,
    window: str = "1h",
    baseline_window: str = "24h",
    warning_threshold: float = 70.0,
    critical_threshold: float = 50.0,
    only_crossings: bool = True
) -> pd.DataFrame

Emit an event when the fused index falls to warning or critical.

Parameters:

Name Type Description Default
window str

Evaluation window passed to :meth:health_index.

'1h'
baseline_window str

Baseline period passed to :meth:health_index.

'24h'
warning_threshold float

Score at or below which a warning fires.

70.0
critical_threshold float

Score at or below which a critical fires.

50.0
only_crossings bool

When True (default) only the window that enters a severity band emits a row, so a machine sitting at 40 for a week reports one critical, not 168. Set False to emit every window that sits below a threshold.

True

Returns:

Type Description
DataFrame

Point-shape DataFrame: systime, uuid, source_uuid,

DataFrame

asset_id, asset_health_score, severity, threshold,

DataFrame

dominant_failure_mode, confidence_level, direction.

Raises:

Type Description
ValueError

If critical_threshold exceeds warning_threshold.

signal_contributions ¤

signal_contributions(
    *, window: str = "1h", baseline_window: str = "24h"
) -> pd.DataFrame

Rank the configured signals by how much health they cost the asset.

The contribution of a signal is its mean weighted health deficit (100 - health) * weight over the evaluated windows, expressed as a share of the total deficit. A perfectly healthy asset has no deficit to distribute and every contribution is 0.

Parameters:

Name Type Description Default
window str

Evaluation window passed to the per-signal scorer.

'1h'
baseline_window str

Baseline period passed to the per-signal scorer.

'24h'

Returns:

Type Description
DataFrame

Static-shape DataFrame: asset_id, signal_uuid,

DataFrame

failure_mode, weight, mean_health, min_health,

DataFrame

weighted_deficit, contribution_pct, windows, rank,

DataFrame

method.

maintenance_forecast ¤

maintenance_forecast(
    *,
    window: str = "1h",
    baseline_window: str = "24h",
    critical_threshold: float = 50.0,
    min_confidence: float = 0.5
) -> pd.DataFrame

Project when the asset index reaches critical_threshold.

Fits a least-squares line through the fused index and extrapolates it to the threshold. confidence is the fit's R²: a flat but noisy index nearly always slopes slightly one way, so a fit below min_confidence reports its slope and confidence but no horizon, rather than handing out a maintenance date the data cannot support. An index that is flat or improving likewise yields NaN for the horizon columns.

Parameters:

Name Type Description Default
window str

Evaluation window passed to :meth:health_index.

'1h'
baseline_window str

Baseline period passed to :meth:health_index.

'24h'
critical_threshold float

Score treated as "intervention required".

50.0
min_confidence float

Minimum R² of the trend fit before a horizon is projected. Pass 0.0 to always project.

0.5

Returns:

Type Description
DataFrame

Summary-shape DataFrame with a single row: start, end,

DataFrame

duration_seconds, uuid, source_uuid, asset_id,

DataFrame

current_health, decline_per_day,

DataFrame

recommended_maintenance_days, forecast_time,

DataFrame

critical_threshold, confidence, sample_count,

DataFrame

method.

DegradationDetectionEvents ¤

DegradationDetectionEvents(
    dataframe: DataFrame,
    signal_uuid: str,
    *,
    event_uuid: str = "maint:degradation",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Detect degradation patterns in time series signals: trend degradation, variance increases, level shifts, and composite health scores.

Designed for predictive maintenance on manufacturing/industrial IoT data.

detect_trend_degradation ¤

detect_trend_degradation(
    window: str = "1h",
    min_slope: float = 0.0,
    direction: str = "decreasing",
    *,
    interval_end: str = "next_change"
) -> pd.DataFrame

Detect intervals where a rolling linear regression slope exceeds min_slope in the given direction, indicating trend-based degradation.

Parameters:

Name Type Description Default
window str

Rolling window size (e.g. '1h', '30min').

'1h'
min_slope float

Minimum absolute slope to consider degradation.

0.0
direction str

'decreasing' (negative slope) or 'increasing' (positive slope).

'decreasing'
interval_end str

"next_change" (default) ends an interval at the next sample (the transition), so the interval spans the time the condition held and change-encoded signals -- one row per change -- keep their duration. "last_sample" ends it at its last flagged sample. See :func:ts_shape.utils.intervals.interval_end_times.

'next_change'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end, uuid, source_uuid, is_delta,

DataFrame

avg_slope, total_change, duration_seconds. source_uuid is the

DataFrame

analyzed signal.

detect_variance_increase ¤

detect_variance_increase(
    window: str = "1h",
    threshold_factor: float = 2.0,
    *,
    interval_end: str = "next_change"
) -> pd.DataFrame

Compare rolling variance against a baseline (first window) and flag intervals where the ratio exceeds threshold_factor.

Parameters:

Name Type Description Default
window str

Rolling window size.

'1h'
threshold_factor float

Minimum variance ratio to flag.

2.0
interval_end str

"next_change" (default) ends an interval at the next sample (the transition), so the interval spans the time the condition held and change-encoded signals -- one row per change -- keep their duration. "last_sample" ends it at its last flagged sample. See :func:ts_shape.utils.intervals.interval_end_times.

'next_change'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end, uuid, source_uuid, is_delta,

DataFrame

baseline_variance, current_variance, ratio, duration_seconds

DataFrame

(float seconds from start to end).

detect_level_shift ¤

detect_level_shift(
    min_shift: float, hold: str = "5min"
) -> pd.DataFrame

CUSUM-like detection for permanent mean shifts in the signal.

Parameters:

Name Type Description Default
min_shift float

Minimum absolute shift magnitude to detect.

required
hold str

Minimum duration the new level must persist.

'5min'

Returns:

Type Description
DataFrame

DataFrame with columns: systime, uuid, source_uuid, is_delta,

DataFrame

shift_magnitude, prev_mean, new_mean.

health_score ¤

health_score(
    window: str = "1h", baseline_window: str = "24h"
) -> pd.DataFrame

Composite 0-100 health score based on mean drift, variance change, and trend slope, computed over rolling windows.

Parameters:

Name Type Description Default
window str

Rolling window for current metrics.

'1h'
baseline_window str

Initial period used to establish baseline behavior.

'24h'

Returns:

Type Description
DataFrame

DataFrame with columns: systime, uuid, source_uuid, is_delta,

DataFrame

health_score, mean_drift_pct, variance_ratio, trend_slope.

FailurePredictionEvents ¤

FailurePredictionEvents(
    dataframe: DataFrame,
    signal_uuid: str,
    *,
    event_uuid: str = "maint:failure_pred",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Predict remaining useful life and detect escalating failure patterns in time series signals from manufacturing/industrial IoT systems.

remaining_useful_life ¤

remaining_useful_life(
    degradation_rate: float, failure_threshold: float
) -> pd.DataFrame

Estimate remaining useful life (RUL) at each point via linear extrapolation from the recent trend to a failure threshold.

Parameters:

Name Type Description Default
degradation_rate float

Expected rate of change per second (used as fallback if local slope cannot be computed).

required
failure_threshold float

The signal level that represents failure. The sign of degradation_rate gives the failure direction (positive: failure when the value rises to the threshold).

required

Returns:

Type Description
DataFrame

DataFrame with columns: systime, uuid, source_uuid, is_delta,

DataFrame

current_value, rul_seconds, rul_hours, confidence. rul_* is 0 once the

DataFrame

threshold is reached or passed, and None when no failure is

DataFrame

projected (flat trend, or a trend moving away from the threshold).

detect_exceedance_pattern ¤

detect_exceedance_pattern(
    warning_threshold: float,
    critical_threshold: float,
    window: str = "1h",
) -> pd.DataFrame

Track frequency of threshold exceedances in rolling windows and flag escalating patterns (increasing exceedance counts).

Parameters:

Name Type Description Default
warning_threshold float

Warning level (absolute value comparison).

required
critical_threshold float

Critical level (absolute value comparison).

required
window str

Rolling window size.

'1h'

Returns:

Type Description
DataFrame

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

DataFrame

source_uuid, is_delta, warning_count, critical_count,

DataFrame

escalation_detected. end is start plus window.

time_to_threshold ¤

time_to_threshold(
    threshold: float, direction: str = "increasing"
) -> pd.DataFrame

Estimate time to reach a threshold based on recent rate of change.

Parameters:

Name Type Description Default
threshold float

Target threshold value.

required
direction str

'increasing' or 'decreasing'.

'increasing'

Returns:

Type Description
DataFrame

DataFrame with columns: systime, uuid, source_uuid, is_delta,

DataFrame

current_value, rate_of_change, estimated_time_seconds.

ReliabilityEvents ¤

ReliabilityEvents(
    dataframe: DataFrame,
    run_state_uuid: str,
    *,
    failure_states: Sequence[object] = (True,),
    value_column: str = "value_bool",
    max_gap: str | Timedelta | None = None,
    data_end: str | Timestamp | None = None,
    event_uuid: str = "maint:reliability",
    time_column: str = "systime"
)

Bases: Base

Maintenance: reliability KPIs from a failure-state signal.

  • failure_events: One interval per failure, with its repair time and the operating time before it.
  • mtbf_mttr: MTBF, MTTR, availability and failure rate, overall or per calendar window.
  • weibull_fit: Weibull life model of the times between failures, with right censoring; shape beta tells infant mortality / random / wear-out.
  • reliability_at: Reliability and hazard at given operating times from the fitted model, optionally conditional on the current age.
Example

import pandas as pd, ts_shape t = pd.date_range("2025-01-01", periods=8, freq="1h") df = pd.DataFrame({"systime": t, "uuid": "fault", "value_bool": ... [False, False, True, False, False, False, True, False]}) kpi = ts_shape.ReliabilityEvents(df, "fault").mtbf_mttr() kpi[["failures", "mtbf_hours", "mttr_hours", "availability_pct"]].round(1) failures mtbf_hours mttr_hours availability_pct 0 2 2.5 1.0 71.4

Parameters:

Name Type Description Default
dataframe DataFrame

Long-format data.

required
run_state_uuid str

The failure-state signal.

required
failure_states Sequence[object]

Values meaning "failed / down for repair". The default (True,) fits a fault bit; for a status code pass e.g. ("BREAKDOWN", "REPAIR").

(True,)
value_column str

Column holding the state.

'value_bool'
max_gap str | Timedelta | None

Longest time a state is held; longer gaps are no data. Default None: every state is held until the next sample, however long the gap.

None
data_end str | Timestamp | None

End of the observation (e.g. "now"); the last state holds until then. Default: the last sample.

None
event_uuid str

uuid of the emitted events.

'maint:reliability'
time_column str

Timestamp column.

'systime'

failure_events ¤

failure_events() -> pd.DataFrame

One interval per failure.

Returns:

Type Description
DataFrame

Intervals start (failure) to end (back in service) with

DataFrame

repair_hours (known failed time; data gaps excluded),

DataFrame

operating_hours_before (operating time since the previous

DataFrame

repair) and first_observed (True when that operating period

DataFrame

began before the data did, so its length is a lower bound).

mtbf_mttr ¤

mtbf_mttr(
    window: str | None = None, tz: str | None = None
) -> pd.DataFrame

MTBF, MTTR, availability and failure rate.

Parameters:

Name Type Description Default
window str | None

Calendar window (e.g. "1D", "7D", "MS"); None = one row over the whole observation. A failure belongs to the window it starts in; operating and repair time are split exactly at window boundaries.

None
tz str | None

Timezone for the window grid (DST-correct day lengths). Default: the data's timezone.

None

Returns:

Type Description
DataFrame

Summary rows (start, end, duration_seconds, uuid,

DataFrame

source_uuid) with

DataFrame

operating_hours, repair_hours, no_data_hours,

DataFrame

failures, mtbf_hours, mtbf_iso22400_hours,

DataFrame

mttr_hours, availability_pct and

DataFrame

failure_rate_per_hour. Ratios with no failures (or no

DataFrame

known time) are NaN.

weibull_fit ¤

weibull_fit(include_initial: bool = False) -> pd.DataFrame

Two-parameter Weibull model of the times between failures.

Fitted by maximum likelihood (scipy.stats.weibull_min, location fixed at 0). The operating period still running at the end of the data is right-censored.

Parameters:

Name Type Description Default
include_initial bool

Also use the operating time before the first failure as a complete observation. Off by default: that period started before the data did, so the asset's age at the first failure is unknown.

False

Returns:

Type Description
DataFrame

One row: beta (shape), eta_hours (scale: 63.2 % have

DataFrame

failed by then), mttf_hours (eta * Gamma(1 + 1/beta)),

DataFrame

b10_hours (10 % have failed by then), n_failures,

DataFrame

n_censored and failure_pattern (infant_mortality

DataFrame

for beta < 0.9, random up to 1.1, else wear_out).

DataFrame

Empty when fewer than two failure intervals are available.

DataFrame

When the times between failures (almost) all have the same

DataFrame

length, the model has no finite fit: the parameters are NaN,

DataFrame

failure_pattern is "unknown" and a

DataFrame

class:~ts_shape.errors.DataQualityWarning is emitted.

reliability_at ¤

reliability_at(
    hours: Sequence[float],
    age_hours: float = 0.0,
    include_initial: bool = False,
) -> pd.DataFrame

Reliability and hazard from the fitted Weibull model.

Parameters:

Name Type Description Default
hours Sequence[float]

Operating hours ahead to evaluate.

required
age_hours float

Operating hours already survived since the last repair. Reliability is then conditional: R(age + t) / R(age) -- "given it has run 200 h, how likely is it to run another 100 h?".

0.0
include_initial bool

Passed to :meth:weibull_fit.

False

Returns:

Type Description
DataFrame

One row per value of hours: hours, age_hours,

DataFrame

reliability, failure_probability and

DataFrame

hazard_per_hour (instantaneous failure rate at age + t).

DataFrame

Empty when there are too few failures to fit; NaN values when

DataFrame

the fit is degenerate (see :meth:weibull_fit).

VibrationAnalysisEvents ¤

VibrationAnalysisEvents(
    dataframe: DataFrame,
    signal_uuid: str,
    *,
    event_uuid: str = "maint:vibration",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Analyze vibration signals from industrial equipment: RMS exceedance, amplitude growth, and bearing health indicators (kurtosis, crest factor).

detect_rms_exceedance ¤

detect_rms_exceedance(
    baseline_rms: float,
    threshold_factor: float = 1.5,
    window: str = "1min",
    *,
    interval_end: str = "next_change"
) -> pd.DataFrame

Compute rolling RMS and flag intervals exceeding baseline_rms * threshold_factor.

Parameters:

Name Type Description Default
baseline_rms float

Known baseline RMS value for healthy equipment.

required
threshold_factor float

Multiplier above baseline to trigger alarm.

1.5
window str

Rolling window size.

'1min'
interval_end str

"next_change" (default) ends an interval at the next sample (the transition), so the interval spans the time the condition held and change-encoded signals -- one row per change -- keep their duration. "last_sample" ends it at its last flagged sample. See :func:ts_shape.utils.intervals.interval_end_times.

'next_change'

Returns:

Type Description
DataFrame

DataFrame with columns: start, end, uuid, source_uuid, is_delta,

DataFrame

rms_value, baseline_rms, ratio, duration_seconds.

detect_amplitude_growth ¤

detect_amplitude_growth(
    window: str = "1h", growth_threshold: float = 0.1
) -> pd.DataFrame

Track peak-to-peak amplitude in non-overlapping windows and flag windows where amplitude grows beyond growth_threshold relative to baseline.

Parameters:

Name Type Description Default
window str

Window size for amplitude measurement.

'1h'
growth_threshold float

Minimum fractional growth (e.g. 0.1 = 10%) to flag.

0.1

Returns:

Type Description
DataFrame

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

DataFrame

source_uuid, is_delta, amplitude, baseline_amplitude, growth_pct.

DataFrame

end is start plus window.

bearing_health_indicators ¤

bearing_health_indicators(
    window: str = "5min",
) -> pd.DataFrame

Compute bearing health indicators per window: RMS, peak value, crest factor (peak/RMS), and kurtosis.

Parameters:

Name Type Description Default
window str

Window size for indicator computation.

'5min'

Returns:

Type Description
DataFrame

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

DataFrame

source_uuid, is_delta, rms, peak, crest_factor, kurtosis.

DataFrame

end is start plus window.