================= Calibration Loads ================= The HOT/COLD load system provides the absolute flux reference for the heterodyne calibration. This page describes how raw load data is processed into the gain calibration factor :math:`\gamma`, receiver temperature :math:`T_{rec}`, and bad channel mask. Load Extraction --------------- Calibration subscans are identified by their ``sobsmode`` string: - **HOT** — hot load (ambient temperature blackbody) - **COLD** / **COL** — cold load (typically 77 K LN₂) - **SKY** — sky measurement - **ZERO** — zero-level check For each calibration subscan, the count data ``[C, D]`` is averaged over the dump axis (NaN-aware, skipping padded values) to produce mean hot/cold counts per channel. **Implementation:** ``cal-core/src/math/dump_mean.rs`` → ``nan_mean_axis()`` Effective Load Temperature -------------------------- The hot load is at ambient temperature, but spillover past the load couples to the ambient environment. The effective load temperature corrects for this: .. math:: T_{hot,eff}^{sig} = \frac{T_{RJ}(\nu_{sig}, T_{hot}) - f_{amb} \cdot T_{RJ}(\nu_{sig}, T_{amb})}{1 - f_{amb}} where :math:`f_{amb} = 1 - f_{eff}` is the ambient coupling fraction and :math:`f_{eff}` is the forward efficiency. The sky coupling coefficient relates ambient to effective temperature: .. math:: a_{sig} = \frac{T_{RJ}(\nu_{sig}, T_{amb})}{T_{hot,eff}^{sig}} **Implementation:** ``cal-io/src/resolve.rs`` Gamma (Gain Calibration Factor) ------------------------------- The gamma factor converts count differences to temperature differences: .. math:: \gamma(\nu) = \frac{C_{hot}(\nu) - C_{cold}(\nu)}{T'_{hot}(\nu) - T'_{cold}(\nu)} \cdot (g_s x_s + g_i x_i) This is the sensitivity in counts per Kelvin, including the sideband gain weighting. **Implementation:** ``cal-core/src/math/gamma.rs`` → ``gain_calibration_formula()`` Receiver Temperature -------------------- The Y-factor method yields the primed receiver temperature: .. math:: y = \frac{C_{hot}}{C_{cold}} .. math:: T'_{rec} = \frac{T'_{hot} - y \cdot T'_{cold}}{y - 1} Converting to single-sideband: .. math:: T_{rec,SSB} = \left(T'_{rec} - T'_{term}\right) \cdot \frac{g_s x_s + g_i x_i}{g_s x_s} where :math:`T'_{term}` is the sideband-weighted termination temperature (spillover). **Implementation:** ``cal-core/src/math/temperature.rs`` → ``t_rec_formula()`` Bad Channel Detection --------------------- A channel is flagged as bad if any of the following conditions hold: 1. :math:`C_{hot} \leq C_{cold}` — load signal not detected 2. :math:`(C_{hot} - C_{cold}) < \text{clip\_counts} \cdot \max(\text{smoothed}(C_{hot} - C_{cold}))` — weak relative signal 3. :math:`T_{rec,SSB} \leq 0` — unphysical receiver temperature 4. :math:`T_{rec,SSB} > \text{clip\_tsys} \cdot \frac{h \nu_{typ}}{k_B}` — unrealistically high The ``clip_tsys`` (default 200 K) and ``clip_counts`` (default 0.01) thresholds are configurable. **Implementation:** ``cal-core/src/math/temperature.rs`` → ``compute_bad_channels()`` Per-Channel Load Temperature Tables ------------------------------------- Some receivers provide per-channel RJ load temperatures via the ``LOAD_TEMP_ARRAY`` (pre-computed from load emission models). When available, these replace the scalar :math:`T_{RJ}(T_{hot})` with per-channel values, improving accuracy near band edges where the load is not perfectly isothermal. **Implementation:** ``cal-core/src/scan.rs`` → ``CalibrationLoad::new_with_load_temps()`` Data Flow --------- .. mermaid:: graph LR CS[CalibrationSnapshot
raw HOT/COLD] -->|extract & average| HC[hot_counts, cold_counts
per channel] HC --> G[gamma] HC --> TR[T_rec_prime, T_rec_SSB] HC --> BC[bad_channels mask] G --> CL[CalibrationLoad
all derived quantities] TR --> CL BC --> CL