cycles_extractor
cycles_extractor ¤
Cut a signal into production cycles.
Every process_* method returns one row per cycle with the columns
cycle_start, cycle_end, cycle_uuid, is_complete and the
canonical interval columns start, end, duration_seconds, uuid
("cycles:<method>") and source_uuid (the start signal). Rules shared by
all methods:
- Only the rows of
start_uuid(andend_uuid) are read; other signals in the frame are ignored. A frame without auuidcolumn is taken as one pre-filtered signal. - Time columns keep the input's dtype (a tz-aware
systimestays tz-aware). - An end closes the cycle that is open at that moment. At one timestamp, an end is applied before a start, so back-to-back cycles may share a timestamp (the end of one is the start of the next).
- A second start while a cycle is open aborts the open cycle: it stays in the
output with
cycle_end = NaTandis_complete = False, and the end goes to the newer start. Cycles never overlap. - An end with no open cycle (for example before the first start) is ignored
and counted in
get_extraction_stats()["unmatched_ends"]. is_completeis True only when both boundaries were seen. A cycle with no end (the last one, or an aborted one) hascycle_end = NaT. A cycle that was already running at the first sample (its real start lies before the data) keeps its observed end but hasis_complete = False.- Several start rows at the same timestamp are one start.
cycle_uuidis deterministic: the same signal, method and start time always give the same id, so ids are stable across runs and unique within a result.- No cycles: an empty frame with the full column set.
CycleExtractor ¤
CycleExtractor(
dataframe: DataFrame,
start_uuid: str,
end_uuid: str | None = None,
value_change_threshold: float = 0.0,
*,
time_column: str = "systime",
uuid_column: str = "uuid"
)
Bases: Base
Class for processing cycles based on different criteria.
Initializes the class with the data and the UUIDs for cycle start and end.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataframe
|
DataFrame
|
Input DataFrame with cycle data |
required |
start_uuid
|
str
|
UUID for cycle start variable |
required |
end_uuid
|
str | None
|
UUID for cycle end variable (defaults to start_uuid) |
None
|
value_change_threshold
|
float
|
Minimum threshold for considering a value change significant (default: 0.0) |
0.0
|
time_column
|
str
|
Timestamp column. Default |
'systime'
|
uuid_column
|
str
|
Signal identifier column. Default |
'uuid'
|
Raises:
| Type | Description |
|---|---|
ColumnNotFoundError
|
If |
ValueError
|
If |
process_persistent_cycle ¤
process_persistent_cycle() -> pd.DataFrame
Processes cycles where the value of the variable stays true during the cycle.
A cycle starts at a rising edge (False -> True) and ends at the next
falling edge (True -> False), i.e. at the first False sample. A missing
sample holds the previous state. A signal already True at its first
sample gives a first cycle with is_complete = False.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); empty, with the full column set, when no cycle is found. |
process_trigger_cycle ¤
process_trigger_cycle() -> pd.DataFrame
Processes cycles triggered by a true pulse (true, then back to false).
Each trigger starts a cycle that ends at the next trigger. A trigger is a rising edge (False -> True); for a signal that is never False (an event log of True rows) every row is a trigger. The last trigger gives an incomplete cycle.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); empty, with the full column set, when no cycle is found. |
process_separate_start_end_cycle ¤
process_separate_start_end_cycle() -> pd.DataFrame
Processes cycles where different variables indicate cycle start and end.
Start events are the True events of start_uuid, end events the True
events of end_uuid (a held True counts once, at its rising edge; a
signal that is never False is an event log where every True row
counts). An end closes the open cycle; a second start aborts it. When
end_uuid equals start_uuid (or the frame has no uuid
column), each event closes the previous cycle and opens the next.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); empty, with the full column set, when no cycle is found. |
process_step_sequence ¤
process_step_sequence(
start_step: int, end_step: int
) -> pd.DataFrame
Processes cycles based on a step sequence, where specific integer values denote cycle start and end.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start_step
|
int
|
|
required |
end_step
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); |
process_state_change_cycle ¤
process_state_change_cycle() -> pd.DataFrame
Processes cycles where the start of a new cycle is the end of the previous cycle.
Every sample of the signal is a boundary: a cycle runs from one sample to the next later one. The first cycle starts at the first sample, whose state began before the data, so it is marked incomplete.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); empty, with the full column set, when no cycle is found. |
process_value_change_cycle ¤
process_value_change_cycle() -> pd.DataFrame
Processes cycles where a change in the value indicates a new cycle.
A sample is a boundary when one of its value columns differs from the
previous sample: numbers by more than value_change_threshold
(compared sample to sample), bools and strings by any change. A missing
value holds the previous one. The first sample is a boundary too; its
cycle began before the data and is marked incomplete.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per cycle (see the module docstring); empty, with the full column set, when no cycle is found. |
validate_cycles ¤
validate_cycles(
cycle_df: DataFrame,
min_duration: str = "1s",
max_duration: str = "1h",
warn: bool = True,
) -> pd.DataFrame
Validate cycles based on duration constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cycle_df
|
DataFrame
|
DataFrame with cycle data (output from process_* methods) |
required |
min_duration
|
str
|
Minimum acceptable cycle duration (default: '1s') |
'1s'
|
max_duration
|
str
|
Maximum acceptable cycle duration (default: '1h') |
'1h'
|
warn
|
bool
|
Whether to emit a
:class: |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
A copy of |
detect_overlapping_cycles ¤
detect_overlapping_cycles(
cycle_df: DataFrame, resolve: str = "flag"
) -> pd.DataFrame
Detect and optionally resolve overlapping cycles.
Two cycles overlap when one starts strictly before the other ends, so back-to-back cycles sharing a timestamp do not overlap. Only cycles with a known end are compared.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cycle_df
|
DataFrame
|
DataFrame with cycle data |
required |
resolve
|
str
|
How to handle overlaps - 'flag' (mark only), 'keep_first' (earliest start wins), 'keep_last' (latest start wins), 'keep_longest' (longest wins). Resolution is greedy, so the kept cycles never overlap and a cycle is dropped only when it overlaps a kept one. |
'flag'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
For an unknown |
suggest_method ¤
suggest_method() -> dict[str, Any]
Suggest the best cycle extraction method based on data characteristics.
Analyzes the start signal's rows to recommend extraction method(s).
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary with method suggestions and reasoning |
get_extraction_stats ¤
get_extraction_stats() -> dict[str, Any]
Get statistics about the last cycle extraction.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary with |