# Calibration Equation This page presents the final calibration formula that produces antenna temperature $T_A^*$ from raw counts. ## The Calibration Equation For each spectral channel $\nu$, dump $d$, receiver $r$, array $a$, and subscan $s$: $$ T_A^*(\nu, d, r, a, s) = \frac{\big(C_{ON}(\nu,d,r,a,s) - C_{REF}(\nu,r,a,s)\big) \cdot \gamma(\nu,r,a)} {\big(C_{hot}(\nu,r,a) - C_{cold}(\nu,r,a)\big) \cdot t_r^{sig}(\nu)} $$ where: - $C_{ON}$ — raw counts from the ON-source subscan - $C_{REF}$ — reference counts (mode-dependent, see {doc}`observation-modes`) - $\gamma$ — gain calibration factor (see {doc}`calibration-loads`) - $C_{hot}, C_{cold}$ — mean HOT/COLD load counts - $t_r^{sig}$ — signal sideband atmospheric transmission (see {doc}`atmosphere`) ### Atmospheric Correction Only the **signal sideband** transmission is applied in the denominator. The image sideband contribution is already accounted for in $\gamma$ through the sideband gain weighting $(g_s x_s + g_i x_i)$. This is the standard single-sideband (SSB) calibration convention. **Implementation:** `cal-core/src/calibrate.rs` → `calibrate_full()` ## Vectorized Implementation The inner loop precomputes a combined factor to minimise per-element operations: $$ F(\nu, r, a) = \frac{\gamma(\nu, r, a)} {\big(C_{hot}(\nu, r, a) - C_{cold}(\nu, r, a)\big) \cdot t_r^{sig}(\nu)} $$ Then the calibration reduces to: $$ T_A^*(\nu, d, r, a, s) = \big(C_{ON}(\nu,d,r,a,s) - C_{REF}(\nu,r,a,s)\big) \cdot F(\nu, r, a) $$ Loop order is `C → R → A → D → S` for row-major cache-friendly access, with the innermost loop (S) achieving stride-1 memory access on the subscan axis. ## System Temperature The system temperature includes receiver noise, load coupling, and atmospheric contributions: $$ T_{sys} = T'_{rec} + T'_{hot} + (1 - f_{amb}) \Big[ g_s x_s \cdot T_{hot,eff}^{sig} \cdot \big(a_s (1 - t_r^{sig}) - 1\big) + g_i x_i \cdot T_{hot,eff}^{img} \cdot \big(a_i (1 - t_r^{img}) - 1\big) \Big] $$ $T_{sys}$ is computed per channel, per pixel, per subscan and written to the L1 output. **Implementation:** `cal-core/src/math/temperature.rs` → `tsys_formula()` ## Flag Propagation The calibration stage propagates flags from the bad channel mask (bit 0 = `BAD_CHANNEL`) to the output `flags` array. All dumps and subscans for a flagged channel receive the flag. The corresponding spectral values are set to `NaN`. See {doc}`/source/developer/flag-system` for the complete flag architecture. ## Output: CalibrationResult The calibration produces a `CalibrationResult` containing: ```{eval-rst} .. list-table:: :header-rows: 1 :widths: 25 20 55 * - Field - Shape - Description * - ``spectra`` - [C, D, R, A, S] - Calibrated :math:`T_A^*` (K) * - ``t_sys`` - [C, R, A, S] - System temperature (K) * - ``t_int`` - [S] - Integration time (s) * - ``t_rec_ssb`` - [C, R, A] - Receiver temperature SSB (K) * - ``gamma`` - [C, R, A] - Gain factor * - ``tau_signal`` - [C] - Zenith opacity, signal (Np) * - ``tau_image`` - [C] - Zenith opacity, image (Np) * - ``t_sky`` - [C, R, A] - Sky contribution (K) * - ``flags`` - [C, D, R, A, S] - u16 quality bitmask * - ``signal_freqs`` - [C] - Signal frequencies (Hz) * - ``image_freqs`` - [C] - Image frequencies (Hz) * - ``pwv`` - scalar - Fitted PWV (mm) ``` Plus scan metadata (source, mode, arrays, pixel names, strategies). ## QA Metrics Quality metrics are computed per scan and stored as L1 attributes: - Mean and median $T_{sys}$ across channels - Fraction of flagged channels - PWV convergence information **Implementation:** `cal-core/src/qa.rs` → `QaMetrics`