Skip to content

init

development ¤

Development Events

Detectors for product and process development (R&D) workflows: design of experiments, design-space qualification, golden-batch comparison, recipe phase adherence, and outcome-driven critical parameter ranking.

These detectors target activities that happen before (or alongside) commercial production -- the work of process development engineers, formulation scientists, and validation teams -- as opposed to the operations-focused detectors in the other event packs.

  • DesignOfExperimentsEvents: Segment continuous signals into DOE runs and estimate main effects per factor.
  • detect_runs: Identify stable factor-setting intervals as DOE runs.
  • compute_effects: Aggregate run response and main effects per factor.

  • DesignSpaceEvents: Establish a multivariate qualified operating window from R&D data and monitor commercial operation against it.

  • fit_box: Per-axis bounds (quantile or min/max).
  • fit_hull: scipy convex hull of the qualified region.
  • detect_excursions: Intervals where operation leaves the design space.
  • boundary_proximity: Per-sample distance to the design-space boundary.

  • GoldenBatchDeviationEvents: Quantify deviation of new batch trajectories against a reference (golden) batch.

  • compare: Pointwise, area-between-curves, or DTW deviation.
  • phase_breakdown: Deviation broken down by recipe phase.

  • RecipePhaseAdherenceEvents: Evaluate batch recipe phases against a declarative spec (duration, hold value, ramp rate, peak).

  • evaluate: One event per phase with pass/fail and failed criteria.

  • CriticalParameterRankingEvents: Rank candidate input parameters by their statistical association with a quality outcome.

  • rank: Pearson / Spearman correlation or one-way ANOVA F-statistic.
  • top_drivers: Filter and sort the ranking to the top-k significant.

CriticalParameterRankingEvents ¤

CriticalParameterRankingEvents(
    dataframe: DataFrame,
    *,
    event_uuid: str = "dev:cpp_ranking",
    time_column: str = "systime"
)

Bases: Base

Rank input parameters by their statistical link to a quality outcome.

The detector operates on a per-run table where each row is a completed run (batch, DOE point, shift), each candidate column is the aggregated value of an input parameter during that run, and an outcome column holds the quality / yield measurement of interest.

The constructor still accepts a long-form dataframe for symmetry with the rest of ts-shape, but :meth:rank requires the wide-format per-run table directly because aggregating "the right number" for each parameter is a development-engineer judgment call (mean of the hold phase? settled value? peak?) that varies by parameter.

rank ¤

rank(
    per_run_df: DataFrame,
    candidate_columns: list[str],
    outcome_column: str,
    *,
    method: str = "spearman",
    anova_bins: int = 3
) -> pd.DataFrame

Rank candidate parameters by statistical association with the outcome.

Parameters:

Name Type Description Default
per_run_df DataFrame

One row per run, one column per candidate parameter, plus an outcome column.

required
candidate_columns list[str]

Columns to evaluate as candidate CPPs.

required
outcome_column str

Outcome (response) column.

required
method str

"pearson", "spearman", or "anova_f".

'spearman'
anova_bins int

Only used for method="anova_f". Each candidate column is quantile-binned into this many groups before the one-way ANOVA is run.

3

Returns:

Type Description
DataFrame

Summary DataFrame: parameter, method, statistic,

DataFrame

p_value, abs_effect_size, rank. Sorted by

DataFrame

abs_effect_size descending so the top driver is the first

DataFrame

row.

top_drivers ¤

top_drivers(
    per_run_df: DataFrame,
    candidate_columns: list[str],
    outcome_column: str,
    *,
    method: str = "spearman",
    k: int = 5,
    alpha: float = 0.05,
    anova_bins: int = 3
) -> pd.DataFrame

Return the top-k candidates with p_value <= alpha.

Wraps :meth:rank and filters by significance. The result keeps the same column schema as :meth:rank.

DesignOfExperimentsEvents ¤

DesignOfExperimentsEvents(
    dataframe: DataFrame,
    factor_uuids: list[str],
    *,
    event_uuid: str = "dev:doe_run",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Segment continuous process data into DOE runs and estimate effects.

A run is a contiguous interval during which every factor signal sits on a single discrete level (low rolling std relative to its tolerance) long enough to be a deliberate experimental setting rather than a transient. Tagging each run with its factor-level combination produces an experimental dataset that downstream effect estimation can act on.

detect_runs ¤

detect_runs(
    *,
    min_duration: str = "5min",
    stability_tol: float = 0.02,
    n_levels: dict[str, int] | None = None
) -> pd.DataFrame

Identify DOE runs as stable intervals across all factor signals.

Parameters:

Name Type Description Default
min_duration str

Minimum run length to be reported (e.g. "5min"). Shorter stable intervals are treated as transients.

'5min'
stability_tol float

Maximum relative range (max - min) / (|mean| + eps) permitted within a run for each factor. Default 2%.

0.02
n_levels dict[str, int] | None

Optional {factor_uuid: k} mapping. When given, the factor values are quantile-binned into k levels; otherwise the rounded observed value is used as the level.

None

Returns:

Type Description
DataFrame

Interval-shape DataFrame with columns: start, end,

DataFrame

duration_seconds, uuid, run_id, and one

DataFrame

factor__<uuid>_level column per factor.

compute_effects ¤

compute_effects(
    response_uuid: str,
    *,
    statistic: str = "mean",
    min_duration: str = "5min",
    stability_tol: float = 0.02,
    n_levels: dict[str, int] | None = None
) -> pd.DataFrame

Aggregate the response signal per factor level (main effects).

Parameters:

Name Type Description Default
response_uuid str

UUID of the response (output) signal.

required
statistic str

Aggregation applied to the response within each run. One of "mean" (default), "median", "max", "min", or "settled" -- the latter takes the mean of the final third of the run, useful for response signals that need to stabilise after a factor change.

'mean'
min_duration str

Forwarded to :meth:detect_runs.

'5min'
stability_tol float

Forwarded to :meth:detect_runs.

0.02
n_levels dict[str, int] | None

Forwarded to :meth:detect_runs.

None

Returns:

Type Description
DataFrame

Summary DataFrame with one row per (factor, level), columns:

DataFrame

factor, level, n_runs, response_mean,

DataFrame

response_std, main_effect.

DataFrame

main_effect is response_mean minus the grand mean

DataFrame

across all runs.

DesignSpaceEvents ¤

DesignSpaceEvents(
    dataframe: DataFrame,
    cpp_uuids: list[str],
    *,
    event_uuid: str = "dev:design_space",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Fit and monitor a multivariate qualified operating window.

Workflow::

ds = DesignSpaceEvents(qualification_df, cpp_uuids=[...])
ds.fit_box()                    # or ds.fit_hull()
excursions = ds.detect_excursions(operation_df)
near = ds.boundary_proximity(operation_df, warn_margin=0.1)

fit_box ¤

fit_box(
    quantiles: tuple[float, float] = (0.05, 0.95)
) -> DesignSpaceEvents

Fit per-axis bounds from the qualification data.

Parameters:

Name Type Description Default
quantiles tuple[float, float]

(low, high) quantile pair used to set each axis's bounds. (0.0, 1.0) reduces to absolute min/max.

(0.05, 0.95)

Returns:

Type Description
DesignSpaceEvents

self to allow DesignSpaceEvents(...).fit_box() chaining.

fit_hull ¤

fit_hull() -> DesignSpaceEvents

Fit a convex hull around the qualification data.

Requires :mod:scipy.spatial.ConvexHull. The hull captures correlation between CPPs that a per-axis box cannot, at the cost of needing len(cpps) + 1 non-degenerate qualification points.

Returns:

Type Description
DesignSpaceEvents

self for chaining.

detect_excursions ¤

detect_excursions(operation_df: DataFrame) -> pd.DataFrame

Find contiguous intervals where operation leaves the design space.

Parameters:

Name Type Description Default
operation_df DataFrame

Long-form signal DataFrame containing all CPP signals; only the configured cpp_uuids are used.

required

Returns:

Type Description
DataFrame

Interval-shape DataFrame with columns: start, end,

DataFrame

duration_seconds, uuid, excursion_mode

DataFrame

("box" / "hull").

boundary_proximity ¤

boundary_proximity(
    operation_df: DataFrame, warn_margin: float = 0.1
) -> pd.DataFrame

Emit point events for samples within warn_margin of the boundary.

Only supported for the fit_box mode -- a convex hull's boundary distance is more expensive to compute per facet and is not in scope for this detector. Call :meth:detect_excursions for hull-fitted spaces.

Parameters:

Name Type Description Default
operation_df DataFrame

Long-form signal DataFrame.

required
warn_margin float

Normalised distance threshold (fraction of the axis span). A sample is reported when its closest axis margin is below this value while still inside the box.

0.1

Returns:

Type Description
DataFrame

Point-shape DataFrame: systime, uuid,

DataFrame

signed_margin, closest_axis.

GoldenBatchDeviationEvents ¤

GoldenBatchDeviationEvents(
    reference_df: DataFrame,
    signal_uuid: str,
    *,
    event_uuid: str = "dev:golden_batch_deviation",
    value_column: str = "value_double",
    time_column: str = "systime",
    n_resample: int = 256
)

Bases: Base

Quantify deviation of a new batch from a golden reference batch.

compare ¤

compare(
    batch_df: DataFrame,
    *,
    mode: str = "pointwise",
    dtw_band_frac: float = 0.1
) -> pd.DataFrame

Compare a single new batch to the stored golden reference.

Parameters:

Name Type Description Default
batch_df DataFrame

Long-form DataFrame containing the candidate batch's signal. The configured signal_uuid is used to extract the trace.

required
mode str

"pointwise", "area", or "dtw".

'pointwise'
dtw_band_frac float

Sakoe-Chiba band width as a fraction of the resampled grid length. Only used for mode="dtw".

0.1

Returns:

Type Description
DataFrame

Interval-shape DataFrame with one row, columns: start,

DataFrame

end, duration_seconds, uuid, mode,

DataFrame

deviation_score, max_abs_residual,

DataFrame

batch_time_at_max.

phase_breakdown ¤

phase_breakdown(
    batch_df: DataFrame,
    phase_df: DataFrame,
    *,
    phase_uuid: str
) -> pd.DataFrame

Per-phase deviation of a batch against the golden reference.

The reference batch is sliced into phases by the same boundaries applied to the candidate batch -- this assumes the phase sequence is consistent across runs, which is true for recipes that are executed phase-by-phase under recipe control.

Parameters:

Name Type Description Default
batch_df DataFrame

Long-form signal DataFrame for the candidate batch.

required
phase_df DataFrame

Long-form DataFrame containing the phase-tracking signal, where value_string (or the configured value column) carries the phase name.

required
phase_uuid str

UUID of the phase signal in phase_df.

required

Returns:

Type Description
DataFrame

Summary DataFrame: start, end, duration_seconds,

DataFrame

phase, deviation_score, max_abs_residual.

RecipePhaseAdherenceEvents ¤

RecipePhaseAdherenceEvents(
    dataframe: DataFrame,
    phase_uuid: str,
    value_uuid: str,
    spec: dict[str, dict[str, Any]],
    *,
    event_uuid: str = "dev:recipe_phase_adherence",
    value_column: str = "value_double",
    time_column: str = "systime"
)

Bases: Base

Evaluate batch recipe phases against a declarative spec.

The spec is a mapping {phase_name: criteria_dict}. Recognised criteria keys (all optional) per phase:

  • duration_s -- (min, max) seconds.
  • hold_value -- (min, max) for the mean value during the phase.
  • ramp_rate_max -- maximum absolute slope (value-units per second) computed from the first to the last sample.
  • peak_value -- (min, max) for the phase max.
  • trough_value -- (min, max) for the phase min.

Missing criteria are not checked. A phase whose name is absent from the spec is reported with pass=True and an empty criteria_failed list (the phase was observed but not constrained).

evaluate ¤

evaluate() -> pd.DataFrame

Evaluate every observed phase interval against the spec.

Returns:

Name Type Description
DataFrame

Interval-shape DataFrame, one row per phase occurrence,

columns DataFrame

start, end, duration_seconds, uuid,

DataFrame

phase, mean_value, min_value, max_value,

DataFrame

observed_ramp_per_s, criteria_failed (list[str]),

DataFrame

pass.