DutyCycleEvents¤
On/off intervals, duty cycle per window, transition counts and excessive cycling from one boolean signal (True = on), e.g. a heater, motor or valve.
ts_shape.events.production.duty_cycle · Production guide · API reference
Example¤
import numpy as np
import pandas as pd
from ts_shape.events.production.duty_cycle import DutyCycleEvents
df = pd.DataFrame({
"systime": pd.date_range("2024-01-01 06:00", periods=3600, freq="1s"),
"uuid": "oven1:heater_on",
"value_bool": np.arange(3600) % 90 < 60, # on 60 s, off 30 s
})
dc = DutyCycleEvents(df, signal_uuid="oven1:heater_on")
result = dc.duty_cycle_by_window(window="15min")
print(result[["start", "on_time", "off_time", "duty_cycle_pct"]])
intervals = dc.on_off_intervals()
excessive = dc.excessive_cycling(max_transitions=20, window="15min")
Methods¤
| Method | Returns |
|---|---|
on_off_intervals(max_gap=None) |
every interval: start, end, state (on/off), duration_seconds, duration (Timedelta). With max_gap (e.g. "15min") an interval ends at its last sample before a longer gap and a new one starts after it |
duty_cycle_by_window(window='1h', time_weighted=True) |
per window: on_time, off_time, duty_cycle_pct |
cycle_count(window='1h') |
per window: on_count, off_count, total_transitions |
excessive_cycling(max_transitions=20, window='1h') |
windows above max_transitions: transition_count, avg_on_duration, avg_off_duration (seconds) |
Notes¤
- Missing values count as off.
- Intervals close at the next transition by default (
interval_end="next_change"), so signals that only log a row per change are measured correctly.interval_end="last_sample"ends each interval at its own last sample. time_weighted=True(default) weights each sample by the time to the next one.time_weighted=Falseaverages the samples, which matches the time share only for uniform sampling (On@09:00, Off@09:59reads 50 %).- For absolute run hours, start counts and an hour meter, use RuntimeAccountingEvents.