Observation Modes#

Different observing strategies require different reference selection and data preparation. This page describes the supported modes and how to add new ones.

Mode Detection#

The engine auto-detects the observation mode from the data via prepare() in cal-core/src/modes/prepare.rs:

  1. Check the instmode attribute and sobsmode strings

  2. Detect OTF-chopped (dual beam switch) from SWA/SWB patterns

  3. Detect OTF from OTF-ON/OTF-OFF patterns

  4. Fall back to TotalPower if ambiguous

This can be overridden with --mode otf, --mode tp, or --mode otf-chopped on the command line.

Implementation: cal-core/src/config.rsObsMode enum, cal-core/src/modes/prepare.rsprepare() dispatcher

Implemented Modes#

TotalPower (TP)#

Single-point position-switched observations with discrete ON/OFF pairs.

        graph LR
  OFF1[OFF] --> ON1[ON]
  ON1 --> OFF2[OFF]
  OFF2 --> ON2[ON]
  ON2 --> OFF3[OFF]

  style OFF1 fill:#bbdefb
  style OFF2 fill:#bbdefb
  style OFF3 fill:#bbdefb
  style ON1 fill:#c8e6c9
  style ON2 fill:#c8e6c9
    
  • ON subscans: single dump per pointing

  • Reference: linear interpolation between bracketing OFFs (by MJD)

  • Matching: each ON is paired with its temporally bracketing OFFs

OTF TotalPower#

On-the-fly scanning where multiple dumps trace a path across the source.

        graph LR
  OFF1[OFF] --> OTF1[OTF-ON<br/>D dumps]
  OTF1 --> OFF2[OFF]
  OFF2 --> OTF2[OTF-ON<br/>D dumps]
  OTF2 --> OFF3[OFF]

  style OFF1 fill:#bbdefb
  style OFF2 fill:#bbdefb
  style OFF3 fill:#bbdefb
  style OTF1 fill:#c8e6c9
  style OTF2 fill:#c8e6c9
    
  • ON subscans: multiple dumps along scan direction (D > 1)

  • Reference: linear interpolation between bracketing OFFs, averaged over all dumps (NaN-aware)

  • OTF coordinates: otf_lon and otf_lat are propagated to the output as [D, S] arrays

OTF Chopped (Dual Beam Switch)#

On-the-fly scanning with beam switching (OTFSWA/OTFSWB patterns). Each ON subscan is paired with its same-beam OFF. Beams A and B are calibrated independently.

  • ON subscans: SWA-ON and SWB-ON dumps

  • Reference: per-dump OFF subtraction (matching kalibrate’s per-dump subtraction for chopped data)

  • DBS coupling: optional adhesive coupling (--dbs-coupling) enables cross-beam OFF averaging and post-calibration A+B merge

Implementation: cal-core/src/modes/prepare.rsprepare_otf_chopped(), cal-io/src/pipeline/dbs.rsmerge_dbs_pairs()

Data Preparation#

File: cal-core/src/modes/prepare.rs

A single prepare() function dispatches to mode-specific preparation based on auto-detected ObsMode:

pub fn prepare(scan: &ScanData) -> Result<(PreparedData, ObsMode), CalibrationError> {
    let mode = scan.detect_obs_mode();
    let prepared = match mode {
        ObsMode::OtfTotalPower => prepare_otf(scan)?,
        ObsMode::OtfChopped => prepare_otf_chopped(scan)?,
        ObsMode::TotalPower => prepare_tp(scan)?,
        // ...
    };
    Ok((prepared, mode))
}

The preparation phase decouples reference selection from calibration math, enabling vectorized processing:

  1. Identify ON subscan indices from sobsmode

  2. For each ON, find bracketing OFFs and interpolate linearly by MJD

  3. Deduplicate OFF references (compute average once, reuse for all ONs sharing the same reference)

  4. Build ref_data[C, R, A, S_on] from interpolated OFF averages

  5. Compute integration time t_int[S_on]

The ON data is not copiedPreparedData stores indices into ScanData.data, and the calibration loop reads from there directly. This avoids a ~1 GB allocation for large OTF datasets.

The calibration math (calibrate_full) is mode-agnostic – it operates on the PreparedData output uniformly.

Stubbed / Future Modes#

The ObsMode enum includes placeholders for:

  • BeamSwitch – standalone (non-OTF) beam-switched reference

  • FrequencySwitch – reference from frequency-shifted spectra

These will be implemented when test data becomes available. See /source/developer/adding-observation-mode for the extension guide.