Diagnostic Normalisation¶
MIF-016 bounds dirty diagnostic channels before they enter AER encoding. Each
calibrated channel declares its physical unit interval, affine offset, scale,
clip policy, provenance, and optional AER address. Samples are mapped into
[-1, 1] by
The runtime never leaves out-of-range handling implicit. clip saturates at
the nearest endpoint and records the channel in the clip mask; reject fails
closed with a deterministic error. Every output vector is a read-only
float64 array bounded in [-1, 1].
Calibration validation also checks the derived affine coefficients, not only
the raw endpoint values. A finite endpoint pair is rejected if the physical
span or scale would become non-finite. The midpoint is computed as x_min +
0.5 * (x_max - x_min) so finite endpoints with a finite positive span keep a
finite offset instead of overflowing through x_min + x_max.
Python API¶
normalisation
¶
Bound physical diagnostic channels before AER encoding (MIF-016).
Each channel is mapped from its calibrated physical interval
[physical_min, physical_max] into [-1, 1] using the affine map
.. math::
x_\mathrm{norm} = 2 \frac{x - x_\min}{x_\max - x_\min} - 1.
Out-of-range behaviour is explicit per channel: clip saturates
deterministically at the endpoint and records a clip mask, while reject
raises. The resulting feature vectors are read-only float64 NumPy arrays
so downstream AER front-ends cannot observe overflow beyond [-1, 1].
Finite endpoint pairs are also rejected when the derived affine span or scale
would be non-finite. The stable midpoint offset remains finite whenever both
endpoints and the span are finite.
DiagnosticChannelCalibration(name, unit, physical_min, physical_max, clip_policy, provenance, aer_address=None)
dataclass
¶
Calibration record for one physical diagnostic channel.
Parameters are deliberately stored in physical units. The derived
offset and scale properties are included in manifests so an AER
ingestion chain can reproduce the exact affine mapping without inferring
it from opaque data.
offset
property
¶
Physical midpoint subtracted before applying scale.
scale
property
¶
Multiplicative factor from physical units into the normalized interval.
__post_init__()
¶
Validate channel labels, physical range, clip policy, and AER address.
normalise_value(value)
¶
Return (normalised_value, clipped) for a single channel sample.
to_manifest_row()
¶
Return the durable manifest row for this channel.
NormalisedDiagnosticSample(channel_names, features, clip_mask, out_of_range_channels, sample_period_ns=None)
dataclass
¶
DiagnosticNormalisationState(calibrations, *, sample_period_ns=None)
¶
Deterministic ordered normalisation state for a diagnostic vector.
calibrations
property
¶
Ordered immutable channel calibrations.
channel_names
property
¶
Ordered channel names matching feature-vector order.
sample_period_ns
property
¶
Nominal sample period associated with the diagnostic frame.
normalise_sample(sample)
¶
Normalise a mapping of physical channel samples into [-1, 1].
normalise_vector(values)
¶
Normalise a positional vector in calibration order.
normalise_batch(samples)
¶
Return a read-only (n_samples, n_channels) matrix of bounded features.
calibration_manifest()
¶
Return the explicit calibration manifest required by MIF-016.
fit_diagnostic_calibrations(observations, *, units, provenance, clip_policy='clip', aer_addresses=None)
¶
Fit min/max calibrations from observed physical samples.
Channel order follows the order of units. Every observation must
contain every declared channel, and each channel must span a non-zero
physical range.
Manifest Contract¶
DiagnosticNormalisationState.calibration_manifest() records:
schema_version,kernel,sample_period_ns, and output range;- one row per channel with physical range, offset, scale, clip policy, provenance, and AER address;
deterministic_mapping = trueso downstream AER replay can reproduce the exact transform.
Dispatch¶
Use scpn_mif_core.diagnostics.dispatched_normalisation_state(...) for the
fastest available measured backend:
The Python reference remains the canonical manifest surface. Rust mirrors the affine kernel through PyO3, and Julia mirrors the reference behaviour for calibration/scaling audit scripts.
Validation¶
The committed tests verify:
- exact affine mapping and manifest fields;
- deterministic clipping and bounded AER features;
- reject-policy failure semantics;
- invalid range, non-finite endpoint, non-finite affine-span, subnormal-scale, missing-channel, and zero-span fit guards;
- Python/Rust parity across 16 seeded random vectors;
- Julia reference behaviour in
julia/SCPNMIFCore/test/runtests.jl.
End-to-end ControlObservation cosimulation remains downstream of MIF-015. This surface supplies the bounded feature vector and manifest required by that later integration.
Benchmarks¶
The benchmark harness ships at bench/kernels/bench_diagnostic_normalisation.py.
It measures one four-channel frame and a 4 096-frame batch for the allocated
Python, Rust, and Julia surfaces. The committed benchmark is local comparison
evidence, not CPU-isolated production latency evidence; host load, governor,
and runtime versions are recorded in
bench/results/diagnostic_normalisation.json.