Code for reducing full polarization continuum observations from ALMA.
This pipeline is designed to automate and guide the reduction process, split into two primary stages (Pre-calibration and Calibration), followed by optional self-calibration, point source fitting, and polarization variability analysis.
- CASA: The pipeline must be run inside a CASA (Common Astronomy Software Applications) environment. CASA version 6.x is recommended.
- Dependencies: The auxiliary scripts require standard Python libraries such as
numpy,matplotlib, andurllib(typically pre-installed in CASA's Python environment). - HPC/MPI: For large datasets, running CASA with MPI (
mpicasa) is highly recommended.
How to access the ALMA polarization calibration scripts.
Here are the instructions for cloning the almapol repository to your HPC home directory:
- Check if you have an
~/.ssh/id_rsa.pubfile. If so, skip to step 3. - If not, generate one by running:
Press enter through the prompts to accept the defaults.
ssh-keygen
- Run
cat ~/.ssh/id_rsa.puband copy the output contents. - Navigate to GitHub.
- Click on your profile photo in the top right corner and select Settings.
- Navigate to the SSH and GPG keys tab on the left.
- Click New SSH key in the top right, give it a descriptive name, and paste the copied public key into the Key field.
- Clone the repository using SSH:
git clone git@github.com:alexander-group/almapol.git
From now on, run cd ~/almapol && git pull before starting a data reduction to ensure you are using the most up-to-date scripts!
The calibration process is divided into two sequential stages.
This stage imports the ASDMs, generates listing files, applies a priori flags, runs Tsys and WVR calibration, concatenates the observations, and splits the data.
- Setup:
- Copy
almapol/alma_precal.pyandalmapol/config.pyinto your current working directory. - Create symbolic links for the necessary files (don't forget the trailing dot
.):ln -s /path/to/measurement/sets/*.ms . ln -s /path/to/almapol/almapol/util.py . ln -s /path/to/almapol/almapol/calibrate.py .
- Start CASA (using MPI if available):
ml casa mpicasa -n 17 $(which casa)
- Copy
- Import:
- Listobs (requires manual inspection):
- Set
dolistobs = Trueinconfig.pyand re-runalma_precal.py. - Open the generated
.listobs.txtfiles to identify and update:fieldnames,tsysfields_self,tsysfields_alt,tsysfields_ref,spw0, andspwmaxinconfig.py. You will need to search the logs/text files to determine the base spectral windowspw0for later calibration scaling.
- Set
- Apriori Flags:
- Set
aprioriflags = Trueinconfig.pyand re-runalma_precal.py.
- Set
- Fix Syscal Times:
- Set
dofixsyscaltimes = Trueinconfig.pyand re-runalma_precal.py.
- Set
- Tsys and WVR Calibration:
- Set
docalibrate = True,dogencal = Trueand re-runalma_precal.py. - Set
docalibrate = True,dogencal = False,doapplycal = Trueand re-runalma_precal.py.
- Set
- Concat:
- Set
docalibrate = False,doapplycal = False,doconcat = Trueand re-runalma_precal.py.
- Set
- Split:
- Run
listobson the concatenated Measurement Set to determine the science spectral windows and setsciencespwinconfig.py. - Set
doconcat = False,dosplit = Trueand re-runalma_precal.py.
- Run
This stage derives the parallel-hand and cross-hand/leakage calibrations, and applies them to your calibrators and targets.
- Setup:
- Run
listobson the output of the split command from Stage 1. Identify the field names for polarization (Lcal), bandpass (Bcal), flux (Fcal), and gain (Gcal) calibrators, and enter them inconfig.py. - Run
plotantsto select a reference antenna near the center of the array, and setrefantinconfig.py.
- Run
- Derive Parallel-Hand Calibration:
- Set
dosplit = False,docal_SetJy = True,doflagedge = True,docal_Bandpass = True,docal_Gain = True,docal_Fluxscale = Trueinconfig.py. - Run in CASA:
run -i "calibrate.py"
- Check the
setjy.lastfile in the terminal to verify and record the flux calibrator's flux density and spectral index. - Inspect
fig7.pngfor bandpass solutions. Flag data as necessary, remove the calibration tables, and repeat this step if flags were modified.
- Set
- Apply Parallel-Hand and Start Polarization Calibration:
- Set
docal_SetJy = False,doflagedge = False,docal_Bandpass = False,docal_Gain = False,docal_Fluxscale = False,applycal_ParallelHand = True,dopol_Gain = Trueinconfig.py. - Re-run
calibrate.py. - Inspect
fig8.png(flux calibrator) andfig9.png(gain calibrator) for polarization structure in gains. - Check
fig10-prelim.png(leakage calibrator) for the gain amplitude ratio, flag bad data if necessary, and re-run this step.
- Set
- Determine the Kcrs Scan:
- Set
applycal_ParallelHand = False,dopol_Gain = False,dopol_ApplyGainBP = True,dopol_QU = Trueinconfig.py. - Re-run
calibrate.py. - This opens the
plotmsGUI and savesfig10.png. Identify a scan showing average polarization values and setpolscaninconfig.pyto this scan number. - Check
fig11.pngfor any data requiring flags. - Note the derived polarization of the leakage calibrator outputted to the terminal and save it for your records.
- Set
- Derive the Cross-Hand Delay:
- Set
dopol_ApplyGainBP = False,dopol_QU = False,dopol_CrossHandDelay = Trueinconfig.py. - Re-run
calibrate.py. - In the
plotmsGUI, page through the baselines relative torefant(one is saved asfig12.png). Note that phase scatter on low S/N scans is normal.
- Set
- Apply Cross-Hand Delay & Solve for XY Phase:
- Set
dopol_CrossHandDelay = False,dopol_ApplyKcrs = True,dopol_XYphase = Trueinconfig.py. - Re-run
calibrate.py. - Inspect
fig13.pngto confirm the phases have been flattened (residual non-linear scatter is resolved in the cross-hand bandpass). - Inspect
fig14.pngto check for opposite color signatures (indicating the reference antenna's non-zero cross-hand phase).
- Set
- Derive Instrumental Leakage & Cross-Hand Bandpass:
- Set
dopol_ApplyKcrs = False,dopol_XYphase = False,dopol_ApplyXYphase = True,dopol_RegenLcalGains = True,dopol_Leakage = True,dopol_XYamp = Trueinconfig.py. - Re-run
calibrate.py. This generates:fig17.png: Verify the phase ramp has been successfully removed.fig18a.png/fig18b.png: Verify the second plot accounts for the leakage calibrator's intrinsic polarization.fig19.png,fig20.png,fig21.png(a and b): Verify leakage amplitude, real, and imaginary components across the array are flat. Run customplotmscommands in CASA to inspect all antennas:plotms(vis=msname+'.Df0gen', xaxis='frequency', yaxis='amp', spw='0~3', iteraxis='antenna', coloraxis='corr', gridrows=2, gridcols=2, showgui=True)
fig22.pngandfig23.png: Cross-hand gain amplitudes and amplitude ratios (should be close to 1).
- Record the residual polarization of the leakage calibrator from the terminal output (it should be very small).
- Set
- Verify Leakage Calibrator Calibration:
- Set
dopol_ApplyXYphase = False,dopol_RegenLcalGains = False,dopol_Leakage = False,dopol_XYamp = False,applycal_Lcal = Trueinconfig.py. - Re-run
calibrate.py. This produces:fig26.png: Imaginary vs. Real (signal should be entirely real).fig27.png/fig28.png: Calibrated amplitude/phase vs. frequency (parallel hands should be ~1, cross-hands should be small, phase should be 0 or 180 degrees).
- Set
- Apply to Target and Split Data:
- Set
applycal_Lcal = False,applycal_Trgt = True,dosplit_Target = True,dosplit_Gcal = True,dosplit_Lcal = Trueinconfig.py. - Re-run
calibrate.pyto create the final split Measurement Sets and generatefig30.png/fig31.pngshowing the Stokes signals before and after calibration.
- Set
For targets requiring self-calibration, almapol/imaging.py provides an interactive loop to perform phase and amplitude self-cal cycles:
- It computes the optimal clean cellsize based on antenna UVW coordinates.
- It calculates the minimum recommended solution interval (
t_sol) for each self-cal cycle. - It prompts the user for solution intervals and calibration modes (phase-only
'p'or amp+phase'ap'), runsgaincalandapplycal, and shows diagnostic plots before asking whether to proceed or repeat the step.
To use:
- Copy or symlink
almapol/imaging.pyto your working directory. - Edit the variables at the top of
imaging.py(e.g.,main_vis,target,refant, andsplit_from_main). - Run CASA and execute:
execfile("imaging.py")
The almapol/imgfitpoltasks.py script contains helper tasks to analyze Stokes images (IQUV and polarized intensity P maps):
- Point-Source Fitting (
dopointsourcefit): Automatically locates the Stokes-I peak, defines on/off-source regions based on the synthesized beam shape, performs multi-Stokes component fitting using CASAimfit, measures local RMS noise levels, and appends the values (RA, Dec, Flux, Error, RMS) toresults.txt. - Per-Scan Imaging & Fit (
dovartests): Automates imaging per scan range and runs point source fits to produce a timeline of flux density and polarization parameters. - Variability Plotting (
doplotpolvary): Reads the tabular scan outputs, calculates offsets, fractions, and errors relative to a reference time, and produces polarization variability plots (QUVoffsets or fractions).
The table below describes the layout of files and folders in this repository:
| Path | Description |
|---|---|
.github/ |
Directory containing GitHub configuration files and workflows. |
└── .github/workflows/zenodo.yml |
GitHub Actions workflow to publish releases to Zenodo or Zenodo Sandbox. |
almapol/ |
Directory containing all calibration, imaging, and fitting Python scripts. |
├── almapol/alma_precal.py |
Stage 1 pre-calibration pipeline. Prepares ASDMs, generates listing files, and handles initial calibration (Tsys/WVR). |
├── almapol/calibrate.py |
Stage 2 calibration pipeline. Performs parallel-hand, cross-hand, and leakage calibration. |
├── almapol/config.py |
Configuration template where paths, calibrator names, science SPWs, and pipeline step toggles are defined. |
├── almapol/imaging.py |
Interactive self-calibration loop script (calculates cell sizes, runs tclean and applycal). |
├── almapol/imgfitpoltasks.py |
Fits point sources to Stokes I/Q/U/V and polarized intensity images. Supports variability analysis. |
├── almapol/plotcommands.py |
Collection of CASA plotms commands corresponding to steps in standard NRAO polarization guides. |
├── almapol/poltutorial-plotcommands.py |
CASA plotms commands customized for the 3C286 Band 6 polarization calibration guide tutorial dataset. |
├── almapol/util.py |
Utility functions for frequency conversions, querying the ALMA online flux database, and parsing XML VOTables. |
.gitignore |
Specifies patterns for files and directories (like CASA output files and logs) that git should ignore. |
.zenodo.json |
Metadata description file used by Zenodo to automatically populate release records. |
LICENSE |
The license terms for the repository. |
README.md |
This documentation file. |