Skip to content

part_tracking

part_tracking ¤

Production tracking by part number.

Simple, practical module for daily production reporting: - How many parts were produced? - Production by part number and time window - Daily summaries

Counters are assumed to be monotonically increasing during normal operation. Many real-world counters reset back to zero (or to a lower value) - for example at a shift change, a part change, or a controller restart. A naive last - first calculation silently loses all of the production that happened in a window where a reset occurred. Pass handle_resets=True to account for these resets, and use :meth:PartProductionTracking.detect_resets to inspect when they happened.

PartProductionTracking ¤

PartProductionTracking(
    dataframe: DataFrame, *, time_column: str = "systime"
)

Bases: Base

Track production quantities by part number.

Each UUID represents one signal: - part_id_uuid: string signal with current part number - counter_uuid: monotonic counter for production count

The counter is expected to increase as parts are produced. If the counter is reset during operation (back to zero or a lower value), enable handle_resets so the reset is treated as new production instead of being discarded.

Example usage

tracker = PartProductionTracking(df)

Hourly production by part, accounting for counter resets¤

hourly = tracker.production_by_part( part_id_uuid='part_number_signal', counter_uuid='counter_signal', window='1h', handle_resets=True, )

Daily summary¤

daily = tracker.daily_production_summary( part_id_uuid='part_number_signal', counter_uuid='counter_signal', handle_resets=True, )

When did the counter reset?¤

resets = tracker.detect_resets( part_id_uuid='part_number_signal', counter_uuid='counter_signal', )

Initialize part production tracker.

Parameters:

Name Type Description Default
dataframe DataFrame

Input DataFrame with timeseries data

required
time_column str

Name of timestamp column (default: 'systime')

'systime'

production_by_part ¤

production_by_part(
    part_id_uuid: str,
    counter_uuid: str,
    *,
    window: str = "1h",
    value_column_part: str = "value_string",
    value_column_counter: str = "value_integer",
    handle_resets: bool = False
) -> pd.DataFrame

Calculate production quantity per part number.

Parameters:

Name Type Description Default
part_id_uuid str

UUID for part number signal

required
counter_uuid str

UUID for production counter

required
window str

Time window for aggregation (e.g., '1h', '8h', '1d')

'1h'
value_column_part str

Column containing part numbers

'value_string'
value_column_counter str

Column containing counter values

'value_integer'
handle_resets bool

When True, treat a decreasing counter as a reset and count the production after the reset instead of losing it. The result gains a resets column with the number of resets observed in each window. When False (default), the quantity is simply max(0, last_count - first_count) and a window containing a reset reports 0.

False

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • start: Start of time window
DataFrame
  • part_number: Part number/ID
DataFrame
  • quantity: Parts produced in window
DataFrame
  • first_count: Counter value at window start
DataFrame
  • last_count: Counter value at window end
DataFrame
  • resets: Number of counter resets in window (only when handle_resets=True)
Example

production_by_part('part_id', 'counter', window='1h') start part_number quantity first_count last_count 0 2024-01-01 08:00:00 PART_A 150 1000 1150 1 2024-01-01 09:00:00 PART_A 145 1150 1295 2 2024-01-01 10:00:00 PART_B 98 1295 1393

With handle_resets=True, a window where the counter drops from 432 to 61 reports a quantity of 61 (and resets=1) instead of 0.

detect_resets ¤

detect_resets(
    part_id_uuid: str,
    counter_uuid: str,
    *,
    value_column_part: str = "value_string",
    value_column_counter: str = "value_integer"
) -> pd.DataFrame

Find the points in time where the counter was reset.

A reset is any reading where the counter value is lower than the previous reading.

Parameters:

Name Type Description Default
part_id_uuid str

UUID for part number signal

required
counter_uuid str

UUID for production counter

required
value_column_part str

Column containing part numbers

'value_string'
value_column_counter str

Column containing counter values

'value_integer'

Returns:

Type Description
DataFrame

DataFrame with one row per reset and columns:

DataFrame
  • : Timestamp of the reading after the reset
DataFrame
  • part_number: Active part number at the reset
DataFrame
  • count_before: Counter value just before the reset
DataFrame
  • count_after: Counter value just after the reset
DataFrame
  • drop: How far the counter fell (count_before - count_after)
Example

detect_resets('part_id', 'counter') systime part_number count_before count_after drop 0 2026-06-15 17:00:00 8842580 432 61 371 1 2026-06-16 19:00:00 9423376 854 0 854

daily_production_summary ¤

daily_production_summary(
    part_id_uuid: str,
    counter_uuid: str,
    *,
    value_column_part: str = "value_string",
    value_column_counter: str = "value_integer",
    handle_resets: bool = False
) -> pd.DataFrame

Daily production summary by part number.

Parameters:

Name Type Description Default
part_id_uuid str

UUID for part number signal

required
counter_uuid str

UUID for production counter

required
value_column_part str

Column containing part numbers

'value_string'
value_column_counter str

Column containing counter values

'value_integer'
handle_resets bool

Account for counter resets (see :meth:production_by_part). Adds a resets column with the number of resets observed that day.

False

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • date: Production date
DataFrame
  • part_number: Part number/ID
DataFrame
  • total_quantity: Total parts produced that day
DataFrame
  • hours_active: Number of hours with production
DataFrame
  • resets: Number of counter resets that day (only when handle_resets=True)
Example

daily_production_summary('part_id', 'counter') date part_number total_quantity hours_active 0 2024-01-01 PART_A 1200 8 1 2024-01-01 PART_B 850 6 2 2024-01-02 PART_A 1150 8

production_totals ¤

production_totals(
    part_id_uuid: str,
    counter_uuid: str,
    *,
    start_date: str | None = None,
    end_date: str | None = None,
    value_column_part: str = "value_string",
    value_column_counter: str = "value_integer",
    handle_resets: bool = False
) -> pd.DataFrame

Total production by part number for a date range.

Parameters:

Name Type Description Default
part_id_uuid str

UUID for part number signal

required
counter_uuid str

UUID for production counter

required
start_date str | None

Start date 'YYYY-MM-DD' (optional)

None
end_date str | None

End date 'YYYY-MM-DD' (optional)

None
value_column_part str

Column containing part numbers

'value_string'
value_column_counter str

Column containing counter values

'value_integer'
handle_resets bool

Account for counter resets (see :meth:production_by_part). Adds a resets column with the total number of resets in the range.

False

Returns:

Type Description
DataFrame

DataFrame with total production per part

Example

production_totals('part_id', 'counter', ... start_date='2024-01-01', end_date='2024-01-07') part_number total_quantity days_produced 0 PART_A 8450 5 1 PART_B 6200 4