The method was developed in 09W3 (W in RMP) and generalized to every species in
09W4. Call it with analyze_shot(shot), Shot.analyze_injections() or
GroupShots.analyze_injections().
Steps
- Signal:
shot.emission(shot.default_signal), the core line with its
physical sign. - Detection, with
find_injections(shot).- The
scan_injectionssweep looks for rises of the smoothed signal (5 pts)
over 30 ms that exceedk=8sigma (MAD). - Events near a
-lboN.txt(−80/+200 ms) getsource="lbo file". - An unlisted event gets
source="detected"if
z >= max(z_strong=30, z_rel=0.2 * z_max_listado), or if it falls on the
shot's firing grid (grid_period=1 s, same phase ±30 ms as the listed
ones, and only when those have a consistent phase). extra_times=[...]andexclude_times=[...]correct by hand.- The full sweep is kept in
df.attrs["candidates"].
- The
- Characterization, with
characterize_injection(t, y, t_ref): peak (smoothed
maximum in −80/+200 ms), baseline and noise (100 ms before the onset,
iterated), onset (last point below baseline + 4σ/√3), amplitude, SNR,
t_onset_to_peak_msandt_rise_10_90_ms. - Decay window, with
decay_end: from the peak tot_peak + t_max
(DECAY_T_MAX: W 0.45 s; Fe/Ni/Mo 0.6 s). It is cut 50 ms before the next
injection or an ECRH step (heating_steps), and at the end of the data. - Normalized curve, with
decay_curve:tr = t − t_peak,
yn = (I − baseline)/A. It never includes the rise. - Fits (
aug.models.exponential):fit_single_exp:a·exp(−t/τ) + b.fit_double_exp:a_f·exp(−t/τ_f) + a_s·exp(−t/τ_s) + b, multi-start,
τ_f ∈ [6, 60] ms.τ_imp = τ_s. The fit is identifiable if each
amplitude is ≥ 0.1,τ_s > 1.5 τ_f,τ_fis not at its bound,
σ(τ_s) < 50 %andτ_s < 0.75 ×the window.select_decay_modelpicks "double" only if the F-test givesp < 0.05,
ΔAIC > 2, and the fit is identifiable.block_bootstrap_tauestimates the error of τ (single) with a
moving-block bootstrap of the residuals (blocks of 10 samples).fit_rise_decay: a rise + decay model, as a check (τ_r and τ_d come out
correlated).
- Window sensitivity: single τ with the start at peak + {0, 10, 20, 40} ms
and length {⅔, 1, 4/3}·t_max. This givestau_sys_ms(p16-p84
half-range). - Context, with
plasma_context:P_ECRH_MW,P_NBI_MW,Te_c_keV,
ne_1e19,Wmhd_kJ,Ip_MA,Zeff;elm_rate(peaks ofIpolsola);
dFe23_sigma(change in Fe23+ during the window, for non-Fe shots). - Flags (
FLAGS).cleanmeans no flags.
Adopted τ
- If
recommended == "single",tau_imp_ms = tau_1exp_msand the statistical
error is the larger of the covariance and bootstrap errors. - If
recommended == "double",tau_imp_ms = tau_slow_2exp_mswith the
covariance error. tau_imp_err_ms= statistical ⊕tau_sys_ms.
Flags
| Flag | Condition |
|---|---|
ECRH_step |
ECRH step < 150 ms before the onset |
Fe_influx |
Fe23+ rises > 5σ during the window (species ≠ Fe only) |
no_decay |
single-fit R² < 0.5 |
low_snr |
amplitude < 5σ |
ELMy |
> 10 ELMs/s during the decay (RMP regime only) |
window_sensitive |
tau_sys_ms > 30 % of τ |
short_window |
window < 100 ms or shorter than τ |
fit_failed |
a fit did not converge, or there are < 10 points |
InjectionSet
res = group.analyze_injections()
res.table # DataFrame, una fila por inyección
res.details[(shot, inj)] # dict: t, y, char, t_end, tr, yn, model, rd, boot, sens
res_a + res_b # concatena
Main columns of res.table: dataset, regime, species, heating, signal, shot, inj, source, t_ref, t_onset, t_peak, snr, t_onset_to_peak_ms, t_rise_10_90_ms, tau_rise_ms, window_ms, tau_1exp_ms, tau_1exp_err_ms, tau_1exp_err_boot_ms, tau_sys_ms, r2_1exp, tau_slow_2exp_ms, tau_slow_2exp_err_ms, tau_fast_2exp_ms, a_fast, a_slow, identifiable_2exp, p_F, dAIC, recommended, tau_imp_ms, tau_imp_err_ms, P_ECRH_MW, P_NBI_MW, Te_c_keV, ne_1e19, Ip_MA, elm_rate_decay_Hz, dFe23_sigma, <flags>, clean, flags.