======================== Adding an Observation Mode ======================== This guide walks through adding a new observation mode (e.g., FrequencySwitch) to the calibration engine. Step 1: Add ObsMode Variant ---------------------------- In ``cal-core/src/config.rs``, add the variant to the ``ObsMode`` enum: .. code-block:: rust pub enum ObsMode { Auto, TotalPower, OtfTotalPower, FrequencySwitch, // ← new BeamSwitch, } Step 2: Implement Preparation ------------------------------ Create a new file ``cal-core/src/modes/frequency_switch.rs`` and implement the preparation function: .. code-block:: rust pub fn prepare_frequency_switch( scan: &ScanData, cal_full: &CalibrationLoadFull, ) -> Result { // 1. Identify ON subscan indices from sobsmode // 2. Build reference from frequency-shifted spectra // 3. Return PreparedData { ref_data, on_subscan_indices, t_int } todo!() } The key contract: ``PreparedData`` must provide: - ``ref_data[C, R, A, S_on]`` — reference spectra for each ON - ``on_subscan_indices`` — which entries in ``ScanData.data`` are ON - ``t_int[S_on]`` — integration time per ON subscan Register the module in ``cal-core/src/modes/mod.rs``. Step 3: Add Detection Logic ---------------------------- In ``cal-core/src/config.rs`` or where mode detection occurs, add pattern matching for the new mode's ``sobsmode`` strings or ``instmode`` attribute. Step 4: Wire into the Pipeline ------------------------------- In ``cal-io/src/pipeline.rs`` → ``process_prefetched_scan()``, add a match arm for the new mode: .. code-block:: rust let prepared = match effective_mode { ObsMode::TotalPower => prepare_tp(&scan, &cal_full)?, ObsMode::OtfTotalPower => prepare_otf(&scan, &cal_full)?, ObsMode::FrequencySwitch => prepare_frequency_switch(&scan, &cal_full)?, _ => return Err(CalibrationError::InvalidMode { ... }), }; The calibration math (``calibrate_full``) is mode-agnostic — it operates on the ``PreparedData`` output uniformly. Step 5: Add CLI/Python Parsing ------------------------------- In ``cal-cli/src/main.rs`` → ``parse_obs_mode()``: .. code-block:: rust "freqswitch" | "fs" => Ok(ObsMode::FrequencySwitch), In ``cal-py/src/lib.rs`` → ``parse_config()``: .. code-block:: rust "frequency_switch" | "freq_switch" | "fs" => ObsMode::FrequencySwitch, Step 6: Add Parity Test ------------------------- 1. Obtain reference output from the legacy kalibrate for a test dataset 2. Place the reference CSV in ``kalibrate_test_lib/reference_data/`` 3. Add a test case to ``cal-io/tests/parity_multi.rs`` Step 7: Update Documentation ------------------------------ - Add the mode to :doc:`/source/physics/observation-modes` - Update the ``ObsMode`` table in :doc:`/source/reference/configuration` Checklist --------- .. code-block:: text [ ] ObsMode variant added to config.rs [ ] Preparation function implemented in modes/ [ ] Mode detection logic added [ ] Pipeline dispatch updated [ ] CLI parsing added [ ] Python parsing added [ ] Parity test with reference data [ ] Documentation updated