===========
Multi-Pixel
===========
CHAI-class receivers have multiple pixels per array (e.g., 7 HFA pixels)
and multiple arrays (HFA, LFA, 4G1–4G4). The engine handles this in
two ways.
Vectorized Path (Primary)
--------------------------
``resolve_calibration_load_full()`` computes gamma, T_rec, and bad
channels for **all pixels simultaneously** as ``[C, R, A]`` arrays.
The calibration loop (``calibrate_full``) broadcasts these across the
dump and subscan axes — no per-pixel loop needed.
This is the path used by ``cal-cli`` and ``cal-io::pipeline``.
Per-Pixel Path (Python/Dask)
-----------------------------
``cal-py`` uses a per-pixel strategy for Dask compatibility:
.. mermaid::
graph TD
P0[Pixel 0,0] -->|calibrate_scan| R0[Result 0,0
+ fitted PWV]
R0 -->|extract PWV| PWV[Common PWV]
PWV --> P1[Pixel 0,1]
PWV --> P2[Pixel 1,0]
PWV --> PN[Pixel N,M]
P1 -->|calibrate_scan| R1[Result 0,1]
P2 --> R2[Result 1,0]
PN --> RN[Result N,M]
R0 --> MR[merge_pixel_results]
R1 --> MR
R2 --> MR
RN --> MR
MR --> CR[CalibrationResult
full R,A]
1. ``slice_pixel(0, 0)`` extracts pixel 0 as a single-pixel ``ScanData``
2. Calibrate pixel 0 → extract fitted PWV
3. For all other pixels: calibrate with ``PwvSource::External(pwv)``
4. ``merge_pixel_results()`` stitches single-pixel results into full
``[C, D, R, A, S]``
Common PWV Strategy
~~~~~~~~~~~~~~~~~~~
By default (``pwv_per_pixel = false``), PWV is fitted on pixel 0 only
and propagated to all other pixels. This ensures consistent atmospheric
correction across the focal plane and reduces computation by
:math:`\frac{1}{N_{pixels}}`.
Set ``pwv_per_pixel = true`` to fit each pixel independently (useful
for diagnosing receiver-dependent systematics).
**Implementation:**
- ``cal-core/src/scan.rs`` → ``ScanData::slice_pixel()``,
``merge_pixel_results()``
- ``cal-io/src/pipeline.rs`` → ``common_pwv_source()``
- ``cal-py/src/lib.rs`` → ``calibrate_one_scan()``