Visibility data weights#

Pyralysis distinguishes MS data weights (WEIGHT, WEIGHT_SPECTRUM, SIGMA, SIGMA_SPECTRUM) from imaging weights handled by pyralysis.transformers.weighting_schemes (Natural, Uniform, Robust), which populate IMAGING_WEIGHT_SPECTRUM for gridding.

CASA convention (see CASA data weights):

\[\sigma_{ij}(\nu) = \mathrm{noise\ per\ visibility},\quad w_{ij}(\nu) = 1 / \sigma_{ij}(\nu)^2\]

ChiSquared reads IMAGING_WEIGHT_SPECTRUM. After thermal noise injection, data and imaging weights should both reflect the radiometer \(\sigma\) so \(\chi^2\) is consistent with the simulated noise. For the imaging-weighting schemes themselves, see Gridding Techniques in Pyralysis.

Thermal noise injection#

ThermalNoiseInjector writes weight columns by default (update_weights=True) using the same \(\sigma\) as the noise draw:

from pyralysis.injectors import ThermalNoiseInjector

thermal = ThermalNoiseInjector(
    system_temperature=50.0,
    integration_time=10.0,
    channel_bandwidth=1e6,
    update_weights=True,
    sync_imaging_weights=True,
)
dataset = thermal.apply(dataset)

Set update_weights=False only for deliberate experiments, such as testing how a misweighted objective behaves. Multiplicative noise injectors (gain, bandpass, phase, antenna gain) do not modify MS weights.

Analytic estimator#

AnalyticWeightEstimator computes weights from the radiometer / SEFD model without modifying DATA:

from pyralysis.visibility_weights import AnalyticWeightEstimator

estimator = AnalyticWeightEstimator(
    system_temperature=50.0,
    integration_time=10.0,
    channel_bandwidth=1e6,
)
dataset = estimator.apply_dataset(dataset)

Use this to precompute theoretical weights before noise injection or to refresh weights after loading a measurement set.

Empirical estimator#

EmpiricalWeightEstimator estimates weights from residual scatter grouped by baseline (statwt-inspired):

from pyralysis.visibility_weights import EmpiricalWeightEstimator

empirical = EmpiricalWeightEstimator(use_model=True, minsamp=2)
dataset = empirical.apply_dataset(dataset)

When MODEL_DATA is present and use_model=True, residuals are DATA - MODEL_DATA. Otherwise, Pyralysis subtracts a per-baseline mean before estimating scatter. Empirical weights reflect all noise in DATA (thermal plus uncorrected calibration errors); analytic weights track thermal noise only.