The measured parallel-hand correlations are related to the true (ideal, superscript $\circ$) values by the correlation-space measurement gains $G_x^m$ and $G_y^m$:
$$XX^m = G_x^m \, XX^\circ \tag{I}$$ $$YY^m = G_y^m \, YY^\circ \tag{II}$$where $G_x^m = g_x g_x^* = |g_x|^2$ and $G_y^m = g_y g_y^* = |g_y|^2$ ($g$ acts on voltages; $G$ acts on correlations).
We attempt to correct the measured data by dividing out the measurement gain, producing the interim-calibrated visibility $XX^{ic}$:
$$XX^{ic} = \frac{1}{G_x^m} \cdot XX^m = G_x^{ic} \cdot XX^\circ \tag{III}$$ $$YY^{ic} = \frac{1}{G_y^m} \cdot YY^m = G_y^{ic} \cdot YY^\circ$$The residual $G_x^{ic}$ captures how imperfect the correction was. If the correction were perfect, $G_x^{ic} = 1$ and $XX^{ic} = XX^\circ$ exactly. The goal is to measure and remove $G_x^{ic}$ and $G_y^{ic}$.
1934−638 is unpolarised, so $Q^\circ = XX^\circ - YY^\circ = 0$ and each polarisation carries half the total intensity: $XX^\circ = YY^\circ = \tfrac{1}{2}I^\circ$. Substituting into (III):
$$XX^{ic} = G_x^{ic} \cdot \tfrac{1}{2}I^\circ \tag{IV}$$ $$YY^{ic} = G_y^{ic} \cdot \tfrac{1}{2}I^\circ \tag{V}$$Adding and subtracting:
$$I^{ic} = XX^{ic} + YY^{ic} = \tfrac{1}{2}\bigl(G_x^{ic} + G_y^{ic}\bigr)\,I^\circ$$ $$Q^{ic} = XX^{ic} - YY^{ic} = \tfrac{1}{2}\bigl(G_x^{ic} - G_y^{ic}\bigr)\,I^\circ$$The two equations at the end of §3 have two unknowns. Adding and subtracting them directly:
$$G_x^{ic} = \frac{I^{ic} + Q^{ic}}{I^\circ} \tag{VI}$$ $$G_y^{ic} = \frac{I^{ic} - Q^{ic}}{I^\circ} \tag{VII}$$This is the exact, assumption-free result. Both gains are fully determined by three measurables: $I^{ic}$, $Q^{ic}$ (from 1934−638 after interim calibration), and $I^\circ$ (the known true flux of 1934−638). Defining $dQ = Q^{ic}/I^{ic}$, these can be written:
$$G_x^{ic} = \frac{I^{ic}}{I^\circ}\,(1 + dQ), \qquad G_y^{ic} = \frac{I^{ic}}{I^\circ}\,(1 - dQ) \tag{VIII}$$The prefactor $I^{ic}/I^\circ$ is the flux-scale accuracy of the interim calibration. If total-intensity has been correctly calibrated so that $I^{ic} = I^\circ$, this prefactor is unity and (VIII) simplifies to:
$$G_x^{ic} = 1 + dQ, \qquad G_y^{ic} = 1 - dQ \qquad \text{(when } I^{ic}/I^\circ = 1\text{)} \tag{IX}$$In this case $dQ$ alone determines both gain errors. If $I^{ic}/I^\circ \neq 1$, using (IX) would absorb a flux-scale error into the bandpass table; the full form (VIII) must be used instead, requiring an independent measurement of $I^\circ$ (e.g. a flux model of 1934−638).
From (III), any raw measurement $XX_{\rm target}^m$ is related to the true sky by both $G_x^m$ and $G_x^{ic}$:
$$XX_{\rm target}^m = G_x^m \cdot G_x^{ic} \cdot XX^\circ$$We already hold $g_x^m$ (the voltage gain) in the bandpass table, and we have now derived the correction factor $G_x^{ic}$ from the 1934−638 data above. The combined voltage gain that removes both factors is:
$$g_x^f = g_x^m \cdot \sqrt{G_x^{ic}} = g_x^m \cdot \sqrt{\frac{I^{ic}}{I^\circ}\,(1+dQ)} \tag{X}$$ $$g_y^f = g_y^m \cdot \sqrt{G_y^{ic}} = g_y^m \cdot \sqrt{\frac{I^{ic}}{I^\circ}\,(1-dQ)}$$When $I^{ic}/I^\circ = 1$, these simplify to $g_x^f = g_x^m\sqrt{1+dQ}$, $g_y^f = g_y^m\sqrt{1-dQ}$. The $\sqrt{\cdot}$ converts $G_x^{ic}$ from the correlation (power) domain in which it was derived back to the voltage domain in which bandpass tables operate. Applying $g^f$ to any new target data gives:
$$\frac{XX_{\rm target}^m}{|g_x^f|^2} = \frac{G_x^m \cdot G_x^{ic} \cdot XX^\circ}{G_x^m \cdot G_x^{ic}} = XX^\circ$$The updated table $g^f$ replaces the interim bandpass table and is applied directly to uncalibrated data — no intermediate calibration step is required.
The pipeline produces two files alongside the per-field line plots in
<data-root>/phase3/plots/:
dq_du_correction_factors.csv — machine-readable, one row per
(footprint, field, variant, beam) quad; pure data file (no embedded comments)
suitable for pandas/numpy consumption by downstream processing scripts and
opens cleanly in Numbers / Excel.dq_du_correction_factors_README.txt — plain-text companion with
full provenance, column schema, physical meaning and usage examples.dq_du_correction_factors.txt — fixed-width ASCII companion;
human-readable and greppable without Python.| Column | Type | Description |
|---|---|---|
footprint | str | ASKAP beam footprint name (e.g. closepack36); read from weights.footprint_name in the schedblock metadata. All rows produced from a single manifest share the same footprint; rows from different footprints (different manifests) can be safely appended before filtering. |
field | str | Reference field name, e.g. REF_1324-28 |
variant | str | bpcal (bandpass-cal measurement) or lcal (leakage-cal measurement) |
beam | int | ASKAP beam index, 0-based (0–35 for closepack36) |
mean_dQ | float, % | Mean signed $dQ/I$ leakage averaged across all SB_REF × ODC observations |
std_dQ | float, % | Standard deviation of $dQ/I$ across observations — indicates repeatability |
mean_dU | float, % | Mean signed $dU/I$ (present when --dU was passed to plot_dQ_vs_beam.py) |
std_dU | float, % | Standard deviation of $dU/I$ |
n_obs | int | Number of (SB_REF, ODC) rows averaged for this beam |
The CSV is a pure data file (column header row + data rows only) and opens
cleanly in any spreadsheet. Full provenance and schema documentation is in the
companion dq_du_correction_factors_README.txt in the same directory.
import pandas as pd
df = pd.read_csv("phase3/plots/dq_du_correction_factors.csv")
# Per-beam lookup for a specific footprint / field / variant / beam
row = df[
(df.footprint == "closepack36") &
(df.field == "REF_1324-28") &
(df.variant == "bpcal") &
(df.beam == 12)
].iloc[0]
dq, dq_std = row.mean_dQ, row.std_dQ # fractional Stokes-Q leakage, %
du, du_std = row.mean_dU, row.std_dU # fractional Stokes-U leakage, %
# All 36 beams as a numpy array (for vectorised correction)
sub = df[
(df.footprint == "closepack36") &
(df.field == "REF_1324-28") &
(df.variant == "bpcal")
].sort_values("beam")
dq_array = sub.mean_dQ.to_numpy() # shape (36,)
From equation (X), the corrected bandpass voltage gain for beam $b$ is:
$$g_x^f[b] = g_x^m[b]\,\sqrt{1 + dQ[b]/100}$$ $$g_y^f[b] = g_y^m[b]\,\sqrt{1 - dQ[b]/100}$$where $dQ[b]$ is mean_dQ for that beam (in percent, so the division by 100
converts to a fractional correction). The $\sqrt{\cdot}$ converts from the
correlation (power) domain back to the voltage domain required by the bandpass
table.
The std_dQ and n_obs columns allow a downstream script to propagate
uncertainty or to apply a beam-quality threshold (e.g. reject beams with
$\sigma_{dQ} \gt 1\%$ or $n_{\mathrm{obs}} \lt 3$) before applying the correction.