fields
tit.fields ¶
Carrier-derived high-frequency field metrics — single source of truth.
Safety metrics computed from per-pair carrier E-field vector arrays (shape
(..., 3) each), following Cassarà et al. 2025, Recommendations for the
Safe Application of Temporal Interference Stimulation in the Human Brain
Part I (Bioelectromagnetics 46(2), e22542) and Part II (46(1), e22536).
The governing rule is Part II, p. 8: "In the presence of multiple currents (e.g., TIS channels), coherent field superposition was used for identical frequencies, and incoherent superposition (i.e., SAR addition) was used when the frequencies differed." Fields at one frequency are summed as vectors first; only then do distinct carriers combine — in power for time-averaged quantities, and by worst-case relative phase for the peak.
Which fields share a frequency is fixed by the montage, and since v2.5.0 the
toolbox has exactly one wiring: positional. electrode_pairs are taken
two at a time, each pair driven at its own carrier frequency, so one field is
one carrier and the coherent sum within a frequency is the identity. (The
optional Lee-2022 style channels grouping, where several pairs shared one
carrier, was removed on main — see 7a5ee2dd, d4706e5a,
b19a1c26. If it ever returns, the coherent pre-sum goes here.) These
functions therefore take the carrier fields positionally and sum them
incoherently.
hf_peak(*fields) — peak carrier field. Distinct carriers run at mutually
incommensurate frequencies, so every relative phase combination occurs over
time; the worst-case instantaneous magnitude is the max over sign choices,
max_s |sum_c s_c * E_c| over carriers c. At two carriers this is
exactly max(|E1+E2|, |E1-E2|) (Cassarà Part I, Eq. 3, p. 11: the worst
case is "in-phase, spatially aligned fields").
hf_sar(*fields) — heating driver, proportional to SAR. Distinct carriers
are incoherent, so power adds rather than amplitude: sum_c |E_c|^2
(Cassarà Part I, p. 11: "the SAR distributions from the two channels, rather
than the E-fields themselves, must be summed"; Part II, p. 16: total power
deposition "is equal to the summed combination from all channels (incoherent
field superposition)").
Both are distinct from the stimulation-relevant modulation envelope
(TI_max / TI_normal), computed in :mod:tit.calc.
See Also¶
tit.sim.TI : Writes hf_peak / hf_sar as volume fields on the TI mesh. tit.sim.mTI : Writes hf_peak / hf_sar as volume fields on the mTI mesh. tit.source.fsaverage : Projects hf_peak / hf_sar onto fsaverage.
hf_peak_is_exact ¶
Is :func:hf_peak exact for this many carriers, or a lower bound?
True up to EXACT_SIGN_ENUM_MAX_FIELDS carriers, where every one of
the 2**(C-1) sign patterns is enumerated. Above that the direction
sweep tries only the sign patterns implied by sampled directions, so the
result is a lower bound on the true worst-case peak and is therefore
slightly non-conservative as a safety metric. Callers that record or
display hf_peak should carry this flag alongside the value.
With the positional wiring one field is one carrier, so n_fields is the carrier count.
Source code in tit/fields.py
hf_peak ¶
hf_peak(*fields) -> ndarray
Peak carrier field: max over sign choices of the carrier vector sum.
Each field is one carrier (positional wiring). Carriers combine at their
worst-case relative phase, which for incommensurate frequencies is
realised over time:
max_s |sum_c s_c E_c|. At two carriers this is Cassarà et al. 2025
Part I, Eq. 3 (p. 11), max(|E1+E2|, |E1-E2|).
Exact sign enumeration (2**(C-1) combinations over C carriers) is
used up to EXACT_SIGN_ENUM_MAX_FIELDS. Above that, a Fibonacci-sphere
direction sweep picks the best-sampled direction and evaluates the exact,
realizable vector sum for the sign pattern it implies -- tighter than a
raw support-function value, but still a lower bound (hence slightly
non-conservative) since only sampled directions' sign patterns are tried.
Query :func:hf_peak_is_exact for which path a montage takes.
Parameters¶
*fields : array-like, shape (..., 3)
Two or more carrier E-field vectors (one per electrode pair), all
the same shape.
Returns¶
numpy.ndarray, shape (...,)
The worst-case peak carrier field magnitude.
Source code in tit/fields.py
hf_sar ¶
hf_sar(*fields) -> ndarray
Incoherent carrier heating driver, proportional to SAR: sum_c |E_c|^2.
Each field is one carrier (positional wiring), and the carriers sit at different, incommensurate frequencies, so their SAR/power adds rather than their amplitudes — Cassarà et al. 2025 Part II, p. 8: "coherent field superposition was used for identical frequencies, and incoherent superposition (i.e., SAR addition) was used when the frequencies differed."
This is a field-domain proxy in (V/m)^2, not calibrated SAR.
With E_c the sinusoidal amplitude (peak, as the paper's thresholds
are stated), the time-averaged SAR of Part II Eq. 1 is
(sigma / 2 rho) * hf_sar — the 1/2 being the sinusoid's
time-average, applied once here and nowhere else in the toolbox.
Equivalently the RMS-squared carrier field is hf_sar / 2.
Parameters¶
*fields : array-like, shape (..., 3)
Two or more carrier E-field vectors (one per electrode pair), all
the same shape.
Returns¶
numpy.ndarray, shape (...,)
sum_c |E_c|^2 in (V/m)^2 — proportional to tissue heating.