Skip to content

Index

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.
  • 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 | None = None,
    *,
    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.

:meth:rank takes the wide 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. The constructor's long-format dataframe is optional and not used by :meth:rank: CriticalParameterRankingEvents().rank(runs, ...) works without a time column.

Example

import pandas as pd runs = pd.DataFrame({"temp": [180, 185, 190, 195, 200], ... "speed": [5, 3, 4, 2, 1], ... "yield_pct": [90, 92, 94, 96, 98]}) ranked = CriticalParameterRankingEvents().rank( ... runs, ["temp", "speed"], "yield_pct") ranked["parameter"].tolist() ['temp', 'speed']

Parameters:

Name Type Description Default
dataframe DataFrame | None

Optional long-format data; :meth:rank does not use it.

None
event_uuid str

uuid of the emitted rows.

'dev:cpp_ranking'
time_column str

Timestamp column of dataframe.

'systime'

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.

Raises:

Type Description
ColumnNotFoundError

If outcome_column is not in per_run_df (a ValueError subclass).

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.

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". Default "spearman".

'spearman'
k int

Maximum number of significant parameters to return.

5
alpha float

Significance level; only parameters with p_value <= alpha are kept.

0.05
anova_bins int

Only used for method="anova_f"; number of quantile bins per candidate column.

3

Returns:

Type Description
DataFrame

Same columns as :meth:rank (parameter, method,

DataFrame

statistic, p_value, abs_effect_size, rank),

DataFrame

limited to at most k significant rows.

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, source_uuid (the comma-joined

DataFrame

factor UUIDs), run_id, and one factor__<uuid>_level column

DataFrame

per factor.

effects ¤

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

Normalized 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, expressed in normalized batch time (the same 0..1 axis compare uses): a phase spanning the fraction [a, b] of the candidate batch (first to last candidate sample) is compared against the fraction [a, b] of the golden batch. Both slices are resampled to n_resample points. This assumes the phase sequence and relative phase lengths are 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}. Recognized criteria keys (all optional) per phase:

  • duration_seconds -- (min, max) seconds. duration_s is the deprecated spelling of the same criterion: it still works, with a DeprecationWarning, until the next major release (giving both for one phase raises ValueError); criteria_failed names the key the spec used.
  • 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(
    *,
    interval_end: str = "next_change",
    data_end: Timestamp | None = None
) -> pd.DataFrame

Evaluate every observed phase interval against the spec.

Parameters:

Name Type Description Default
interval_end str

How each phase interval is closed. "next_change" (default) closes a phase at the next phase change; value samples are taken from [start, end) (the sample at the transition belongs to the next phase), and the final phase is closed at data_end when given, otherwise at its own last sample. "last_sample" spans the first to the last phase-signal sample carrying the phase; on a change-encoded (is_delta) phase signal, which logs one row per transition, every phase is then zero-length.

'next_change'
data_end Timestamp | None

Optional bound for the final phase when interval_end="next_change" (e.g. the batch end).

None

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.