Skip to content

scrap_tracking

scrap_tracking ¤

Scrap and material waste tracking.

Track material waste and scrap (different from NOK parts): - Scrap by shift and reason - Scrap cost calculation - Scrap trends over time

ScrapEvents ¤

ScrapEvents(
    dataframe: DataFrame,
    *,
    time_column: str = "systime",
    shift_definitions: (
        dict[str, tuple[str, str]] | None
    ) = None
)

Bases: Base

Track material scrap and waste.

Each UUID represents one signal: - scrap_uuid: scrap weight or count signal - reason_uuid: scrap reason code (optional) - part_id_uuid: part number / material type (optional)

Merge keys: [date, shift] for shift-level, [period] for trend, [reason] for reason-level, [part_number] for part-level.

Pipeline example::

scrap = ScrapEvents(df)
shift_scrap = scrap.scrap_by_shift('scrap_weight')
# → merge with ShiftReportEvents.shift_production() on [date, shift]
# → merge with QualityEvents.nok_by_shift() on [date, shift]
cost = scrap.scrap_cost('scrap_weight', 'part_id', {'A': 12.5})
# → merge with QualityEvents.quality_by_part() on [part_number]
Example

import pandas as pd, ts_shape scrap = ts_shape.make_timeseries(["scrap_kg"], n_points=20, freq="1min", ... baseline=0.0, noise=0, drift=9.5) reason = ts_shape.make_id_signal("reason", ["Burr", "Crack"], freq="1min") out = ts_shape.ScrapEvents(pd.concat([scrap, reason])).scrap_by_reason( ... "scrap_kg", "reason") out[["reason", "scrap_quantity", "share_of_total_pct"]].round(1) reason scrap_quantity share_of_total_pct 0 Crack 5.0 52.6 1 Burr 4.5 47.4

scrap_by_shift ¤

scrap_by_shift(
    scrap_uuid: str,
    *,
    value_column: str = "value_double",
    handle_resets: bool = True,
    production_day: bool = True
) -> pd.DataFrame

Scrap quantity per shift.

Parameters:

Name Type Description Default
scrap_uuid str

UUID for scrap weight/count signal.

required
value_column str

Column containing scrap values.

'value_double'
handle_resets bool

When True (default), treat a decreasing counter as a reset and count the scrap accumulated after the reset instead of losing it. The increments are computed once over the whole signal and booked to the shift of the reading that reports them, so the shifts add up to the signal total. The result gains a resets column with the number of resets observed in each shift. When False, the quantity is max(0, last - first) of the shift's own readings: a shift containing a reset reports too little (often 0) and the production between two shifts' readings is lost.

True
production_day bool

When True, an overnight shift's post-midnight readings are attributed to the shift's start date, so a night shift is one contiguous (date, shift) group. Default True; False groups by raw calendar date, which splits a night shift across two rows. Only affects overnight schedules.

True

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • start, end, duration_seconds: the shift window from shift_definitions (date at the shift start time, tz-aware in the data's tz; an overnight shift ends on the next day)
DataFrame
  • date, shift, scrap_quantity
DataFrame
  • resets: Number of counter resets in the shift (only when handle_resets=True)

scrap_by_reason ¤

scrap_by_reason(
    scrap_uuid: str,
    reason_uuid: str,
    *,
    value_column_scrap: str = "value_double",
    value_column_reason: str = "value_string",
    handle_resets: bool = True
) -> pd.DataFrame

Scrap quantity by reason code.

Parameters:

Name Type Description Default
scrap_uuid str

UUID for scrap weight/count signal.

required
reason_uuid str

UUID for scrap reason code signal.

required
value_column_scrap str

Column containing scrap values.

'value_double'
value_column_reason str

Column containing reason codes.

'value_string'
handle_resets bool

When True (default), treat a decreasing counter as a reset and count the scrap accumulated after the reset. The reason is attached to a single global counter, so the reset-aware quantity is the sum of per-reading increments over the full time-sorted series, grouped by reason -- this also corrects the over-count that last - first produces when reasons alternate over a non-contiguous group. The result gains a resets column with the number of resets attributed to each reason. When False, the quantity is max(0, last - first) per reason group and a reset is lost.

True

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • reason, scrap_quantity, pct_of_total
DataFrame
  • resets: Number of counter resets for the reason (only when handle_resets=True)
DataFrame

Canonical twin columns: share_of_total_pct (after pct_of_total); each

DataFrame

holds the same values as the deprecated column right before it, which is

DataFrame

removed in the next major release.

scrap_cost ¤

scrap_cost(
    scrap_uuid: str,
    part_id_uuid: str,
    material_costs: dict[str, float],
    *,
    value_column_scrap: str = "value_double",
    value_column_part: str = "value_string",
    handle_resets: bool = True
) -> pd.DataFrame

Convert scrap quantities to monetary cost.

Parameters:

Name Type Description Default
scrap_uuid str

UUID for scrap weight/count signal.

required
part_id_uuid str

UUID for part number / material type signal.

required
material_costs dict[str, float]

Dict mapping part numbers to cost per unit scrap.

required
value_column_scrap str

Column containing scrap values.

'value_double'
value_column_part str

Column containing part numbers.

'value_string'
handle_resets bool

When True (default), treat a decreasing counter as a reset and count the scrap accumulated after the reset. The increments are computed once over the whole signal and booked to the part of the reading that reports them, so the parts add up to the signal total (also when parts alternate). The result gains a resets column with the number of resets observed for each part. When False, the quantity is max(0, last - first) per part and a reset is lost.

True

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • part_number, scrap_quantity, cost_per_unit, total_cost
DataFrame
  • resets: Number of counter resets for the part (only when handle_resets=True)

scrap_trend ¤

scrap_trend(
    scrap_uuid: str,
    *,
    value_column: str = "value_double",
    window: str = "1D",
    handle_resets: bool = True
) -> pd.DataFrame

Track scrap quantity trend over time.

Parameters:

Name Type Description Default
scrap_uuid str

UUID for scrap weight/count signal.

required
value_column str

Column containing scrap values.

'value_double'
window str

Time window for aggregation (default '1D').

'1D'
handle_resets bool

When True (default), treat a decreasing counter as a reset and count the scrap accumulated after the reset. The increments are computed once over the whole signal and booked to the period of the reading that reports them, so the periods add up to the signal total. The result gains a resets column with the number of resets observed in each period. When False, the quantity is max(0, last - first) of the period's own readings: a reset and the production between two periods' readings are lost.

True

Returns:

Type Description
DataFrame

DataFrame with columns:

DataFrame
  • start, end (start + window), duration_seconds
DataFrame
  • period, scrap_quantity
DataFrame
  • resets: Number of counter resets in the period (only when handle_resets=True)