cycle_time_tracking
cycle_time_tracking ¤
Cycle time tracking by part number.
Simple, practical module for cycle time analysis: - Cycle time per part number - Statistics (min, avg, max, std) - Slow cycle detection - Trend analysis
CycleTimeEvents ¤
CycleTimeEvents(
dataframe: DataFrame,
*,
time_column: str = "systime",
event_uuid: str = "prod:cycle_time"
)
Bases: Base
Track cycle times by part number.
Each UUID represents one signal: - part_id_uuid: string signal with current part number - cycle_trigger_uuid: boolean/integer signal for cycle completion
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) stats = ts_shape.CycleTimeEvents(df).cycle_time_statistics("part", "cycle") stats[["part_number", "count", "avg_seconds"]].round(1) part_number count avg_seconds 0 A 7 111.4 1 B 5 198.0
Initialize cycle time tracker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataframe
|
DataFrame
|
Input DataFrame with timeseries data |
required |
time_column
|
str
|
Name of timestamp column (default: 'systime') |
'systime'
|
event_uuid
|
str
|
UUID tagged on derived cycle events (the |
'prod:cycle_time'
|
cycle_time_by_part ¤
cycle_time_by_part(
part_id_uuid: str,
cycle_trigger_uuid: str,
*,
value_column_part: str = "value_string",
value_column_trigger: str = "value_bool",
max_cycle_gap: str | None = None
) -> pd.DataFrame
Calculate cycle time for each part number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
part_id_uuid
|
str
|
UUID for part number signal |
required |
cycle_trigger_uuid
|
str
|
UUID for cycle completion trigger |
required |
value_column_part
|
str
|
Column containing part numbers |
'value_string'
|
value_column_trigger
|
str
|
Column containing cycle triggers |
'value_bool'
|
max_cycle_gap
|
str | None
|
Optional cap (e.g. "5min"). Intervals between consecutive completions longer than this are dropped as inter-cycle downtime rather than reported as a cycle. Without it, a stoppage between completions (a break, a jam) becomes one giant "cycle" that inflates max/avg and is falsely flagged as a slow cycle. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with columns: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) out = ts_shape.CycleTimeEvents(df).cycle_time_by_part("part", "cycle") out[["part_number", "cycle_time_seconds"]].head(3) part_number cycle_time_seconds 0 A 60.0 1 A 120.0 2 A 120.0
cycle_time_statistics ¤
cycle_time_statistics(
part_id_uuid: str,
cycle_trigger_uuid: str,
*,
value_column_part: str = "value_string",
value_column_trigger: str = "value_bool",
max_cycle_gap: str | None = None
) -> pd.DataFrame
Calculate statistics: min, avg, max, std cycle time by part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
part_id_uuid
|
str
|
UUID for part number signal |
required |
cycle_trigger_uuid
|
str
|
UUID for cycle completion trigger |
required |
value_column_part
|
str
|
Column containing part numbers |
'value_string'
|
value_column_trigger
|
str
|
Column containing cycle triggers |
'value_bool'
|
max_cycle_gap
|
str | None
|
Optional cap (e.g. "5min") forwarded to
:meth: |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with statistics per part: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) stats = ts_shape.CycleTimeEvents(df).cycle_time_statistics("part", "cycle") stats[["part_number", "count", "median_seconds", "max_seconds"]] part_number count median_seconds max_seconds 0 A 7 120.0 180.0 1 B 5 150.0 420.0
detect_slow_cycles ¤
detect_slow_cycles(
part_id_uuid: str,
cycle_trigger_uuid: str,
*,
threshold_factor: float = 1.5,
value_column_part: str = "value_string",
value_column_trigger: str = "value_bool",
max_cycle_gap: str | None = None
) -> pd.DataFrame
Identify cycles that exceed normal time by threshold factor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
part_id_uuid
|
str
|
UUID for part number signal |
required |
cycle_trigger_uuid
|
str
|
UUID for cycle completion trigger |
required |
threshold_factor
|
float
|
Cycles slower than median * factor are flagged (default: 1.5) |
1.5
|
value_column_part
|
str
|
Column containing part numbers |
'value_string'
|
value_column_trigger
|
str
|
Column containing cycle triggers |
'value_bool'
|
max_cycle_gap
|
str | None
|
Optional cap (e.g. "5min") forwarded to
:meth: |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with slow cycles: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) slow = ts_shape.CycleTimeEvents(df).detect_slow_cycles("part", "cycle") slow[["part_number", "cycle_time_seconds", "deviation_factor"]] part_number cycle_time_seconds deviation_factor 0 A 180.0 1.5 1 B 240.0 1.6 2 B 420.0 2.8
cycle_time_trend ¤
cycle_time_trend(
part_id_uuid: str,
cycle_trigger_uuid: str,
part_number: str,
*,
window_size: int = 20,
value_column_part: str = "value_string",
value_column_trigger: str = "value_bool",
max_cycle_gap: str | None = None
) -> pd.DataFrame
Analyze cycle time trends for a specific part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
part_id_uuid
|
str
|
UUID for part number signal |
required |
cycle_trigger_uuid
|
str
|
UUID for cycle completion trigger |
required |
part_number
|
str
|
Specific part number to analyze |
required |
window_size
|
int
|
Number of cycles for moving average (default: 20) |
20
|
value_column_part
|
str
|
Column containing part numbers |
'value_string'
|
value_column_trigger
|
str
|
Column containing cycle triggers |
'value_bool'
|
max_cycle_gap
|
str | None
|
Optional cap (e.g. "5min") forwarded to
:meth: |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with trend data: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) trend = ts_shape.CycleTimeEvents(df).cycle_time_trend( ... "part", "cycle", "A", window_size=3) trend[["cycle_time_seconds", "moving_avg", "trend"]].tail(3) cycle_time_seconds moving_avg trend 4 60.0 120.0 improving 5 120.0 120.0 stable 6 120.0 100.0 improving
hourly_cycle_time_summary ¤
hourly_cycle_time_summary(
part_id_uuid: str,
cycle_trigger_uuid: str,
*,
value_column_part: str = "value_string",
value_column_trigger: str = "value_bool",
max_cycle_gap: str | None = None
) -> pd.DataFrame
Hourly summary of cycle times by part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
part_id_uuid
|
str
|
UUID for part number signal |
required |
cycle_trigger_uuid
|
str
|
UUID for cycle completion trigger |
required |
value_column_part
|
str
|
Column containing part numbers |
'value_string'
|
value_column_trigger
|
str
|
Column containing cycle triggers |
'value_bool'
|
max_cycle_gap
|
str | None
|
Optional cap (e.g. "5min") forwarded to
:meth: |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with hourly statistics: |
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
DataFrame
|
|
Example
import pandas as pd, ts_shape df = pd.concat([ts_shape.make_id_signal("part", ["A", "B"], hold=30), ... ts_shape.make_timeseries(["cycle"], n_points=60, value_column="value_bool")]) hourly = ts_shape.CycleTimeEvents(df).hourly_cycle_time_summary("part", "cycle") hourly[["part_number", "cycles_completed", "avg_cycle_time"]] part_number cycles_completed avg_cycle_time 0 A 7 111.428571 1 B 5 198.000000