Python Bindings#
The cal-py crate provides a thin PyO3 surface for calling the
calibration engine from Python. It contains zero logic — all work
is dispatched to cal-core and cal-io.
Module: _cal_rs#
Build with maturin:
cd crates/cal-py
maturin develop # debug
maturin build --release # release wheel
Exported Functions#
Function |
Description |
|---|---|
|
Returns the crate version string |
|
List scan numbers in an L0 Zarr store |
|
Calibrate all scans in a store |
|
Calibrate a single scan (Dask-friendly) |
|
Convert FITS folder to Zarr (* requires |
Configuration Dict#
The config parameter accepts a Python dict:
config = {
"obs_mode": "otf", # auto, totalpower, otf
"pwv": 1.2, # fixed PWV in mm (omit to fit)
"physics": "kalibrate_compat", # exact or kalibrate_compat
"clip_tsys": 200.0, # bad channel threshold (K)
"clip_counts": 0.01, # min hot-cold ratio
"eta_fss": 1.0, # forward scattering efficiency
"eta_mb": 1.0, # main beam efficiency
"n_threads": 4, # Rayon thread count
}
Dask Integration#
For distributed processing, use calibrate_scan_py as a Dask
delayed function:
import dask
tasks = [
dask.delayed(_cal_rs.calibrate_scan_py)(
input_path, output_path, atm_table_path, scan_num
)
for scan_num in scan_numbers
]
results = dask.compute(*tasks)
Each call processes one scan independently, making this suitable for
dask.distributed or multiprocessing.
Design: Zero Logic in cal-py#
cal-py is intentionally thin:
No calibration math
No data manipulation
No error recovery logic
All work dispatched to
cal-coreandcal-ioMulti-pixel orchestration (slice → calibrate → merge) is the only structured logic, and it delegates each step
This keeps the Python surface stable while the Rust internals evolve.