Skip to content

Fire-Time Selection

Retrospective selection of the fire instant over an evaluated merge-window trace. FIRST_LOCK — the default and the streaming trigger's latch instant — stays the reference policy; MAX_WINDOW_MARGIN is the opt-in optimiser that picks the locked sample with the widest normalised window margin min((phi_tol - phi_err)/phi_tol, (x_tol - x_ref)/x_tol) (ties go to the earliest sample).

from scpn_mif_core import (
    FireTimePolicy,
    certify_sampled_kinematic_safety,
    evaluate_merge_window_trace,
    select_fire_time,
)

trace = evaluate_merge_window_trace(window, time_s, phases_rad, positions_m)
certificate = certify_sampled_kinematic_safety([s.separation_m for s in trace.samples])
decision = select_fire_time(
    trace,
    window,
    certificate,
    bank_feasible=True,
    policy=FireTimePolicy.MAX_WINDOW_MARGIN,   # opt-in; FIRST_LOCK is the default
)

Subordination guarantee

The optimiser never widens the verified fire envelope: it selects only among samples the deterministic merge-window law already locked, and only when the MIF-011 batch safety certificate passed, the bank is feasible, and the lane is armed — the same gates the batch pipeline applies. A failed gate yields a non-firing decision regardless of policy, so the policy can change when an admissible shot fires, never whether an inadmissible one does. The seeded sweep in tests/unit/kinematic/test_fire_time.py pins this property, and the FIRST_LOCK instant is pinned against the actual streaming engine.

No acceleration path

This is once-per-shot selection logic over an already-evaluated trace — a handful of comparisons per sample after the dispatched kernels have done the numeric work — so, like the merge-window feature boundary and the advisory predictor, it has no multi-language acceleration path.

API

fire_time

Fire-time selection over an evaluated merge-window trace.

:func:select_fire_time chooses which locked sample of a nominal :class:~scpn_mif_core.kinematic.merge_window.MergeWindowTrace a batch analysis should call the fire instant. Two policies:

  • FIRST_LOCK (the default) — the first sample whose sustained lock is achieved, matching the streaming trigger's latch and the batch pipeline.
  • MAX_WINDOW_MARGIN (opt-in) — the locked sample that maximises the normalised window margin min((phi_tol - phi_err)/phi_tol, (x_tol - x_ref)/x_tol) (the binding merge-window constraint, so both observables are commensurate); ties go to the earliest such sample.

The optimiser is subordinate by construction and never widens the verified fire envelope: it only ever selects among samples the deterministic merge-window law already locked, and only when the MIF-011 batch safety certificate passed, the bank is feasible, and the lane is armed — exactly the gates the batch pipeline applies. A failed gate yields a non-firing decision regardless of policy; the policy can change when an already admissible shot fires, never whether an inadmissible one does.

This is once-per-shot selection logic over an already-evaluated trace — a handful of comparisons per sample after the dispatched kernels have done the numeric work — so, like the merge-window feature boundary and the advisory predictor, it has no multi-language acceleration path.

FireTimePolicy

Bases: StrEnum

Fire-time selection policy over the locked samples of a trace.

FireTimeDecision(policy, fired, fire_index, fire_time_s, window_margin, eligible_count, reason) dataclass

Outcome of a fire-time selection.

Attributes

policy: The policy that produced this decision. fired: Whether a fire instant was selected. fire_index: Zero-based index of the selected sample, or None. fire_time_s: The selected sample's time, or None when not fired or when the trace carries no per-sample time. window_margin: The selected sample's normalised window margin, or None when not fired. eligible_count: Number of locked samples the selection could choose from. reason: One-sentence explanation of the outcome.

window_margin(spec, phase_lock_error_rad, reference_error_m)

Return the normalised merge-window margin of one sample.

min((phi_tol - phi_err)/phi_tol, (x_tol - x_ref)/x_tol) — the relative slack of the binding constraint; 0 sits exactly on a tolerance, 1 is a perfectly centred sample, negative values lie outside the window.

select_fire_time(trace, merge_window, certificate, *, bank_feasible, armed=True, policy=FireTimePolicy.FIRST_LOCK)

Select the fire instant of an evaluated merge-window trace.

Parameters

trace: The evaluated nominal merge-window trace. merge_window: The tolerances the trace was evaluated against (used for margins). certificate: The MIF-011 batch safety certificate for the same approach. A failed certificate blocks every policy — batch semantics: any envelope violation aborts the whole shot. bank_feasible: The MIF-005 feasibility verdict for the requested pulse. armed: Whether the lane is armed; an unarmed lane never fires. policy: FIRST_LOCK (default) or the opt-in MAX_WINDOW_MARGIN.

Returns

FireTimeDecision The selected fire instant, or a non-firing decision with the gate that blocked it.