Event Handling — Visual Overview¤
Note
This page zooms into the events layer. For the full library map with every package, class and detector method — searchable and clickable — see Architecture.
How ts-shape turns raw signals into events. Three layers, four archetypes, one canonical event log.
Every detection in ts-shape — whether it comes from one of the 290 built-in detector methods or a user-authored lambda rule — passes through the same three-layer flow:
- Signals — raw timeseries DataFrame columns (booleans, floats, categoricals).
- Events — rows in the canonical
EventLogproduced by a detector method. - Rule — the code or YAML that defines when signals trigger an event, classified into one of four archetypes:
threshold,interval,aggregate,static.
The archetype determines the event's shape (point / interval / summary / static), which standard attributes the rule must populate (e.g. ts_shape:method, ts_shape:lifecycle_state), and which OCEL object types are auto-extracted.
The four diagrams below show one representative scenario per archetype. Read each as a stack: raw signals on top, derived events in the middle, rule definition on the bottom. Dashed links read rule → signal it watches; solid links read rule → event it produces.
Archetype 1 — threshold (point shape)¤
Per-row check: a single sample compared against a reference. Outliers, SPC violations, tolerance deviations, exceedances. One True row → one point event.
Representative scenario. Tool wear: emit one event per torque sample that exceeds 75 Nm while the tool is running.
flowchart TB
subgraph SIG["① Signals — raw DataFrame columns"]
direction LR
S1["<b>torque</b><br/>72 · 74 · <b>79.5</b> · <b>86</b> · 73 · <b>95</b> · 68"]
S2["<b>state</b><br/>run · run · run · run · run · run · idle"]
S3["<b>source_uuid</b><br/>asset-A everywhere"]
end
subgraph EVT["② Events — canonical EventLog rows"]
direction LR
E1["⚠ high_torque @ t₃<br/>severity=warn · value=79.5"]
E2["🛑 high_torque @ t₄<br/>severity=critical · value=86"]
E3["🛑 high_torque @ t₆<br/>severity=critical · value=95"]
end
subgraph RULE["③ Rule — threshold archetype"]
R["<b>OutlierDetectionEvents.detect_outliers_iqr</b><br/>(built-in)<br/>— or —<br/><b>LambdaToolWear.high_torque</b><br/>(YAML rule)<br/><br/>expression: torque > 75 & state == 'run'<br/>activity template: maintenance.tool.high_torque<br/>required standard_attrs: ts_shape:method, ts_shape:direction"]
end
R -.watches.-> S1
R -.watches.-> S2
R ==>|emits| E1
R ==>|emits| E2
R ==>|emits| E3
S3 -.auto-extract→ asset object.-> E1
style SIG fill:#0f2a3d,stroke:#38bdf8,color:#e0f2fe
style EVT fill:#3d2a0f,stroke:#fbbf24,color:#fef3c7
style RULE fill:#1a3a2e,stroke:#34d399,color:#d1fae5
style E1 fill:#78350f,color:#fef3c7
style E2 fill:#7f1d1d,color:#fee2e2
style E3 fill:#7f1d1d,color:#fee2e2
Required standard_attrs for threshold: ts_shape:method, ts_shape:direction.
Archetype 2 — interval (interval shape)¤
Contiguous runs of True samples are coalesced (per group) into one event with start, end, duration. Optional min_duration_s filter rejects short blips (hysteresis).
Representative scenario. Sustained hot-bearing windows per machine: ignore single-sample spikes, flag any window of ≥ 30 s where bearing_temp_c > 85.
flowchart TB
subgraph SIG["① Signals — multi-asset stream"]
direction LR
SA["<b>bearing_temp_c</b> @ asset-A<br/>82 · 86 · 88 · 87 · 84 · 83 · 90 · 82"]
SB["<b>bearing_temp_c</b> @ asset-B<br/>80 · 81 · 82 · 80 · 89 · 90 · 91 · 92"]
SU["<b>source_uuid</b><br/>used as group_by key"]
end
subgraph MASK["② Mask + coalesce per group"]
direction LR
MA["asset-A run 1: 3 samples · 45 s ✓"]
MA2["asset-A run 2: 1 sample · 0 s ✗ drop"]
MB["asset-B run: 4 samples · 45 s ✓"]
end
subgraph EVT["③ Events — interval rows"]
direction LR
EA["🟥 hot_window @ asset-A<br/>start=t₁ · end=t₃ · 45 s · mean=87"]
EB["🟥 hot_window @ asset-B<br/>start=t₄ · end=t₆ · 45 s · mean=90"]
end
subgraph RULE["④ Rule — interval archetype"]
R["<b>MachineStateEvents.detect_run_idle</b> (built-in)<br/>— or —<br/><b>LambdaBearing.hot_window</b> (YAML rule)<br/><br/>expression: bearing_temp_c > 85<br/>min_duration_s: 30 · group_by: [source_uuid]<br/>activity template: maintenance.bearing.hot<br/>required standard_attrs: ts_shape:lifecycle_state"]
end
R -.watches.-> SA
R -.watches.-> SB
R -.group by.-> SU
SA --> MA
SA --> MA2
SB --> MB
MA ==> EA
MB ==> EB
MA2 -. dropped .-x EA
R --> MA
style SIG fill:#0f2a3d,stroke:#38bdf8,color:#e0f2fe
style MASK fill:#2a1a3d,stroke:#a78bfa,color:#ede9fe
style EVT fill:#3d2a0f,stroke:#fbbf24,color:#fef3c7
style RULE fill:#1a3a2e,stroke:#34d399,color:#d1fae5
style EA fill:#7f1d1d,color:#fee2e2
style EB fill:#7f1d1d,color:#fee2e2
style MA2 fill:#3f3f46,color:#a1a1aa,stroke-dasharray: 4 3
Required standard_attrs for interval: ts_shape:lifecycle_state.
Archetype 3 — aggregate (summary shape)¤
Window-based statistics. One row per period × group: per-shift OEE, per-day production, hourly cycle-time stats. The event timestamp marks the period end; ts_shape:start_timestamp marks the period start.
Representative scenario. OEE by shift: roll cycle counts, downtime, and reject counts into one summary row per (shift × asset).
flowchart TB
subgraph SIG["① Signals — multi-source"]
direction LR
SC["<b>cycle_count</b><br/>1 · 1 · 1 · 0 · 1 · 1 · …"]
SR["<b>reject_count</b><br/>0 · 0 · 1 · 0 · 0 · 0 · …"]
SS["<b>state</b> (run/idle/down)"]
SP["<b>part_id, shift_id</b><br/>(context columns)"]
end
subgraph AGG["② Aggregation window"]
direction LR
W1["shift_id = A · 08:00–16:00<br/>parts=412 · rejects=7 · downtime=18min"]
W2["shift_id = B · 16:00–00:00<br/>parts=389 · rejects=4 · downtime=22min"]
end
subgraph EVT["③ Events — summary rows"]
direction LR
EW1["📊 oee_shift @ shift-A<br/>availability=0.95 · performance=0.91 · quality=0.98<br/>OEE=0.85 · sample_count=412"]
EW2["📊 oee_shift @ shift-B<br/>availability=0.93 · performance=0.89 · quality=0.99<br/>OEE=0.82 · sample_count=389"]
end
subgraph RULE["④ Rule — aggregate archetype"]
R["<b>OEECalculator.calculate_oee</b> (built-in)<br/>— or —<br/><b>PartProductionTracking.daily_production_summary</b><br/><br/>group_by: [shift_id, asset]<br/>window: per shift<br/>activity template: production.oee.shift_summary<br/>required standard_attrs: ts_shape:sample_count"]
end
R -.watches.-> SC
R -.watches.-> SR
R -.watches.-> SS
R -.group by.-> SP
SC --> W1
SR --> W1
SS --> W1
SC --> W2
W1 ==> EW1
W2 ==> EW2
style SIG fill:#0f2a3d,stroke:#38bdf8,color:#e0f2fe
style AGG fill:#2a1a3d,stroke:#a78bfa,color:#ede9fe
style EVT fill:#3d2a0f,stroke:#fbbf24,color:#fef3c7
style RULE fill:#1a3a2e,stroke:#34d399,color:#d1fae5
style EW1 fill:#064e3b,color:#d1fae5
style EW2 fill:#064e3b,color:#d1fae5
Required standard_attrs for aggregate: ts_shape:sample_count.
Archetype 4 — static (static shape)¤
No natural time axis. Reference data, snapshots, top-N tables, gauge R&R results. One event per row, timestamped at the export moment so it still fits the canonical schema.
Representative scenario. SPC control-limit calculation: produce a single snapshot per signal capturing UCL/LCL/centre line for downstream rule evaluation.
flowchart TB
subgraph SIG["① Signals — historical baseline window"]
direction LR
SH["<b>value_double</b><br/>(100 historical samples for asset-A · torque)"]
end
subgraph CALC["② Control-limit calculation"]
C["mean = 42.1<br/>std = 1.4<br/>UCL = mean + 3σ = 46.3<br/>LCL = mean − 3σ = 37.9"]
end
subgraph EVT["③ Events — static rows"]
direction LR
ES["📐 spc_limits @ asset-A · torque<br/>method=xbar_r · UCL=46.3 · LCL=37.9 · mean=42.1<br/>sample_count=100"]
end
subgraph RULE["④ Rule — static archetype"]
R["<b>StatisticalProcessControlRuleBased.calculate_control_limits</b><br/>— or —<br/><b>GaugeRepeatabilityEvents.repeatability</b><br/><br/>method: xbar_r / nelson / westgard<br/>activity template: quality.spc.control_limits<br/>required standard_attrs: ts_shape:method"]
end
R -.watches.-> SH
SH --> C
C ==> ES
style SIG fill:#0f2a3d,stroke:#38bdf8,color:#e0f2fe
style CALC fill:#2a1a3d,stroke:#a78bfa,color:#ede9fe
style EVT fill:#3d2a0f,stroke:#fbbf24,color:#fef3c7
style RULE fill:#1a3a2e,stroke:#34d399,color:#d1fae5
style ES fill:#1e3a8a,color:#dbeafe
Required standard_attrs for static: ts_shape:method.
Reading the diagrams¤
| Visual cue | Meaning |
|---|---|
| Blue subgraph | Raw signals — DataFrame columns the detector reads. |
| Purple subgraph | Intermediate computation (mask, coalescing, aggregation window). Not always present. |
| Amber subgraph | Events — rows in the canonical EventLog. Color of an event node hints at severity. |
| Green subgraph | The rule itself — code (built-in detector class.method) or YAML (lambda rule). |
| Dashed arrow | Rule watches this signal — it appears as a column reference in the trigger or as a parameter to the detector constructor. |
| Solid bold arrow | Rule emits this event row. |
| Dotted X arrow | Filtered out (e.g., interval shorter than min_duration_s). |
Where this fits in the rest of the library¤
For the full module map — including loaders, transforms, features, and how the event layer plugs into them — see the architecture chart in Concept. For the canonical event-log schema events ultimately land in, see Event Log (XES & OCEL). For the user-authored path that emits straight into this same flow, see Lambda Rules.