Atmosphere#

The atmosphere attenuates celestial signals and adds thermal emission. The calibration engine determines the atmospheric state from the data itself by fitting precipitable water vapour (PWV) to the observed sky signal.

Atmospheric Transmission#

Transmission through the atmosphere at frequency \(\nu\) depends on the line-of-sight path through the atmosphere:

\[t_r(\nu) = \exp\!\Big(-\text{airmass} \cdot \tau_0(\nu)\Big)\]

where the zenith optical depth is modelled as:

\[\tau_0(\nu) = b(\nu) \cdot \text{PWV} + c(\nu)\]

The coefficients \(b(\nu)\) and \(c(\nu)\) come from the ATM table (a precomputed atmospheric model) and are extracted by interpolating in pressure and frequency.

The airmass is the plane-parallel approximation:

\[\text{airmass} = \frac{1}{\sin(\text{elevation})}\]

Implementation: cal-core/src/math/transmission.rs

ATM Table#

The atmospheric model is a lookup table providing opacity coefficients as a function of frequency and ambient pressure. It is produced by atmospheric radiative transfer codes (e.g., ATM by Pardo et al.).

Two storage formats are supported:

Format

File

Use case

Text

.dat or .dat.gz

Portable, human-readable

Binary

.catm

Fast loading (memory-mapped)

Convert text to binary for production use:

calibrate convert --input atm.dat.gz --output atm.catm

Implementation: cal-core/src/atm/ (trait + TableAtm), cal-io/src/atm_table.rs, cal-io/src/atm_table_bin.rs

Sky Signal Observation#

The observed sky signal is derived from OFF-source counts and HOT load counts:

\[S_{H,obs}(\nu) = \frac{\bar{C}_{OFF}(\nu) - C_{hot}(\nu)}{\gamma(\nu)}\]

where \(\bar{C}_{OFF}\) is the NaN-aware mean of the nearest OFF subscan over dumps. This quantity represents the sky contribution as seen through the calibration gain.

Implementation: cal-core/src/atmosphere.rsdetermine_atmosphere_full()

PWV Retrieval#

The PWV is fitted by minimising the residual between the observed sky signal and the model prediction:

\[\text{residual}(\text{PWV}) = \sum_c \left(S_{H,obs}(c) - T_{sky,fit}(c, \text{PWV})\right)^2\]

where the model sky temperature combines both sidebands:

\[T_{sky,fit} = (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]\]

The summation runs only over valid channels (not flagged, finite \(S_{H,obs}\)).

Grid Search + Newton Refinement (Primary)#

  1. Evaluate the residual at 100 PWV values from 0.01 to 10 mm

  2. Find the grid minimum

  3. Refine with 5 Newton iterations using numerical derivatives

  4. Convergence: \(\Delta\text{PWV} < 10^{-8}\) mm or Hessian \(< 10^{-30}\)

A fused residual function (residual_ss_precomputed) computes transmission and sky temperature in one loop with zero heap allocation, yielding 5–10× speedup over separate function calls.

Implementation: cal-core/src/pwv/fit_grid.rs

Levenberg-Marquardt (Fallback)#

A 1-parameter least-squares fit using the levenberg_marquardt crate with numerical Jacobian. Used when the grid+Newton method does not converge.

Implementation: cal-core/src/pwv/fit_lm.rs

External (Fixed PWV)#

When the PWV is known a priori (e.g., from a radiometer), it can be provided directly via --pwv or config. No fitting is performed.

Implementation: cal-core/src/pwv/external.rs

Zenith Opacity#

After PWV is determined, per-channel zenith opacities are computed:

\[\tau_0(\nu) = -\frac{\ln\big(t_r(\nu)\big)}{\text{airmass}}\]

Both signal and image sideband opacities are stored in the L1 output for downstream quality assessment.