VLA Polarization pipe Tutorial: Difference between revisions

From CASA Guides
Jump to navigationJump to search
Akapinsk (talk | contribs)
Created page with "Category:EVLACategory:CalibrationCategory:VLA <b>This CASA Guide is for the monolithic, not the modular pip-wheel version, version 6.4.1 of CASA that includes the..."
 
Alawson (talk | contribs)
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:EVLA]][[Category:Calibration]][[Category:VLA]]
[[Category:EVLA]][[Category:Calibration]][[Category:VLA]]


<b>This CASA Guide is for the monolithic, not the modular pip-wheel version, version 6.4.1 of CASA that includes the VLA pipeline.</b> If you are using a later version of CASA and this is the most recent available guide, then you should be able to use most, if not all, of this tutorial. This guide also uses [https://cartavis.org/ CARTA] as its choice of image viewer. We strongly recommend using [https://cartavis.org/ CARTA] over the built in CASA viewer, used by tasks such as [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casaviewer.imview.html?highlight=imview imview], as it provides a much more efficient, stable, and feature rich user experience. A comparison of the CASA viewer and [https://cartavis.org/ CARTA], as well as instructions on how to use [https://cartavis.org/ CARTA] at NRAO is provided in the respective section of [https://casadocs.readthedocs.io/en/stable/notebooks/carta.html CASA docs].
== Notes on CASA ==


== Overview ==
<b>This CASA Guide is for Version 6.4.1 of CASA.</b> If you are using a later version of CASA and this is the most recent available guide, then you should be able to use most, if not all, of this tutorial. This guide is meant to be completed using the monolithic CASA and not modular CASA as the GUI may not work correctly otherwise.  
This CASA guide describes the calibration and imaging of a single-pointing continuum data set taken with the Karl G. Jansky Very Large Array (VLA) of the binary black hole system 3C 75 in Abell 400 cluster of galaxies.
[http://simbad.u-strasbg.fr/simbad/sim-id?Ident=3C75].  The data were taken as a demonstration for the VLA data reduction workshops under project code TDRW0001. To reduce the dataset size, the data was recorded with a single 1 GHz baseband centered at 3.0 GHz, resulting in 8x128 MHz wide spectral windows with 64 channels each. The observation was set up to allow for full polarization calibration. The calibration part of this tutorial can be performed on a laptop computer with sufficient storage. The imaging part, however, will require more computing power and memory. This CASA guide was also used as basis for a presentation on polarization calibration at the 7th VLA data reduction workshop: [https://science.nrao.edu/science/meetings/2019/vla-data-reduction/Schinzel_Polarization.pdf]


== How to Use This CASA Guide ==
There are a number of possible ways to run CASA, described in more detail in [[Getting Started in CASA]]. In this tutorial we would like you to use either (or both) of the following methods so that you can familiarize yourself with the CASA software:


Here are a number of possible ways to run CASA, described in more detail in [https://casadocs.readthedocs.io/en/v6.4.1/notebooks/usingcasa.html Getting Started in CASA]. In brief, there are at least three different ways to run CASA:
* Interactive: examining task inputs. In this mode, one types '''taskname''' to load the task, '''inp''' to examine the inputs, and '''go''' once those inputs have been set to your satisfaction. Allowed inputs are shown in blue and bad inputs are colored red. The input parameters themselves are changed one by one, e.g., ''selectdata=True''. Screenshots of the inputs to various tasks used in the data reduction below are provided, to illustrate which parameters need to be set. More detailed help can be obtained on any task by typing '''help ''taskname'''''. Once a task is run, the set of inputs is stored and can be retrieved via '''tget ''taskname'''''; subsequent runs will overwrite the previous '''tget''' file.


* Interactively examining task inputs. In this mode, one types '''default taskname''' to load the task (this will also set all the task parameters to default values), '''inp''' to examine the inputs, and '''go''' once those inputs have been set to your satisfaction. Allowed inputs are colored blue and bad inputs are colored red. The input parameters themselves are changed one by one, e.g., ''selectdata=True''. Screenshots of the inputs to various tasks used in the data reduction are provided to illustrate which parameters need to be set. More detailed help can be obtained on any task by typing '''help ''taskname'''''. Once a task is run, the set of inputs are stored and can be retrieved via '''tget ''taskname'''''; subsequent runs will overwrite the previous '''tget''' file.
* Pseudo-interactive: task function calls. In this mode, all of the desired inputs to a task are provided at once inn the CASA command line. This tutorial is made up of such calls, which were developed by looking at the inputs for each task and deciding what needed to be changed from default values. For task function calls, only parameters that you want to be different from their defaults need to be set.


* Pseudo-interactively via task function calls. In this case, all of the desired inputs to a task are provided at once on the CASA command line. This tutorial is made up of such calls, which were developed by looking at the inputs for each task and deciding what needed to be changed from default values. For task function calls, only parameters that you want to be different from their defaults need to be set.
This tutorial is largely self-paced. Any time you have a question, or something doesn't look right or you are unsure of, please do summon one of the tutors present in the room.


* Non-interactively via a script. A series of task function calls can be combined together into a script and run from within CASA via '''execfile('scriptname.py')'''. This and other CASA Tutorial Guides have been designed to be extracted into a script via the script extractor by using the method described at the [[Extracting scripts from these tutorials]] page. Should you decide to use the script generated by the script extractor for this CASA Guide, be aware that it will require some small amount of interaction related to the plotting, occasionally suggesting that you close the graphics window and hitting return in the terminal to proceed. It is, in fact, unnecessary to close the graphics windows (it is suggested that you do so purely to keep your desktop uncluttered).
== Data Set ==


If you are a relative novice or just new to CASA, it is strongly recommended to work through this tutorial by cutting and pasting the task function calls provided below after you have read all the associated explanations. Work at your own pace, look at the inputs to the tasks to see what other options exist, and read the help files. Later, when you are more comfortable, you might try to extract the script, modify it for your purposes, and begin to reduce other data.
This CASA guide describes the calibration and imaging of a single-pointing continuum data set taken with the Karl G. Jansky Very Large Array (VLA) of the binary black hole system 3C 75 in Abell 400 cluster of galaxies [http://simbad.u-strasbg.fr/simbad/sim-id?Ident=3C75]. The observations were performed with a single 1 GHz baseband centered at 3.0 GHz, resulting in 8x128 MHz wide spectral windows with 64 channels each. The observation was set up to allow for full polarization calibration.


== Obtaining the Data ==
Prior to the synthesis imaging workshop you should have received instructions to download the data for this tutorial. If you have not already, you will need to untar and unzip the file using the command: 'tar -xzvf TDRW0001_calibrated_CASA6.4.1.ms.tgz' and then give it the same name as the guide uses: 'mv TDRW0001_calibrated_CASA6.4.1.ms TDRW0001_calibrated.ms'.


If starting from scratch, you can obtain the dataset from the [https://data.nrao.edu/ NRAO archive] and search for the Archive File ID: 'TDRW0001.sb35624494.eb35628826.58395.23719237269'. The uncalibrated visibilities have a size of 12.5 GB. Make sure to select to download the SDM-BDF dataset, if you want to start from the lowest level, because by default a .ms file will be provided by the archive.
The first step of polarization calibration is to first obtain a decent Stokes I (RR and LL) calibration. This has already been done for you by running the raw data through the CASA 6.4.1 version of the VLA pipeline. One additional step was required which involved removing the parallactic angle correction that was applied by the standard pipeline. For those familiar with the VLA pipeline, we essentially repeated what pipeline tasks hifv_applycals, hifv_targetflag, and hifv_statwt did, but disabled the application of parallactic angle corrections.


For those who want to skip the step of obtaining a continuum Stokes I calibrated measurement set, we have created a starting dataset on which the polarization calibration steps and final imaging can be performed: ['https://casa.nrao.edu/Data/VLA/Polarization/TDRW0001_calibrated_CASA6.4.1.ms.tgz '] (size: 11 GB). It is recommended to use the command line tool '''wget''' to download the calibrated data or directly download through the browser. You will need to untar and unzip the file using the command: 'tar -xzvf TDRW0001_calibrated_CASA6.4.1.ms.tgz' and then give it the same name as the guide uses: 'mv TDRW0001_calibrated_CASA6.4.1.ms TDRW0001_calibrated.ms'. Then you can skip ahead to the section 'The Observation'.


== Pipeline Calibration of Parallel Hands (RR/LL) ==
== The Observation ==


If you start with the uncalibrated visibilities obtained from the archive, you will need to first perform a standard continuum calibration of the parallel-hand (RR/LL) cross-correlation visibilities. In this guide we use the standard VLA pipeline that is packaged with the CASA release. You can find more information on the latest release of the VLA pipeline at: [https://science.nrao.edu/facilities/vla/data-processing/pipeline https://science.nrao.edu/facilities/vla/data-processing/pipeline].
Before starting the calibration process, we want to get some basic information about the data set. To examine the observing conditions during the observing run, and to find out any known problems with the data, we can take a look at the [http://www.vla.nrao.edu/cgi-bin/oplogs.cgi observer log], but in order to get to our observation we'll need the date it was observed on. The CASA task to use to get that information, and other very useful information on the setup of the observation is: [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.information.listobs.html?highlight=listobs listobs].


In this example, we will not run the pipeline in its standard way but tweak it to force a certain reference antenna, ea10. The pipeline typically tries to pick a reference antenna at the center of the array; however, this dataset was observed in D array configuration with very short baselines. It is better to use one of the outer antennas for reference, which provides longer baselines and more stable phase solutions. To set the reference antenna, we specify the ''refantignore'' parameter in some of the pipeline tasks to exclude all but the reference antenna, and use a pipeline execution script ('casa_pipescript.py'). Take the script given below and paste it into a text file inside your working directory that also contains the dataset you downloaded from the NRAO archive and name it casa_pipescript.py.
Once you've gotten the date of observation for this data set find its [http://www.vla.nrao.edu/cgi-bin/oplogs.cgi observer log] and note the two antennas that had issues during the observation.
 
<source lang="python">
# casa_pipescript.py


__rethrow_casa_exceptions = True
Before beginning our polarization calibration, we should inspect the pipeline calibration weblog for any obvious issues. You can download the weblog from ['https://casa.nrao.edu/Data/VLA/Polarization/SIW19pipeline-20230103T175723.tgz '] or view it through a browser [https://casa.nrao.edu/Data/VLA/Polarization/pipeline-20230103T175723/html/ here]. For those not familiar with viewing these weblogs, they are basically a little report that is meant to help judge how well the VLA pipeline did with its calibration. Feel free to explore it as you wish, but you'll likely find two of the more useful stages to look at are hifv_finalcals (plots of the final solution tables) and hifv_plotsummary (various plots of the calibrated data). For more details on the pipeline output you can have a look at the [https://casaguides.nrao.edu/index.php?title=VLA-S-CASA_Pipeline-CASA6.4.1 VLA CASA Pipeline Guide].
context = h_init()
context.set_state('ProjectSummary', 'observatory', 'Karl G. Jansky Very Large Array')
context.set_state('ProjectSummary', 'telescope', 'EVLA')
context.set_state('ProjectStructure', 'recipe_name', 'hifv_cal')
try:
    hifv_importdata(vis=['TDRW0001.sb35624494.eb35628826.58395.23719237269'], session=['default'])
    hifv_hanning(pipelinemode="automatic")
    hifv_flagdata(hm_tbuff='1.5int', intents='*POINTING*,*FOCUS*,*ATMOSPHERE*,*SIDEBAND_RATIO*, *UNKNOWN*, *SYSTEM_CONFIGURATION*, *UNSPECIFIED#UNSPECIFIED*')
    hifv_vlasetjy(pipelinemode="automatic")
    hifv_priorcals(pipelinemode="automatic")
    hifv_testBPdcals(weakbp=False, refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_checkflag(pipelinemode="automatic")
    hifv_semiFinalBPdcals(weakbp=False, refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_checkflag(checkflagmode='semi')
    hifv_semiFinalBPdcals(weakbp=False, refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_solint(refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_fluxboot(fitorder=2, refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_finalcals(refantignore='ea01,ea02,ea03,ea04,ea05,ea06,ea07,ea08,ea09,ea11,ea12,ea13,ea14,ea15,ea16,ea17,ea18,ea19,ea20,ea21,ea22,ea23,ea24,ea26,ea28')
    hifv_applycals(pipelinemode="automatic")
    hifv_targetflag(intents='*CALIBRATE*,*TARGET*')
    hifv_statwt(pipelinemode="automatic")
    hifv_plotsummary(pipelinemode="automatic")
    hif_makeimlist(intent='PHASE,BANDPASS', specmode='cont')
    hif_makeimages(hm_masking='none')
finally:
    h_save()


</source>
You will likely note that there are four sources observed. Here the sources are introduced briefly, with more detail contained in the sections below in which they are used:
* 0137+331=3C48, which will serve as a calibrator for the visibility amplitudes, i.e., it is assumed to have precisely known flux density, the spectral bandpass, and the polarization position angle;
* J0259+0747, which will serve as a calibrator for the visibility phases and can be used to determine the instrumental polarization;
* J2355+4950, which can serve as a secondary instrumental polarization calibrator or to check residual instrumental polarization, and;
* 3C75, which is the science target.


Now that we have the script, we can execute the pipeline. Type on the command line the following.
Both to get a sense of the array, as well as identify the location of the reference antenna that we told the pipeline to choose for parallel hand calibration, have a look at the antenna setup page of the weblog. For calibration purposes, you would generally select an antenna that is close to the center of the array (and that is not listed in the operator's log as having had problems!).  


<source lang="bash">
# On the command line, for your own installation of CASA 6.4.1-12
casa --pipeline --nogui -c casa_pipescript.py


# If using an NRAO computer, to select the right CASA version use instead
Can you tell which antenna we chose for our reference antenna?
casa -r 6.4.1-12-pipeline-2022.2.0.64 --pipeline --nogui -c casa_pipescript.py
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
</source>
<div style="font-weight:bold;line-height:1.6;">Answer</div>
<div class="mw-collapsible-content">
The reference antenna by definition has its delays and phases set to zero. So by looking at those solution tables in the hifv_finalcals stage we can see that ea10 was our reference antenna.
</div></div>


Now you can go and get a cup of coffee or lunch; this will take a while. On a beefy computer expect about two hours. Once the pipeline has successfully finished you will see some similar messages on the command line prompt.
== Examining and Editing the Data ==
<pre style="background-color: #E0FFFF;">
2021-11-25 00:55:08 INFO: Plotting oussid.s19_0._0137+331_3C48__bp.S_band.cont.I.iter0.psf.tt0
2021-11-25 00:55:08 INFO: Plotting oussid.s19_0._0137+331_3C48__bp.S_band.cont.I.iter0.pb.tt0
2021-11-25 00:55:09 INFO: Plotting oussid.s19_0._0137+331_3C48__bp.S_band.cont.I.iter0.residual.tt0
2021-11-25 00:55:09 INFO: Plotting oussid.s19_0._0137+331_3C48__bp.S_band.cont.I.iter1.image.tt0
2021-11-25 00:55:09 INFO: Plotting oussid.s19_0._0137+331_3C48__bp.S_band.cont.I.iter1.image.tt0


2021-11-25 00:55:20 INFO: Saving context to 'pipeline-20211124T225215.context'
It is always a good idea to examine the data before jumping straight into calibration. Even though the pipeline did a good job of calibrating and flagging the data, it isn't perfect. From the pipeline weblog, looking at the final amplitude gain calibration vs time plots in hifv_finalcals, we can see that during the second half of the observation antennas ea03, ea12, and ea16 shows some gain instability; otherwise there are no issues identified at this point.  
</pre>


In order to be able to continue calibration for polarization, i.e. the cross-hand correlations (RL/LR), on pre-calibrated visibilities, we need to perform additional steps that remove the parallactic angle correction that was applied by the standard pipeline. To do so, start CASA and execute the following commands.
We will start by making a simple overview plot.


<source lang="python">
<source lang="python">
# In CASA
# In CASA
flagmanager(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms',mode='restore',versionname='applycal_5')
plotms(vis='TDRW0001_calibrated.ms', selectdata=True, correlation='RR', averagedata=True, avgchannel='64', coloraxis='field', plotfile='colorbyfield.jpeg')
</source>
[[Image:Colorbyfield_CASA6.2.1.jpeg|200px|right|thumb|Figure 1: Overview of the observation: amplitude vs time, color-coded by field.]]
* ''selectdata=True '': One can choose to plot only selected subsets of the data.
* ''correlation='RR' '': Plot only the right-handed (left-handed omited only for speed) polarization products. The cross-terms ('RL' and 'LR') will be close to zero for non-polarized sources.
* ''averagedata=True'': One can choose to average data points before plotting them.
* ''avgchannel='64' '': With this plot, we are mainly interested in the fields vs time. Averaging over all 64 channels in the spectral window makes the plotting faster.
* ''coloraxis='field' '': Color-code the plotting symbols by field name/number.
The default x- and y-axis parameters are 'time' and 'amp', so the above call to [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] produces an amplitude vs time plot of the data for a selected subset of the data (if desired) and with data averaging (if desired). Many other values have been left to defaults, but it is possible to select them from within the plotms GUI. 


applycal(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms',
Based on what you've learned from the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.information.listobs.html?highlight=listobs listobs] task you should be able to tell which sources are which in the plot.
        antenna='*&*',
        gaintable=['TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_priorcals.s5_2.gc.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_priorcals.s5_3.opac.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_priorcals.s5_4.rq.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_priorcals.s5_6.ants.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_finalcals.s13_2.finaldelay.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_finalcals.s13_4.finalBPcal.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_finalcals.s13_5.averagephasegain.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_finalcals.s13_7.finalampgaincal.tbl',
        'TDRW0001.sb35624494.eb35628826.58395.23719237269.ms.hifv_finalcals.s13_8.finalphasegaincal.tbl'],
        gainfield=['', '', '', '', '', '', '', '', ''], interp=['', '', '', '',
        '', 'linear,linearflag', '', '', ''], spwmap=[[], [], [], [], [], [],
        [], [], []], calwt=[False, False, False, False, False, False, False,
        False, False], parang=False, applymode='calflagstrict', flagbackup=False)


flagdata(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms',
Another example of using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] for a quick look at your data, select the Data tab and specify ''field 2'' (the complex gain calibrator J0259+0747) to display data associated with the target, then select the Axes tab and change the X-axis to be ''UVdist'' (baseline length in meters). Remove the channel averaging (Data tab), and plot the data using the ''Plot'' button at the bottom of the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] GUI. The important observation is that the amplitude distribution is relatively constant as a function of UV distance or baseline length (i.e., <math>\sqrt{u^2+v^2}</math>; see Figure 2A). A relatively constant visibility amplitude as a function of baseline length means that the source is very nearly a point source (the Fourier transform of a point source, i.e. a delta function, is a constant function). You can see occasional spikes in the calibrated amplitudes. This is most likely caused by radio frequency interference that correlates on certain baselines. We will get to those further in the guide.
        mode='rflag', correlation='ABS_RR,LL', intent='*CALIBRATE*',
        datacolumn='corrected', ntime='scan', combinescans=False,
        extendflags=False, winsize=3, timedevscale=4.0, freqdevscale=4.0,
        action='apply', flagbackup=True, savepars=True)


flagdata(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms',
By contrast, if you make a similar plot for ''field 3'' (our target 3C 75), the result is a visibility function that falls rapidly with increasing baseline length. Figure 2B shows this example, including time averaging of '1e6' seconds (any large number that encompasses more than a full scan will do, we want to fully average each scan). Such a visibility function indicates a highly resolved source. To plot baseline length in wavelengths rather than meters, select ''UVwave'' as the X-axis parameter.
        mode='rflag', correlation='ABS_RR,LL', intent='*TARGET*',
        datacolumn='corrected', ntime='scan', combinescans=False,
        extendflags=False, winsize=3, timedevscale=4.0, freqdevscale=4.0,
        action='apply', flagbackup=True, savepars=True)


statwt(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms', minsamp=8,
A final example is shown in Figure 2C. In this example, we have elected to show phase as a function of (frequency) channel for a single baseline (''antenna='ea01&ea21' '') on the bandpass calibrator, field 0, and non-averaged data. If you choose to iterate by baseline (e.g., ''antenna='ea01' '' and ''iteraxis='baseline' ''), you can see similar phase-frequency variations on all baselines. They center around zero phase, because we are looking at the calibrated visibilities; however, you are seeing a butterfly shaped pattern with phase noise higher toward the channel edges. This pattern is due to a small mismatch in the delay measurement timing (also known as 'delay clunking') which is an internally generated effect and is typically averaged out over time. 
      datacolumn='corrected')
{|
| [[File:Plotms-J0259+0747-Amp-vs-UVdist-CASA6.2.1.jpeg|200px|left|thumb|Figure 2A: plotms view of amp vs. uvdist of J0259+0747, a point source]]
| [[File:Plotms-3C75-Amp-vs-UVwave-CASA6.2.1.jpeg|200px|center|thumb|Figure 2B: plotms view of amp vs. uvwave of 3C 75, a resolved source]]
| [[File:Plotms-3C48-delays-ea01ea21_CASA6.2.1.jpeg|200px|right|thumb|Figure 2C: plotms view of phase vs. channel on one baselines, showing phase delay across the calibrated bandpass]]
|}


split(vis='TDRW0001.sb35624494.eb35628826.58395.23719237269.ms',outputvis='TDRW0001_calibrated.ms',datacolumn='corrected',spw='2~9')
</source>


This applies the flagging state before the final [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] stage of the pipeline, then reapplies the calibration to the corrected column with ''parang=False'', disabling the parallactic angle corrections. After that, we rerun RFI flagging, and recompute the weights based on the new flags that were applied and split out the corrected column for the target spectral windows. Essentially we repeated what pipeline tasks hifv_applycals, hifv_targetflag, and hifv_statwt did, but disabling application of parallactic angle corrections. This is the measurement set we will be using in the following to demonstrate polarization calibration.
On Figure 1 you'll notice that the sources colored in black and green show much more spread in amplitude as compared to the others. Do you know the cause of this?
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
<div style="font-weight:bold;line-height:1.6;">Answer</div>
<div class="mw-collapsible-content">
The black source is our flux density scale and bandpass calibrator, 3C48, and the green source is our target, 3C75. As we saw in Figure 2B, the spread in amplitude of 3C75 is primarily due to the presence of extended structure, that is to say, every baseline sees a slightly different amplitude. However if you make a similar plot of 3C48 you'll notice it is a point source. The spread on it is due to its spectral index (coloring by spectral window should make this stand out).
</div></div>


If you still have the "--nogui" version of CASA running go ahead and close it. Then reopen it without the "--nogui" as we will need the GUIs for further data inspection.


== The Observation ==
You can find similar plots in the CASA pipeline weblog under the task hifv_plotsummary. At this stage the pipeline has taken care of most of the calibration. There might be some remaining issues though that were not caught by the pipeline. In the following we note a couple issues that you might have found while inspecting data in this section. We will take care of those through additional flagging.


Before starting the calibration process, we want to get some basic information about the data set. To examine the observing conditions during the observing run, and to find out any known problems with the data, download the [http://www.vla.nrao.edu/cgi-bin/oplogs.cgi observer log]. Simply fill in the known observing date (in our case 2018-Oct-04) as both the Start and Stop date and click on the '''Show Logs''' button.  The relevant log is labelled with the project code, TDRW0001, and can be downloaded as a [http://www.vla.nrao.edu/operators/logs/2018/10/2018-10-04_0541_TDRW0001.pdf PDF file]. From this, we find the following:
<pre style="background-color: #fffacd;">
 
Issues that you might find:
<pre style="background-color: #E0FFFF;">
- ea12, scan 17: amplitude spike at the end of the scan (can be spotted already in Figure 1)
Information from observing log:
- Residual RFI (see Figure 2A)
Antennas in the D-array may be shadowed at low elevations.  If shadowing
occurs, sensitivity will be affected.
 
NOTE!: The VLA is still recovering from a long power outage, and these data may
have unusual artifacts, missing antennas or IFs, ect., in them. NRAO staff will
examine the data closely after observing to determine if they meet the criteria for
a successful observation.
 
Antenna ea05: S-band receiver cooling after work performed, currently 65/177K,
              thus we expect lower sensitivity from this antenna.
Antenna ea12: C-band receiver warm for cold head replacement.
 
Winds at 5-7 m/s, API RMS phase around 4.5 deg, 10-20% sky cover, cumuliform and stratiform clouds.
</pre>
</pre>


Before beginning our data reduction, we should inspect the pipeline calibration weblog for any obvious issues. You can download the weblog from ['https://casa.nrao.edu/Data/VLA/Polarization/pipeline-20230103T175723.tgz '].
In the case of the amplitude spike, we can flag the affected time period by invoking the casa task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata]. It is a good idea to save the original flags before performing any flagging by setting '''flagbackup=True'''.  


Inside the weblog you have access to the overview page and the listobs task output that provide some basic information about the data.
<source lang="python">
# In CASA
flagdata(vis='TDRW0001_calibrated.ms', flagbackup=True, mode='manual', antenna='ea12',scan='17',timerange='07:25:57~07:26:18')
</source>


You will note that there are four sources observed. Here the sources are introduced briefly, with more detail contained in the sections below in which they are used:
You can check the effect of this flagging by replotting Figure 2A. The spikes we saw before on some baselines should have disappeared. If you plot frequency against amplitude without averaging, however, you will still see some channels with interference that we will need to flag, especially on the instrumental polarization calibrators. Polarization calibration is very sensitive to interference, especially in the cross-hand correlations RL,LR. The pipeline does a good job at this, but there are still some RFI left; we will perform some additional flagging steps in the next section.  
* 0137+331=3C48, which will serve as a calibrator for the visibility amplitudes, i.e., it is assumed to have precisely known flux density, the spectral bandpass, and the polarization position angle;
* J0259+0747, which will serve as a calibrator for the visibility phases and can be used to determine the instrumental polarization;
* J2355+4950, which can serve as a secondary instrumental polarization calibrator or to check residual instrumental polarization, and;
* 3C75, which is the science target.


=== Additional Flagging ===


<pre style="background-color: #fffacd;">
First we try to get a good sense of additional flagging that might be needed by plotting frequency against amplitude for the RR,LL and RL,LR polarizations of our calibrators (fields 0 through 2). You will notice some left over RFI on the bandpass calibrator in RR, LL. However, we also need to pay particular attention to RL, LR (see Figure 4A). Here we consider calibrators only; we will perform additional flagging on the target field at a later stage.
================================================================================
          MeasurementSet Name:  /lustre/aoc/sciops/alawson/casaguides/TDRW0001_calibrated.ms      MS Version 2
================================================================================
  Observer: Dr. Emmanuel Momjian    Project: uid://evla/pdb/35621723 
Observation: EVLA
Data records: 5503680      Total elapsed time = 9910 seconds
  Observed from  04-Oct-2018/05:47:35.to   04-Oct-2018/08:32:45.0 (UTC)


  ObservationID = 0        ArrayID = 0
<source lang="python">
  Date        Timerange (UTC)          Scan  FldId FieldName            nRows    SpwIds  Average Interval(s)    ScanIntent
# In CASA
  04-Oct-2018/05:47:35.0 - 05:48:30.0    3      0 0137+331=3C48            30888  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [SYSTEM_CONFIGURATION#UNSPECIFIED]
# for parallel hands
              05:48:35.0 - 05:49:00.0    4      0 0137+331=3C48            14040  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [SYSTEM_CONFIGURATION#UNSPECIFIED]
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RR,LL')
              05:49:05.0 - 05:53:25.0    5      0 0137+331=3C48          146016  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_BANDPASS#UNSPECIFIED,CALIBRATE_FLUX#UNSPECIFIED,CALIBRATE_POL_ANGLE#UNSPECIFIED]
# for cross-hands
              05:53:30.0 - 05:57:55.0    6      1 J2355+4950              148824  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED]
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RL,LR')
              05:58:00.0 - 06:03:55.0    7      2 J0259+0747              199368  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
</source>  
              06:04:00.0 - 06:18:55.0    8      3 3C75                    502632  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              06:19:00.0 - 06:20:10.0    9      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              06:20:15.0 - 06:35:05.0    10      3 3C75                    499824  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              06:35:10.0 - 06:36:20.0    11      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              06:36:25.0 - 06:51:20.0    12      3 3C75                    502632  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              06:51:25.0 - 06:52:30.0    13      2 J0259+0747              36504  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              06:52:35.0 - 07:07:30.0    14      3 3C75                    502632  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              07:07:35.0 - 07:08:45.0    15      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              07:08:50.0 - 07:23:40.0    16      3 3C75                    499824  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              07:23:45.0 - 07:26:25.0    17      2 J0259+0747              89856  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              07:26:30.0 - 07:41:25.0    18      3 3C75                    502632  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              07:41:30.0 - 07:42:40.0    19      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              07:42:45.0 - 07:57:35.0    20      3 3C75                    499824  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              07:57:40.0 - 07:58:50.0    21      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              07:58:55.0 - 08:13:50.0    22      3 3C75                    502632  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              08:13:55.0 - 08:15:05.0    23      2 J0259+0747              39312  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
              08:15:10.0 - 08:30:00.0    24      3 3C75                    499824  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [OBSERVE_TARGET#UNSPECIFIED]
              08:30:05.0 - 08:32:45.0    25      2 J0259+0747              89856  [0,1,2,3,4,5,6,7]  [5, 5, 5, 5, 5, 5, 5, 5] [CALIBRATE_AMPLI#UNSPECIFIED,CALIBRATE_PHASE#UNSPECIFIED,CALIBRATE_POL_LEAKAGE#UNSPECIFIED]
          (nRows = Total number of rows per scan)
Fields: 4
  ID  Code Name                RA              Decl          Epoch  SrcId      nRows
  0    NONE 0137+331=3C48      01:37:41.299431 +33.09.35.13299 J2000  0        190944
  1    NONE J2355+4950          23:55:09.458169 +49.50.08.34001 J2000  1        148824
  2    NONE J0259+0747          02:59:27.076633 +07.47.39.64322 J2000  2        651456
  3    NONE 3C75                02:57:42.630000 +06.01.04.80000 J2000  3        4512456
Spectral Windows:  (8 unique spectral windows and 1 unique polarization setups)
  SpwID  Name          #Chans  Frame  Ch0(MHz)  ChanWid(kHz)  TotBW(kHz) CtrFreq(MHz) BBC Num  Corrs         
  0      EVLA_S#A0C0#2    64  TOPO    2488.000      2000.000    128000.0  2551.0000      12  RR  RL LR  LL
  1      EVLA_S#A0C0#3    64  TOPO    2616.000      2000.000    128000.0  2679.0000      12  RR  RL  LR  LL
  2      EVLA_S#A0C0#4    64  TOPO    2744.000      2000.000    128000.0  2807.0000      12  RR  RL  LR  LL
  3      EVLA_S#A0C0#5    64  TOPO    2872.000      2000.000    128000.0  2935.0000      12  RR  RL  LR  LL
  4      EVLA_S#A0C0#6    64  TOPO    3000.000      2000.000    128000.0  3063.0000      12  RR  RL  LR  LL
  5      EVLA_S#A0C0#7    64  TOPO    3128.000      2000.000    128000.0  3191.0000      12  RR  RL  LR  LL
  6      EVLA_S#A0C0#8    64  TOPO    3256.000      2000.000    128000.0  3319.0000      12  RR  RL  LR LL
  7      EVLA_S#A0C0#9    64  TOPO    3384.000      2000.000    128000.0  3447.0000      12  RR  RL  LR  LL
Sources: 32
  ID  Name                SpwId RestFreq(MHz) SysVel(km/s)
  0    0137+331=3C48      0    -              -           
  0    0137+331=3C48      1    -              -           
  0    0137+331=3C48      2    -              -           
  0    0137+331=3C48      3    -              -           
  0    0137+331=3C48      4    -              -           
  0    0137+331=3C48      5    -              -           
  0    0137+331=3C48      6    -              -           
  0    0137+331=3C48      7    -              -           
  1    J2355+4950          2    -              -           
  1    J2355+4950          3    -              -           
  1    J2355+4950          4    -              -           
  1    J2355+4950          5    -              -           
  1    J2355+4950          6    -              -           
  1    J2355+4950          7    -              -           
  2    J0259+0747          2    -              -           
  2    J0259+0747          3    -              -           
  2    J0259+0747          4    -              -           
  2    J0259+0747          5    -              -           
  2    J0259+0747          6    -              -           
  2    J0259+0747          7    -              -             
  3    3C75                2    -              -           
  3    3C75                3    -              -           
  3    3C75                4    -              -           
  3    3C75                5    -              -           
  3    3C75                6    -              -           
  3    3C75                7    -              -             
Antennas: 27:
  ID  Name  Station  Diam.    Long.        Lat.                Offset from array center (m)                ITRF Geocentric coordinates (m)       
                                                                    East        North    Elevation              x              y              z
  0    ea01  W06      25.0 m  -107.37.15.6  +33.53.56.4      -275.8278    -166.7360      -2.0595 -1601447.195400 -5041992.497600  3554739.694800
  1    ea02  W04      25.0 m  -107.37.10.8  +33.53.59.1      -152.8711      -83.7955      -2.4675 -1601315.900500 -5041985.306670  3554808.309400
  2    ea03  W07      25.0 m  -107.37.18.4  +33.53.54.8      -349.9804    -216.7527      -1.7877 -1601526.383100 -5041996.851000  3554698.331400
  3    ea04  N04      25.0 m  -107.37.06.5  +33.54.06.1        -42.6260      132.8521      -3.5428 -1601173.981600 -5041902.657800  3554987.528200
  4    ea05  E05      25.0 m  -107.36.58.4  +33.53.58.8        164.9709      -92.7908      -2.5361 -1601014.465100 -5042086.235700  3554800.804900
  5    ea06  N06      25.0 m  -107.37.06.9  +33.54.10.3        -54.0745      263.8800      -4.2325 -1601162.598500 -5041828.990800  3555095.895300
  6    ea07  E04      25.0 m  -107.37.00.8  +33.53.59.7        102.8035      -63.7671      -2.6299 -1601068.794800 -5042051.918100  3554824.842700
  7    ea08  E01      25.0 m  -107.37.05.7  +33.53.59.2        -23.8867      -81.1272      -2.5808 -1601192.486700 -5042022.840700  3554810.460900
  8    ea09  N05      25.0 m  -107.37.06.7  +33.54.08.0        -47.8569      192.6072      -3.8789 -1601168.794400 -5041869.042300  3555036.937000
  9    ea10  E08      25.0 m  -107.36.48.9  +33.53.55.1        407.8379    -206.0064      -3.2255 -1600801.917500 -5042219.370600  3554706.449200
  10  ea11  N07      25.0 m  -107.37.07.2  +33.54.12.9        -61.1072      344.2424      -4.6414 -1601155.630600 -5041783.816000  3555162.366400
  11  ea12  E07      25.0 m  -107.36.52.4  +33.53.56.5        318.0401    -164.1704      -2.6834 -1600880.582300 -5042170.386600  3554741.476400
  12  ea13  W02      25.0 m  -107.37.07.5  +33.54.00.9        -67.9810      -26.5266      -2.7142 -1601225.261900 -5041980.363990  3554855.705700
  13  ea14  E09      25.0 m  -107.36.45.1  +33.53.53.6        506.0539    -251.8836      -3.5735 -1600715.958300 -5042273.202200  3554668.175800
  14  ea15  N03      25.0 m  -107.37.06.3  +33.54.04.8        -39.1086      93.0234      -3.3585 -1601177.399560 -5041925.041300  3554954.573300
  15  ea16  E02      25.0 m  -107.37.04.4  +33.54.01.1          9.8042      -20.4562      -2.7822 -1601150.083300 -5042000.626900  3554860.706200
  16  ea17  N09      25.0 m  -107.37.07.8  +33.54.19.0        -77.4340      530.6515      -5.5829 -1601139.481300 -5041679.026500  3555316.554900
  17  ea18  W09      25.0 m  -107.37.25.2  +33.53.51.0      -521.9447    -332.7673      -1.2061 -1601710.016800 -5042006.914600  3554602.360000
  18  ea19  W05      25.0 m  -107.37.13.0  +33.53.57.8      -210.1007    -122.3814      -2.2582 -1601377.012800 -5041988.659800  3554776.399200
  19  ea20  N02      25.0 m  -107.37.06.2  +33.54.03.5        -35.6257      53.1906      -3.1311 -1601180.861780 -5041947.450400  3554921.638900
  20  ea21  N01      25.0 m  -107.37.06.0  +33.54.01.8        -30.8742      -1.4746      -2.8653 -1601185.628465 -5041978.158516  3554876.414800
  21  ea22  W03      25.0 m  -107.37.08.9  +33.54.00.1      -105.3218      -51.7280      -2.6013 -1601265.134100 -5041982.547450  3554834.851200
  22  ea23  E06      25.0 m  -107.36.55.6  +33.53.57.7        236.9085    -126.3395      -2.4685 -1600951.579800 -5042125.894100  3554772.996600
  23  ea24  W08      25.0 m  -107.37.21.6  +33.53.53.0      -432.1080    -272.1502      -1.5080 -1601614.082500 -5042001.654800  3554652.505900
  24  ea25  N08      25.0 m  -107.37.07.5  +33.54.15.8        -68.9105      433.1823      -5.0689 -1601147.943900 -5041733.832200  3555235.945600
  25  ea26  E03      25.0 m  -107.37.02.8  +33.54.00.5        50.6698      -39.4668      -2.7317 -1601114.356200 -5042023.141200  3554844.955400
  26  ea28  W01      25.0 m  -107.37.05.9  +33.54.00.5        -27.3603      -41.2944      -2.7520 -1601189.030040 -5042000.479400  3554843.427200
</pre>


Note that the antenna IDs, which are numbered sequentially up to the total number of antennas in the array (from 0 to 26 in this instance), do not correspond to the actual antenna names (ea01 to ea28). Instead, these eaNumbers correspond to those painted on the antennas themselves. The antennas can be referenced using either convention; ''antenna='22' '' would correspond to ea23, whereas ''antenna='ea22' '' would correspond to ea22.  Note that the antenna numbers in the observer log correspond to the actual antenna names, i.e., the 'ea??' numbers given in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.information.listobs.html listobs].
{|
| [[File:Plotms-preflag-Amp-vs-Freq-CASA6.2.1.jpeg|200px|left|thumb|Figure 4a: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency before additional flagging]]
| [[File:Plotms-rflag-Amp-vs-Freq-CASA6.2.1.jpeg|200px|right|thumb|Figure 4b: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency after an additional run of rflag]]
|}


Both to get a sense of the array, as well as identify the location of the reference antenna that we told the pipeline to choose for parallel hand calibration, have a look at the antenna setup page. For calibration purposes, you would generally select an antenna that is close to the center of the array (and that is not listed in the operator's log as having had problems!). As noted above, in a compact configuration there is a benefit to choosing an outer antenna to increase the bias toward longer baselines.
Since we are dealing with point sources, we do not have to worry about overflagging of shorter baselines, so we can run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata] with ''mode='rflag' ''over the calibrator fields and cross-hand correlations to remove any residual RFI. For completeness, we also use ''mode='tfcrop' ''to reduce the amount of residual RFI in the parallel hands.


At this point it is also a good idea to check the quality of the pipeline calibration. Go to the task overview page and pay particular attention to hifv_finalcals and hifv_plotsummary. Try to see if you can recognize which reference antenna was picked. For more details on the pipeline output you can have a look at the [https://casaguides.nrao.edu/index.php?title=VLA-S-CASA_Pipeline-CASA6.4.1 VLA CASA Pipeline Guide]. We assume that the pipeline calibration is good and can use it as a starting point for further calibration steps focusing on polarization calibration and imaging.
<source lang="python">
# In CASA


== Examining and Editing the Data ==
# for the parallel hands
flagdata(vis='TDRW0001_calibrated.ms',
mode='tfcrop',
field='0~2',
correlation='',
freqfit='line',
extendflags=False,
flagbackup=False)


At this point we must start CASA. If you have not used CASA before, some helpful tips are available on the [https://casadocs.readthedocs.io/en/v6.4.1/notebooks/usingcasa.html Getting Started in CASA] page.
# for the cross-hands
flagdata(vis='TDRW0001_calibrated.ms',
mode='rflag',
datacolumn='data',
field='0~2',
correlation='RL,LR',
extendflags=True,
flagbackup=False)
</source>


It is always a good idea to examine the data before jumping straight into calibration. From the observer's log there were no major issues noted besides a potentially warm receiver on antenna ea05. Even though the pipeline did a good job of calibrating and flagging the data, it isn't perfect. From the pipeline weblog, looking at the final amplitude gain calibration vs time plots in hifv_finalcals, we can see that during the second half of the observation antennas ea03, ea12, and ea16 shows some gain instability; otherwise there are no issues identified at this point.  
As you can see in Figure 4B, this additional flagging step took care of most of the obvious residual RFI. We are now ready to move on to calibrate the visibilities for linear polarization.


Start by inspecting these three particular antennas using the CASA task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms], plot frequency against amplitude and frequency against time for the parallel hands, iterate over field or scan, and note if you find something at odds. 
== Polarization Calibration ==


<source lang="python">
<pre style="background-color: #fffacd;">
# In CASA
Polarization calibration is done in three steps:
plotms(vis='TDRW0001_calibrated.ms', selectdata=True, correlation='RR,LL', averagedata=True, avgchannel='64', coloraxis='field', plotfile='colorbyfield.jpeg')
</source>
[[Image:Colorbyfield_CASA6.2.1.jpeg|200px|right|thumb|Figure 1: Overview of the observation: amplitude vs time, color-coded by field.]]
* ''selectdata=True '': One can choose to plot only selected subsets of the data.
* ''correlation='RR,LL' '': Plot only the left- and right-handed polarization products. The cross-terms ('RL' and 'LR') will be close to zero for non-polarized sources.
* ''averagedata=True'': One can choose to average data points before plotting them.
* ''avgchannel='64' '': With this plot, we are mainly interested in the fields vs time. Averaging over all 64 channels in the spectral window makes the plotting faster.
* ''coloraxis='field' '': Color-code the plotting symbols by field name/number.
The default x- and y-axis parameters are 'time' and 'amp', so the above call to [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] produces an amplitude vs time plot of the data for a selected subset of the data (if desired) and with data averaging (if desired). Many other values have been left to defaults, but it is possible to select them from within the plotms GUI. 


Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] allows one to select and view the data in many ways. Figure 1 shows the result of running plotms with the field selection discussed above. You can quickly see that the first source observed, 3C48 (the primary flux density, bandpass, and polarization angle calibrator source), is the brightest source in this observation. The next brightest is the second source observed, J2355+4950, a compact symmetric object (CSO; radio galaxy) and the secondary instrumental polarization calibrator. The complex gain calibrator J0259+0747 (shown in orange) is around 1 Jy. The target scans on 3C75 are colored in green. The spread of amplitudes is primarily due to the presence of extended structure, thus every baseline sees a slightly different amplitude.
* First, we determine the instrumental delay between the two polarization outputs;


Across the top of the left panel of the GUI are a set of tabs labelled Plot, Flag, Tools, Annotate, and Options. By default, the Plot tab is visible. There are a number of tabs running down the side of the left hand panel: Data, Calibration, Axes, Page, Transform, Display, and Canvas; these allow you to make changes to the plotting selection without having to re-launch [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms]. Even if it was started with ''xaxis=' ' '' (defaulting to 'time'), you can choose a different X-axis by selecting the Axes tab, then using the dropdown menu to switch (for example) to ''xaxis='Frequency' '' (to get something sensible when plotting with frequency, channel averaging must be turned off).
* Second, we solve for the instrumental polarization (the frequency-dependent leakage terms, 'D-terms'), using either an unpolarized source or a source which has sufficiently good parallactic angle coverage;


You should spend several minutes displaying the data in various formats. You can save the version of the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] plot as a graphics file by using the menu bar in the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] GUI to select the ''Export...'' option under the Export menu.
* Third, we solve for the polarization position angle using a source with a known polarization position angle (we use 3C48 here).  
</pre>


Another example of using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] for a quick look at your data, select the Data tab and specify ''field 2'' (the complex gain calibrator J0259+0747) to display data associated with the target, then select the Axes tab and change the X-axis to be ''UVdist'' (baseline length in meters). Remove the channel averaging (Data tab), and plot the data using the ''Plot'' button at the bottom of the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] GUI. The important observation is that the amplitude distribution is relatively constant as a function of UV distance or baseline length (i.e., <math>\sqrt{u^2+v^2}</math>; see Figure 2A). A relatively constant visibility amplitude as a function of baseline length means that the source is very nearly a point source (the Fourier transform of a point source, i.e. a delta function, is a constant function). You can see occasional spikes in the calibrated amplitudes. This is most likely caused by radio frequency interference that correlates on certain baselines. We will get to those further in the guide.  
Before solving for the calibration solutions, we first use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] to set the polarization model for our polarized position-angle calibrator. The pipeline only set the total intensity (Stokes I) of the flux density calibrator source 3C48, which did not include any polarization information. This source is known to have a fairly stable linear fractional polarization (measured to be 2% in S-band around the time of the observations), a polarization position angle of -100 degrees at 3 GHz, and a rotation measure of -68 rad/m^2. Note that 3C48 had an outburst in 2017 and is expected to show a significant degree of variability at higher frequencies in the first instance, progressively affecting lower frequencies as time passes since the event.  


By contrast, if you make a similar plot for ''field 3'' (our target 3C 75), the result is a visibility function that falls rapidly with increasing baseline length. Figure 2B shows this example, including time averaging of '1e6' seconds (any large number that encompasses more than a full scan will do, we want to fully average each scan). Such a visibility function indicates a highly resolved source. The baseline length at which the visibility function falls to some fiducial value (e.g., 1/2 of its peak value) gives a rough estimate of the angular scale of the source (Angular scale [in radians] ~ 1/baseline [in wavelengths]). To plot baseline length in wavelengths rather than meters, select ''UVwave'' as the X-axis parameter.
The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] task will calculate the values of Stokes Q and U (in the reference channel) for user inputs of the reference frequency, Stokes I, polarization fraction, polarization angle, and rotation measure. It is possible to capture a frequency variation in Q, U, and alpha terms by providing coefficients of polynomial expansion for polarization fraction, polarization angle, and spectral index as a function of frequency. In general, it is left to the user to derive these coefficients, which can be accomplished by fitting a polynomial to observed values of the polarization fraction (here also called polarization index), polarization angle, and flux density (for the case of spectral index). These coefficients are then passed to the setjy task as lists along with the reference frequency and the Stokes I flux density.


A final example is shown in Figure 2C. In this example, we have elected to show phase as a function of (frequency) channel for a single baseline (''antenna='ea01&ea21' '') on the bandpass calibrator, field 0, and non-averaged data. If you choose to iterate by baseline (e.g., ''antenna='ea01' '' and ''iteraxis='baseline' ''), you can see similar phase-frequency variations on all baselines. They center around zero phase, because we are looking at the calibrated visibilities; however, you are seeing a butterfly shaped pattern with phase noise higher toward the channel edges. This pattern is due to a small mismatch in the delay measurement timing (also known as 'delay clunking') which is an internally generated effect and is typically averaged out over time. 
As an example on how to derive the polarization parameters for the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] call, you can perform the following next steps or jump right to the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] call below.  
{|
| [[File:Plotms-J0259+0747-Amp-vs-UVdist-CASA6.2.1.jpeg|200px|left|thumb|Figure 2A: plotms view of amp vs. uvdist of J0259+0747, a point source]]
| [[File:Plotms-3C75-Amp-vs-UVwave-CASA6.2.1.jpeg|200px|center|thumb|Figure 2B: plotms view of amp vs. uvwave of 3C 75, a resolved source]]
| [[File:Plotms-3C48-delays-ea01ea21_CASA6.2.1.jpeg|200px|right|thumb|Figure 2C: plotms view of phase vs. channel on one baselines, showing phase delay across the calibrated bandpass]]
|}


You can find similar plots in the CASA pipeline weblog under the task hifv_plotsummary. At this stage the pipeline has taken care of most of the calibration. There might be some remaining issues, though, that were not caught by the pipeline.
=== Deriving the Polarization Properties of the Polarization Angle Calibrator ===


[[Image:Plotms-3C75guide-datastream-CASA6.2.1.jpeg|200px|right|thumb|Figure 3: datastream view of MS]]
First, we tabulate the frequency dependent Stokes I flux density, polarization fraction, and polarization angle in a textfile, which we will call 3C48.dat. The data is taken from [https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/flux-density-scale-polarization-leakage-polarization-angle-tables] and the corresponding Stokes I value is calculated from the Perley & Butler (2017) scale.
One final useful plot we will make is a datastream plot of the antenna2 in a baseline for the data versus ea01. This shows, assuming that ea01 is in the entire observation, when various antennas drop out (see Figure 3).
 
<pre>
# Frequency  I      P.F.      P.A.
# (GHz)      (Jy)              (rad)
1.022        20.68  0.00293    0.07445
1.465        15.62  0.00457    -0.60282
1.865        12.88  0.00897    0.39760
2.565        9.82    0.01548    -1.97046
3.565        7.31    0.02911    -1.46542
4.885        5.48    0.04286    -1.24875
6.680        4.12    0.05356    -1.15533
8.435        3.34    0.05430    -1.10638
11.320      2.56    0.05727    -1.08602
14.065      2.14    0.06097    -1.09597
16.564      1.86    0.06296    -1.11891
19.064      1.67    0.06492    -1.18266
25.564      1.33    0.07153    -1.25369
32.064      1.11    0.06442    -1.32430
37.064      1.00    0.06686    -1.33697
42.064      0.92    0.05552    -1.46381
48.064      0.82    0.06773    -1.46412
</pre>
 
Now to fit Stokes I, we execute in CASA the following commands. These could also be put into a text file and run from inside the CASA prompt using [https://casadocs.readthedocs.io/en/v6.4.1/api/casashell/execfile.html?highlight=execfile#casashell.execfile execfile].


<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='',correlation='RR,LL',
      timerange='',antenna='ea01',spw='0:31',
      xaxis='time',yaxis='antenna2',
      plotrange=[-1,-1,0,26],coloraxis='field')
</source>


From this display you can immediately see that flagging performed by the pipeline is present.  
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt


In the following we note on a couple issues that you might have found while inspecting data in this section. We will take care of those through additional flagging.
data = np.loadtxt('3C48.dat')


<pre style="background-color: #fffacd;">
def S(f,S,alpha,beta):
Issues that you might find:
        return S*(f/3.0)**(alpha+beta*np.log10(f/3.0))
- ea12, scan 17: amplitude spike at the end of the scan (can be spotted already in Figure 1)
- Residual RFI (see Figure 2A)
</pre>


In the case of the amplitude spike, we can flag the affected time period by invoking the casa task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata]. It is a good idea to save the original flags before performing any flagging by setting '''flagbackup=True'''.
# Fit 1 - 5 GHz data points
popt, pcov = curve_fit(S, data[0:6,0], data[0:6,1])
print('I@3GHz', popt[0], ' Jy')
print('alpha', popt[1])
print('beta', popt[2])
print( 'Covariance')
print(pcov)


<source lang="python">
plt.plot(data[0:6,0], data[0:6,1], 'ro', label='data')
# In CASA
plt.plot(np.arange(1,5,0.1), S(np.arange(1,5,0.1), *popt), 'r-', label='fit')
flagdata(vis='TDRW0001_calibrated.ms', flagbackup=True, mode='manual', antenna='ea12',scan='17',timerange='07:25:57~07:26:18')
</source>


You can check the effect of this flagging by replotting Figure 2A. The spikes we saw before on some baselines should have disappeared. If you plot frequency against amplitude without averaging, however, you will still see some channels with interference that we will need to flag, especially on the instrumental polarization calibrators. Polarization calibration is very sensitive to interference, especially in the cross-hand correlations RL,LR. The pipeline does a good job at this, but there are still some RFI left; we will perform some additional flagging steps in the next section.  
plt.title('3C48')
 
plt.legend()
=== Additional Flagging ===
plt.xlabel('Frequency (GHz)')
plt.ylabel('Flux Density (Jy)')
plt.show()


First we try to get a good sense of additional flagging that might be needed by plotting frequency against amplitude for the RR,LL and RL,LR polarizations of our calibrators (fields 0 through 2). You will notice some left over RFI on the bandpass calibrator in RR, LL. However, we also need to pay particular attention to RL, LR (see Figure 4A). Here we consider calibrators only; we will perform additional flagging on the target field at a later stage.
</source>


<source lang="python">
This will generate a plot for visual inspection, as well as the following text output.  
# In CASA
# for parallel hands
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RR,LL')
# for cross-hands
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RL,LR')
</source>


{|
<pre>
| [[File:Plotms-preflag-Amp-vs-Freq-CASA6.2.1.jpeg|200px|left|thumb|Figure 4a: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency before additional flagging]]
I@3GHz 8.555570817459328  Jy
| [[File:Plotms-rflag-Amp-vs-Freq-CASA6.2.1.jpeg|200px|right|thumb|Figure 4b: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency after executing addition run of rflag]]
alpha -0.8863795595286049
|}
beta -0.14320026298724836
Covariance
[[1.30835675e-04 1.69587670e-05 2.05918186e-06]
[1.69587670e-05 1.36709052e-05 2.62217377e-05]
[2.05918186e-06 2.62217377e-05 6.27504685e-05]]
</pre>


Since we are dealing with point sources, we do not have to worry about overflagging of shorter baselines, so we can run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata] with ''mode='rflag' ''over the calibrator fields and cross-hand correlations to remove any residual RFI. For completeness, we also use ''mode='tfcrop' ''to reduce the amount of residual RFI in the parallel hands. This is not strictly needed at this point, since the polarization calibration is based on the cross-hand correlations.
This provides the coefficients for Stokes I flux density at 3 GHz, the spectral index (alpha), and curvature (beta). It also provides the covariance matrix for the fit.


We repeat the same for the polarization fraction.
<source lang="python">
<source lang="python">
# In CASA
# In CASA


# for the parallel hands
import numpy as np
flagdata(vis='TDRW0001_calibrated.ms',
from scipy.optimize import curve_fit
mode='tfcrop',
import matplotlib.pyplot as plt
field='0~2',
correlation='',
freqfit='line',
extendflags=False,
flagbackup=False)


# for the cross-hands
data = np.loadtxt('3C48.dat')
flagdata(vis='TDRW0001_calibrated.ms',
mode='rflag',
datacolumn='data',
field='0~2',
correlation='RL,LR',
extendflags=True,
flagbackup=False)
</source>


As you can see in Figure 4B, this additional flagging step took care of most of the obvious residual RFI. We are now ready to move on to calibrate the visibilities for linear polarization.
def PF(f,a,b,c,d):
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3


== Polarization Calibration ==
# Fit 1 - 5 GHz data points
popt, pcov = curve_fit(PF, data[0:6,0], data[0:6,2])
print("Polfrac Polynomial: ", popt)
print("Covariance")
print(pcov)


<pre style="background-color: #fffacd;">
plt.plot(data[0:6,0], data[0:6,2], 'ro', label='data')
Polarization calibration is done in three steps:
plt.plot(np.arange(1,5,0.1), PF(np.arange(1,5,0.1), *popt), 'r-', label='fit')


* First, we determine the instrumental delay between the two polarization outputs;
plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Lin. Pol. Fraction')
plt.show()
</source>


* Second, we solve for the instrumental polarization (the frequency-dependent leakage terms, 'D-terms'), using either an unpolarized source or a source which has sufficiently good parallactic angle coverage;
<pre>
 
Polfrac Polynomial:  [ 0.02152856  0.03937167  0.003804  -0.01969663]
* Third, we solve for the polarization position angle using a source with a known polarization position angle (we use 3C48 here).  
Covariance
[[ 2.52776017e-07  3.20765692e-07 -7.13270651e-07 -8.06571096e-07]
[ 3.20765692e-07  4.07949498e-06 -5.46918397e-07 -1.05897559e-05]
[-7.13270651e-07 -5.46918397e-07  3.26372075e-06  1.85490535e-06]
[-8.06571096e-07 -1.05897559e-05  1.85490535e-06  3.07101526e-05]]
</pre>
</pre>


For information on polarization calibrators suitable for VLA observations, see the [https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/pol VLA Observing Guide on Polarimetry]. The [https://casadocs.readthedocs.io/en/v6.4.1/notebooks/synthesis_calibration.html#Polarization-Calibration CASA related documentation] also provides helpful information on polarization calibration steps and the different options that are available.
<source lang="python">
 
import numpy as np
Before solving for the calibration solutions, we first use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] to set the polarization model for our polarized position-angle calibrator. The pipeline only set the total intensity of the flux density calibrator source 3C48, which did not include any polarization information. This source is known to have a fairly stable linear fractional polarization (measured to be 2% in S-band around the time of the observations), a polarization position angle of -100 degrees at 3 GHz, and a rotation measure of -68 rad/m^2. Note that 3C48 had an outburst in 2017 and is expected to show a significant degree of variability at higher frequencies in the first instance, progressively affecting lower frequencies as time passes since the event. Since we have applied the pipeline calibration and not corrected for parallactic angle, we can continue polarization calibration using a split measurement set.
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt


The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] task will calculate the values of Stokes Q and U (in the reference channel) for user inputs of the reference frequency, Stokes I, polarization fraction, polarization angle, and rotation measure. The setjy input parameters can be obtained from Perley & Butler (2017) for Stokes I information and Perley & Butler (2013) for polarization information. Other sources can also be consulted, such as archival observations of variable polarization calibrators available under the project codes TPOL0003 or TCAL0009.
data = np.loadtxt('3C48.dat')


It is possible to capture a frequency variation in Q, U, and alpha terms by providing coefficients of polynomial expansion for polarization fraction, polarization angle, and spectral index as a function of frequency. At this time, it is left to the user to derive these coefficients, which can be accomplished by fitting a polynomial to observed values of the polarization fraction (here also called polarization index), polarization angle, and flux density (for the case of spectral index). Updated values of the broad band polarimetric information for the four calibration sources 3C48, 3C138, 3C147, and 3C286 can be found at (https://science.nrao.edu/facilities/vla/docs/manuals/oss/performance/fdscale) and at (https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/pol); of these sources, 3C48, 3C138, and 3C147 have been found to be variable. These coefficients are then passed to the setjy task as lists along with the reference frequency and the Stokes I flux density.
def PA(f,a,b,c,d,e):
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3+e*((f-3.0)/3.0)**4
 
# Fit 2 - 9 GHz data points
popt, pcov = curve_fit(PA, data[2:8,0], data[2:8,3])
print("Polangle Polynomial: ", popt)
print("Covariance")
print(pcov)


The calibrator used for this guide, 3C48, has a rotation measure and thus changes its Q and U with frequency. Therefore, for our purposes, it is not sufficient to use only the first Taylor term of the expansion. For deriving the setjy input parameters you can consult the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy CASA documentation]. Currently setjy only supports unresolved polarized emission models assuming that the Stokes I,Q,U peak are co-located on the sky. This is not necessarily the case for more complicated objects or even for 3C48 in extended VLA configurations.
plt.plot(data[2:8,0], data[2:8,3], 'ro', label='data')
plt.plot(np.arange(1,9,0.1), PA(np.arange(1,9,0.1), *popt), 'r-', label='fit')


As an example on how to derive the polarization parameters for the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] call, you can perform the following next steps or jump right to the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] call below.
plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Lin. Pol. Angle (rad)')
plt.show()
</source>


=== Deriving the Polarization Properties of the Polarization Angle Calibrator ===
<pre>
Polangle Polynomial: [-2.5929737  -2.03374017  5.20812942 -2.01696093  0.30491012]
Covariance
[[  0.46219415  0.41124375  -1.26430855  0.50302926  -0.34715067]
[  0.41124375  6.58090631  9.88051382  -7.56477931 -17.11605473]
[ -1.26430855  9.88051382  58.3052678  -35.16883692 -58.08218227]
[  0.50302926  -7.56477931 -35.16883692  21.77461974  37.45331953]
[ -0.34715067 -17.11605473 -58.08218227  37.45331953  72.39830352]]
</pre>


First, we tabulate the frequency dependent Stokes I flux density, polarization fraction, and polarization angle in a textfile, which we will call 3C48.dat. The data is taken from [https://science.nrao.edu/facilities/vla/docs/manuals/obsguide/modes/flux-density-scale-polarization-leakage-polarization-angle-tables] and the corresponding Stokes I value is calculated from the Perley & Butler (2017) scale.  
You'll notice that the fit for the polarization angle is much less smooth than the other fits. There appears to be something wrong with the first data point in our selection. Something special needs to happen to this point. There is a concept known as the <math>N\pi</math> ambiguity issue in polarimetry. You are encouraged to read more about this concept and see if you can figure out how to recover this data point.


Note: The polarization angle values given in the tables have not been derotated.
=== Setting the Polarization Calibrator Models ===
 
<pre>
# Frequency  I      P.F.      P.A.
# (GHz)      (Jy)              (rad)
1.022        20.68  0.00293    0.07445
1.465        15.62  0.00457    -0.60282
1.865        12.88  0.00897    0.39760
2.565        9.82    0.01548    -1.97046
3.565        7.31    0.02911    -1.46542
4.885        5.48    0.04286    -1.24875
6.680        4.12    0.05356    -1.15533
8.435        3.34    0.05430    -1.10638
11.320      2.56    0.05727    -1.08602
14.065      2.14    0.06097    -1.09597
16.564      1.86    0.06296    -1.11891
19.064      1.67    0.06492    -1.18266
25.564      1.33    0.07153    -1.25369
32.064      1.11    0.06442    -1.32430
37.064      1.00    0.06686    -1.33697
42.064      0.92    0.05552    -1.46381
48.064      0.82    0.06773    -1.46412
</pre>
 
Now to fit Stokes I, we execute in CASA the following commands. These could also be put into a text file and run from inside the CASA prompt using [https://casadocs.readthedocs.io/en/v6.4.1/api/casashell/execfile.html?highlight=execfile#casashell.execfile execfile].


<source lang="python">
<source lang="python">
# In CASA
# In CASA


import numpy as np
# Reference Frequency for fit values
from scipy.optimize import curve_fit
reffreq = '3.0GHz'
import matplotlib.pyplot as plt
# Stokes I flux density
 
I =       8.55557
data = np.loadtxt('3C48.dat')
# Spectral Index
 
alpha =    [-0.8864, -0.1432]
def S(f,S,alpha,beta):
# Polarization Fraction
        return S*(f/3.0)**(alpha+beta*np.log10(f/3.0))
polfrac = [0.02152856, 0.03937167, 0.003804, -0.01969663]
 
# Polarization Angle
# Fit 1 - 5 GHz data points
polangle = [-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514]
popt, pcov = curve_fit(S, data[0:6,0], data[0:6,1])
print('I@3GHz', popt[0], ' Jy')
print('alpha', popt[1])
print('beta', popt[2])
print( 'Covariance')
print(pcov)
 
plt.plot(data[0:6,0], data[0:6,1], 'ro', label='data')
plt.plot(np.arange(1,5,0.1), S(np.arange(1,5,0.1), *popt), 'r-', label='fit')
 
plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Flux Density (Jy)')
plt.show()


setjy(vis='TDRW0001_calibrated.ms',
      field='0137+331=3C48',
      spw='',
      selectdata=False,
      timerange="",
      scan="",
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[I,0,0,0],
      spix=alpha,
      reffreq=reffreq,
      polindex=polfrac,
      polangle=polangle,
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)
</source>
</source>
* ''field='0137+331=3C48' '': if the flux density calibrator is not specified then ''all'' sources will be assumed to have the input model parameters.
* ''standard='manual' '': the user will supply the flux density, spectral index, and polarization parameters rather than giving a model (the CASA models currently do not include polarization).
* ''fluxdensity=[I,0,0,0] '': you may provide values of Q and U rather than having setjy calculate them.However, if you set Q and U as input using the ''fluxdensity'' parameter, then the first value given in polindex or polangle will be ignored.
* ''spix=alpha=[-0.8864, -0.1432] '': set the spectral index using the value above. This will apply to all non-zero Spokes parameters. In this example, we only use the first two coefficients of the Taylor expansion.
* ''reffreq='3.0GHz' '': The reference frequency for the input Stokes values.
* ''polindex=polfrac=[0.02152856, 0.03937167, 0.003804, -0.01969663] '': The coefficients of polynomial expansion for the polarization index as a function of frequency.
* ''polangle=polangle=[-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514] '': The coefficients of polynomial expansion for the polarization angle as a function of frequency (only acquirable with proper derotation).
* ''scalebychan=True'': This allows setjy to compute unique values per channel, rather than applying the reference frequency values to the entire spectral window.
* ''usescratch=True'': DO create/use the MODEL_DATA column explicitly. (''usescratch=False'' saves disk space by not filling the model column, however due to current bugs it is suggested to not use it)
The Stokes V flux has been set to zero, corresponding to no circular polarization.


This will generate a plot for visual inspection, as well as the following text output.  
[https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html Setjy] returns a Python dictionary (CASA record) that reports the Stokes I, Q, U and V terms. This is reported to the CASA command line window.
 
<pre>
<pre>
I@3GHz 8.555570817459328 Jy
{'0': {'0': {'fluxd': array([10.07724056,  0.15082879,  0.01240901, 0.        ])},
alpha -0.8863795595286049
  '1': {'fluxd': array([9.64869223, 0.15381396, 0.04441096, 0.        ])},
beta -0.14320026298724836
  '2': {'fluxd': array([9.25487752, 0.15053557, 0.07574993, 0.        ])},
Covariance
  '3': {'fluxd': array([8.89166708, 0.14187061, 0.10510616, 0.        ])},
[[1.30835675e-04 1.69587670e-05 2.05918186e-06]
  '4': {'fluxd': array([8.55557  , 0.12889591, 0.13157306, 0.        ])},
[1.69587670e-05 1.36709052e-05 2.62217377e-05]
  '5': {'fluxd': array([8.24361379, 0.11273472, 0.15463414, 0.       ])},
[2.05918186e-06 2.62217377e-05 6.27504685e-05]]
  '6': {'fluxd': array([7.95325066, 0.09444074, 0.17410041, 0.       ])},
  '7': {'fluxd': array([7.68228356, 0.0749225 , 0.19002888, 0.       ])},
  'fieldName': '0137+331=3C48'},
'format': "{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}"}
</pre>
</pre>


This provides the coefficients for Stokes I flux density at 3 GHz, the spectral index (alpha), and curvature (beta). It also provides the covariance matrix for the fit.
We can see the results in the model column in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] (Figure 5A) showing the model source spectrum:
<source lang="python">
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RR',
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='amp',ydatacolumn='model')


We repeat the same for the polarization fraction.
</source>
We can see this translates to the spectrum in QU (Figure 5B):
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='amp',ydatacolumn='model')
</source>


import numpy as np
Finally, we plot our R-L phase differences, which should be twice the value of the polarization angle without other complications such as the <math>N\pi</math> ambiguity (Figure 5C):
from scipy.optimize import curve_fit
<source lang="python">
import matplotlib.pyplot as plt
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='phase',ydatacolumn='model')
</source>


data = np.loadtxt('3C48.dat')
{|
| [[Image:Plotms-3C48-model-amp-RR-CASA6.4.1.png|200px|thumb|left|Figure 5A: Model RR amplitudes of 3C48.]]
| [[Image:Plotms-3C48-model-amp-RL-CASA6.4.1.png|200px|thumb|center|Figure 5B: Model RL amplitudes of 3C48.]]
| [[Image:Plotms-3C48-model-phs-RL-CASA6.4.1.png|200px|thumb|right|Figure 5C: Model RL phases of 3C48.]]
|}
 
In order to obtain the correct amplitude scaling for instrumental polarization calibration, we need to also specify the Stokes I model that was used for the D-term calibrator(s). The model values of the two D-term calibrators can be obtained from the pipeline weblog under the task hifv_fluxboot inside the [https://casa.nrao.edu/Data/VLA/Polarization/pipeline-20230103T175723/html/t2-4m.html?sidebar=sidebar_stage12&ms=all&subpage=t2-4m_details.html CASA log] associated with that task. Take this opportunity to try to find them. We've purposely removed the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] calls in the log so as to not spoil the fun. While not specific to polarization calibration, this exercise should reveal an important aspect of the VLA pipeline: It sets a correct Stokes I model of the secondary calibrators before the final calibration tables are produced (you may appreciate this difference more if you also participated in the Continuum Tutorial and remember how it handled the flux density scale calibration for the secondary calibrators). Your goal when looking over the log is to figure out where the pipeline is getting the inputs for [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] from. Once you've found the relevant lines in the log try to make up the setjy calls on your own.  


def PF(f,a,b,c,d):
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3


# Fit 1 - 5 GHz data points
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
popt, pcov = curve_fit(PF, data[0:6,0], data[0:6,2])
<div style="font-weight:bold;line-height:1.6;">The casapy.log lines of interest and setjy calls</div>
print("Polfrac Polynomial: ", popt)
<div class="mw-collapsible-content">
print("Covariance")
<pre style="background-color: #fffacd;">
print(pcov)
2023-01-03 19:07:54 INFO fluxscale:::: Fitted spectrum for J2355+4950 with fitorder=2: Flux density = 1.76871 +/- 0.000646066 (freq=2.98457 GHz) spidx: a_1 (spectral index) =-0.599569 +/- 0.00275835 a_2=-0.196812 +/- 0.0670986 covariance matrix for the fit:  covar(0,0)=8.14129e-08 covar(0,1)=-1.12826e-07 covar(0,2)=-2.46336e-05 covar(1,0)=-1.12826e-07 covar(1,1)=2.4614e-05 covar(1,2)=0.000242613 covar(2,0)=-2.46336e-05 covar(2,1)=0.000242613 covar(2,2)=0.0145649


plt.plot(data[0:6,0], data[0:6,2], 'ro', label='data')
2023-01-03 19:07:55 INFO fluxscale:::: Fitted spectrum for J0259+0747 with fitorder=2: Flux density = 0.970568 +/- 0.000712514 (freq=2.98457 GHz) spidx: a_1 (spectral index) =0.169919 +/- 0.00510126 a_2=-0.143294 +/- 0.134104 covariance matrix for the fit: covar(0,0)=1.87159e-06 covar(0,1)=-2.56746e-06 covar(0,2)=-0.000583154 covar(1,0)=-2.56746e-06 covar(1,1)=0.000479139 covar(1,2)=-9.51772e-05 covar(2,0)=-0.000583154 covar(2,1)=-9.51772e-05 covar(2,2)=0.331122
plt.plot(np.arange(1,5,0.1), PF(np.arange(1,5,0.1), *popt), 'r-', label='fit')
</pre>


plt.title('3C48')
This translates to the following [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] calls.
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Lin. Pol. Fraction')
plt.show()
</source>
 
<pre>
Polfrac Polynomial:  [ 0.02152856  0.03937167  0.003804  -0.01969663]
Covariance
[[ 2.52776017e-07  3.20765692e-07 -7.13270651e-07 -8.06571096e-07]
[ 3.20765692e-07  4.07949498e-06 -5.46918397e-07 -1.05897559e-05]
[-7.13270651e-07 -5.46918397e-07  3.26372075e-06  1.85490535e-06]
[-8.06571096e-07 -1.05897559e-05  1.85490535e-06  3.07101526e-05]]
</pre>


<source lang="python">
<source lang="python">
import numpy as np
setjy(vis='TDRW0001_calibrated.ms',
from scipy.optimize import curve_fit
      field='J2355+4950',
import matplotlib.pyplot as plt
      spw='',
 
      selectdata=False,
data = np.loadtxt('3C48.dat')
      timerange="",
 
      scan="",
def PA(f,a,b,c,d,e):
      intent="",
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3+e**((f-3.0)/3.0)**4
      observation="",
 
      scalebychan=True,
# Derotate the 1.8GHz point's polarization angle
      standard="manual",
data[2,3] = data[2,3]-np.pi
      model="",
 
      modimage="",
# Fit 2 - 9 GHz data points
      listmodels=False,
popt, pcov = curve_fit(PA, data[2:8,0], data[2:8,3])
      fluxdensity=[1.76871, 0, 0, 0],
print("Polangle Polynomial: ", popt)
      spix=[-0.599569, -0.196812],
print("Covariance")
      reffreq="2.98457GHz",
print(pcov)
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)


plt.plot(data[2:8,0], data[2:8,3], 'ro', label='data')
setjy(vis='TDRW0001_calibrated.ms',
plt.plot(np.arange(1,9,0.1), PA(np.arange(1,9,0.1), *popt), 'r-', label='fit')
      field='J0259+0747',
 
      spw='',
plt.title('3C48')
      selectdata=False,
plt.legend()
      timerange="",
plt.xlabel('Frequency (GHz)')
      scan="",
plt.ylabel('Lin. Pol. Angle (rad)')
      intent="",
plt.show()
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[0.970568, 0, 0, 0],
      spix=[0.169919, -0.143294],
      reffreq='2.98457GHz',
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)
</source>
</source>
</div></div>


<pre>
Polangle Polynomial:  [-2.74375466  1.77557424 -1.77089873  0.60309194  0.96199514]
Covariance
[[ 5.97681212e-03  6.08206221e-03 -2.00614015e-02 -1.82633882e-03
  8.18331342e-03]
[ 6.08206221e-03  2.68419354e-01 -6.09514004e-02 -1.36381216e+00
  1.05931297e+00]
[-2.00614015e-02 -6.09514004e-02  1.52116682e-01 -1.32931084e-03
  -4.98635228e-02]
[-1.82633882e-03 -1.36381216e+00 -1.32931084e-03  8.12008149e+00
  -6.20697680e+00]
[ 8.18331342e-03  1.05931297e+00 -4.98635228e-02 -6.20697680e+00
  4.76282285e+00]]
</pre>


=== Setting the Polarization Calibrator Models ===
==== Solving for the Cross-Hand delays ====
 
Just as the pipeline did for the parallel-hand (RR,LL) delays before bandpass calibration, we solve for the cross-hand (RL,LR) delays because of the residual delay difference between the R and L on the reference antenna used for the original delay calibration (''ea10'' in this tutorial). In our case we simply use 3C48, which has a moderately polarized signal in the RL,LR correlations, and we set its polarized model above using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy]. Since the release of CASA 6.1.2, there are two options to solve for the cross-hand delays, both of them will be illustrated here. The first option fits the cross-hand delay for the entire baseband (here 8 spectral windows form a single baseband), which we call multiband delay. The second option solves the cross-hand delay independently per spectral window. Note that if a dataset contains multiple basebands and you wanted to solve for multiband delays, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] has to be executed for each baseband separately, selecting the appropriate spectral windows and appending the results to a single calibration table for later use.


<source lang="python">
<source lang="python">
# In CASA
# In CASA


# Reference Frequency for fit values
# Solve using Multiband Delay
reffreq = '3.0GHz'
kcross_mbd = "TDRW0001_calibrated.Kcross_mbd"
# Stokes I flux density
gaincal(vis='TDRW0001_calibrated.ms',
I =        8.55557
    caltable=kcross_mbd,
# Spectral Index
    field='0137+331=3C48',
alpha =    [-0.8864, -0.1432]
    spw='0~7:5~58',
# Polarization Fraction
    refant='ea10',
polfrac =  [0.02152856, 0.03937167, 0.003804, -0.01969663]
    gaintype="KCROSS",
# Polarization Angle
    solint="inf",
polangle = [-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514]
    combine="scan,<?>",
 
    calmode="ap",
setjy(vis='TDRW0001_calibrated.ms',
    append=False,
      field='0137+331=3C48',
    gaintable=[''],
      spw='',
    gainfield=[''],
      selectdata=False,
    interp=[''],
      timerange="",
    spwmap=[[]],
      scan="",
    parang=True)
      intent="",
 
      observation="",
# Solve using Single Band Delay
      scalebychan=True,
kcross_sbd = "TDRW0001_calibrated.Kcross_sbd"
      standard="manual",
gaincal(vis='TDRW0001_calibrated.ms',
      model="",
    caltable=kcross_sbd,
      modimage="",
    field='0137+331=3C48',
      listmodels=False,
    spw='0~7:5~58',
      fluxdensity=[I,0,0,0],
    refant='ea10',
      spix=alpha,
    gaintype="KCROSS",
      reffreq=reffreq,
    solint="inf",
      polindex=polfrac,
    combine="scan",
      polangle=polangle,
    calmode="ap",
      rotmeas=0,
    append=False,
      fluxdict={},
    gaintable=[''],
      useephemdir=False,
    gainfield=[''],
      interpolation="nearest",
    interp=[''],
      usescratch=True,
    spwmap=[[]],
      ismms=False,
    parang=True)
)
</source>
</source>
* ''field='0137+331=3C48' '': if the flux density calibrator is not specified then ''all'' sources will be assumed to have the input model parameters.
 
* ''standard='manual' '': the user will supply the flux density, spectral index, and polarization parameters rather than giving a model (the CASA models currently do not include polarization).
 
* ''fluxdensity=[I,0,0,0] '': you may provide values of Q and U rather than having setjy calculate them.However, if you set Q and U as input using the ''fluxdensity'' parameter, then the first value given in polindex or polangle will be ignored.
These commands essentially only differ with how the 'combine' parameter is defined. Based on the description above what should this parameter be in order to fit across the entire baseband?
* ''spix=alpha=[-0.8864, -0.1432] '': set the spectral index using the value above. This will apply to all non-zero Spokes parameters. In this example, we only use the first two coefficients of the Taylor expansion.
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
* ''reffreq='3.0GHz' '': The reference frequency for the input Stokes values.
<div style="font-weight:bold;line-height:1.6;">Answer</div>
* ''polindex=polfrac=[0.02152856, 0.03937167, 0.003804, -0.01969663] '': The coefficients of polynomial expansion for the polarization index as a function of frequency.
<div class="mw-collapsible-content">
* ''polangle=polangle=[-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514] '': The coefficients of polynomial expansion for the polarization angle as a function of frequency.
The only real difference between the commands is that the first is using the entire baseband as input to create one solution and the second is using each spectral window to get individual solutions. In order to tell CASA to combine all of the spectral windows (and scans in this case) one simply has to use: combine='scan,spw'.
* ''scalebychan=True'': This allows setjy to compute unique values per channel, rather than applying the reference frequency values to the entire spectral window.
</div></div>
* ''usescratch=True'': DO create/use the MODEL_DATA column explicitly. (''usescratch=False'' saves disk space by not filling the model column, however due to current bugs it is suggested to not use it)
 
The Stokes V flux has been set to zero, corresponding to no circular polarization.
 
 
[[Image:Plotms-3C48-Kcross-delay-CASA6.4.1.png|200px|thumb|right|Figure 6: Single band cross-hand delay solutions.]]
[https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html Setjy] returns a Python dictionary (CASA record) that reports the Stokes I, Q, U and V terms. This is reported to the CASA command line window (unless you used the execfile() method in which case results will be printed in the CASA log window only):
We can plot the single band solutions (see Figure 6):
<pre>
{'0': {'0': {'fluxd': array([10.07724056, 0.15082879,  0.01240901,  0.        ])},
  '1': {'fluxd': array([9.64869223, 0.15381396, 0.04441096, 0.        ])},
  '2': {'fluxd': array([9.25487752, 0.15053557, 0.07574993, 0.        ])},
  '3': {'fluxd': array([8.89166708, 0.14187061, 0.10510616, 0.        ])},
  '4': {'fluxd': array([8.55557  , 0.12889591, 0.13157306, 0.        ])},
  '5': {'fluxd': array([8.24361379, 0.11273472, 0.15463414, 0.        ])},
  '6': {'fluxd': array([7.95325066, 0.09444074, 0.17410041, 0.        ])},
  '7': {'fluxd': array([7.68228356, 0.0749225 , 0.19002888, 0.        ])},
  'fieldName': '0137+331=3C48'},
'format': "{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}"}
</pre>
Alternatively, you may capture this dictionary in a return variable, if you call [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] as '''myset=setjy(...)'''.
 
We can see the results in the model column in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] (Figure 5A) showing the model source spectrum:
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RR',
plotms(vis=kcross_sbd,xaxis='frequency',yaxis='delay',antenna='ea10',coloraxis='corr')
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='amp',ydatacolumn='model')
 
</source>
We can see this translates to the spectrum in QU (Figure 5B):
<source lang="python">
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='amp',ydatacolumn='model')
</source>
</source>
You can also look at the solutions reported in the logger.
<pre style="background-color: #fffacd;">
For multiband delay there is one solution:
Multi-band cross-hand delay=3.68373 nsec
For single band delay there are 8 solutions:
Spw=0 Global cross-hand delay=5.58964 nsec
Spw=1 Global cross-hand delay=1.49907 nsec
Spw=2 Global cross-hand delay=-1.26208 nsec
Spw=3 Global cross-hand delay=0.522402 nsec
Spw=4 Global cross-hand delay=4.25883 nsec
Spw=5 Global cross-hand delay=1.25194 nsec
Spw=6 Global cross-hand delay=3.69895 nsec
Spw=7 Global cross-hand delay=3.02677 nsec
</pre>
Notice that the per spectral window solutions are very scattered. The mean delay is 2.32 ns, quite different from the multiband delay. This demonstrates the strength of fitting the cross-hand delay across multiple spectral windows, especially when using a calibrator with a significant frequency dependence, i.e. rotation measure and a polarization fraction of only a few percent. We will continue calibration using the single multiband delay that was derived at 3.68 ns.
==== Solving for the Leakage Terms ====
The task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] is used for polarization calibration. In this data set, we observed the unpolarized calibrator J2355+4950 to demonstrate solving for the instrumental polarization. Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] uses the Stokes I, Q, and U values in the model data (Q and U being zero for an unpolarized calibrator) to derive the leakage solutions. We also observed the polarized calibrator J0259+0747 (which has about 4.7% fractional polarization) that is also our complex gain calibrator.


Finally, our R-L phase difference is constant at 66 degrees (twice the polarization
angle) as desired (Figure 5C):
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
      timerange='',antenna='ea01&ea02',
      xaxis='frequency',yaxis='phase',ydatacolumn='model')
</source>


{|
# J2355+4950 / Df
| [[Image:Plotms-3C48-model-amp-RR-CASA6.4.1.png|200px|thumb|left|Figure 5A: Model RR amplitudes of 3C48.]]
dtab_J2355 = 'TDRW0001_calibrated.Df'
| [[Image:Plotms-3C48-model-amp-RL-CASA6.4.1.png|200px|thumb|center|Figure 5B: Model RL amplitudes of 3C48.]]
polcal(vis='TDRW0001_calibrated.ms',
| [[Image:Plotms-3C48-model-phs-RL-CASA6.4.1.png|200px|thumb|right|Figure 5C: Model RL phases of 3C48.]]
      caltable=dtab_J2355,
|}
      field='J2355+4950',
      spw='0~7',
      refant='ea10',
      poltype='Df',
      solint='inf,2MHz',
      combine='scan',
      gaintable=[kcross_mbd],
      gainfield=[''],
      spwmap=[[0,0,0,0,0,0,0,0]],
      append=False)


In order to obtain the correct amplitude scaling for instrumental polarization calibration, we need to also specify the Stokes I model that was used for the D-term calibrator(s). If we carried all tables, instead of splitting out the calibrated data from the pipeline, we wouldn't need to do this since the gain amplitudes provide the correct Stokes I scale for all the calibrators. The model values of the two D-term calibrators can be obtained from the pipeline weblog under the task hifv_fluxboot inside the CASA log (file stage12/casapy.log).  
# J0259+0747 / Df+QU
 
dtab_J0259 = 'TDRW0001_calibrated.DfQU'  
<pre style="background-color: #fffacd;">
polcal(vis='TDRW0001_calibrated.ms',
2023-01-03 19:07:54 INFO fluxscale:::: Fitted spectrum for J2355+4950 with fitorder=2: Flux density = 1.76871 +/- 0.000646066 (freq=2.98457 GHz) spidx: a_1 (spectral index) =-0.599569 +/- 0.00275835 a_2=-0.196812 +/- 0.0670986 covariance matrix for the fit:  covar(0,0)=8.14129e-08 covar(0,1)=-1.12826e-07 covar(0,2)=-2.46336e-05 covar(1,0)=-1.12826e-07 covar(1,1)=2.4614e-05 covar(1,2)=0.000242613 covar(2,0)=-2.46336e-05 covar(2,1)=0.000242613 covar(2,2)=0.0145649
      caltable=dtab_J0259,
      intent='CALIBRATE_POL_LEAKAGE#UNSPECIFIED',
      spw='0~7',
      refant='ea10',
      poltype='Df+QU',
      solint='inf,2MHz',
      combine='scan',
      gaintable=[kcross_mbd],
      gainfield=[''],
      spwmap=[[0,0,0,0,0,0,0,0]],  
      append=False)
</source>


2023-01-03 19:07:55 INFO fluxscale:::: Fitted spectrum for J0259+0747 with fitorder=2: Flux density = 0.970568 +/- 0.000712514 (freq=2.98457 GHz) spidx: a_1 (spectral index) =0.169919 +/- 0.00510126 a_2=-0.143294 +/- 0.134104 covariance matrix for the fitcovar(0,0)=1.87159e-06 covar(0,1)=-2.56746e-06 covar(0,2)=-0.000583154 covar(1,0)=-2.56746e-06 covar(1,1)=0.000479139 covar(1,2)=-9.51772e-05 covar(2,0)=-0.000583154 covar(2,1)=-9.51772e-05 covar(2,2)=0.331122
* ''caltable '': [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] will create a new calibration table containing the leakage solutions, which we specify with the ''caltable'' parameter.
</pre>
* ''field='' or ''intent='' : The unpolarized source J2355+4950 is used to solve for the leakage terms in the unpolarized case. For the polarized source J0259+0747 we set the intent leakage polarization.
 
* ''spw='0~7' '': Select all spectral windows.
This translates to the following [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy] calls.
* ''poltype='Df' ''or ''poltype='Df+QU' '': Solve for the leakages (''D'') on a per-channel basis (''f''), assuming zero source polarization, +QU will also solve for the calibrator polarization Q,U per spectral window.
* ''solint='inf,2MHz', combine='scan' '': One solution over the entire run, per spectral channel of 2 MHz
* ''gaintable=['kcross_mbd']'': The previous Kcross multiband delay is applied
* ''spwmap=[0,0,0,0,0,0,0,0]'': This applies a spectral window map, where the first spw solution in the kcross_mbd table is mapped to all other spectral windows. Note there is only one value listed inside the kcross calibration table which is for the lowest spectral window that was used when solving using the multiband delay option (i.e. ''combine='spw' '').
 
In the case of Df+QU, the logger window will show the Q/U values it derived for the calibrator and the corresponding polarization fraction and angle that can be derived.
<pre style="background-color: #fffacd;">
Fractional polarization solution for J0259+0747 (spw = 0): : Q = 0.0259049, U = 0.0336301  (P = 0.0424505, X = 26.1967 deg)
Fractional polarization solution for J0259+0747 (spw = 1): : Q = 0.0139972, U = 0.0382244  (P = 0.0407066, X = 34.944 deg)
Fractional polarization solution for J0259+0747 (spw = 2): : Q = 0.0165052, U = 0.0384224  (P = 0.0418175, X = 33.3765 deg)
Fractional polarization solution for J0259+0747 (spw = 3): : Q = 0.0118274, U = 0.0422875 (P = 0.0439104, X = 37.1871 deg)
Fractional polarization solution for J0259+0747 (spw = 4): : Q = 0.00816816, U = 0.0404744  (P = 0.0412903, X = 39.2952 deg)
Fractional polarization solution for J0259+0747 (spw = 5): : Q = 0.00649365, U = 0.0412879  (P = 0.0417954, X = 40.5309 deg)
Fractional polarization solution for J0259+0747 (spw = 6): : Q = -0.00225595, U = 0.0429258  (P = 0.0429851, X = 46.5042 deg)
Fractional polarization solution for J0259+0747 (spw = 7): : Q = -0.00776873, U = 0.0474773  (P = 0.0481087, X = 49.6465 deg)
</pre>
 
From this you can see that J0259+0747 has a fractional polarization of 4.1&ndash;4.8% across the 1 GHz bandwidth with a small rotation measure causing a change in angle from 26 to 49 degrees over 1 GHz. In cases where the derived Q/U values seem random and the fractional polarization seems to be very small you might be able to derive better D-term solutions by using ''poltype='Df' ''.
 
After we run the two executions of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal], you are strongly advised to examine the solutions with [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] to ensure that everything looks good and to compare the results using two different calibrators and poltype methods.
{|
|[[Image:Plotms-J0259-Damp-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7a: J0259+0747 Df amplitude vs. frequency for antenna ea01.]]
|[[Image:Plotms-J2355-Damp-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7b: J2355+4950 Df+QU amplitude vs. frequency for antenna ea01.]]
|[[Image:Plotms-J0259-Dphs-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7c: J0259+0747 Df phase vs. frequency for antenna ea01.]]
|[[Image:Plotms-J2355-Dphs-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7d: J2355+4950 Df+QU phase vs. frequency for antenna ea01.]]
|}


<source lang="python">
<source lang="python">
setjy(vis='TDRW0001_calibrated.ms',
# In CASA
      field='J2355+4950',
plotms(vis=dtab_J0259,xaxis='freq',yaxis='amp',  
      spw='',
      iteraxis='antenna',coloraxis='corr')
      selectdata=False,
 
      timerange="",
plotms(vis=dtab_J2355,xaxis='freq',yaxis='amp',  
      scan="",
      iteraxis='antenna',coloraxis='corr')
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[1.76871, 0, 0, 0],
      spix=[-0.599569, -0.196812],
      reffreq="2984571609.0079317Hz",
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)


setjy(vis='TDRW0001_calibrated.ms',
plotms(vis=dtab_J0259,xaxis='chan',yaxis='phase',  
      field='J0259+0747',
      iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])
      spw='',
      selectdata=False,
      timerange="",
      scan="",
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[0.970568, 0, 0, 0],
      spix=[0.169919, -0.143294],
      reffreq='2984571609.0079317Hz',
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)
</source>


==== Solving for the Cross-Hand delays ====
plotms(vis=dtab_J2355,xaxis='chan',yaxis='phase',
      iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])


Just as the pipeline did for the parallel-hand (RR,LL) delays before bandpass calibration, we solve for the cross-hand (RL,LR) delays because of the residual delay difference between the R and L on the reference antenna used for the original delay calibration (''ea10'' in this tutorial). In our case we simply use 3C48, which has a moderately polarized signal in the RL,LR correlations, and we set its polarized model above using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy]. Since the release of CASA 6.1.2, there are two options to solve for the cross-hand delays, both of them will be illustrated here. The first option fits the cross-hand delay for the entire baseband (here 8 spectral windows form a single baseband), which we call multiband delay. The second option solves the cross-hand delay independently per spectral window. Note that if a dataset contains multiple basebands and you wanted to solve for multiband delays, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] has to be executed for each baseband separately, selecting the appropriate spectral windows and appending the results to a single calibration table for later use.
</source>
This will produce plots similar to those shown in Figures 7A-D. You can cycle through the antennas by clicking the Next button within [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms]. You should see leakages of between 5&ndash;17% in most cases. Both Df and Df+QU results should be comparable. However, we will be using the solutions from J0259+0747 to continue calibration and will use J2355+4950 to verify the polarization calibration.  


We can also display these in a single plot versus antenna index (see Figure 8):
[[Image:Plotms-J0259-DfQU-CASA6.4.1.png|thumb|Figure 8: Df+QU solutions for J0259+0747 versus antenna index]]
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis=dtab_J0259,xaxis='antenna1',yaxis='amp',coloraxis='corr')
</source>
==== Solving for the R-L polarization angle ====


# Solve using Multiband Delay
Having calibrated for the instrumental polarization, the total polarization is now correct, but the R-L phase still needs to be calibrated in order to obtain an accurate polarization position angle.  We use the same task, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal], but this time set parameter ''poltype='Xf', ''which specifies a frequency-dependent (''f'') position angle (''X'') calibration using the source 3C48, the position angle of which is known, having set this earlier with [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy]. Note that we must correct for the leakages before determining the R-L phase, which we do by adding the calibration table made in the previous step ('''dtab_J0259''') to the kcross table that is applied on-the-fly.
kcross_mbd = "TDRW0001_calibrated.Kcross_mbd"
gaincal(vis='TDRW0001_calibrated.ms',
    caltable=kcross_mbd,
    field='0137+331=3C48',
    spw='0~7:5~58',
    refant='ea10',
    gaintype="KCROSS",
    solint="inf",
    combine="scan,spw",
    calmode="ap",
    append=False,
    gaintable=[''],
    gainfield=[''],
    interp=[''],
    spwmap=[[]],
    parang=True)


# Solve using Single Band Delay
kcross_sbd = "TDRW0001_calibrated.Kcross_sbd"
gaincal(vis='TDRW0001_calibrated.ms',
    caltable=kcross_sbd,
    field='0137+331=3C48',
    spw='0~7:5~58',
    refant='ea10',
    gaintype="KCROSS",
    solint="inf",
    combine="scan",
    calmode="ap",
    append=False,
    gaintable=[''],
    gainfield=[''],
    interp=[''],
    spwmap=[[]],
    parang=True)
</source>
[[Image:Plotms-3C48-Kcross-delay-CASA6.4.1.png|200px|thumb|right|Figure 6: Single band cross-hand delay solutions.]]
We can plot the single band solutions (see Figure 6):
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis=kcross_sbd,xaxis='frequency',yaxis='delay',antenna='ea10',coloraxis='corr')
xtab = "TDRW0001_calibrated.Xf"
</source>
polcal(vis='TDRW0001_calibrated.ms',
You can also look at the solutions reported in the logger.
      caltable=xtab,
 
      spw='0~7',
<pre style="background-color: #fffacd;">
      field='0137+331=3C48',
For multiband delay there is one solution:
      solint='inf,2MHz',
Multi-band cross-hand delay=3.68373 nsec
      combine='scan',
      poltype='Xf',
      refant = 'ea10',
      gaintable=[kcross_mbd,dtab_J0259],
      gainfield=['',''],
      spwmap=[[0,0,0,0,0,0,0,0],[]],
      append=False)
</source>


For single band delay there are 8 solutions:
[[Image:Plotms-3C48-Xf-CASA6.4.1.png|thumb|Figure 9: Xf solutions versus frequency.]]
Spw=0 Global cross-hand delay=5.58964 nsec
Strictly speaking, there is no need to specify a reference antenna for ''poltype='Xf' ''(for circularly polarized receivers only) because the X solutions adjust the cross-hand phases for each antenna to match the given polarization angle of the model. However, for consistency/safety, it is recommended to always specify refant when performing polarization calibration.
Spw=1 Global cross-hand delay=1.49907 nsec
Spw=2 Global cross-hand delay=-1.26208 nsec
Spw=3 Global cross-hand delay=0.522402 nsec
Spw=4 Global cross-hand delay=4.25883 nsec
Spw=5 Global cross-hand delay=1.25194 nsec
Spw=6 Global cross-hand delay=3.69895 nsec
Spw=7 Global cross-hand delay=3.02677 nsec
</pre>


Notice that the per spectral window solutions are very scattered. The mean delay is 2.32 ns, quite different from the multiband delay. This demonstrates the strength of fitting the cross-hand delay across multiple spectral windows, especially when using a calibrator with a significant frequency dependence, i.e. rotation measure and a polarization fraction of only a few percent. We will continue calibration using the single multiband delay that was derived at 3.68 ns. 
It is strongly suggested you check that the calibration worked properly by plotting up the newly-generated calibration table using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] (see Figure 9):
 
<source lang="python">
Note that if we did not solve for this delay, it would be absorbed into the phases per channel of the following Df and Xf solutions. This would not cause us problems if we used an unpolarized D-term calibrator like J2355+4950, because we would not be solving for the Q+iU polarization. But if we were (e.g., using our gain calibrator J0259+0747 with parameter ''poltype='Df+QU' ''), then this step is essential.
# In CASA
plotms(vis=xtab,xaxis='frequency',yaxis='phase',coloraxis='spw')
</source>
Because the Xf term captures the residual R-L phase on the reference antenna over the array, there is only one value for all antennas. Also, as we took out the RL delays using the Kcross solution, these Xf variations do not show a significant slope in phase. And since we were using a single multiband delay, the phases connect from one spectral window to another; had we used the single band delays, we would see phase jumps from one to another spectral window.


==== Solving for the Leakage Terms ====
At this point, you have all the necessary polarization calibration tables.


The task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] is used for polarization calibration. In this data set, we observed the unpolarized calibrator J2355+4950 to demonstrate solving for the instrumental polarization. Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] uses the Stokes I, Q, and U values in the model data (Q and U being zero for an unpolarized calibrator) to derive the leakage solutions. We also observed the polarized calibrator J0259+0747 (which has about 4.7% fractional polarization) that is also our complex gain calibrator. The observations of J0259+0747 have a parallactic angle coverage of 31 degrees with 10 visits/slices, 3 of which were a bit longer to boost the signal-to-noise to at least 1000 per channel for each of the three passes. We will showcase solving for D-terms for both cases. The function calls are:
== Applying the Calibration ==


Now that we have derived all the calibration solutions, we need to apply them to the actual data using the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal]. The measurement set DATA column contains the original split data. To apply the calibration we have derived, we specify the appropriate calibration tables which are then applied to the DATA column, with the results being written in the CORRECTED_DATA column.
<source lang="python">
<source lang="python">
# In CASA
# In CASA
applycal(vis = 'TDRW0001_calibrated.ms',
        field='',
        gainfield=['', '', ''],
        flagbackup=True,
        interp=['', '', ''],
        gaintable=[kcross_mbd,dtab_J0259,xtab],
        spw='0~7',
        calwt=[False, False, False],
        applymode='calflagstrict',
        antenna='*&*',
        spwmap=[[0,0,0,0,0,0,0,0],[],[]],
        parang=True)


# J2355+4950 / Df
</source>
dtab_J2355 = 'TDRW0001_calibrated.Df'  
 
polcal(vis='TDRW0001_calibrated.ms',
* ''gaintable'' : We provide a Python list of the calibration tables to be applied. This list must contain the cross-hand delays (kcross), the leakage calibration (dtab; here derived from J0259+0747), and the R-L phase corrections (xtab).
      caltable=dtab_J2355,
* ''calwt=[False] '': At the time of this writing, we are not yet using system calibration data to compute real (1/Jy<sup>2</sup>) weights; trying to calibrate them can produce nonsensical results. Experience has shown that calibrating the weights will lead to problems, especially in the self-calibration steps. You can specify ''calwt'' on a per-table basis, here is set all to ''False''.
      field='J2355+4950',
* ''parang '': If polarization calibration has been performed, set parameter ''parang=True''.
      spw='0~7',
      refant='ea10',
      poltype='Df',
      solint='inf,2MHz',
      combine='scan',
      gaintable=[kcross_mbd],
      gainfield=[''],
      spwmap=[[0,0,0,0,0,0,0,0]],
      append=False)


# J0259+0747 / Df+QU
dtab_J0259 = 'TDRW0001_calibrated.DfQU'
polcal(vis='TDRW0001_calibrated.ms',
      caltable=dtab_J0259,
      intent='CALIBRATE_POL_LEAKAGE#UNSPECIFIED',
      spw='0~7',
      refant='ea10',
      poltype='Df+QU',
      solint='inf,2MHz',
      combine='scan',
      gaintable=[kcross_mbd],
      gainfield=[''],
      spwmap=[[0,0,0,0,0,0,0,0]],
      append=False)
</source>


* ''caltable '': [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal] will create a new calibration table containing the leakage solutions, which we specify with the ''caltable'' parameter.
We should now have fully-calibrated visibilities in the CORRECTED_DATA column of the measurement set, and it is worthwhile pausing to inspect them to ensure that the calibration did what we expected it to.  We make some standard plots (see Figures 10A-F). Now that you've used [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] a few times try making the below plots on your own. The only bit of information you cannot derive from the figures themselves is that we have averaged them in time by 60 seconds.
* ''field='' or ''intent='' : The unpolarized source J2355+4950 is used to solve for the leakage terms in the unpolarized case. For the polarized source J0259+0747 we set the intent leakage polarization.
* ''spw='0~7' '': Select all spectral windows.
* ''poltype='Df' ''or ''poltype='Df+QU' '': Solve for the leakages (''D'') on a per-channel basis (''f''), assuming zero source polarization, +QU will also solve for the calibrator polarization Q,U per spectral window.
* ''solint='inf,2MHz', combine='scan' '': One solution over the entire run, per spectral channel of 2 MHz
* ''gaintable=['kcross_mbd']'': The previous Kcross multiband delay is applied
* ''spwmap=[0,0,0,0,0,0,0,0]'': This applies a spectral window map, where the first spw solution in the kcross_mbd table is mapped to all other spectral windows. Note there is only one value listed inside the kcross calibration table which is for the lowest spectral window that was used when solving using the multiband delay option (i.e. ''combine='spw' '').


In the case of Df+QU, the logger window will show the Q/U values it derived for the calibrator and the corresponding polarization fraction and angle that can be derived.
<div class="toccolours mw-collapsible mw-collapsed" style="width:1000px; overflow:auto;">
<pre style="background-color: #fffacd;">
<div style="font-weight:bold;line-height:1.6;">Plotms Calls</div>
Fractional polarization solution for J0259+0747 (spw = 0): : Q = 0.0259049, U = 0.0336301  (P = 0.0424505, X = 26.1967 deg)
<div class="mw-collapsible-content">
Fractional polarization solution for J0259+0747 (spw = 1): : Q = 0.0139972, U = 0.0382244  (P = 0.0407066, X = 34.944 deg)
<source lang="python">
Fractional polarization solution for J0259+0747 (spw = 2): : Q = 0.0165052, U = 0.0384224  (P = 0.0418175, X = 33.3765 deg)
# In CASA
Fractional polarization solution for J0259+0747 (spw = 3): : Q = 0.0118274, U = 0.0422875  (P = 0.0439104, X = 37.1871 deg)
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
Fractional polarization solution for J0259+0747 (spw = 4): : Q = 0.00816816, U = 0.0404744  (P = 0.0412903, X = 39.2952 deg)
      timerange='',antenna='',avgtime='60',
Fractional polarization solution for J0259+0747 (spw = 5): : Q = 0.00649365, U = 0.0412879  (P = 0.0417954, X = 40.5309 deg)
      xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
Fractional polarization solution for J0259+0747 (spw = 6): : Q = -0.00225595, U = 0.0429258  (P = 0.0429851, X = 46.5042 deg)
      coloraxis='corr',
Fractional polarization solution for J0259+0747 (spw = 7): : Q = -0.00776873, U = 0.0474773  (P = 0.0481087, X = 49.6465 deg)
      plotfile='Plotms-3C48-fld0-corrected-amp-CASA6.4.1.jpeg')
</pre>


From this you can see that J0259+0747 has a fractional polarization of 4.1&ndash;4.8% across the 1 GHz bandwidth with a small rotation measure causing a change in angle from 26 to 49 degrees over 1 GHz. In cases where the derived Q/U values seem random and the fractional polarization seems to be very small you might be able to derive better D-term solutions by using ''poltype='Df' ''.
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
      timerange='',antenna='',avgtime='60',
      xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
      plotrange=[-1,-1,-180,180],coloraxis='corr',
      plotfile='Plotms-3C48-fld0-corrected-phase-CASA6.4.1.jpeg')


After we run the two executions of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal], you are strongly advised to examine the solutions with [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] to ensure that everything looks good and to compare the results using two different calibrators and poltype methods.
plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='',
{|
      timerange='',antenna='',avgtime='60',
|[[Image:Plotms-J0259-Damp-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7a: J0259+0747 Df amplitude vs. frequency for antenna ea01.]]
      xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
|[[Image:Plotms-J2355-Damp-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7b: J2355+4950 Df+QU amplitude vs. frequency for antenna ea01.]]
      coloraxis='corr',
|[[Image:Plotms-J0259-Dphs-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7c: J0259+0747 Df phase vs. frequency for antenna ea01.]]
      plotfile='Plotms-J2355-fld1-corrected-amp-CASA6.4.1.jpeg')
|[[Image:Plotms-J2355-Dphs-ea01-CASA6.4.1_Antennaea01@W06.png|thumb|Figure 7d: J2355+4950 Df+QU phase vs. frequency for antenna ea01.]]
|}


<source lang="python">
plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='RR,LL',
# In CASA
       timerange='',antenna='',avgtime='60',
plotms(vis=dtab_J0259,xaxis='freq',yaxis='amp',  
      xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       iteraxis='antenna',coloraxis='corr')
      plotrange=[-1,-1,-180,180],coloraxis='corr',
      plotfile='Plotms-J2355-fld1-corrected-phase-CASA6.4.1.jpeg')


plotms(vis=dtab_J2355,xaxis='freq',yaxis='amp',  
plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
       iteraxis='antenna',coloraxis='corr')
       timerange='',antenna='',avgtime='60',
 
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
plotms(vis=dtab_J0259,xaxis='chan',yaxis='phase',  
       coloraxis='corr',
       iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])
      plotfile='Plotms-J0259-fld2-corrected-amp-CASA6.4.1.jpeg')
 
plotms(vis=dtab_J2355,xaxis='chan',yaxis='phase',  
       iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])


plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
      timerange='',antenna='',avgtime='60',
      xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
      plotrange=[-1,-1,-180,180],coloraxis='corr',avgbaseline=True,
      plotfile='Plotms-J0259-fld2-corrected-phase-CASA6.4.1.jpeg')
</source>
</source>
This will produce plots similar to those shown in Figures 7A-D. You can cycle through the antennas by clicking the Next button within [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms]. You should see leakages of between 5&ndash;17% in most cases. Both Df and Df+QU results should be comparable. However, we will be using the solutions from J0259+0747 to continue calibration and will use J2355+4950 to verify the polarization calibration.
</div></div>


We can also display these in a single plot versus antenna index (see Figure 8):
[[Image:Plotms-J0259-DfQU-CASA6.4.1.png|thumb|Figure 8: Df+QU solutions for J0259+0747 versus antenna index]]
<source lang="python">
# In CASA
plotms(vis=dtab_J0259,xaxis='antenna1',yaxis='amp',coloraxis='corr')
</source>


In some cases there are outlier solutions above 0.25 that are most likely due to residual RFI. You can flag those from the Dterm table using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata]. If everything went correctly, then this step should not be necessary for this dataset.
For 3C48 (figures 10A, 10B) we see the polarized signal in the cross-hands; there is some sign of bad data remaining in 3C48. Also, the RL phase plots of J0259+4950 (figure 10F) indicate that the Xf solutions, thus polarization angles, in the lowest two spectral windows are problematic. You can also estimate from the RL,LR amplitudes in J2355+4950 (figure 10E) what the level of residual instrumental polarization, which we expect to be around <0.5%. A more accurate evaluation of residual instrumental polarization fraction can be made imaging the secondary D-term calibrator per spectral window and calculating its residual polarization.  
<source lang="python">
flagdata(vis=dtab_J2355, mode='clip', correlation='ABS_ALL', clipminmax=[0.0, 0.25], datacolumn='CPARAM', clipoutside=True, action='apply', flagbackup=False, savepars=False)


flagdata(vis=dtab_J0259, mode='clip', correlation='ABS_ALL', clipminmax=[0.0, 0.25], datacolumn='CPARAM', clipoutside=True, action='apply', flagbackup=False, savepars=False)
{|
</source>
| [[Image:Plotms-3C48-fld0-corrected-amp-CASA6.4.1.png|thumb|Figure 10A: amplitude vs channel for 3C48 RR,RL,LR,LL]]
| [[Image:Plotms-3C48-fld0-corrected-phase-CASA6.4.1.png|thumb|Figure 10B: phase vs channel for 3C48 RR,RL,LR,LL]]
| [[Image:Plotms-J2355-fld1-corrected-amp-CASA6.4.1.png|thumb|Figure 10C: amplitude vs channel for J2355+4950 RR,RL,LR,LL]]
| [[Image:Plotms-J2355-fld1-corrected-phase-CASA6.4.1.png|thumb|Figure 10D: phase vs channel for J2355+4950 RR,LL]]
|}
 
{|
| [[Image:Plotms-J0259-fld2-corrected-amp-CASA6.4.1.png|thumb|Figure 10E: amplitude vs channel for J0259+4950 RR,RL,LR,LL]]
| [[Image:Plotms-J0259-fld2-corrected-phase-CASA6.4.1.png|thumb|Figure 10F: phase vs channel for J0259+4950 RR,RL,LR,LL with baseline averaging]]
|}


==== Solving for the R-L polarization angle ====


Having calibrated for the instrumental polarization, the total polarization is now correct, but the R-L phase still needs to be calibrated in order to obtain an accurate polarization position angle.  We use the same task, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.polcal.html polcal], but this time set parameter ''poltype='Xf', ''which specifies a frequency-dependent (''f'') position angle (''X'') calibration using the source 3C48, the position angle of which is known, having set this earlier with [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.setjy.html setjy]. Note that we must correct for the leakages before determining the R-L phase, which we do by adding the calibration table made in the previous step ('''dtab_J0259''') to the kcross table that is applied on-the-fly.
Now that the calibration has been applied to the target data, we split off the science targets to create a new, calibrated measurement set containing the target field.  


<source lang="python">
<source lang="python">
# In CASA
# In CASA
xtab = "TDRW0001_calibrated.Xf"
split(vis='TDRW0001_calibrated.ms',outputvis='3C75.ms',
polcal(vis='TDRW0001_calibrated.ms',
      datacolumn='corrected',field='3')
      caltable=xtab,
      spw='0~7',
      field='0137+331=3C48',
      solint='inf,2MHz',
      combine='scan',
      poltype='Xf',
      refant = 'ea10',
      gaintable=[kcross_mbd,dtab_J0259],
      gainfield=['',''],
      spwmap=[[0,0,0,0,0,0,0,0],[]],
      append=False)
</source>
</source>


[[Image:Plotms-3C48-Xf-CASA6.4.1.png|thumb|Figure 9: Xf solutions versus frequency.]]
* ''outputvis '': We give the name of the new measurement set to be written, which will contain the calibrated data on the science target.
Strictly speaking, there is no need to specify a reference antenna for ''poltype='Xf' ''(for circularly polarized receivers only) because the X solutions adjust the cross-hand phases for each antenna to match the given polarization angle of the model. However, for consistency/safety, it is recommended to always specify refant when performing polarization calibration.
* ''datacolumn '': We use the CORRECTED_DATA column, containing the calibrated data which we just wrote using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal].
* ''field '': We wish to place the target field into a measurement set for imaging and joint deconvolution.
 
Prior to imaging, it is a good idea to run the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.manipulation.statwt.html statwt] task to correct the data weights (<i>weight</i> and <i>sigma</i> columns) in the measurement set.  Running [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.manipulation.statwt.html statwt] will remove the effects of relative noise scatter that may have been introduced from flagging uneven bits in the visibility data between the channels and times. We will run this task here on the newly calibrated and split data set before moving on to imaging.
 
<source lang="python">
# In CASA
statwt(vis='3C75.ms',datacolumn='data',minsamp=8)
</source>
 
= Imaging =
 
Now that we have split off the target data into a separate measurement set with all the calibration applied, it's time to make an image. It is important to have an idea of what values to use for the image pixel (cell) size and the overall size of the image. Setting the appropriate pixel size for imaging depends upon basic optics aspects of interferometry. Use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] to look at the newly calibrated, target-only data set:


It is strongly suggested you check that the calibration worked properly by plotting up the newly-generated calibration table using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] (see Figure 9):
[[Image:plotms_3c75-uvwave-CASA6.4.1.png|thumb|Figure 11: ''plotms'' plot showing Amplitude vs UV Distance in wavelengths for 3C75 at 3000 MHz]]
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis=xtab,xaxis='frequency',yaxis='phase',coloraxis='spw')
plotms(vis='3C75.ms',xaxis='uvwave',yaxis='amp',
      ydatacolumn='data', field='0',avgtime='30',correlation='RR',
      plotfile='plotms_3c75-uvwave.jpeg',avgspw=False,overwrite=True)
</source>
</source>
Because the Xf term captures the residual R-L phase on the reference antenna over the array, there is only one value for all antennas. Also, as we took out the RL delays using the Kcross solution, these Xf variations do not show a significant slope in phase. And since we were using a single multiband delay, the phases connect from one spectral window to another; had we used the single band delays, we would see phase jumps from one to another spectral window.
You should obtain a plot similar to Figure 11 with the (calibrated) visibility amplitude as a function of <math>u</math>-<math>v</math> distance. You will also see some outliers there which are primarily from residual amplitude errors of ea05, that had a warm receiver which we can isolate to particular time periods. We will be addressing this after the initial imaging.  
 


At this point, you have all the necessary polarization calibration tables.
Based on the UVwave plot can you determine approximately what the smallest angular scale of the image will be?
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
<div style="font-weight:bold;line-height:1.6;">Answer</div>
<div class="mw-collapsible-content">
We can see in the plot that the maximum baseline is about 12,000 wavelengths. If we recall that the VLA works via diffraction then it follows that: <math>\theta\approx\lambda/D=1/12000 radians\approx17 arcsec</math>.
Furthermore, the most effective cleaning occurs with 3&ndash;5 pixels across the synthesized beam. So for this data a cell size of 3.4 arcseconds will give just about 5 pixels per beam.
</div></div>


== Applying the Calibration ==


Now that we have derived all the calibration solutions, we need to apply them to the actual data using the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal]. The measurement set DATA column contains the original split data. To apply the calibration we have derived, we specify the appropriate calibration tables which are then applied to the DATA column, with the results being written in the CORRECTED_DATA column. If the dataset does not already have a CORRECTED_DATA scratch column, then one will be created in the first [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] run.
The 3C75 binary black hole system is known to have a maximum extent of at least 8-9 arcminutes, corresponding to about 147 pixels for the chosen cell size. Therefore, we need to choose an image size that covers most of the extent of the source. We therefore set ''imsize=[480,480]'' and the source will fit comfortably within that image.


In this tutorial, we will run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] interactively so that we can set and modify the mask:
<source lang="python">
<source lang="python">
# In CASA
# In CASA
applycal(vis = 'TDRW0001_calibrated.ms',
tclean(vis='3C75.ms',
        field='',
      field="3C75",
        gainfield=['', '', ''],
      spw="",timerange="",
        flagbackup=True,
      uvrange="",antenna="",scan="",observation="",intent="",
        interp=['', '', ''],
      datacolumn="data",
        gaintable=[kcross_mbd,dtab_J0259,xtab],
      imagename="3C75_initial",
        spw='0~7',  
      imsize=480,
        calwt=[False, False, False],
      cell="3.4arcsec",
        applymode='calflagstrict',  
      phasecenter="",
        antenna='*&*',  
      stokes="IQUV",
        spwmap=[[0,0,0,0,0,0,0,0],[],[]],  
       projection="SIN",
        parang=True)
       specmode="mfs",
 
       reffreq="3.0GHz",
</source>
       nchan=-1,
 
      start="",
* ''gaintable'' : We provide a Python list of the calibration tables to be applied. This list must contain the cross-hand delays (kcross), the leakage calibration (dtab; here derived from J0259+0747), and the R-L phase corrections (xtab).
      width="",
* ''calwt=[False] '': At the time of this writing, we are not yet using system calibration data to compute real (1/Jy<sup>2</sup>) weights; trying to calibrate them can produce nonsensical results. Experience has shown that calibrating the weights will lead to problems, especially in the self-calibration steps. You can specify ''calwt'' on a per-table basis, here is set all to ''False''.
       outframe="LSRK",
* ''parang '': If polarization calibration has been performed, set parameter ''parang=True''.
       veltype="radio",
 
       restfreq=[],
We should now have fully-calibrated visibilities in the CORRECTED_DATA column of the measurement set, and it is worthwhile pausing to inspect them to ensure that the calibration did what we expected it to.  We make some standard plots (see Figures 10A-10F):
      interpolation="linear",
<source lang="python">
       gridder="standard",
# In CASA
       mosweight=True,
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
       cfcache="",
       timerange='',antenna='',avgtime='60',
       computepastep=360.0,
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
       rotatepastep=360.0,
       coloraxis='corr',
      pblimit=0.0001,
       plotfile='Plotms-3C48-fld0-corrected-amp-CASA6.4.1.jpeg')
       normtype="flatnoise",
 
       deconvolver="mtmfs",
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
       scales=[0, 6, 18],
       timerange='',antenna='',avgtime='60',
      nterms=2,
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       smallscalebias=0.6,
       plotrange=[-1,-1,-180,180],coloraxis='corr',
      restoration=True,
       plotfile='Plotms-3C48-fld0-corrected-phase-CASA6.4.1.jpeg')
      restoringbeam=[],
 
      pbcor=False,
plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='',
       outlierfile="",
       timerange='',antenna='',avgtime='60',
      weighting="briggs",
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
      robust=0.5,
       coloraxis='corr',
       npixels=0,
       plotfile='Plotms-J2355-fld1-corrected-amp-CASA6.4.1.jpeg')
      uvtaper=[],
 
       niter=20000,
plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='RR,LL',
       gain=0.1,
       timerange='',antenna='',avgtime='60',
      threshold=0.0,
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
      nsigma=0.0,
       plotrange=[-1,-1,-180,180],coloraxis='corr',
      cycleniter=1000,
       plotfile='Plotms-J2355-fld1-corrected-phase-CASA6.4.1.jpeg')
       cyclefactor=1.0,
 
      restart=True,
plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
      savemodel="modelcolumn",
       timerange='',antenna='',avgtime='60',
       calcres=True,
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
      calcpsf=True,
       coloraxis='corr',
       parallel=False,
       plotfile='Plotms-J0259-fld2-corrected-amp-CASA6.4.1.jpeg')
       interactive=True)
 
plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       plotrange=[-1,-1,-180,180],coloraxis='corr',avgbaseline=True,
       plotfile='Plotms-J0259-fld2-corrected-phase-CASA6.4.1.jpeg')
</source>
</source>
For 3C48 (figures 10A, 10B) we see the polarized signal in the cross-hands; there is some sign of bad data remaining in 3C48. Also, the RL phase plots of J0259+4950 (figure 10F) indicate that the Xf solutions, thus polarization angles, in the lowest two spectral windows are problematic. You can also estimate from the RL,LR amplitudes in J2355+4950 (figure 10E) what the level of residual instrumental polarization, which we expect to be around <0.5%. A more accurate evaluation of residual instrumental polarization fraction can be made imaging the secondary D-term calibrator per spectral window and calculating its residual polarization.


{|
[[Image:3C75-tclean-interactive-start-CASA6.2.1.png|thumb|Figure 12: Interactive clean at the beginning, having selected polygon region and ready to double-click inside to set the mask.]]
| [[Image:Plotms-3C48-fld0-corrected-amp-CASA6.4.1.png|thumb|Figure 10A: amplitude vs channel for 3C48 RR,RL,LR,LL]]
Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] is powerful with many inputs and a certain amount of experimentation likely is required. The below is an explanation of several of the parameters we've used.
| [[Image:Plotms-3C48-fld0-corrected-phase-CASA6.4.1.png|thumb|Figure 10B: phase vs channel for 3C48 RR,RL,LR,LL]]
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
| [[Image:Plotms-J2355-fld1-corrected-amp-CASA6.4.1.png|thumb|Figure 10C: amplitude vs channel for J2355+4950 RR,RL,LR,LL]]
<div style="font-weight:bold;line-height:1.6;">tclean parameters</div>
| [[Image:Plotms-J2355-fld1-corrected-phase-CASA6.4.1.png|thumb|Figure 10D: phase vs channel for J2355+4950 RR,LL]]
<div class="mw-collapsible-content">
|}
* ''vis='3C75.ms' '': this split MS contains the target field only.
* ''imagename='3C75_initial' '': our output image cubes will all start with this name root, e.g., 3C75_initial.image
* ''specmode='mfs' '': Use multi-frequency synthesis imaging. The fractional bandwidth of these data is non-zero (1000 MHz at a central frequency of 3.0 GHz). Recall that the <math>u</math> and <math>v</math> coordinates are defined as the baseline coordinates, measured in wavelengths. Thus, slight changes in the frequency from channel to channel result in slight changes in <math>u</math> and <math>v</math>. There is a concomitant improvement in <math>u</math>-<math>v</math> coverage if the visibility data from the multiple spectral channels are gridded separately onto the <math>u</math>-<math>v</math> plane, as opposed to treating all spectral channels as having the same frequency.
* ''niter=20000,gain=0.1,threshold='0.0mJy' '': Recall that the gain is the amount by which a clean component is subtracted during the cleaning process. Parameters ''niter'' and ''threshold'' are (coupled) means of determining when to stop the cleaning process, with ''niter'' specifying to find and subtract that many clean components while ''threshold'' specifies a minimum flux density threshold a clean component can have before [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] stops (also see ''interactive'' below). Imaging is an iterative process, and to set the threshold and number of iterations, it is usually wise to clean interactively in the first instance, stopping when spurious emission from sidelobes (arising from gain errors) dominates the residual emission in the field. Here, we have set the threshold level to zero and let the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] task define an appropriate threshold. The number of iterations should then be set high enough to reach the threshold found by tclean.
* ''gridder='standard' '': The standard tclean gridder is sufficient for our purposes, since we are not combining multiple pointings from a mosaic or try to perform widefield imaging in an extended configuration.
* ''interactive=True '': Very often, particularly when one is exploring how a source appears for the first time, it can be valuable to interact with the cleaning process. If True, ''interactive'' causes a [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.viewer.html viewer] window to appear. One can then set clean regions, restricting where [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] searches for clean components, as well as monitor the cleaning process. A standard procedure is to set a large value for ''niter'', and stop the cleaning when it visually appears to be approaching the noise level. This procedure also allows one to change the cleaning region, in cases when low-level intensity becomes visible as the cleaning process proceeds. 
* ''imsize=480,cell='3.4arcsec' '': See the discussion above regarding setting the image size and cell size. If only one value is specified for the parameter, the same value is used in both directions (declination and right ascension).
* ''stokes='IQUV' '': [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will output an image cube containing all: total intensity I, and Stokes Q, U, and V.
* ''deconvolver='mtmfs', scales=[0, 6, 18], smallscalebias=0.9 '': The settings for ''scales'' are in units of pixels, with 0 pixels equivalent to the traditional delta-function clean.  The scales here are chosen to provide delta functions and then two logarithmically scaled sizes to fit to the data. The first scale (6 pixels) is chosen to be comparable to the size of the synthesized beam. The ''smallscalebias'' attempts to balance the weight given to larger scales, which often have more flux density, and the smaller scales, which often are brighter. Considerable experimentation is likely to be necessary; one of the authors of this document found that it was useful to clean several rounds with this setting, change to ''multiscale=[]'' and remove much of the smaller scale structure, then return to this setting.
* ''weighting='briggs',robust=0.5 '': 3C75 has diffuse, extended emission that is, at least partially, resolved out by the interferometer even though we are in the most compact VLA configuration. A naturally-weighted image would show large-scale patchiness in the noise. In order to suppress this effect, Briggs weighting is used (intermediate between natural and uniform weighting), with a default robust factor of 0.5 (which corresponds to something between natural and uniform weighting).
* ''pbcor=False '': by default ''pbcor=False'' and a flat-noise image is produced. We can do the primary beam correction later (see below).
* ''savemodel='modelcolumn' '': We recommend here the use of a physical MODEL_DATA scratch column. This will save some time, as it can be faster in the case of complicated gridding to read data from disk instead of doing all of the computations on-the-fly. However, this has the unfortunate side effect of increasing the size of the MS on disk.
</div></div>


{|
[[Image:3C75-tclean-interactive-300iters-CASA6.2.1.png|thumb|Figure 13: After the first approximately 300 iterations of multi-scale mfs clean]]
| [[Image:Plotms-J0259-fld2-corrected-amp-CASA6.4.1.png|thumb|Figure 10E: amplitude vs channel for J0259+4950 RR,RL,LR,LL]]
| [[Image:Plotms-J0259-fld2-corrected-phase-CASA6.4.1.png|thumb|Figure 10F: phase vs channel for J0259+4950 RR,RL,LR,LL with baseline averaging]]
|}


As mentioned above, we can guide the clean process by allowing it to find clean components only within a user-specified region.  When [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] runs in interactive mode, an [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.imview.html imview] window will pop up as shown in Figure 12. '''First, you'll want to navigate to the green box and select "All Polarizations" rather than use the default "This Polarization"'''; this way the cleaning we are about to do will apply to all of the polarizations rather than just the one we are currently viewing. Similarly, select "All channels". To get a more detailed view of the central regions containing the emission, zoom in by first left clicking on the zoom button (leftmost button in third row) and tracing out a rectangle with the left mouse button and double-clicking inside the zoom box you just made. Play with the color scale to bring out the emission better by holding down the middle mouse button and moving it around. To create a clean box (a region within which components may be found), hold down the right mouse button and trace out a rectangle around the source, then double-click inside that rectangle to set it as a box. Note that the clean box must turn white for it to be registered - if the box is not white, it has not been set. Alternatively, you can trace out a more custom shape to better enclose the irregular outline of the radio galaxy jets. To do this, right-click on the closed polygonal icon then trace out a shape by right-clicking where you want the corners of that shape. Once you have come full circle, the shape will be traced out in green, with small squares at the corners. Double-click inside this region and the green outline will turn white. You have now set the clean region. If you have made a mistake with your clean box, click on the Erase button, trace out a rectangle around your erroneous region, and double-click inside that rectangle. You can also set multiple clean regions.


Inspecting the data at this stage may well show up previously-unnoticed bad data. Plotting the '''corrected''' amplitude against UV distance or against time is a good way to find such issues. If you find bad data, you can remove them via interactive flagging in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] or via manual flagging in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagdata.html flagdata] once you have identified the offending antennas/baselines/channels/times. When you are happy that all data (particularly on your target source) look good, you may proceed. However, especially for the target, we will return to additional flagging at a later stage.  
At any stage in the cleaning, you can adjust the number of iterations that [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will do before returning to the GUI (''cycleniter''). This is set to 1000 (see the iterations field in mid-upper left of panel), values from 500 to 1000 later on seem to work. Note that this will override the ''cycleniter'' value that you might had set before starting [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will keep going until it reaches threshold or runs out of cycles (the cycles field to the right of the iterations).


Now that the calibration has been applied to the target data, we split off the science targets to create a new, calibrated measurement set containing the target field. This is not strictly necessary if you want to save disk space.  
[[Image:3C75-tclean-interactive-residuals-CASA6.2.1.png|thumb|Figure 14: Interactive residuals after about 13000 iterations of multi-scale mfs clean]]
When you are happy with the clean regions, press the green circular arrow button on the far right to continue deconvolution. After completing a cycle, a revised image will come up. As the brightest points are removed from the image (cleaned off), fainter emission may show up. You can adjust the clean boxes each cycle, to enclose all real emission. After many cycles, when only noise is left, you can hit the red-and-white stop-sign icon to stop cleaning. Figure 13 shows the interactive viewer panel later in the process, after cleaning about 500 iterations. We have used the polygon tool to add to the clean region, drawing around emission that shows up in the residual image outside of the original clean region. After about 13000 iterations (Figure 14) the residuals were looking good (similar noise level inside and outside of the cleaned mask region). As mentioned before, restarting [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] with different ''multiscale=[...]'' choices can help also. You see that there is a significant amount of residual structure (the various spikes and streaks throughout the image), these are most likely due to calibration errors which we will try to correct for in the next section during self-calibration.


<source lang="python">
Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will make several output files, all named with the prefix given as ''imagename''.  These include:
# In CASA
* ''.image'': final restored image(s) with the clean components convolved with a restoring beam and added to the remaining residuals at the end of the imaging process, one for each Taylor Term (.tt0 and .tt1)
split(vis='TDRW0001_calibrated.ms',outputvis='3C75.ms',
* ''.pb.tt0'': effective response of the telescope (the primary beam)
      datacolumn='corrected',field='3')
* ''.mask'': areas where [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] has been allowed to search for emission
</source>
* ''.model'': sum of all the clean components, which also has been stored as the MODEL_DATA column in the measurement set, one for each Taylor Term (.tt0 and .tt1)
* ''.psf'': dirty beam, which is being deconvolved from the true sky brightness during the clean process, one for each Taylor Term (.tt0, .tt1, .tt2)
* ''.residual'': what is left at the end of the deconvolution process; this is useful to diagnose whether or not to clean more deeply, one for each Taylor Term (.tt0, .tt1)
* ''.sumwt'': a single pixel image containing sum of weights per plane, one for each Taylor Term (.tt0, .tt1, .tt2)
 
{|
|[[Image:3c75-CARTA-multiscale-initialI-CASA6.4.1.png|thumb|Figure 15A: Viewer panel of final restored Stokes I image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialQ-CASA6.4.1.png|thumb|Figure 15B: Viewer panel of final restored Stokes Q image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialU-CASA6.4.1.png|thumb|Figure 15C: Viewer panel of final restored Stokes U image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialV-CASA6.4.1.png|thumb|Figure 15D: Viewer panel of final restored Stokes V image (using viridis colormap, linear scale, 99.9%)]]
|}


* ''outputvis '': We give the name of the new measurement set to be written, which will contain the calibrated data on the science target.
After the imaging and deconvolution process has finished, you can use [https://cartavis.org/ CARTA] to look at your image.
* ''datacolumn '': We use the CORRECTED_DATA column, containing the calibrated data which we just wrote using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal].
* ''field '': We wish to place the target field into a measurement set for imaging and joint deconvolution.


Prior to imaging, it is a good idea to run the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.manipulation.statwt.html statwt] task to correct the data weights (<i>weight</i> and <i>sigma</i> columns) in the measurement set. Running [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.manipulation.statwt.html statwt] will remove the effects of relative noise scatter that may have been introduced from flagging uneven bits in the visibility data between the channels and times. We will run this task here on the newly calibrated and split data set before moving on to imaging.
Take some time to play with the color scale to better emphasize the faint emission and to see the underlying noise patterns. For the figures above we selected the viridis color map, the linear scale function, and the 99.9% data range on the histogram. You can also use the Animators slider/buttons to switch between the four different Stokes parameter images that were computed. If you are unfamiliar with [https://cartavis.org/ CARTA] then take some time to look over its extensive built in documentation and help features. You can find its searchable online manual via the "Help" button at the top or to get more information on a particular widget you can click the corresponding "?" button near it. If you click the Animator tab you'll also notice that [https://cartavis.org/ CARTA] attempts to create total polarization, linear polarization, fractional total polarization, fractional linear polarization, and linear polarization angle images for you. This can be quite convenient, but we'll show how to create these yourself later in this guide.


The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] task naturally operates in a flat noise image, i.e., an image where the effective weighting across the field of view is set so that the noise is constant. This is so that the clean threshold has a uniform meaning for the stopping criterion and that the image fed into the minor cycles has uniform noise levels. This means, however, that the image does not take into account the primary beam response fall-off in the edges. In principle, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] produces primary beam response image, and if we had set parameter ''pbcor=True'' [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] would had saved a primary beam corrected restored image of our target. Since we used ''deconvolver='mtmfs' ''  and ''nterms=2'', the calculation of the primary beam response requires special treatment. To perform wideband primary beam correction, we will use task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.widebandpbcor.html widebandpbcor]. In the future this task will be incorporated into [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean], but until then this separate task needs to be used.
<source lang="python">
<source lang="python">
# In CASA
# In CASA
statwt(vis='3C75.ms',datacolumn='data',minsamp=8)
widebandpbcor(vis='3C75.ms',imagename='3C75_initial',nterms=2, action='pbcor',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])
</source>
</source>


= Imaging =
The task will produce primary beam corrected images of our target (3C75_initial.pbcor.image.tt0, 3C75_initial.pbcor.image.tt1, 3C75_initial.pbcor.image.alpha, 3C75_initial.pbcor.image.alpha.error). You can open image 3C75_initial.pbcor.image.tt0 in [https://cartavis.org/ CARTA], and compare it to screenshots in Figure 15. You will see noise (and signal) at the edges of the image has indeed increased.


Now that we have split off the target data into a separate measurement set with all the calibration applied, it's time to make an image. Recall that the visibility data and the sky brightness distribution (a.k.a. image) are Fourier transform pairs.
== Self-Calibration ==


<math>
Before we get started with self-calibration, it might be good to check whether we need to perform additional flagging on the target data. Since we have established an image model in the previous section, we can use it to look at the residuals by dividing out the model. We can make a similar plot to Figure 11 above, however, we will divide the image model that was created. The division will help us to see low level interfrence we might not otherwise notice by just looking at the data column. Since we performed full-polarization imaging, we can also do the same to the cross-hand data RL,LR. Figures 16A & B shows example plots. You should also have a look at time plotted against amplitude and frequency against amplitude to see if there are any obvious times of interference.
I(l,m) = \int V(u,v) e^{[2\pi i(ul + vm)]} dudv
</math>
 
The <math>u</math> and <math>v</math> coordinates are the baselines measured in units of the observing wavelength, while the <math>l</math> and <math>m</math> coordinates are the direction cosines on the sky. In general, the sky coordinates are written in terms of direction cosines; but for most VLA (and ALMA) observations, they can be related simply to the right ascension (<math>l</math>) and declination (<math>m</math>). Recall that this equation is valid only if the <math>w</math> coordinate of the baselines can be neglected; this assumption is almost always true at high frequencies and smaller VLA configurations. The <math>w</math> coordinate cannot be neglected at lower frequencies and larger configurations (e.g., 0.33 GHz, A-configuration observations). This expression also neglects other factors, such as the shape of the primary beam. For more information on imaging, see the [https://casadocs.readthedocs.io/en/v6.4.1/notebooks/synthesis_imaging.html section of the CASA documentation.]
 
[[Image:plotms_3c75-uvwave-CASA6.4.1.png|thumb|Figure 11: ''plotms'' plot showing Amplitude vs UV Distance in wavelengths for 3C75 at 3000 MHz]]
CASA has a task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] which both Fourier transforms the data and deconvolves the resulting image. We will use a multi-scale cleaning algorithm because our target source, a complex radio galaxy, contains both diffuse, extended structures on large spatial scales as well as point-like components. This approach will do a better job of modeling the image than the classic clean delta function. For broader examples of many [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] options, please see the [https://casaguides.nrao.edu/index.php/Karl_G._Jansky_VLA_Tutorials#Imaging_VLA_Data_in_CASA Topical Guide for Imaging VLA Data].
 
== Multi-scale Clean ==


It is important to have an idea of what values to use for the image pixel (cell) size and the overall size of the image. Setting the appropriate pixel size for imaging depends upon basic optics aspects of interferometry. Use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] to look at the newly calibrated, target-only data set:
<source lang="python">
<source lang="python">
# In CASA
# In CASA
plotms(vis='3C75.ms',xaxis='uvwave',yaxis='amp',
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
       ydatacolumn='data', field='0',avgtime='30',correlation='RR',
       ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RR',
       plotfile='plotms_3c75-uvwave.jpeg',avgspw=False,overwrite=True)
      plotfile='plotms_3c75-uvdist_resid_RR.png',avgspw=False,overwrite=True)
 
# If you made a mistake above and didn't clean the polarization as well, then this plot will be empty.
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
      ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RL',
       plotfile='plotms_3c75-uvdist_resid_RL.png',avgspw=False,overwrite=True)
</source>
</source>
You should obtain a plot similar to Figure 11 with the (calibrated) visibility amplitude as a function of <math>u</math>-<math>v</math> distance. You will also see some outliers there which are primarily from residual amplitude errors of ea05, that had a warm receiver which we can isolate to particular time periods. We will be addressing this after the initial imaging. The maximum baseline is about 12,000 wavelengths, i.e., an angular scale of 17 arcseconds (<math>\theta\approx\lambda/D=1/12000</math>). The most effective cleaning occurs with 3&ndash;5 pixels across the synthesized beam. For example, a cell size of 3.4 arcseconds will give just about 5 pixels per beam. 


The 3C75 binary black hole system is known to have a maximum extent of at least 8-9 arcminutes, corresponding to about 147 pixels for the chosen cell size. Therefore, we need to choose an image size that covers most of the extent of the source. To aid deconvolution, especially when bright sources far from phase center are present, we should at the minimum image the size of the primary beam. Although CASA has the feature that its Fourier transform engine (FFTW) does ''not'' require a strict power of 2 for the number of linear pixels in a given image axis, it is somewhat more efficient if the number of pixels on a side is a composite number divisible by ''any pair'' of 2 and 3 and/or 5. Because [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] internally applies a padding of 1.2 (=3x2/5), choose 480 which is 2<sup>5</sup> &times; 3 &times; 5 (so 480 &times; 1.2 = 576 = 2<sup>6</sup> &times; 3<sup>2</sup>). We therefore set ''imsize=[480,480]'' and the source will fit comfortable within that image.
{|
| [[Image:plotms-3c75-uvdist-residRR-CASA6.4.1-corr.png|thumb|Figure 16A: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RR correlations.]]
| [[Image:plotms-3c75-uvdist-residRL-CASA6.4.1-corr.png|thumb|Figure 16B: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RL correlations.]]
|}


In this tutorial, we will run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] interactively so that we can set and modify the mask:
Since we are seeing a significant amount of weak residual interference, we will take a few steps to reduce these.  
<source lang="python">
<source lang="python">
# In CASA
# In CASA
tclean(vis='3C75.ms',
 
# tfcrop
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RR,ABS_LL',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RL,ABS_LR',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
# rflag
flagdata(vis='3C75.ms',mode='rflag',correlation='RR,LL',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
flagdata(vis='3C75.ms',mode='rflag',correlation='RL,LR',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
# extend flags
flagdata(vis='3C75.ms',mode='extend',flagbackup=False)
</source>
 
This should have gotten rid of the worst remaining outliers, but will leave some residual weak RFI on certain baseline lengths. Since we are not trying to win any records on high dynamic range imaging, this additional flagging should suffice for our dataset. 
 
'''In addition to residual RFI, even after calibration using the amplitude calibrator and the phase calibrator, there are likely to be residual phase and/or amplitude errors in the data. Self-calibration uses an existing model, often constructed from imaging the data itself, provided that sufficient visibility data have been obtained.''' This is essentially always the case with data: the system of equations is wildly over-constrained for the number of unknowns. 
 
 
For an array of <math>N</math> antennas there are at any given instant only <math>N</math> gain factors, but how many visibilities?
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
<div style="font-weight:bold;line-height:1.6;">Answer</div>
<div class="mw-collapsible-content">
<math>{N(N-1) \over 2}</math>
 
Since we are only considering one instance of time (i.e. one integration) this is also the number of baselines in the array. For a typical 27 antenna VLA observation that comes out to 351.
</div></div>
 
 
For an array with a reasonable number of antennas, <math>N</math> >~ 8, solutions to this set of coupled equations converge quickly. There is some discussion in the old CASA Reference Manual on [http://casa.nrao.edu/docs/cookbook/casa_cookbook006.html#section%3Aim.selfcal self calibration] (see Section 5.11), but more detailed discussion can be found in lectures on [https://science.nrao.edu/facilities/alma/naasc-workshops/nrao-cd-stsci/cde_selfcal.pdf Self-calibration] given at NRAO community days.
 
In self-calibrating data, it is useful to keep in mind the structure of a Measurement Set. There are three columns of interest for an MS: the DATA column, the MODEL column, and the CORRECTED_DATA column. In normal usage, as part of the initial split, the DATA column of the new MS is set to be equal the previous MS's CORRECTED_DATA column. The self-calibration procedure is then:
 
* Produce an image ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]) using the (corrected copy) DATA column.
* Derive a series of gain corrections ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]) by comparing the DATA columns and the Fourier transform of the image, which is stored in the MODEL column. These corrections are stored in an external table.
** Optionally, we can also derive a bandpass correction&mdash;which is also referred to as bandpass self calibration&mdash;to correct for global amplitude errors.
* Apply these corrections ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal]) to the DATA column to form a new CORRECTED_DATA column ''overwriting'' the previous contents of CORRECTED_DATA should it exist.
 
The following example begins with the standard data set, 3C75.ms (resulting from the steps above). We have previously generated an IQUV multiscale image cube. We discard it for this step and create a new Stokes I image, which we will use to generate a series of gain corrections (phase only self-calibration) that will be stored in 3C75.ScG0. With this solution, we then perform bandpass self-calibration to remove any amplitude slope that might be present. Next, we apply the derived phase and amplitude corrections to the data to form a set of self-calibrated data, and then re-image the dataset (3C75_selfcal.image). For the purpose of self-calibration, note that in the clean before the self-calibration, it is important that we only use the Stokes I model so that any cleaned polarization does not affect the gaincal. We first use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.delmod.html?highlight=delmod# delmod] on the MS to get rid of the previous polarized model, and run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] to generate Stokes I-only image.
<source lang="python">
#In CASA
delmod('3C75.ms')
 
tclean(vis='3C75.ms',
       field="3C75",
       field="3C75",
       spw="",timerange="",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="data",
       datacolumn="data",
       imagename="3C75_initial",
       imagename="3C75_initial_I",
       imsize=480,
       imsize=480,
       cell="3.4arcsec",
       cell="3.4arcsec",
       phasecenter="",
       phasecenter="",
       stokes="IQUV",
       stokes="I",
       projection="SIN",
       projection="SIN",
       specmode="mfs",
       specmode="mfs",
Line 1,105: Line 1,029:
       npixels=0,
       npixels=0,
       uvtaper=[],
       uvtaper=[],
       niter=20000,
       niter=3500,
       gain=0.1,
       gain=0.1,
       threshold=0.0,
       threshold=0.0,
       nsigma=0.0,
       nsigma=0.0,
       cycleniter=1000,
       cycleniter=750,
       cyclefactor=1.0,
       cyclefactor=1.0,
       restart=True,
       restart=True,
Line 1,118: Line 1,042:
       interactive=True)
       interactive=True)
</source>
</source>
As discussed, this [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] call will ignore the polarized structure. You should not clean very deeply at this point. You want to be sure to capture as much of the source's total flux density as possible, but not include low level questionable features or sub-structures (ripples) that might be due to calibration or deconvolution artifacts. We modified the two parameters controlling [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]'s minor and major cycles to the following values ''cycleniter=750'' and ''niter=3500'' to reflect this, but you may find that you don't even need 3500 iterations for this first [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] pass.


[[Image:3C75-tclean-interactive-start-CASA6.2.1.png|thumb|Figure 12: Interactive clean at the beginning, having selected polygon region and ready to double-click inside to set the mask.]]
If you are happy with the new image, perform the following self-calibration steps:
Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] is powerful with many inputs and a certain amount of experimentation likely is required.
<source lang="python">
* ''vis='3C75.ms' '': this split MS contains the target field only.
#In CASA
* ''imagename='3C75_initial' '': our output image cubes will all start with this name root, e.g., 3C75_initial.image
gaincal(vis='3C75.ms', caltable='3C75.ScG0', field='', solint='inf', refant='ea10',  
* ''specmode='mfs' '': Use multi-frequency synthesis imaging. The fractional bandwidth of these data is non-zero (1000 MHz at a central frequency of 3.0 GHz). Recall that the <math>u</math> and <math>v</math> coordinates are defined as the baseline coordinates, measured in wavelengths. Thus, slight changes in the frequency from channel to channel result in slight changes in <math>u</math> and <math>v</math>. There is a concomitant improvement in <math>u</math>-<math>v</math> coverage if the visibility data from the multiple spectral channels are gridded separately onto the <math>u</math>-<math>v</math> plane, as opposed to treating all spectral channels as having the same frequency.
          spw='',minsnr=3.0, gaintype='G', parang=False, calmode='p')
* ''niter=20000,gain=0.1,threshold='0.0mJy' '': Recall that the gain is the amount by which a clean component is subtracted during the cleaning process. Parameters ''niter'' and ''threshold'' are (coupled) means of determining when to stop the cleaning process, with ''niter'' specifying to find and subtract that many clean components while ''threshold'' specifies a minimum flux density threshold a clean component can have before [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] stops (also see ''interactive'' below). Imaging is an iterative process, and to set the threshold and number of iterations, it is usually wise to clean interactively in the first instance, stopping when spurious emission from sidelobes (arising from gain errors) dominates the residual emission in the field. Here, we have set the threshold level to zero and let the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] task define an appropriate threshold. The number of iterations should then be set high enough to reach the threshold found by tclean.
* ''gridder='standard' '': The standard tclean gridder is sufficient for our purposes, since we are not combining multiple pointings from a mosaic or try to perform widefield imaging in an extended configuration.
* ''interactive=True '': Very often, particularly when one is exploring how a source appears for the first time, it can be valuable to interact with the cleaning process. If True, ''interactive'' causes a [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.viewer.html viewer] window to appear. One can then set clean regions, restricting where [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] searches for clean components, as well as monitor the cleaning process. A standard procedure is to set a large value for ''niter'', and stop the cleaning when it visually appears to be approaching the noise level. This procedure also allows one to change the cleaning region, in cases when low-level intensity becomes visible as the cleaning process proceeds. 
* ''imsize=480,cell='3.4arcsec' '': See the discussion above regarding setting the image size and cell size. If only one value is specified for the parameter, the same value is used in both directions (declination and right ascension).
* ''stokes='IQUV' '': [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will output an image cube containing all: total intensity I, and Stokes Q, U, and V.
* ''deconvolver='multiscale', scales=[0, 6, 18], smallscalebias=0.9 '':  The settings for ''multiscale'' are in units of pixels, with 0 pixels equivalent to the traditional delta-function clean.  The scales here are chosen to provide delta functions and then two logarithmically scaled sizes to fit to the data. The first scale (6 pixels) is chosen to be comparable to the size of the synthesized beam. The ''smallscalebias'' attempts to balance the weight given to larger scales, which often have more flux density, and the smaller scales, which often are brighter. Considerable experimentation is likely to be necessary; one of the authors of this document found that it was useful to clean several rounds with this setting, change to ''multiscale=[]'' and remove much of the smaller scale structure, then return to this setting.
* ''weighting='briggs',robust=0.5 '': 3C75 has diffuse, extended emission that is, at least partially, resolved out by the interferometer even though we are in the most compact VLA configuration. A naturally-weighted image would show large-scale patchiness in the noise. In order to suppress this effect, Briggs weighting is used (intermediate between natural and uniform weighting), with a default robust factor of 0.5 (which corresponds to something between natural and uniform weighting).
* ''pbcor=False '': by default ''pbcor=False'' and a flat-noise image is produced. We can do the primary beam correction later (see below).
* ''savemodel='modelcolumn' '': We recommend here the use of a physical MODEL_DATA scratch column. This will save some time, as it can be faster in the case of complicated gridding to read data from disk instead of doing all of the computations on-the-fly. However, this has the unfortunate side effect of increasing the size of the MS on disk.


[[Image:3C75-tclean-interactive-300iters-CASA6.2.1.png|thumb|Figure 13: After the first approximately 300 iterations of multi-scale mfs clean]]
bandpass(vis='3C75.ms', caltable='3C75.ScB0', field='', solint='inf', refant='ea10', minsnr=3.0, spw='',
                parang = False, gaintable=['3C75.ScG0'], interp=[])


As mentioned above, we can guide the clean process by allowing it to find clean components only within a user-specified region.  When [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] runs in interactive mode, an [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.imview.html imview] window will pop up as shown in Figure 12. '''First, you'll want to navigate to the green box and select "All Polarizations" rather than use the default "This Polarization"'''; this way the cleaning we are about to do will apply to all of the polarizations rather than just the one we are currently viewing. Similarly, select "All channels". To get a more detailed view of the central regions containing the emission, zoom in by first left clicking on the zoom button (leftmost button in third row) and tracing out a rectangle with the left mouse button and double-clicking inside the zoom box you just made. Play with the color scale to bring out the emission better by holding down the middle mouse button and moving it around. To create a clean box (a region within which components may be found), hold down the right mouse button and trace out a rectangle around the source, then double-click inside that rectangle to set it as a box. Note that the clean box must turn white for it to be registered - if the box is not white, it has not been set. Alternatively, you can trace out a more custom shape to better enclose the irregular outline of the radio galaxy jets. To do this, right-click on the closed polygonal icon then trace out a shape by right-clicking where you want the corners of that shape. Once you have come full circle, the shape will be traced out in green, with small squares at the corners. Double-click inside this region and the green outline will turn white. You have now set the clean region. If you have made a mistake with your clean box, click on the Erase button, trace out a rectangle around your erroneous region, and double-click inside that rectangle. You can also set multiple clean regions.
applycal(vis='3C75.ms', gaintable=['3C75.ScG0','3C75.ScB0'], spw='', applymode='calflagstrict', parang=False)
</source>
The ''CORRECTED_DATA'' column of the MS now contains the self-calibrated visibilities which will be used by next execution of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] step will report a number of solutions with insufficient SNR. By default, with parameter ''applymode='calflag','' data with no good solutions will be flagged by [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] which may or may not be a good thing. You can control the action of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] by changing the value of parameter ''applymode''. Setting ''applymode='calflagstrict' ''will be more stringent about flagging data points without valid calibration, while ''applymode='calonly'  '' will calibrate those with solutions while passing unchanged the data without solutions. You can see ahead of time what applycal will do by executing it with ''applymode='trial' ''which will do the reporting but nothing else. In our example we used '' applymode='calflagstrict' '', but you will notice that the reported flagged fraction has not changed much, only increasing by 0.6%. This is a good thing.


At any stage in the cleaning, you can adjust the number of iterations that [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will do before returning to the GUI (''cycleniter''). This is set to 1000 (see the iterations field in mid-upper left of panel), values from 500 to 1000 later on seem to work. Note that this will override the ''cycleniter'' value that you might had set before starting [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will keep going until it reaches threshold or runs out of cycles (the cycles field to the right of the iterations).
Having applied these gain and bandpass solutions, we will once again image the target measurement set which we now expect to have better gain solutions and consequently produce a better image. We do this by invoking the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] command once again.  
 
[[Image:3C75-tclean-interactive-residuals-CASA6.2.1.png|thumb|Figure 14: Interactive residuals after about 13000 iterations of multi-scale mfs clean]]
When you are happy with the clean regions, press the green circular arrow button on the far right to continue deconvolution. After completing a cycle, a revised image will come up. As the brightest points are removed from the image (cleaned off), fainter emission may show up. You can adjust the clean boxes each cycle, to enclose all real emission. After many cycles, when only noise is left, you can hit the red-and-white stop-sign icon to stop cleaning. Figure 13 shows the interactive viewer panel later in the process, after cleaning about 500 iterations. We have used the polygon tool to add to the clean region, drawing around emission that shows up in the residual image outside of the original clean region. After about 13000 iterations (Figure 14) the residuals were looking good (similar noise level inside and outside of the cleaned mask region). As mentioned before, restarting [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] with different ''multiscale=[...]'' choices can help also. You see that there is a significant amount of residual structure, these are most likely due to calibration errors which we will try to correct for in the next section during self-calibration.
 
Task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] will make several output files, all named with the prefix given as ''imagename''.  These include:
* ''.image'': final restored image(s) with the clean components convolved with a restoring beam and added to the remaining residuals at the end of the imaging process, one for each Taylor Term (.tt0 and .tt1)
* ''.pb.tt0'': effective response of the telescope (the primary beam)
* ''.mask'': areas where [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] has been allowed to search for emission
* ''.model'': sum of all the clean components, which also has been stored as the MODEL_DATA column in the measurement set, one for each Taylor Term (.tt0 and .tt1)
* ''.psf'': dirty beam, which is being deconvolved from the true sky brightness during the clean process, one for each Taylor Term (.tt0, .tt1, .tt2)
* ''.residual'': what is left at the end of the deconvolution process; this is useful to diagnose whether or not to clean more deeply, one for each Taylor Term (.tt0, .tt1)
* ''.sumwt'': a single pixel image containing sum of weights per plane, one for each Taylor Term (.tt0, .tt1, .tt2)
 
{|
|[[Image:3c75-CARTA-multiscale-initialI-CASA6.4.1.png|thumb|Figure 15A: Viewer panel of final restored Stokes I image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialQ-CASA6.4.1.png|thumb|Figure 15B: Viewer panel of final restored Stokes Q image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialU-CASA6.4.1.png|thumb|Figure 15C: Viewer panel of final restored Stokes U image (using viridis colormap, linear scale, 99.9%)]]
|[[Image:3c75-CARTA-multiscale-initialV-CASA6.4.1.png|thumb|Figure 15D: Viewer panel of final restored Stokes V image (using viridis colormap, linear scale, 99.9%)]]
|}
 
After the imaging and deconvolution process has finished, you can use [https://cartavis.org/ CARTA] to look at your image.
 
Take some time to play with the color scale to better emphasize the faint emission and to see the underlying noise patterns. For the figures above we selected the viridis color map, the linear scale function, and the 99.9% data range on the histogram. You can also use the Animators slider/buttons to switch between the four different Stokes parameter images that were computed. If you are unfamiliar with [https://cartavis.org/ CARTA] then take some time to look over its extensive built in documentation and help features. You can find its searchable online manual via the "Help" button at the top or to get more information on a particular widget you can click the corresponding "?" button near it. If you click the Animator tab you'll also notice that [https://cartavis.org/ CARTA] attempts to create total polarization, linear polarization, fractional total polarization, fractional linear polarization, and linear polarization angle images for you. This can be quite convenient, but we'll show how to create these yourself later in this guide.
 
The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] task naturally operates in a flat noise image, i.e., an image where the effective weighting across the field of view is set so that the noise is constant. This is so that the clean threshold has a uniform meaning for the stopping criterion and that the image fed into the minor cycles has uniform noise levels. This means, however, that the image does not take into account the primary beam response fall-off in the edges. In principle, [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] produces primary beam response image, and if we had set parameter ''pbcor=True'' [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] would had saved a primary beam corrected restored image of our target. Since we used ''deconvolver='mtmfs' ''  and ''nterms=2'', the calculation of the primary beam response requires special treatment. To perform wideband primary beam correction, we will use task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.widebandpbcor.html widebandpbcor]. In the future this task will be incorporated into [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean], but until then this separate task needs to be used.
<source lang="python">
# In CASA
widebandpbcor(vis='3C75.ms',imagename='3C75_initial',nterms=2, action='pbcor',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])
</source>
 
The task will produce primary beam corrected images of our target (3C75_initial.pbcor.image.tt0, 3C75_initial.pbcor.image.tt1, 3C75_initial.pbcor.image.alpha, 3C75_initial.pbcor.image.alpha.error). You can open image 3C75_initial.pbcor.image.tt0 in [https://cartavis.org/ CARTA], and compare it to screenshots in Figure 15. You will see noise (and signal) at the edges of the image has indeed increased.
 
== Self-Calibration ==
 
Before we get started with self-calibration, it might be good to check whether we need to perform additional flagging on the target data. Since we have established an image model in the previous section, we can use it to look at the residuals by dividing out the model. We can make a similar plot to Figure 11 above, however, we will divide the image model that was created. The division will help us to see low level interfrence we might not otherwise notice by just looking at the data column. Since we performed full-polarization imaging, we can also do the same to the cross-hand data RL,LR. Figures 16A & B shows example plots. You should also have a look at time plotted against amplitude and frequency against amplitude to see if there are any obvious times of interference.


<source lang="python">
<source lang="python">
# In CASA
#In CASA
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
tclean(vis='3C75.ms',
       ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RR',
      field="3C75",
      plotfile='plotms_3c75-uvdist_resid_RR.png',avgspw=False,overwrite=True)
      spw="",timerange="",
      uvrange="",antenna="",scan="",observation="",intent="",
      datacolumn="corrected",
      imagename="3C75_selfcal_1",
      imsize=480,
      cell="3.4arcsec",
      phasecenter="",
      stokes="I",
      projection="SIN",
      specmode="mfs",
      reffreq="3.0GHz",
      nchan=-1,
      start="",
      width="",
      outframe="LSRK",
      veltype="radio",
      restfreq=[],
      interpolation="linear",
      gridder="standard",
      mosweight=True,
      cfcache="",
      computepastep=360.0,
      rotatepastep=360.0,
      pblimit=0.0001,
      normtype="flatnoise",
      deconvolver="mtmfs",
      scales=[0, 6, 18],
      nterms=2,
      smallscalebias=0.6,
      restoration=True,
      restoringbeam=[],
       pbcor=False,
      outlierfile="",
      weighting="briggs",
      robust=0.5,
      npixels=0,
      uvtaper=[],
      niter=3500,
      gain=0.1,
      threshold=0.0,
      nsigma=0.0,
      cycleniter=750,
      cyclefactor=1.0,
      restart=True,
      savemodel="modelcolumn",
      calcres=True,
      calcpsf=True,
      parallel=False,
      interactive=True)
</source>
 
Commonly this self-calibration procedure is applied multiple times. In Figures 17A & B you can see a comparison of the shallow Stokes I image before self-calibration and after two self-calibration steps. The first self-calibration round was done as instructed in this section, while the second round was executed with ''solint='120s' '' and new solution tables were created (3C75.ScG1, 3C75.ScB1). You are encouraged to think about what parameters should and should not differ between the round 1 and round 2 self calibration stages, but they are provided below.
 
 
<div class="toccolours mw-collapsible mw-collapsed" style="width:800px; overflow:auto;">
<div style="font-weight:bold;line-height:1.6;">Round 2 of Self Cal</div>
<div class="mw-collapsible-content">
<source lang="python">
#In CASA
gaincal(vis='3C75.ms', caltable='3C75.ScG1', field='', solint='120s', refant='ea10',  
          spw='',minsnr=3.0, gaintype='G', parang=False, calmode='p')


# If you made a mistake above and didn't clean the polarization as well, then this plot will be empty.
bandpass(vis='3C75.ms', caltable='3C75.ScB1', field='', solint='inf', refant='ea10', minsnr=3.0, spw='',
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
                parang = False, gaintable=['3C75.ScG1'], interp=[])
      ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RL',
      plotfile='plotms_3c75-uvdist_resid_RL.png',avgspw=False,overwrite=True)
</source>


{|
applycal(vis='3C75.ms', gaintable=['3C75.ScG1','3C75.ScB1'], spw='', applymode='calflagstrict', parang=False)
| [[Image:plotms-3c75-uvdist-residRR-CASA6.4.1-corr.png|thumb|Figure 16A: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RR correlations.]]
| [[Image:plotms-3c75-uvdist-residRL-CASA6.4.1-corr.png|thumb|Figure 16B: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RL correlations.]]
|}


Since we are seeing a significant amount of weak residual interference, we will take a few steps to reduce these.
#Producing the Figure 17B image
<source lang="python">
tclean(vis='3C75.ms',
# In CASA
       field="3C75",
 
       spw="",timerange="",
# tfcrop
       uvrange="",antenna="",scan="",observation="",intent="",
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RR,ABS_LL',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
       datacolumn="corrected",
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RL,ABS_LR',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
       imagename="3C75_selfcal_2",
# rflag
       imsize=480,
flagdata(vis='3C75.ms',mode='rflag',correlation='RR,LL',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
       cell="3.4arcsec",
flagdata(vis='3C75.ms',mode='rflag',correlation='RL,LR',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
       phasecenter="",
# extend flags
       stokes="I",
flagdata(vis='3C75.ms',mode='extend',flagbackup=False)
       projection="SIN",
</source>
       specmode="mfs",
 
       reffreq="3.0GHz",
This should have gotten rid of the worst remaining outliers, but will leave some residual weak RFI on certain baseline lengths. Since we are not trying to win any records on high dynamic range imaging, this additional flagging should suffice for our dataset. 
       nchan=-1,
 
       start="",
'''In addition to residual RFI, even after calibration using the amplitude calibrator and the phase calibrator, there are likely to be residual phase and/or amplitude errors in the data. Self-calibration uses an existing model, often constructed from imaging the data itself, provided that sufficient visibility data have been obtained.''' This is essentially always the case with data: the system of equations is wildly over-constrained for the number of unknowns. 
       width="",
 
       outframe="LSRK",
More specifically, the observed visibility data on the <math>i</math>-<math>j</math> baseline can be modeled as:
       veltype="radio",
 
       restfreq=[],
<math>
       interpolation="linear",
V'_{ij} = G_i G^*_j V_{ij}
       gridder="standard",
</math>
       mosweight=True,
 
       cfcache="",
where <math>G_i</math> is the complex gain for the <math>i^{\mathrm{th}}</math> antenna and <math>V_{ij}</math> is the true visibility.  For an array of <math>N</math> antennas, at any given instant, there are <math>{N(N-1) \over 2}</math> visibility data, but only <math>N</math> gain factors. For an array with a reasonable number of antennas, <math>N</math> >~ 8, solutions to this set of coupled equations converge quickly. There is some discussion in the old CASA Reference Manual on [http://casa.nrao.edu/docs/cookbook/casa_cookbook006.html#section%3Aim.selfcal self calibration] (see Section 5.11), but more detailed discussion can be found in lectures on [https://science.nrao.edu/facilities/alma/naasc-workshops/nrao-cd-stsci/cde_selfcal.pdf Self-calibration] given at NRAO community days.
       computepastep=360.0,
 
       rotatepastep=360.0,
In self-calibrating data, it is useful to keep in mind the structure of a Measurement Set. There are three columns of interest for an MS: the DATA column, the MODEL column, and the CORRECTED_DATA column. In normal usage, as part of the initial split, the CORRECTED_DATA column is set equal to the DATA column. The self-calibration procedure is then:
       pblimit=0.0001,
 
       normtype="flatnoise",
* Produce an image ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]) using the CORRECTED_DATA column.
       deconvolver="mtmfs",
* Derive a series of gain corrections ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]) by comparing the DATA columns and the Fourier transform of the image, which is stored in the MODEL column. These corrections are stored in an external table.
       scales=[0, 6, 18],
** Optionally, we can also derive a bandpass correction&mdash;which is also referred to as bandpass self calibration&mdash;to correct for global amplitude errors.
       nterms=2,
* Apply these corrections ([https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal]) to the DATA column to form a new CORRECTED_DATA column ''overwriting'' the previous contents of CORRECTED_DATA.
       smallscalebias=0.6,
 
       restoration=True,
The following example begins with the standard data set, 3C75.ms (resulting from the steps above). We have previously generated an IQUV multiscale image cube. We discard it for this step and create a new Stokes I image, which we will use to generate a series of gain corrections (phase only self-calibration) that will be stored in 3C75.ScG0. With this solution, we then perform bandpass self-calibration to remove any amplitude slope that might be present. Next, we apply the derived phase and amplitude corrections to the data to form a set of self-calibrated data, and then re-image the dataset (3C75_selfcal.image). For the purpose of self-calibration, note that in the clean before the self-calibration, it is important that we only use the Stokes I model so that any cleaned polarization does not affect the gaincal. We first use [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.delmod.html?highlight=delmod# delmod] on the MS to get rid of the previous polarized model, and run [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] to generate Stokes I-only image. In principle, it is possible to use the previous image cube and extract the Stokes I model using the CASA toolkit and have [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] fill the model column appropriately. For simplicity, we just re-image with [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] selecting only Stokes I.
       restoringbeam=[],
<source lang="python">
       pbcor=False,
#In CASA
       outlierfile="",
delmod('3C75.ms')
       weighting="briggs",
 
       robust=0.5,
tclean(vis='3C75.ms',
       npixels=0,
       field="3C75",
       uvtaper=[],
       spw="",timerange="",
       niter=3500,
       uvrange="",antenna="",scan="",observation="",intent="",
       gain=0.1,
       datacolumn="data",
       threshold=0.0,
       imagename="3C75_initial_I",
       nsigma=0.0,
       imsize=480,
       cycleniter=750,
       cell="3.4arcsec",
       cyclefactor=1.0,
       phasecenter="",
       restart=True,
       stokes="I",
       savemodel="modelcolumn",
       projection="SIN",
       calcres=True,
       specmode="mfs",
       calcpsf=True,
       reffreq="3.0GHz",
       parallel=False,
       nchan=-1,
       interactive=True)
       start="",
</source>
       width="",
 
       outframe="LSRK",
Note that only the gaincal call used the 120s solint. The bandpass of the VLA antennas are generally stable in time so it is relatively rare to have a case for using a time variable bandpass. Also note that the new solution interval is not the only difference between these round 2 calls. Since our previous tclean call (imagename="3C75_selfcal_1") also used savemodel='modelcolumn' these calls will be making use of an improved model.
       veltype="radio",
</div></div>
       restfreq=[],
 
       interpolation="linear",
{|
       gridder="standard",
| [[Image:3c75-initial_I-CASA6.4.1.png|thumb|Figure 17A: Shallow Stokes I image before self-calibration.]]
       mosweight=True,
| [[Image:3c75-selfcal_2-CASA6.4.1.png|thumb|Figure 17B: Stokes I image after two rounds of self-calibration.]]
       cfcache="",
|}
       computepastep=360.0,
 
       rotatepastep=360.0,
The number of iterations is determined by a combination of the data quality, the number of antennas in the array, the structure of the source, the extent to which the original self-calibration assumptions are valid, and the user's patience. A not uncommon limitation for moderately high dynamic range imaging is that there may be ''baseline-based'' factors that modify the true visibility. If the corruptions to the true visibility cannot be modeled as antenna-based self-calibration won't help.
       pblimit=0.0001,
 
       normtype="flatnoise",
Self-calibration requires experimentation. Do not be afraid to remove an image, or even a set of gain corrections, change something and try again. Having said that, here are several guidelines to consider:
       deconvolver="mtmfs",
 
       scales=[0, 6, 18],
* Bookkeeping is important! Suppose one conducts 9 iterations of self-calibration. Will it be possible to remember one month later (or maybe even one week later!) which set of gain corrections and images are which? In the example above, the descriptor'' 'selfcal_1' ''is attached to various files to help keep straight what is what. Successive iterations of self-cal could then be'' 'selfcal_2' '','' 'selfcal_3' '', etc.
       nterms=2,
 
       smallscalebias=0.6,
* Care is required in setting ''imagename''. If one has an image that already exists, CASA will continue cleaning it (if it can), which is almost certainly not what one wants during self-calibration. Rather, use a unique ''imagename'' for each pass of self-calibration.
       restoration=True,
 
       restoringbeam=[],
* A common metric for self-calibration is whether the ''dynamic range'' (= peak flux density/rms) of the image has improved. An improvement of 10% is quite acceptable.
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=3500,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=750,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)
</source>
As discussed, this [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] call will ignore the polarized structure. You should not clean very deeply at this point. You want to be sure to capture as much of the source's total flux density as possible, but not include low level questionable features or sub-structures (ripples) that might be due to calibration or deconvolution artifacts. We modified the two parameters controlling [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]'s minor and major cycles to the following values ''cycleniter=750'' and ''niter=3500'' to reflect this, but you may find that you don't even need 3500 iterations for this first [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] pass.


If you are happy with the new image, perform the following self-calibration steps:
* Be careful when making images and setting clean regions or masks; self-calibration assumes that the model is perfect. If one cleans a noise bump, self-calibration will quite happily try to adjust the gains so that the CORRECTED_DATA describe a source at the location of the noise bump. It is far better to exclude some features of a source, or a weak source, from initial cleaning and conduct another round of self-calibration than to create an artificial source. If a real source is excluded from initial cleaning, it will continue to be present in subsequent iterations of self-calibration; if it's not a real source, one probably isn't interested in it anyway.
<source lang="python">
#In CASA
gaincal(vis='3C75.ms', caltable='3C75.ScG0', field='', solint='inf', refant='ea10',  
          spw='',minsnr=3.0, gaintype='G', parang=False, calmode='p')


bandpass(vis='3C75.ms', caltable='3C75.ScB0', field='', solint='inf', refant='ea10', minsnr=3.0, spw='',
* Start self-calibration with phase-only solutions (parameter ''calmode='p' ''in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]). As discussed in the [http://adsabs.harvard.edu/abs/1989ASPC....6..287P High Dynamic Range Imaging] lecture, a phase error of 20 deg is as bad as an amplitude error of 10%.
                parang = False, gaintable=['3C75.ScG0'], interp=[])
 
* In initial rounds of self-calibration, consider solution intervals longer than the nominal sampling time (parameter ''solint'' in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]) and/or lower signal-to-noise ratio thresholds (parameter ''minsnr'' in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]). Depending upon the frequency and configuration and fidelity of the model image, it can be quite reasonable to start with ''solint='30s' ''or'' solint='60s' ''and/or ''minsnr=3''. One may also want to consider specifying a uvrange, if, for example, the field has structure on large scales (small <math>u</math>-<math>v</math>) that is not well represented by the current image.
 
* The task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] will flag data with no good calibration solutions. During the initial self-calibration steps, this flagging may be excessive. If so, one can restore the flags to the state right before running applycal by using the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagmanager.html flagmanager].
 
* You can track the agreement between the DATA, CORRECTED_DATA, and MODEL in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms]. The options in Axes tab allows one to select which column is to be plotted. If the MODEL agrees well with the CORRECTED_DATA, one can use shorter solint and/or higher minsnr values.
 
* You should consider examining the solutions from [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] by using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] in order to assure that the corrections are sensible. Smoothly varying phases are good, jumps are usually not.  (However, because the phases are often plotted &plusmn;180 degrees, there can be apparent jumps if the phases are very near &#043;180 deg or &minus;180 deg.)


applycal(vis='3C75.ms', gaintable=['3C75.ScG0','3C75.ScB0'], spw='', applymode='calflagstrict', parang=False)
== Final Polarization Images ==
</source>
The ''CORRECTED_DATA'' column of the MS now contains the self-calibrated visibilities which will be used by next execution of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. The [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] step will report a number of solutions with insufficient SNR. By default, with parameter ''applymode='calflag','' data with no good solutions will be flagged by [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] which may or may not be a good thing. You can control the action of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] by changing the value of parameter ''applymode''. Setting ''applymode='calflagstrict' ''will be more stringent about flagging data points without valid calibration, while ''applymode='calonly'  '' will calibrate those with solutions while passing unchanged the data without solutions. You can see ahead of time what applycal will do by executing it with ''applymode='trial' ''which will do the reporting but nothing else. In our example we used '' applymode='calflagstrict' '', but you will notice that the reported flagged fraction has not changed much, only increasing by 0.6%. This is a good thing.


Having applied these gain and bandpass solutions, we will once again image the target measurement set which we now expect to have better gain solutions and consequently produce a better image. We do this by invoking the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] command once again.  
At this point, satisfied with the results of self-calibration, it might be a good idea to recalculate the visibility weights since some additional flagging was performed. After this, we get right to full-polarization imaging. We also suspect that there is a bright source outside of the masked field causing some imaging artifacts due to not being cleaned. We thus set the parameter ''pbmask'' value to 0.0 in order to disable masking of areas beyond the primary beam, and make the image larger to incorporate the bright source into our model in this tclean execution.


<source lang="python">
<source lang="python">
#In CASA
# In CASA
statwt(vis='3C75.ms', minsamp=8, datacolumn='corrected', flagbackup=True)
 
tclean(vis='3C75.ms',
tclean(vis='3C75.ms',
       field="3C75",
       field="3C75",
Line 1,307: Line 1,227:
       uvrange="",antenna="",scan="",observation="",intent="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="corrected",
       datacolumn="corrected",
       imagename="3C75_selfcal_1",
       imagename="3C75_final_large",
       imsize=480,
       imsize=800,
       cell="3.4arcsec",
       cell="3.4arcsec",
       phasecenter="",
       phasecenter="",
       stokes="I",
       stokes="IQUV",
       projection="SIN",
       projection="SIN",
       specmode="mfs",
       specmode="mfs",
Line 1,327: Line 1,247:
       computepastep=360.0,
       computepastep=360.0,
       rotatepastep=360.0,
       rotatepastep=360.0,
       pblimit=0.0001,
       pblimit=-0.0001,
      pbmask=0.0,
       normtype="flatnoise",
       normtype="flatnoise",
       deconvolver="mtmfs",
       deconvolver="mtmfs",
Line 1,341: Line 1,262:
       npixels=0,
       npixels=0,
       uvtaper=[],
       uvtaper=[],
       niter=3500,
       niter=20000,
       gain=0.1,
       gain=0.1,
       threshold=0.0,
       threshold=0.0,
       nsigma=0.0,
       nsigma=0.0,
       cycleniter=750,
       cycleniter=1000,
       cyclefactor=1.0,
       cyclefactor=1.0,
       restart=True,
       restart=True,
Line 1,355: Line 1,276:
</source>
</source>


Commonly this self-calibration procedure is applied multiple times. In Figures 17A & B you can see a comparison of the shallow Stokes I image before self-calibration and after two self-calibration steps. The first self-calibration round was done as instructed in this section, while the second round was executed with ''solint='120s' '' and new solution tables were created (3C75.ScG1, 3C75.ScB1).
The final restored Stokes I,Q,U, and V images are shown in Figures 18A&ndash;D. We've set the color scale to match between the images. Note that there is still a star like pattern in the residuals which are artifacts most likely due to the multi-scale multi-term multi-frequency synthesis. You can try on your own to improve upon the shown images by re-imaging and choosing a different set of multi-scale parameters that better match the scales found in the extended structure of 3C 75. Another issue to point out is looking at the Stokes V image. We do not expect a significant amount of Stokes V emission from this object, the emission you are seeing in Stokes V is most likely an effect of incorrectly solving for polarization leakages in the primary beam. In the above calibration we have only addressed leakage between the two polarization referring to the phase center. The extended beam itself, however, shows leakage which manifests itself spatially. The extended polarized emission we see in the Stokes Q and U images is not corrected for beam polarization during imaging. This, in turn, contains errors leading to polarization and de-polarization effects and causes changes to the polarization angle which increases the further away one gets from the beam center. Additionally, the two polarization beams do not sit on top of each other but are slightly offset, introducing a polarization squint. For correct and accurate polarization imaging, these two effects have to be taken into account. Imaging algorithms to address beam polarization are currently under development and will be discussed in this guide when they become available to the general user.
 
{|
{|
  | [[Image:3c75-initial_I-CASA6.4.1.png|thumb|Figure 17A: Shallow Stokes I image before self-calibration.]]
  | [[Image:3C75-final-I-CASA6.4.1.png|thumb|Figure 18A: Viewer panel of final restored Stokes I image.]]
  | [[Image:3c75-selfcal_2-CASA6.4.1.png|thumb|Figure 17B: Stokes I image after two rounds of self-calibration.]]
| [[Image:3C75-final-Q-CASA6.4.1.png|thumb|Figure 18B: Viewer panel of final restored Stokes Q image.]]
|}  
  | [[Image:3C75-final-U-CASA6.4.1.png|thumb|Figure 18C: Viewer panel of final restored Stokes U image.]]
| [[Image:3C75-final-V-CASA6.4.1.png|thumb|Figure 18D: Viewer panel of final restored Stokes V image.]]
|}


The number of iterations is determined by a combination of the data quality, the number of antennas in the array, the structure of the source, the extent to which the original self-calibration assumptions are valid, and the user's patience. With reference to the original self-calibration equation above, if the observed visibility data cannot be modeled well by this equation, no amount of self-calibration will help. A not uncommon limitation for moderately high dynamic range imaging is that there may be ''baseline-based'' factors that modify the true visibility. If the corruptions to the true visibility cannot be modeled as antenna-based, as they are above, self-calibration won't help.
Note, that these images are not yet primary beam corrected and are displayed on log scaling. You should play with the color scaling as well as the bias/contrast widget in [https://cartavis.org/ CARTA] to better see the faint emission.


Self-calibration requires experimentation. Do not be afraid to remove an image, or even a set of gain corrections, change something and try again.  Having said that, here are several guidelines to consider:
=== Spectral & Polarization Maps ===


* Bookkeeping is important! Suppose one conducts 9 iterations of self-calibration. Will it be possible to remember one month later (or maybe even one week later!) which set of gain corrections and images are which? In the example above, the descriptor'' 'selfcal_1' ''is attached to various files to help keep straight what is what. Successive iterations of self-cal could then be'' 'selfcal_2' '','' 'selfcal_3' '', etc.
Note: If you are using [https://cartavis.org/ CARTA] then several of the next steps are actually unnecessary. If supplied a proper IQUV image [https://cartavis.org/ CARTA] will compute polarization intensity, linear polarization, fractional polarization intensity, fractional linear polarization intensity, and polarization angle maps for you. We show the steps one would have to take to manually create some of the images below for completeness. When possible the Figures shown will be using values/images that are generated soley by [https://cartavis.org/ CARTA] itself. You are encouraged though to still manually create your own set of images and then overlay them with the [https://cartavis.org/ CARTA] generated images to see that they match.


* Care is required in setting ''imagename''. If one has an image that already exists, CASA will continue cleaning it (if it can), which is almost certainly not what one wants during self-calibration. Rather, use a unique ''imagename'' for each pass of self-calibration.
If you want to obtain a reasonable map of the in-band spectral index, like the one shown in Fig. 19A, we can compute it with the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.widebandpbcor.html widebandpbcor]. As demonstrated earlier, the task can also correct the images for the telescope's primary beam response; this correction will make the images science ready. Parameter ''action='pbcor' '' will perform both actions (correct for the primary beam and calculate spectral index map) while parameter ''threshold'' sets minimum flux density above which the spectral index is calculated (this will allow us to mask all the noise regions).


* A common metric for self-calibration is whether the ''dynamic range'' (= peak flux density/rms) of the image has improved. An improvement of 10% is quite acceptable.
<source lang="python">
 
# In CASA
* Be careful when making images and setting clean regions or masks; self-calibration assumes that the model is perfect. If one cleans a noise bump, self-calibration will quite happily try to adjust the gains so that the CORRECTED_DATA describe a source at the location of the noise bump. It is far better to exclude some features of a source, or a weak source, from initial cleaning and conduct another round of self-calibration than to create an artificial source. If a real source is excluded from initial cleaning, it will continue to be present in subsequent iterations of self-calibration; if it's not a real source, one probably isn't interested in it anyway.
widebandpbcor(vis='3C75.ms', imagename='3C75_final_large', nterms=2, threshold='1.0mJy/beam', action='pbcor',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])
</source>


* Start self-calibration with phase-only solutions (parameter ''calmode='p' ''in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]). As discussed in the [http://adsabs.harvard.edu/abs/1989ASPC....6..287P High Dynamic Range Imaging] lecture, a phase error of 20 deg is as bad as an amplitude error of 10%.


* In initial rounds of self-calibration, consider solution intervals longer than the nominal sampling time (parameter ''solint'' in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]) and/or lower signal-to-noise ratio thresholds (parameter ''minsnr'' in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal]). Depending upon the frequency and configuration and fidelity of the model image, it can be quite reasonable to start with ''solint='30s' ''or'' solint='60s' ''and/or ''minsnr=3''. One may also want to consider specifying a uvrange, if, for example, the field has structure on large scales (small <math>u</math>-<math>v</math>) that is not well represented by the current image.
For further study of polarization properties, you might want to convert the Stokes images into something more useful for scientific analysis. We will use CASA to calculate polarization intensity, <math>\sqrt{Q^2 + U^2 + V^2}</math>, and polarization angle, <math>{atan2 (U,Q) \over 2}</math>, maps from the final Stokes I,Q,U,V images. You can then look at those with [https://cartavis.org/ CARTA]. For example, Figure 19B shows the polarization intensity image. Since we've yet to apply any mask, the polarization angle image made in the next step will also contain values from low signal-to-noise data.


* The task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.applycal.html applycal] will flag data with no good calibration solutions. During the initial self-calibration steps, this flagging may be excessive. If so, one can restore the flags to the state right before running applycal by using the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.flagging.flagmanager.html flagmanager].
<source lang="python">
# In CASA


* You can track the agreement between the DATA, CORRECTED_DATA, and MODEL in [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms]. The options in Axes tab allows one to select which column is to be plotted. If the MODEL agrees well with the CORRECTED_DATA, one can use shorter solint and/or higher minsnr values.
# Obtain image for the polarization intensity
immath(outfile='3C75_final.poli',mode='poli',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
# Obtain image for the polarization angle
immath(outfile='3C75_final.pola',mode='pola',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
</source>


* You should consider examining the solutions from [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.calibration.gaincal.html gaincal] by using [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.visualization.plotms.html plotms] in order to assure that the corrections are sensible. Smoothly varying phases are good, jumps are usually not. (However, because the phases are often plotted &plusmn;180 degrees, there can be apparent jumps if the phases are very near &#043;180 deg or &minus;180 deg.)
{|
| [[Image:3C75-final-spindx-CASA6.4.1.png|thumb|Figure 19A: CASA Computed spectral index map.]]
| [[Image:3C75-final-Ptot-casa6.4.1.png|thumb|Figure 19B: CARTA Computed polarization intensity image.]]
| [[Image:3C75-final-PAng-CASA6.4.1.png|thumb|Figure 19C: CARTA Computed polarized angles (vectors) superposed on the Stokes I raster image plane. We've selected an intensity threshold within CARTA to exclude low S/N points.]]
|}


== Final Polarization Images ==
Note that for calculations of the polarization intensity and angle images you may &mdash; but do not need to &mdash; use primary beam corrected images; your results will be the same. This is because the primary beam correction cancels out in the equations for these two polarization quantities. If you want to visualize the polarization vectors on top of the Stokes I image, we need to add a mask for the low noise values.  
 
At this point, satisfied with the results of self-calibration, it might be a good idea to recalculate the visibility weights since some additional flagging was performed. After this, we get right to full-polarization imaging. We also suspect that there is a bright source outside of the masked field causing some imaging artifacts due to not being cleaned. We thus set the parameter ''pbmask'' value to 0.0 in order to disable masking of areas beyond the primary beam, and make the image larger to incorporate the bright source into our model in this tclean execution.


<source lang="python">
<source lang="python">
# In CASA
# In CASA
statwt(vis='3C75.ms', minsamp=8, datacolumn='corrected', flagbackup=True)
!cp -r '3C75_final.poli' polimg
 
imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.Q.image',stokes='Q')
imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.U.image',stokes='U')
 
subimPI='polimg'
ia.open(subimPI)
ia.calcmask(mask=subimPI+'>5e-4',name='mymask')
ia.done()
 
ia.open('3C75_final.Q.image')
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
ia.maskhandler('set','polithreshmask')
ia.done()


tclean(vis='3C75.ms',
ia.open('3C75_final.U.image')
      field="3C75",
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
      spw="",timerange="",
ia.maskhandler('set','polithreshmask')
      uvrange="",antenna="",scan="",observation="",intent="",
ia.done()
      datacolumn="corrected",
 
      imagename="3C75_final_large",
immath(imagename=['3C75_final.Q.image', '3C75_final.U.image'], mode='pola', outfile='3C75_final.pola.masked')
      imsize=800,
</source>
      cell="3.4arcsec",
These steps take the polarized intensity image calculated above (Figure 19B) and create a mask using a polarization intensity threshold of 5e-4 Jy/beam. This mask is then applied to the Q and U images from the image cube that was generated above. Then a new polarization angle image is calculated from the Q & U image planes, applying the mask created from the polarization intensity image. Finally, we can load the Stokes I as raster image into [https://cartavis.org/ CARTA] and add the polarization angle as vectors. You can do this by matching the final IQUV image, 3C75_final_large.image.tt0, and the newly created polarization angle image in WCS space by clicking the "XY" under the "Matching" column of the Image List widget. Then open the Vector Overlay Configuration widget to create the vectors. You can compare the vectors calculated with immath to the ones that [https://cartavis.org/ CARTA] generates for you. You may notice that there are some vectors that appear to disagree with each other. If so, it is likely caused by the pixel averaging being done within [https://cartavis.org/ CARTA], which you can toggle off to confirm. Figure 19C shows the resulting image. One can clearly see that the linear polarization angle follows perpendicular to the extended structure. This indicates that the magnetic field lines are oriented along the extended structure, perpendicular to the linear polarization angles.
      phasecenter="",
 
      stokes="IQUV",
=== Rotation Measures ===
      projection="SIN",
 
      specmode="mfs",
The plane of polarization of light is rotated by the magnetic fields present in the intervening plasma. The total rotation to the plane of polarization of light between the source and the user is called Faraday Rotation. Prior to the wide bandwidth capabilities, these rotation measures were computed by fitting a line to the polarization position angle as a function of the square of the wavelength of measurement. The slope of the resulting fit was deemed to be the RM of the source while the intercept would give the true polarization position angle of the source. With the wide bandwidths, it is now possible to determine the rotation measure of the source using the naive fitting approach by making images per spectral window in IQUV and fitting the data (polarization position angle vs lambda^2) with a line.  
      reffreq="3.0GHz",
 
      nchan=-1,
We show how to produce such images with one last [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] call using the following parameters. Since this is the last tclean call you'll need to perform to complete the guide we'll give you the opportunity to see if you can construct it yourself (Tip: using 'inp tclean' in CASA to see the inputs for the command will be quite useful).  
      start="",
Remember two key differences in this call as compared to the previous:
      width="",
 
      outframe="LSRK",
- You are making a cube with one spectral window per plane
      veltype="radio",
      restfreq=[],
      interpolation="linear",
      gridder="standard",
      mosweight=True,
      cfcache="",
      computepastep=360.0,
      rotatepastep=360.0,
      pblimit=-0.0001,
      pbmask=0.0,
      normtype="flatnoise",
      deconvolver="mtmfs",
      scales=[0, 6, 18],
      nterms=2,
      smallscalebias=0.6,
      restoration=True,
      restoringbeam=[],
      pbcor=False,
      outlierfile="",
      weighting="briggs",
      robust=0.5,
      npixels=0,
      uvtaper=[],
      niter=20000,
      gain=0.1,
      threshold=0.0,
      nsigma=0.0,
      cycleniter=1000,
      cyclefactor=1.0,
      restart=True,
      savemodel="modelcolumn",
      calcres=True,
      calcpsf=True,
      parallel=False,
      interactive=True)
</source>


The final restored Stokes I,Q,U, and V images are shown in Figures 18A&ndash;D. We've set the color scale to match between the images. Note that there is still a star like pattern in the residuals which are artifacts most likely due to the multi-scale multi-term multi-frequency synthesis. You can try on your own to improve upon the shown images by re-imaging and choosing a different set of multi-scale parameters that better match the scales found in the extended structure of 3C 75. Another issue to point out is looking at the Stokes V image. We do not expect a significant amount of Stokes V emission from this object, the emission you are seeing in Stokes V is most likely an effect of incorrectly solving for polarization leakages in the primary beam. In the above calibration we have only addressed leakage between the two polarization referring to the phase center. The extended beam itself, however, shows leakage which manifests itself spatially. The extended polarized emission we see in the Stokes Q and U images is not corrected for beam polarization during imaging. This, in turn, contains errors leading to polarization and de-polarization effects and causes changes to the polarization angle which increases the further away one gets from the beam center. Additionally, the two polarization beams do not sit on top of each other but are slightly offset, introducing a polarization squint. For correct and accurate polarization imaging, these two effects have to be taken into account. Imaging algorithms to address beam polarization are currently under development and will be discussed in this guide when they become available to the general user. 
- You already know where the emission is (i.e. you have a mask)
 
{|
| [[Image:3C75-final-I-CASA6.4.1.png|thumb|Figure 18A: Viewer panel of final restored Stokes I image.]]
| [[Image:3C75-final-Q-CASA6.4.1.png|thumb|Figure 18B: Viewer panel of final restored Stokes Q image.]]
| [[Image:3C75-final-U-CASA6.4.1.png|thumb|Figure 18C: Viewer panel of final restored Stokes U image.]]
| [[Image:3C75-final-V-CASA6.4.1.png|thumb|Figure 18D: Viewer panel of final restored Stokes V image.]]
|}
 
Note, that these images are not yet primary beam corrected and are displayed on log scaling. You should play with the color scaling as well as the bias/contrast widget in [https://cartavis.org/ CARTA] to better see the faint emission.


=== Spectral & Polarization Maps ===
Note: If you are using [https://cartavis.org/ CARTA] then several of the next steps are actually unnecessary. If supplied a proper IQUV image [https://cartavis.org/ CARTA] will compute polarization intensity, linear polarization, fractional polarization intensity, fractional linear polarization intensity, and polarization angle maps for you. We show the steps one would have to take to manually create some of the images below for completeness. When possible the Figures shown will be using values/images that are generated soley by [https://cartavis.org/ CARTA] itself. You are encouraged though to still manually create your own set of images and then overlay them with the [https://cartavis.org/ CARTA] generated images to see that they match.
If you want to obtain a reasonable map of the in-band spectral index, like the one shown in Fig. 19A, we can compute it with the task [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.widebandpbcor.html widebandpbcor]. As demonstrated earlier, the task can also correct the images for the telescope's primary beam response; this correction will make the images science ready. Parameter ''action='pbcor' '' will perform both actions (correct for the primary beam and calculate spectral index map) while parameter ''threshold'' sets minimum flux density above which the spectral index is calculated (this will allow us to mask all the noise regions).


<div class="toccolours mw-collapsible mw-collapsed" style="width:1000px; overflow:auto;">
<div style="font-weight:bold;line-height:1.6;">The final tclean</div>
<div class="mw-collapsible-content">
<source lang="python">
<source lang="python">
# In CASA
# In CASA
widebandpbcor(vis='3C75.ms', imagename='3C75_final_large', nterms=2, threshold='1.0mJy/beam', action='pbcor',
tclean(vis='3C75.ms',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])
      field="3C75",
</source>
      spw="",timerange="",
 
      uvrange="",antenna="",scan="",observation="",intent="",
 
      datacolumn="corrected",
For further study of polarization properties, you might want to convert the Stokes images into something more useful for scientific analysis. We will use CASA to calculate polarization intensity, <math>\sqrt{Q^2 + U^2 + V^2}</math>, and polarization angle, <math>{atan2 (U,Q) \over 2}</math>, maps from the final Stokes I,Q,U,V images. You can then look at those with [https://cartavis.org/ CARTA]. For example, Figure 19B shows the polarization intensity image. Since we've yet to apply any mask, the polarization angle image made in the next step will also contain values from low signal-to-noise data.
      imagename="3C75_chan8",
 
      imsize=800,
<source lang="python">
      cell="3.4arcsec",
# In CASA
      phasecenter="",
 
      stokes="IQUV",
# Obtain image for the polarization intensity
      projection="SIN",
immath(outfile='3C75_final.poli',mode='poli',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
      specmode="cube",
# Obtain image for the polarization angle
      reffreq="",
immath(outfile='3C75_final.pola',mode='pola',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
      nchan=-1,
</source>
      start="",
 
      width=64,
{|
      outframe="LSRK",
| [[Image:3C75-final-spindx-CASA6.4.1.png|thumb|Figure 19A: CASA Computed spectral index map.]]
      veltype="radio",
| [[Image:3C75-final-Ptot-casa6.4.1.png|thumb|Figure 19B: CARTA Computed polarization intensity image.]]
      restfreq=[],
| [[Image:3C75-final-PAng-CASA6.4.1.png|thumb|Figure 19C: CARTA Computed polarized angles (vectors) superposed on the Stokes I raster image plane. We've selected an intensity threshold within CARTA to exclude low S/N points.]]
      interpolation="linear",
|}
      gridder="standard",
 
      mosweight=True,
Note that for calculations of the polarization intensity and angle images you may &mdash; but do not need to &mdash; use primary beam corrected images; your results will be the same. This is because the primary beam correction cancels out in the equations for these two polarization quantities. If you want to visualize the polarization vectors on top of the Stokes I image, we need to add a mask for the low noise values.
      cfcache="",
 
      computepastep=360.0,
<source lang="python">
      rotatepastep=360.0,
# In CASA
      pblimit=-0.0001,
!cp -r '3C75_final.poli' polimg
      pbmask=0.0,
 
      mask='3C75_final_large.mask',
imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.Q.image',stokes='Q')
      normtype="flatnoise",
imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.U.image',stokes='U')
      deconvolver="multiscale",
 
      scales=[0, 6, 18],
subimPI='polimg'
      nterms=1,
ia.open(subimPI)
      smallscalebias=0.6,
ia.calcmask(mask=subimPI+'>5e-4',name='mymask')
      restoration=True,
ia.done()
      restoringbeam=[],
      pbcor=False,
      outlierfile="",
      weighting="briggs",
      robust=0.5,
      npixels=0,
      uvtaper=[],
      niter=20000,
      gain=0.1,
      threshold=0.0,
      nsigma=0.0,
      cycleniter=1000,
      cyclefactor=1.0,
      restart=True,
      savemodel="none",
      calcres=True,
      calcpsf=True,
      parallel=False,
      interactive=False)
</source>
Here's the differences as compared to the previous tclean:


ia.open('3C75_final.Q.image')
* specmode="cube": This tells tclean we want a cube (i.e. separate images for separate frequencies) instead of a continuum image (specmode='mfs')
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
ia.maskhandler('set','polithreshmask')
ia.done()


ia.open('3C75_final.U.image')
* width=64: This tells tclean how wide in number of channels (i.e. frequency) each plane of the cube should be. We wanted one plane per spectral window and our spectral windows are 64 channels wide each.
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
 
ia.maskhandler('set','polithreshmask')
* mask='3C75_final_large.mask': We created this in our previous tclean call by interactively drawing it in the GUI. We call it again here to reuse it.
ia.done()
 
* deconvolver="multiscale": Previously we used 'mtmfs' which stands for Multi-Term (Multi-scale) Multi-Frequency Synthesis. Since we are making per spectral window images this time were are no longer in the wideband regime and therefore drop the multi-frequency aspect.


immath(imagename=['3C75_final.Q.image', '3C75_final.U.image'], mode='pola', outfile='3C75_final.pola.masked')
* nterms=1: Same reasoning as the change in deconvolver. Since we are making per spectral window images we need not worry about the spectral index of each image (i.e. we can assume each spectral window has a flat spectrum).
</source>
These steps take the polarized intensity image calculated above (Figure 19B) and create a mask using a polarization intensity threshold of 5e-4 Jy/beam. This mask is then applied to the Q and U images from the image cube that was generated above. Then a new polarization angle image is calculated from the Q & U image planes, applying the mask created from the polarization intensity image. Finally, we can load the Stokes I as raster image into [https://cartavis.org/ CARTA] and add the polarization angle as vectors. You can do this by matching the final IQUV image, 3C75_final_large.image.tt0, and the newly created polarization angle image in WCS space by clicking the "XY" under the "Matching" column of the Image List widget. Then open the Vector Overlay Configuration widget to create the vectors. You can compare the vectors calculated with immath to the ones that [https://cartavis.org/ CARTA] generates for you. You may notice that there are some vectors that appear to disagree with each other. If so, it is likely caused by the pixel averaging being done within [https://cartavis.org/ CARTA], which you can toggle off to confirm. Figure 19C shows the resulting image. One can clearly see that the linear polarization angle follows perpendicular to the extended structure. This indicates that the magnetic field lines are oriented along the extended structure, perpendicular to the linear polarization angles.


=== Rotation Measures ===
* savemodel="none": This change is not strictly needed, but since we have no intention of changing our model with this run of tclean it is good form to make sure this is set. It would be a shame to overwrite your model this late into the process only to decide later that you wanted it for some reason.


The plane of polarization of light is rotated by the magnetic fields present in the intervening plasma. The total rotation to the plane of polarization of light between the source and the user is called Faraday Rotation. Prior to the wide bandwidth capabilities, these rotation measures were computed by fitting a line to the polarization position angle as a function of the square of the wavelength of measurement. The slope of the resulting fit was deemed to be the RM of the source while the intercept would give the true polarization position angle of the source. With the wide bandwidths, it is now possible to determine the rotation measure of the source using the naive fitting approach by making images per spectral window in IQUV and fitting the data (polarization position angle vs lambda^2) with a line.  
* interactive=False: Since we already have a mask we are happy with from the previous run there is no use in having tclean's GUI pop up again.
</div></div>


To produce an image cube with 8 channels, each image is using 128 MHz of bandwidth, we call [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] with the following parameters. Here we take advantage of the imaging mask we generated for the final image above, so we don't need to do an interactive clean.
<source lang="python">
# In CASA
tclean(vis='3C75.ms',
      field="3C75",
      spw="",timerange="",
      uvrange="",antenna="",scan="",observation="",intent="",
      datacolumn="corrected",
      imagename="3C75_chan8",
      imsize=800,
      cell="3.4arcsec",
      phasecenter="",
      stokes="IQUV",
      projection="SIN",
      specmode="cube",
      reffreq="",
      nchan=-1,
      start="",
      width=64,
      outframe="LSRK",
      veltype="radio",
      restfreq=[],
      interpolation="linear",
      gridder="standard",
      mosweight=True,
      cfcache="",
      computepastep=360.0,
      rotatepastep=360.0,
      pblimit=-0.0001,
      pbmask=0.0,
      mask='3C75_final_large.mask',
      normtype="flatnoise",
      deconvolver="multiscale",
      scales=[0, 6, 18],
      nterms=1,
      smallscalebias=0.6,
      restoration=True,
      restoringbeam=[],
      pbcor=False,
      outlierfile="",
      weighting="briggs",
      robust=0.5,
      npixels=0,
      uvtaper=[],
      niter=20000,
      gain=0.1,
      threshold=0.0,
      nsigma=0.0,
      cycleniter=1000,
      cyclefactor=1.0,
      restart=True,
      savemodel="none",
      calcres=True,
      calcpsf=True,
      parallel=False,
      interactive=False)
</source>


Now we use the CASA toolkit to access data for four pixels in the image cube to visualize and fit the rotation measure.  
Now we use the CASA toolkit to access data for four pixels in the image cube to visualize and fit the rotation measure.  
Line 1,734: Line 1,592:
|}
|}


As our source is rather bright, we can derive an IQUV image not just per averaged spectral window as we just did, but rather per channel. To achieve this you can change the above [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] parameter width from 64 to 1, which will result in 512 channels spanning all 8 spectral windows. Note when imaging each channel, the edge channels are flagged which results in the PSF being blank for channels sourrounding each spectral window and some of the images being blank. Don't forget to change the imagename parameter when re-running [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. Due to the increased size of the cube you may find that your machine's avaliable memory struggles to keep up with the new [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] command. If so, then you can reduce the image size to lower the required memory. For our 512 channel cube we reduced the image size from 800x800 to 270x270. If you do reduce the image size as we have then you'll need to make use of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.analysis.imsubimage.html?highlight=imsubimage imsubimage] to first reduce your old image's mask size so it can be used again for your smaller image. Following the same steps as for the 8 channel image cube (adjusting for the new number of channels and new pixel indices for our points of interest), you would then obtain the results shown in Figure 21 where again the polarization position angle as a function of lambda square is shown together with the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.analysis.rmfit.html rmfit] image. We can clearly see that the source exhibits complex structure beyond a simple linear fit we performed earlier. This suggests that deriving a single RM would be an oversimplification. We should ideally perform RM Synthesis (https://arxiv.org/pdf/astro-ph/0507349.pdf). At this point in time CASA does not have an RM synthesis task.
If time allows you can take this even further. As our source is rather bright, we can derive an IQUV image not just per averaged spectral window as we just did, but rather per channel. To achieve this you can change the above [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] parameter width from 64 to 1, which will result in 512 channels spanning all 8 spectral windows. Note when imaging each channel, the edge channels are flagged which results in the PSF being blank for channels sourrounding each spectral window and some of the images being blank. Don't forget to change the imagename parameter when re-running [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean]. Due to the increased size of the cube you may find that your machine's avaliable memory struggles to keep up with the new [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.imaging.tclean.html tclean] command. If so, then you can reduce the image size to lower the required memory. For our 512 channel cube we reduced the image size from 800x800 to 270x270. If you do reduce the image size as we have then you'll need to make use of [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.analysis.imsubimage.html?highlight=imsubimage imsubimage] to first reduce your old image's mask size so it can be used again for your smaller image. Following the same steps as for the 8 channel image cube (adjusting for the new number of channels and new pixel indices for our points of interest), you would then obtain the results shown in Figure 21 where again the polarization position angle as a function of lambda square is shown together with the [https://casadocs.readthedocs.io/en/v6.4.1/api/tt/casatasks.analysis.rmfit.html rmfit] image. We can clearly see that the source exhibits complex structure beyond a simple linear fit we performed earlier. This suggests that deriving a single RM would be an oversimplification. We should ideally perform RM Synthesis (https://arxiv.org/pdf/astro-ph/0507349.pdf). At this point in time CASA does not have an RM synthesis task.




Line 1,837: Line 1,695:


<!-- Similar analysis can be performed on the polarization and spectral index maps, this will be left to the user. -->
<!-- Similar analysis can be performed on the polarization and spectral index maps, this will be left to the user. -->
Questions about this tutorial? Please contact the [http://go.nrao.edu/obshelp NRAO Helpdesk].
{{Checked 6.4.1}}
[[Main Page | &#8629; '''CASAguides''']]


<!-- Edited for content & context by T. Perreault 2021-12-30 -->
<!-- Edited for content & context by T. Perreault 2021-12-30 -->
<!-- Last edit by Anna D. Kapinska 2021-12-17 -->
<!-- Last edit by Anna D. Kapinska 2021-12-17 -->
<!-- Edited by Frank Schinzel 2021-03-30 -->
<!-- Edited by Frank Schinzel 2021-03-30 -->

Latest revision as of 17:42, 22 April 2024


Notes on CASA

This CASA Guide is for Version 6.4.1 of CASA. If you are using a later version of CASA and this is the most recent available guide, then you should be able to use most, if not all, of this tutorial. This guide is meant to be completed using the monolithic CASA and not modular CASA as the GUI may not work correctly otherwise.

There are a number of possible ways to run CASA, described in more detail in Getting Started in CASA. In this tutorial we would like you to use either (or both) of the following methods so that you can familiarize yourself with the CASA software:

  • Interactive: examining task inputs. In this mode, one types taskname to load the task, inp to examine the inputs, and go once those inputs have been set to your satisfaction. Allowed inputs are shown in blue and bad inputs are colored red. The input parameters themselves are changed one by one, e.g., selectdata=True. Screenshots of the inputs to various tasks used in the data reduction below are provided, to illustrate which parameters need to be set. More detailed help can be obtained on any task by typing help taskname. Once a task is run, the set of inputs is stored and can be retrieved via tget taskname; subsequent runs will overwrite the previous tget file.
  • Pseudo-interactive: task function calls. In this mode, all of the desired inputs to a task are provided at once inn the CASA command line. This tutorial is made up of such calls, which were developed by looking at the inputs for each task and deciding what needed to be changed from default values. For task function calls, only parameters that you want to be different from their defaults need to be set.

This tutorial is largely self-paced. Any time you have a question, or something doesn't look right or you are unsure of, please do summon one of the tutors present in the room.

Data Set

This CASA guide describes the calibration and imaging of a single-pointing continuum data set taken with the Karl G. Jansky Very Large Array (VLA) of the binary black hole system 3C 75 in Abell 400 cluster of galaxies [1]. The observations were performed with a single 1 GHz baseband centered at 3.0 GHz, resulting in 8x128 MHz wide spectral windows with 64 channels each. The observation was set up to allow for full polarization calibration.

Prior to the synthesis imaging workshop you should have received instructions to download the data for this tutorial. If you have not already, you will need to untar and unzip the file using the command: 'tar -xzvf TDRW0001_calibrated_CASA6.4.1.ms.tgz' and then give it the same name as the guide uses: 'mv TDRW0001_calibrated_CASA6.4.1.ms TDRW0001_calibrated.ms'.

The first step of polarization calibration is to first obtain a decent Stokes I (RR and LL) calibration. This has already been done for you by running the raw data through the CASA 6.4.1 version of the VLA pipeline. One additional step was required which involved removing the parallactic angle correction that was applied by the standard pipeline. For those familiar with the VLA pipeline, we essentially repeated what pipeline tasks hifv_applycals, hifv_targetflag, and hifv_statwt did, but disabled the application of parallactic angle corrections.


The Observation

Before starting the calibration process, we want to get some basic information about the data set. To examine the observing conditions during the observing run, and to find out any known problems with the data, we can take a look at the observer log, but in order to get to our observation we'll need the date it was observed on. The CASA task to use to get that information, and other very useful information on the setup of the observation is: listobs.

Once you've gotten the date of observation for this data set find its observer log and note the two antennas that had issues during the observation.

Before beginning our polarization calibration, we should inspect the pipeline calibration weblog for any obvious issues. You can download the weblog from ['https://casa.nrao.edu/Data/VLA/Polarization/SIW19pipeline-20230103T175723.tgz '] or view it through a browser here. For those not familiar with viewing these weblogs, they are basically a little report that is meant to help judge how well the VLA pipeline did with its calibration. Feel free to explore it as you wish, but you'll likely find two of the more useful stages to look at are hifv_finalcals (plots of the final solution tables) and hifv_plotsummary (various plots of the calibrated data). For more details on the pipeline output you can have a look at the VLA CASA Pipeline Guide.

You will likely note that there are four sources observed. Here the sources are introduced briefly, with more detail contained in the sections below in which they are used:

  • 0137+331=3C48, which will serve as a calibrator for the visibility amplitudes, i.e., it is assumed to have precisely known flux density, the spectral bandpass, and the polarization position angle;
  • J0259+0747, which will serve as a calibrator for the visibility phases and can be used to determine the instrumental polarization;
  • J2355+4950, which can serve as a secondary instrumental polarization calibrator or to check residual instrumental polarization, and;
  • 3C75, which is the science target.

Both to get a sense of the array, as well as identify the location of the reference antenna that we told the pipeline to choose for parallel hand calibration, have a look at the antenna setup page of the weblog. For calibration purposes, you would generally select an antenna that is close to the center of the array (and that is not listed in the operator's log as having had problems!).


Can you tell which antenna we chose for our reference antenna?

Answer

The reference antenna by definition has its delays and phases set to zero. So by looking at those solution tables in the hifv_finalcals stage we can see that ea10 was our reference antenna.

Examining and Editing the Data

It is always a good idea to examine the data before jumping straight into calibration. Even though the pipeline did a good job of calibrating and flagging the data, it isn't perfect. From the pipeline weblog, looking at the final amplitude gain calibration vs time plots in hifv_finalcals, we can see that during the second half of the observation antennas ea03, ea12, and ea16 shows some gain instability; otherwise there are no issues identified at this point.

We will start by making a simple overview plot.

# In CASA
plotms(vis='TDRW0001_calibrated.ms', selectdata=True, correlation='RR', averagedata=True, avgchannel='64', coloraxis='field', plotfile='colorbyfield.jpeg')
Figure 1: Overview of the observation: amplitude vs time, color-coded by field.
  • selectdata=True : One can choose to plot only selected subsets of the data.
  • correlation='RR' : Plot only the right-handed (left-handed omited only for speed) polarization products. The cross-terms ('RL' and 'LR') will be close to zero for non-polarized sources.
  • averagedata=True: One can choose to average data points before plotting them.
  • avgchannel='64' : With this plot, we are mainly interested in the fields vs time. Averaging over all 64 channels in the spectral window makes the plotting faster.
  • coloraxis='field' : Color-code the plotting symbols by field name/number.

The default x- and y-axis parameters are 'time' and 'amp', so the above call to plotms produces an amplitude vs time plot of the data for a selected subset of the data (if desired) and with data averaging (if desired). Many other values have been left to defaults, but it is possible to select them from within the plotms GUI.

Based on what you've learned from the listobs task you should be able to tell which sources are which in the plot.

Another example of using plotms for a quick look at your data, select the Data tab and specify field 2 (the complex gain calibrator J0259+0747) to display data associated with the target, then select the Axes tab and change the X-axis to be UVdist (baseline length in meters). Remove the channel averaging (Data tab), and plot the data using the Plot button at the bottom of the plotms GUI. The important observation is that the amplitude distribution is relatively constant as a function of UV distance or baseline length (i.e., [math]\displaystyle{ \sqrt{u^2+v^2} }[/math]; see Figure 2A). A relatively constant visibility amplitude as a function of baseline length means that the source is very nearly a point source (the Fourier transform of a point source, i.e. a delta function, is a constant function). You can see occasional spikes in the calibrated amplitudes. This is most likely caused by radio frequency interference that correlates on certain baselines. We will get to those further in the guide.

By contrast, if you make a similar plot for field 3 (our target 3C 75), the result is a visibility function that falls rapidly with increasing baseline length. Figure 2B shows this example, including time averaging of '1e6' seconds (any large number that encompasses more than a full scan will do, we want to fully average each scan). Such a visibility function indicates a highly resolved source. To plot baseline length in wavelengths rather than meters, select UVwave as the X-axis parameter.

A final example is shown in Figure 2C. In this example, we have elected to show phase as a function of (frequency) channel for a single baseline (antenna='ea01&ea21' ) on the bandpass calibrator, field 0, and non-averaged data. If you choose to iterate by baseline (e.g., antenna='ea01' and iteraxis='baseline' ), you can see similar phase-frequency variations on all baselines. They center around zero phase, because we are looking at the calibrated visibilities; however, you are seeing a butterfly shaped pattern with phase noise higher toward the channel edges. This pattern is due to a small mismatch in the delay measurement timing (also known as 'delay clunking') which is an internally generated effect and is typically averaged out over time.

Figure 2A: plotms view of amp vs. uvdist of J0259+0747, a point source
Figure 2B: plotms view of amp vs. uvwave of 3C 75, a resolved source
Figure 2C: plotms view of phase vs. channel on one baselines, showing phase delay across the calibrated bandpass


On Figure 1 you'll notice that the sources colored in black and green show much more spread in amplitude as compared to the others. Do you know the cause of this?

Answer

The black source is our flux density scale and bandpass calibrator, 3C48, and the green source is our target, 3C75. As we saw in Figure 2B, the spread in amplitude of 3C75 is primarily due to the presence of extended structure, that is to say, every baseline sees a slightly different amplitude. However if you make a similar plot of 3C48 you'll notice it is a point source. The spread on it is due to its spectral index (coloring by spectral window should make this stand out).


You can find similar plots in the CASA pipeline weblog under the task hifv_plotsummary. At this stage the pipeline has taken care of most of the calibration. There might be some remaining issues though that were not caught by the pipeline. In the following we note a couple issues that you might have found while inspecting data in this section. We will take care of those through additional flagging.

Issues that you might find:
 - ea12, scan 17: amplitude spike at the end of the scan (can be spotted already in Figure 1)
 - Residual RFI (see Figure 2A)

In the case of the amplitude spike, we can flag the affected time period by invoking the casa task flagdata. It is a good idea to save the original flags before performing any flagging by setting flagbackup=True.

# In CASA
flagdata(vis='TDRW0001_calibrated.ms', flagbackup=True, mode='manual', antenna='ea12',scan='17',timerange='07:25:57~07:26:18')

You can check the effect of this flagging by replotting Figure 2A. The spikes we saw before on some baselines should have disappeared. If you plot frequency against amplitude without averaging, however, you will still see some channels with interference that we will need to flag, especially on the instrumental polarization calibrators. Polarization calibration is very sensitive to interference, especially in the cross-hand correlations RL,LR. The pipeline does a good job at this, but there are still some RFI left; we will perform some additional flagging steps in the next section.

Additional Flagging

First we try to get a good sense of additional flagging that might be needed by plotting frequency against amplitude for the RR,LL and RL,LR polarizations of our calibrators (fields 0 through 2). You will notice some left over RFI on the bandpass calibrator in RR, LL. However, we also need to pay particular attention to RL, LR (see Figure 4A). Here we consider calibrators only; we will perform additional flagging on the target field at a later stage.

# In CASA
# for parallel hands
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RR,LL')
# for cross-hands
plotms(vis='TDRW0001_calibrated.ms',xaxis='frequency',yaxis='amplitude',field='0~2',correlation='RL,LR')
Figure 4a: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency before additional flagging
Figure 4b: plotms() view of calibrators' amplitudes (RL,LR) as a function of frequency after an additional run of rflag

Since we are dealing with point sources, we do not have to worry about overflagging of shorter baselines, so we can run flagdata with mode='rflag' over the calibrator fields and cross-hand correlations to remove any residual RFI. For completeness, we also use mode='tfcrop' to reduce the amount of residual RFI in the parallel hands.

# In CASA

# for the parallel hands
flagdata(vis='TDRW0001_calibrated.ms',
	 mode='tfcrop',
	 field='0~2',
	 correlation='',
	 freqfit='line',
	 extendflags=False,
	 flagbackup=False)

# for the cross-hands
flagdata(vis='TDRW0001_calibrated.ms',
	 mode='rflag',
	 datacolumn='data',
	 field='0~2',
	 correlation='RL,LR',
	 extendflags=True,
	 flagbackup=False)

As you can see in Figure 4B, this additional flagging step took care of most of the obvious residual RFI. We are now ready to move on to calibrate the visibilities for linear polarization.

Polarization Calibration

Polarization calibration is done in three steps:

* First, we determine the instrumental delay between the two polarization outputs;

* Second, we solve for the instrumental polarization (the frequency-dependent leakage terms, 'D-terms'), using either an unpolarized source or a source which has sufficiently good parallactic angle coverage;

* Third, we solve for the polarization position angle using a source with a known polarization position angle (we use 3C48 here). 

Before solving for the calibration solutions, we first use setjy to set the polarization model for our polarized position-angle calibrator. The pipeline only set the total intensity (Stokes I) of the flux density calibrator source 3C48, which did not include any polarization information. This source is known to have a fairly stable linear fractional polarization (measured to be 2% in S-band around the time of the observations), a polarization position angle of -100 degrees at 3 GHz, and a rotation measure of -68 rad/m^2. Note that 3C48 had an outburst in 2017 and is expected to show a significant degree of variability at higher frequencies in the first instance, progressively affecting lower frequencies as time passes since the event.

The setjy task will calculate the values of Stokes Q and U (in the reference channel) for user inputs of the reference frequency, Stokes I, polarization fraction, polarization angle, and rotation measure. It is possible to capture a frequency variation in Q, U, and alpha terms by providing coefficients of polynomial expansion for polarization fraction, polarization angle, and spectral index as a function of frequency. In general, it is left to the user to derive these coefficients, which can be accomplished by fitting a polynomial to observed values of the polarization fraction (here also called polarization index), polarization angle, and flux density (for the case of spectral index). These coefficients are then passed to the setjy task as lists along with the reference frequency and the Stokes I flux density.

As an example on how to derive the polarization parameters for the setjy call, you can perform the following next steps or jump right to the setjy call below.

Deriving the Polarization Properties of the Polarization Angle Calibrator

First, we tabulate the frequency dependent Stokes I flux density, polarization fraction, and polarization angle in a textfile, which we will call 3C48.dat. The data is taken from [2] and the corresponding Stokes I value is calculated from the Perley & Butler (2017) scale.

# Frequency  I       P.F.       P.A.
# (GHz)      (Jy)               (rad)
1.022        20.68   0.00293     0.07445
1.465        15.62   0.00457    -0.60282
1.865        12.88   0.00897     0.39760
2.565        9.82    0.01548    -1.97046
3.565        7.31    0.02911    -1.46542
4.885        5.48    0.04286    -1.24875
6.680        4.12    0.05356    -1.15533
8.435        3.34    0.05430    -1.10638
11.320       2.56    0.05727    -1.08602
14.065       2.14    0.06097    -1.09597
16.564       1.86    0.06296    -1.11891
19.064       1.67    0.06492    -1.18266
25.564       1.33    0.07153    -1.25369
32.064       1.11    0.06442    -1.32430
37.064       1.00    0.06686    -1.33697
42.064       0.92    0.05552    -1.46381
48.064       0.82    0.06773    -1.46412

Now to fit Stokes I, we execute in CASA the following commands. These could also be put into a text file and run from inside the CASA prompt using execfile.

# In CASA

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

data = np.loadtxt('3C48.dat')

def S(f,S,alpha,beta):
        return S*(f/3.0)**(alpha+beta*np.log10(f/3.0))

# Fit 1 - 5 GHz data points
popt, pcov = curve_fit(S, data[0:6,0], data[0:6,1])
print('I@3GHz', popt[0], ' Jy')
print('alpha', popt[1])
print('beta', popt[2])
print( 'Covariance')
print(pcov)

plt.plot(data[0:6,0], data[0:6,1], 'ro', label='data')
plt.plot(np.arange(1,5,0.1), S(np.arange(1,5,0.1), *popt), 'r-', label='fit')

plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Flux Density (Jy)')
plt.show()

This will generate a plot for visual inspection, as well as the following text output.

I@3GHz 8.555570817459328  Jy
alpha -0.8863795595286049
beta -0.14320026298724836
Covariance
[[1.30835675e-04 1.69587670e-05 2.05918186e-06]
 [1.69587670e-05 1.36709052e-05 2.62217377e-05]
 [2.05918186e-06 2.62217377e-05 6.27504685e-05]]

This provides the coefficients for Stokes I flux density at 3 GHz, the spectral index (alpha), and curvature (beta). It also provides the covariance matrix for the fit.

We repeat the same for the polarization fraction.

# In CASA

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

data = np.loadtxt('3C48.dat')

def PF(f,a,b,c,d):
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3

# Fit 1 - 5 GHz data points
popt, pcov = curve_fit(PF, data[0:6,0], data[0:6,2])
print("Polfrac Polynomial: ", popt)
print("Covariance")
print(pcov)

plt.plot(data[0:6,0], data[0:6,2], 'ro', label='data')
plt.plot(np.arange(1,5,0.1), PF(np.arange(1,5,0.1), *popt), 'r-', label='fit')

plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Lin. Pol. Fraction')
plt.show()
Polfrac Polynomial:  [ 0.02152856  0.03937167  0.003804   -0.01969663]
Covariance
[[ 2.52776017e-07  3.20765692e-07 -7.13270651e-07 -8.06571096e-07]
 [ 3.20765692e-07  4.07949498e-06 -5.46918397e-07 -1.05897559e-05]
 [-7.13270651e-07 -5.46918397e-07  3.26372075e-06  1.85490535e-06]
 [-8.06571096e-07 -1.05897559e-05  1.85490535e-06  3.07101526e-05]]
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

data = np.loadtxt('3C48.dat')

def PA(f,a,b,c,d,e):
        return a+b*((f-3.0)/3.0)+c*((f-3.0)/3.0)**2+d*((f-3.0)/3.0)**3+e*((f-3.0)/3.0)**4

# Fit 2 - 9 GHz data points
popt, pcov = curve_fit(PA, data[2:8,0], data[2:8,3])
print("Polangle Polynomial: ", popt)
print("Covariance")
print(pcov)

plt.plot(data[2:8,0], data[2:8,3], 'ro', label='data')
plt.plot(np.arange(1,9,0.1), PA(np.arange(1,9,0.1), *popt), 'r-', label='fit')

plt.title('3C48')
plt.legend()
plt.xlabel('Frequency (GHz)')
plt.ylabel('Lin. Pol. Angle (rad)')
plt.show()
Polangle Polynomial: [-2.5929737  -2.03374017  5.20812942 -2.01696093  0.30491012]
Covariance
[[  0.46219415   0.41124375  -1.26430855   0.50302926  -0.34715067]
 [  0.41124375   6.58090631   9.88051382  -7.56477931 -17.11605473]
 [ -1.26430855   9.88051382  58.3052678  -35.16883692 -58.08218227]
 [  0.50302926  -7.56477931 -35.16883692  21.77461974  37.45331953]
 [ -0.34715067 -17.11605473 -58.08218227  37.45331953  72.39830352]]

You'll notice that the fit for the polarization angle is much less smooth than the other fits. There appears to be something wrong with the first data point in our selection. Something special needs to happen to this point. There is a concept known as the [math]\displaystyle{ N\pi }[/math] ambiguity issue in polarimetry. You are encouraged to read more about this concept and see if you can figure out how to recover this data point.

Setting the Polarization Calibrator Models

# In CASA

# Reference Frequency for fit values
reffreq = '3.0GHz'
# Stokes I flux density
I =        8.55557
# Spectral Index
alpha =    [-0.8864, -0.1432]
# Polarization Fraction
polfrac =  [0.02152856, 0.03937167, 0.003804, -0.01969663]
# Polarization Angle
polangle = [-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514]

setjy(vis='TDRW0001_calibrated.ms',
      field='0137+331=3C48',
      spw='',
      selectdata=False,
      timerange="",
      scan="",
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[I,0,0,0],
      spix=alpha,
      reffreq=reffreq,
      polindex=polfrac,
      polangle=polangle,
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)
  • field='0137+331=3C48' : if the flux density calibrator is not specified then all sources will be assumed to have the input model parameters.
  • standard='manual' : the user will supply the flux density, spectral index, and polarization parameters rather than giving a model (the CASA models currently do not include polarization).
  • fluxdensity=[I,0,0,0] : you may provide values of Q and U rather than having setjy calculate them.However, if you set Q and U as input using the fluxdensity parameter, then the first value given in polindex or polangle will be ignored.
  • spix=alpha=[-0.8864, -0.1432] : set the spectral index using the value above. This will apply to all non-zero Spokes parameters. In this example, we only use the first two coefficients of the Taylor expansion.
  • reffreq='3.0GHz' : The reference frequency for the input Stokes values.
  • polindex=polfrac=[0.02152856, 0.03937167, 0.003804, -0.01969663] : The coefficients of polynomial expansion for the polarization index as a function of frequency.
  • polangle=polangle=[-2.74375466, 1.77557424, -1.77089873, 0.60309194, 0.96199514] : The coefficients of polynomial expansion for the polarization angle as a function of frequency (only acquirable with proper derotation).
  • scalebychan=True: This allows setjy to compute unique values per channel, rather than applying the reference frequency values to the entire spectral window.
  • usescratch=True: DO create/use the MODEL_DATA column explicitly. (usescratch=False saves disk space by not filling the model column, however due to current bugs it is suggested to not use it)

The Stokes V flux has been set to zero, corresponding to no circular polarization.

Setjy returns a Python dictionary (CASA record) that reports the Stokes I, Q, U and V terms. This is reported to the CASA command line window.

{'0': {'0': {'fluxd': array([10.07724056,  0.15082879,  0.01240901,  0.        ])},
  '1': {'fluxd': array([9.64869223, 0.15381396, 0.04441096, 0.        ])},
  '2': {'fluxd': array([9.25487752, 0.15053557, 0.07574993, 0.        ])},
  '3': {'fluxd': array([8.89166708, 0.14187061, 0.10510616, 0.        ])},
  '4': {'fluxd': array([8.55557   , 0.12889591, 0.13157306, 0.        ])},
  '5': {'fluxd': array([8.24361379, 0.11273472, 0.15463414, 0.        ])},
  '6': {'fluxd': array([7.95325066, 0.09444074, 0.17410041, 0.        ])},
  '7': {'fluxd': array([7.68228356, 0.0749225 , 0.19002888, 0.        ])},
  'fieldName': '0137+331=3C48'},
 'format': "{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}"}

We can see the results in the model column in plotms (Figure 5A) showing the model source spectrum:

# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RR',
       timerange='',antenna='ea01&ea02',
       xaxis='frequency',yaxis='amp',ydatacolumn='model')

We can see this translates to the spectrum in QU (Figure 5B):

# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
       timerange='',antenna='ea01&ea02',
       xaxis='frequency',yaxis='amp',ydatacolumn='model')

Finally, we plot our R-L phase differences, which should be twice the value of the polarization angle without other complications such as the [math]\displaystyle{ N\pi }[/math] ambiguity (Figure 5C):

# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='RL',
       timerange='',antenna='ea01&ea02',
       xaxis='frequency',yaxis='phase',ydatacolumn='model')
Figure 5A: Model RR amplitudes of 3C48.
Figure 5B: Model RL amplitudes of 3C48.
Figure 5C: Model RL phases of 3C48.

In order to obtain the correct amplitude scaling for instrumental polarization calibration, we need to also specify the Stokes I model that was used for the D-term calibrator(s). The model values of the two D-term calibrators can be obtained from the pipeline weblog under the task hifv_fluxboot inside the CASA log associated with that task. Take this opportunity to try to find them. We've purposely removed the setjy calls in the log so as to not spoil the fun. While not specific to polarization calibration, this exercise should reveal an important aspect of the VLA pipeline: It sets a correct Stokes I model of the secondary calibrators before the final calibration tables are produced (you may appreciate this difference more if you also participated in the Continuum Tutorial and remember how it handled the flux density scale calibration for the secondary calibrators). Your goal when looking over the log is to figure out where the pipeline is getting the inputs for setjy from. Once you've found the relevant lines in the log try to make up the setjy calls on your own.


The casapy.log lines of interest and setjy calls
2023-01-03 19:07:54	INFO	fluxscale::::	 Fitted spectrum for J2355+4950 with fitorder=2: Flux density = 1.76871 +/- 0.000646066 (freq=2.98457 GHz) spidx: a_1 (spectral index) =-0.599569 +/- 0.00275835 a_2=-0.196812 +/- 0.0670986 covariance matrix for the fit:  covar(0,0)=8.14129e-08 covar(0,1)=-1.12826e-07 covar(0,2)=-2.46336e-05 covar(1,0)=-1.12826e-07 covar(1,1)=2.4614e-05 covar(1,2)=0.000242613 covar(2,0)=-2.46336e-05 covar(2,1)=0.000242613 covar(2,2)=0.0145649

2023-01-03 19:07:55	INFO	fluxscale::::	 Fitted spectrum for J0259+0747 with fitorder=2: Flux density = 0.970568 +/- 0.000712514 (freq=2.98457 GHz) spidx: a_1 (spectral index) =0.169919 +/- 0.00510126 a_2=-0.143294 +/- 0.134104 covariance matrix for the fit:  covar(0,0)=1.87159e-06 covar(0,1)=-2.56746e-06 covar(0,2)=-0.000583154 covar(1,0)=-2.56746e-06 covar(1,1)=0.000479139 covar(1,2)=-9.51772e-05 covar(2,0)=-0.000583154 covar(2,1)=-9.51772e-05 covar(2,2)=0.331122

This translates to the following setjy calls.

setjy(vis='TDRW0001_calibrated.ms',
      field='J2355+4950',
      spw='',
      selectdata=False,
      timerange="",
      scan="",
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[1.76871, 0, 0, 0],
      spix=[-0.599569, -0.196812],
      reffreq="2.98457GHz",
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)

setjy(vis='TDRW0001_calibrated.ms',
      field='J0259+0747',
      spw='',
      selectdata=False,
      timerange="",
      scan="",
      intent="",
      observation="",
      scalebychan=True,
      standard="manual",
      model="",
      modimage="",
      listmodels=False,
      fluxdensity=[0.970568, 0, 0, 0],
      spix=[0.169919, -0.143294],
      reffreq='2.98457GHz',
      polindex=[],
      polangle=[],
      rotmeas=0,
      fluxdict={},
      useephemdir=False,
      interpolation="nearest",
      usescratch=True,
      ismms=False,
)


Solving for the Cross-Hand delays

Just as the pipeline did for the parallel-hand (RR,LL) delays before bandpass calibration, we solve for the cross-hand (RL,LR) delays because of the residual delay difference between the R and L on the reference antenna used for the original delay calibration (ea10 in this tutorial). In our case we simply use 3C48, which has a moderately polarized signal in the RL,LR correlations, and we set its polarized model above using setjy. Since the release of CASA 6.1.2, there are two options to solve for the cross-hand delays, both of them will be illustrated here. The first option fits the cross-hand delay for the entire baseband (here 8 spectral windows form a single baseband), which we call multiband delay. The second option solves the cross-hand delay independently per spectral window. Note that if a dataset contains multiple basebands and you wanted to solve for multiband delays, gaincal has to be executed for each baseband separately, selecting the appropriate spectral windows and appending the results to a single calibration table for later use.

# In CASA

# Solve using Multiband Delay
kcross_mbd = "TDRW0001_calibrated.Kcross_mbd" 
gaincal(vis='TDRW0001_calibrated.ms',
    caltable=kcross_mbd,
    field='0137+331=3C48',
    spw='0~7:5~58',
    refant='ea10',
    gaintype="KCROSS",
    solint="inf",
    combine="scan,<?>",
    calmode="ap",
    append=False,
    gaintable=[''],
    gainfield=[''],
    interp=[''],
    spwmap=[[]],
    parang=True)

# Solve using Single Band Delay
kcross_sbd = "TDRW0001_calibrated.Kcross_sbd"
gaincal(vis='TDRW0001_calibrated.ms',
    caltable=kcross_sbd,
    field='0137+331=3C48',
    spw='0~7:5~58',
    refant='ea10',
    gaintype="KCROSS",
    solint="inf",
    combine="scan",
    calmode="ap",
    append=False,
    gaintable=[''],
    gainfield=[''],
    interp=[''],
    spwmap=[[]],
    parang=True)


These commands essentially only differ with how the 'combine' parameter is defined. Based on the description above what should this parameter be in order to fit across the entire baseband?

Answer

The only real difference between the commands is that the first is using the entire baseband as input to create one solution and the second is using each spectral window to get individual solutions. In order to tell CASA to combine all of the spectral windows (and scans in this case) one simply has to use: combine='scan,spw'.


Figure 6: Single band cross-hand delay solutions.

We can plot the single band solutions (see Figure 6):

# In CASA
plotms(vis=kcross_sbd,xaxis='frequency',yaxis='delay',antenna='ea10',coloraxis='corr')

You can also look at the solutions reported in the logger.

For multiband delay there is one solution:
Multi-band cross-hand delay=3.68373 nsec

For single band delay there are 8 solutions:
Spw=0 Global cross-hand delay=5.58964 nsec
Spw=1 Global cross-hand delay=1.49907 nsec
Spw=2 Global cross-hand delay=-1.26208 nsec
Spw=3 Global cross-hand delay=0.522402 nsec
Spw=4 Global cross-hand delay=4.25883 nsec
Spw=5 Global cross-hand delay=1.25194 nsec
Spw=6 Global cross-hand delay=3.69895 nsec
Spw=7 Global cross-hand delay=3.02677 nsec

Notice that the per spectral window solutions are very scattered. The mean delay is 2.32 ns, quite different from the multiband delay. This demonstrates the strength of fitting the cross-hand delay across multiple spectral windows, especially when using a calibrator with a significant frequency dependence, i.e. rotation measure and a polarization fraction of only a few percent. We will continue calibration using the single multiband delay that was derived at 3.68 ns.

Solving for the Leakage Terms

The task polcal is used for polarization calibration. In this data set, we observed the unpolarized calibrator J2355+4950 to demonstrate solving for the instrumental polarization. Task polcal uses the Stokes I, Q, and U values in the model data (Q and U being zero for an unpolarized calibrator) to derive the leakage solutions. We also observed the polarized calibrator J0259+0747 (which has about 4.7% fractional polarization) that is also our complex gain calibrator.

# In CASA

# J2355+4950 / Df
dtab_J2355 = 'TDRW0001_calibrated.Df' 
polcal(vis='TDRW0001_calibrated.ms',
       caltable=dtab_J2355,
       field='J2355+4950',
       spw='0~7',
       refant='ea10',
       poltype='Df',
       solint='inf,2MHz',
       combine='scan',
       gaintable=[kcross_mbd],
       gainfield=[''],
       spwmap=[[0,0,0,0,0,0,0,0]], 
       append=False)

# J0259+0747 / Df+QU
dtab_J0259 = 'TDRW0001_calibrated.DfQU' 
polcal(vis='TDRW0001_calibrated.ms',
       caltable=dtab_J0259,
       intent='CALIBRATE_POL_LEAKAGE#UNSPECIFIED',
       spw='0~7',
       refant='ea10',
       poltype='Df+QU',
       solint='inf,2MHz',
       combine='scan',
       gaintable=[kcross_mbd],
       gainfield=[''],
       spwmap=[[0,0,0,0,0,0,0,0]], 
       append=False)
  • caltable : polcal will create a new calibration table containing the leakage solutions, which we specify with the caltable parameter.
  • field= or intent= : The unpolarized source J2355+4950 is used to solve for the leakage terms in the unpolarized case. For the polarized source J0259+0747 we set the intent leakage polarization.
  • spw='0~7' : Select all spectral windows.
  • poltype='Df' or poltype='Df+QU' : Solve for the leakages (D) on a per-channel basis (f), assuming zero source polarization, +QU will also solve for the calibrator polarization Q,U per spectral window.
  • solint='inf,2MHz', combine='scan' : One solution over the entire run, per spectral channel of 2 MHz
  • gaintable=['kcross_mbd']: The previous Kcross multiband delay is applied
  • spwmap=[0,0,0,0,0,0,0,0]: This applies a spectral window map, where the first spw solution in the kcross_mbd table is mapped to all other spectral windows. Note there is only one value listed inside the kcross calibration table which is for the lowest spectral window that was used when solving using the multiband delay option (i.e. combine='spw' ).

In the case of Df+QU, the logger window will show the Q/U values it derived for the calibrator and the corresponding polarization fraction and angle that can be derived.

Fractional polarization solution for J0259+0747 (spw = 0): : Q = 0.0259049, U = 0.0336301  (P = 0.0424505, X = 26.1967 deg)
Fractional polarization solution for J0259+0747 (spw = 1): : Q = 0.0139972, U = 0.0382244  (P = 0.0407066, X = 34.944 deg)
Fractional polarization solution for J0259+0747 (spw = 2): : Q = 0.0165052, U = 0.0384224  (P = 0.0418175, X = 33.3765 deg)
Fractional polarization solution for J0259+0747 (spw = 3): : Q = 0.0118274, U = 0.0422875  (P = 0.0439104, X = 37.1871 deg)
Fractional polarization solution for J0259+0747 (spw = 4): : Q = 0.00816816, U = 0.0404744  (P = 0.0412903, X = 39.2952 deg)
Fractional polarization solution for J0259+0747 (spw = 5): : Q = 0.00649365, U = 0.0412879  (P = 0.0417954, X = 40.5309 deg)
Fractional polarization solution for J0259+0747 (spw = 6): : Q = -0.00225595, U = 0.0429258  (P = 0.0429851, X = 46.5042 deg)
Fractional polarization solution for J0259+0747 (spw = 7): : Q = -0.00776873, U = 0.0474773  (P = 0.0481087, X = 49.6465 deg)

From this you can see that J0259+0747 has a fractional polarization of 4.1–4.8% across the 1 GHz bandwidth with a small rotation measure causing a change in angle from 26 to 49 degrees over 1 GHz. In cases where the derived Q/U values seem random and the fractional polarization seems to be very small you might be able to derive better D-term solutions by using poltype='Df' .

After we run the two executions of polcal, you are strongly advised to examine the solutions with plotms to ensure that everything looks good and to compare the results using two different calibrators and poltype methods.

Figure 7a: J0259+0747 Df amplitude vs. frequency for antenna ea01.
Figure 7b: J2355+4950 Df+QU amplitude vs. frequency for antenna ea01.
Figure 7c: J0259+0747 Df phase vs. frequency for antenna ea01.
Figure 7d: J2355+4950 Df+QU phase vs. frequency for antenna ea01.
# In CASA
plotms(vis=dtab_J0259,xaxis='freq',yaxis='amp', 
       iteraxis='antenna',coloraxis='corr')

plotms(vis=dtab_J2355,xaxis='freq',yaxis='amp', 
       iteraxis='antenna',coloraxis='corr')

plotms(vis=dtab_J0259,xaxis='chan',yaxis='phase', 
       iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])

plotms(vis=dtab_J2355,xaxis='chan',yaxis='phase', 
       iteraxis='antenna',coloraxis='corr',plotrange=[-1,-1,-180,180])

This will produce plots similar to those shown in Figures 7A-D. You can cycle through the antennas by clicking the Next button within plotms. You should see leakages of between 5–17% in most cases. Both Df and Df+QU results should be comparable. However, we will be using the solutions from J0259+0747 to continue calibration and will use J2355+4950 to verify the polarization calibration.

We can also display these in a single plot versus antenna index (see Figure 8):

Figure 8: Df+QU solutions for J0259+0747 versus antenna index
# In CASA
plotms(vis=dtab_J0259,xaxis='antenna1',yaxis='amp',coloraxis='corr')

Solving for the R-L polarization angle

Having calibrated for the instrumental polarization, the total polarization is now correct, but the R-L phase still needs to be calibrated in order to obtain an accurate polarization position angle. We use the same task, polcal, but this time set parameter poltype='Xf', which specifies a frequency-dependent (f) position angle (X) calibration using the source 3C48, the position angle of which is known, having set this earlier with setjy. Note that we must correct for the leakages before determining the R-L phase, which we do by adding the calibration table made in the previous step (dtab_J0259) to the kcross table that is applied on-the-fly.

# In CASA
xtab = "TDRW0001_calibrated.Xf"
polcal(vis='TDRW0001_calibrated.ms',
       caltable=xtab,
       spw='0~7',
       field='0137+331=3C48',
       solint='inf,2MHz',
       combine='scan',
       poltype='Xf',
       refant = 'ea10',
       gaintable=[kcross_mbd,dtab_J0259],
       gainfield=['',''],
       spwmap=[[0,0,0,0,0,0,0,0],[]],
       append=False)
Figure 9: Xf solutions versus frequency.

Strictly speaking, there is no need to specify a reference antenna for poltype='Xf' (for circularly polarized receivers only) because the X solutions adjust the cross-hand phases for each antenna to match the given polarization angle of the model. However, for consistency/safety, it is recommended to always specify refant when performing polarization calibration.

It is strongly suggested you check that the calibration worked properly by plotting up the newly-generated calibration table using plotms (see Figure 9):

# In CASA
plotms(vis=xtab,xaxis='frequency',yaxis='phase',coloraxis='spw')

Because the Xf term captures the residual R-L phase on the reference antenna over the array, there is only one value for all antennas. Also, as we took out the RL delays using the Kcross solution, these Xf variations do not show a significant slope in phase. And since we were using a single multiband delay, the phases connect from one spectral window to another; had we used the single band delays, we would see phase jumps from one to another spectral window.

At this point, you have all the necessary polarization calibration tables.

Applying the Calibration

Now that we have derived all the calibration solutions, we need to apply them to the actual data using the task applycal. The measurement set DATA column contains the original split data. To apply the calibration we have derived, we specify the appropriate calibration tables which are then applied to the DATA column, with the results being written in the CORRECTED_DATA column.

# In CASA
applycal(vis = 'TDRW0001_calibrated.ms',
         field='',
         gainfield=['', '', ''], 
         flagbackup=True,
         interp=['', '', ''],
         gaintable=[kcross_mbd,dtab_J0259,xtab],
         spw='0~7', 
         calwt=[False, False, False], 
         applymode='calflagstrict', 
         antenna='*&*', 
         spwmap=[[0,0,0,0,0,0,0,0],[],[]], 
         parang=True)
  • gaintable : We provide a Python list of the calibration tables to be applied. This list must contain the cross-hand delays (kcross), the leakage calibration (dtab; here derived from J0259+0747), and the R-L phase corrections (xtab).
  • calwt=[False] : At the time of this writing, we are not yet using system calibration data to compute real (1/Jy2) weights; trying to calibrate them can produce nonsensical results. Experience has shown that calibrating the weights will lead to problems, especially in the self-calibration steps. You can specify calwt on a per-table basis, here is set all to False.
  • parang : If polarization calibration has been performed, set parameter parang=True.


We should now have fully-calibrated visibilities in the CORRECTED_DATA column of the measurement set, and it is worthwhile pausing to inspect them to ensure that the calibration did what we expected it to. We make some standard plots (see Figures 10A-F). Now that you've used plotms a few times try making the below plots on your own. The only bit of information you cannot derive from the figures themselves is that we have averaged them in time by 60 seconds.

Plotms Calls
# In CASA
plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
       coloraxis='corr',
       plotfile='Plotms-3C48-fld0-corrected-amp-CASA6.4.1.jpeg')

plotms(vis='TDRW0001_calibrated.ms',field='0',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       plotrange=[-1,-1,-180,180],coloraxis='corr',
       plotfile='Plotms-3C48-fld0-corrected-phase-CASA6.4.1.jpeg')

plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
       coloraxis='corr',
       plotfile='Plotms-J2355-fld1-corrected-amp-CASA6.4.1.jpeg')

plotms(vis='TDRW0001_calibrated.ms',field='1',correlation='RR,LL',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       plotrange=[-1,-1,-180,180],coloraxis='corr',
       plotfile='Plotms-J2355-fld1-corrected-phase-CASA6.4.1.jpeg')

plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='amp',ydatacolumn='corrected',
       coloraxis='corr',
       plotfile='Plotms-J0259-fld2-corrected-amp-CASA6.4.1.jpeg')

plotms(vis='TDRW0001_calibrated.ms',field='2',correlation='',
       timerange='',antenna='',avgtime='60',
       xaxis='frequency',yaxis='phase',ydatacolumn='corrected',
       plotrange=[-1,-1,-180,180],coloraxis='corr',avgbaseline=True,
       plotfile='Plotms-J0259-fld2-corrected-phase-CASA6.4.1.jpeg')


For 3C48 (figures 10A, 10B) we see the polarized signal in the cross-hands; there is some sign of bad data remaining in 3C48. Also, the RL phase plots of J0259+4950 (figure 10F) indicate that the Xf solutions, thus polarization angles, in the lowest two spectral windows are problematic. You can also estimate from the RL,LR amplitudes in J2355+4950 (figure 10E) what the level of residual instrumental polarization, which we expect to be around <0.5%. A more accurate evaluation of residual instrumental polarization fraction can be made imaging the secondary D-term calibrator per spectral window and calculating its residual polarization.

Figure 10A: amplitude vs channel for 3C48 RR,RL,LR,LL
Figure 10B: phase vs channel for 3C48 RR,RL,LR,LL
Figure 10C: amplitude vs channel for J2355+4950 RR,RL,LR,LL
Figure 10D: phase vs channel for J2355+4950 RR,LL
Figure 10E: amplitude vs channel for J0259+4950 RR,RL,LR,LL
Figure 10F: phase vs channel for J0259+4950 RR,RL,LR,LL with baseline averaging


Now that the calibration has been applied to the target data, we split off the science targets to create a new, calibrated measurement set containing the target field.

# In CASA
split(vis='TDRW0001_calibrated.ms',outputvis='3C75.ms',
      datacolumn='corrected',field='3')
  • outputvis : We give the name of the new measurement set to be written, which will contain the calibrated data on the science target.
  • datacolumn : We use the CORRECTED_DATA column, containing the calibrated data which we just wrote using applycal.
  • field : We wish to place the target field into a measurement set for imaging and joint deconvolution.

Prior to imaging, it is a good idea to run the statwt task to correct the data weights (weight and sigma columns) in the measurement set. Running statwt will remove the effects of relative noise scatter that may have been introduced from flagging uneven bits in the visibility data between the channels and times. We will run this task here on the newly calibrated and split data set before moving on to imaging.

# In CASA
statwt(vis='3C75.ms',datacolumn='data',minsamp=8)

Imaging

Now that we have split off the target data into a separate measurement set with all the calibration applied, it's time to make an image. It is important to have an idea of what values to use for the image pixel (cell) size and the overall size of the image. Setting the appropriate pixel size for imaging depends upon basic optics aspects of interferometry. Use plotms to look at the newly calibrated, target-only data set:

Figure 11: plotms plot showing Amplitude vs UV Distance in wavelengths for 3C75 at 3000 MHz
# In CASA
plotms(vis='3C75.ms',xaxis='uvwave',yaxis='amp',
       ydatacolumn='data', field='0',avgtime='30',correlation='RR',
       plotfile='plotms_3c75-uvwave.jpeg',avgspw=False,overwrite=True)

You should obtain a plot similar to Figure 11 with the (calibrated) visibility amplitude as a function of [math]\displaystyle{ u }[/math]-[math]\displaystyle{ v }[/math] distance. You will also see some outliers there which are primarily from residual amplitude errors of ea05, that had a warm receiver which we can isolate to particular time periods. We will be addressing this after the initial imaging.


Based on the UVwave plot can you determine approximately what the smallest angular scale of the image will be?

Answer

We can see in the plot that the maximum baseline is about 12,000 wavelengths. If we recall that the VLA works via diffraction then it follows that: [math]\displaystyle{ \theta\approx\lambda/D=1/12000 radians\approx17 arcsec }[/math]. Furthermore, the most effective cleaning occurs with 3–5 pixels across the synthesized beam. So for this data a cell size of 3.4 arcseconds will give just about 5 pixels per beam.


The 3C75 binary black hole system is known to have a maximum extent of at least 8-9 arcminutes, corresponding to about 147 pixels for the chosen cell size. Therefore, we need to choose an image size that covers most of the extent of the source. We therefore set imsize=[480,480] and the source will fit comfortably within that image.

In this tutorial, we will run tclean interactively so that we can set and modify the mask:

# In CASA
tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="data",
       imagename="3C75_initial",
       imsize=480,
       cell="3.4arcsec",
       phasecenter="",
       stokes="IQUV",
       projection="SIN",
       specmode="mfs",
       reffreq="3.0GHz",
       nchan=-1,
       start="",
       width="",
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=0.0001,
       normtype="flatnoise",
       deconvolver="mtmfs",
       scales=[0, 6, 18],
       nterms=2,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=20000,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=1000,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)
Figure 12: Interactive clean at the beginning, having selected polygon region and ready to double-click inside to set the mask.

Task tclean is powerful with many inputs and a certain amount of experimentation likely is required. The below is an explanation of several of the parameters we've used.

tclean parameters
  • vis='3C75.ms' : this split MS contains the target field only.
  • imagename='3C75_initial' : our output image cubes will all start with this name root, e.g., 3C75_initial.image
  • specmode='mfs' : Use multi-frequency synthesis imaging. The fractional bandwidth of these data is non-zero (1000 MHz at a central frequency of 3.0 GHz). Recall that the [math]\displaystyle{ u }[/math] and [math]\displaystyle{ v }[/math] coordinates are defined as the baseline coordinates, measured in wavelengths. Thus, slight changes in the frequency from channel to channel result in slight changes in [math]\displaystyle{ u }[/math] and [math]\displaystyle{ v }[/math]. There is a concomitant improvement in [math]\displaystyle{ u }[/math]-[math]\displaystyle{ v }[/math] coverage if the visibility data from the multiple spectral channels are gridded separately onto the [math]\displaystyle{ u }[/math]-[math]\displaystyle{ v }[/math] plane, as opposed to treating all spectral channels as having the same frequency.
  • niter=20000,gain=0.1,threshold='0.0mJy' : Recall that the gain is the amount by which a clean component is subtracted during the cleaning process. Parameters niter and threshold are (coupled) means of determining when to stop the cleaning process, with niter specifying to find and subtract that many clean components while threshold specifies a minimum flux density threshold a clean component can have before tclean stops (also see interactive below). Imaging is an iterative process, and to set the threshold and number of iterations, it is usually wise to clean interactively in the first instance, stopping when spurious emission from sidelobes (arising from gain errors) dominates the residual emission in the field. Here, we have set the threshold level to zero and let the tclean task define an appropriate threshold. The number of iterations should then be set high enough to reach the threshold found by tclean.
  • gridder='standard' : The standard tclean gridder is sufficient for our purposes, since we are not combining multiple pointings from a mosaic or try to perform widefield imaging in an extended configuration.
  • interactive=True : Very often, particularly when one is exploring how a source appears for the first time, it can be valuable to interact with the cleaning process. If True, interactive causes a viewer window to appear. One can then set clean regions, restricting where tclean searches for clean components, as well as monitor the cleaning process. A standard procedure is to set a large value for niter, and stop the cleaning when it visually appears to be approaching the noise level. This procedure also allows one to change the cleaning region, in cases when low-level intensity becomes visible as the cleaning process proceeds.
  • imsize=480,cell='3.4arcsec' : See the discussion above regarding setting the image size and cell size. If only one value is specified for the parameter, the same value is used in both directions (declination and right ascension).
  • stokes='IQUV' : tclean will output an image cube containing all: total intensity I, and Stokes Q, U, and V.
  • deconvolver='mtmfs', scales=[0, 6, 18], smallscalebias=0.9 : The settings for scales are in units of pixels, with 0 pixels equivalent to the traditional delta-function clean. The scales here are chosen to provide delta functions and then two logarithmically scaled sizes to fit to the data. The first scale (6 pixels) is chosen to be comparable to the size of the synthesized beam. The smallscalebias attempts to balance the weight given to larger scales, which often have more flux density, and the smaller scales, which often are brighter. Considerable experimentation is likely to be necessary; one of the authors of this document found that it was useful to clean several rounds with this setting, change to multiscale=[] and remove much of the smaller scale structure, then return to this setting.
  • weighting='briggs',robust=0.5 : 3C75 has diffuse, extended emission that is, at least partially, resolved out by the interferometer even though we are in the most compact VLA configuration. A naturally-weighted image would show large-scale patchiness in the noise. In order to suppress this effect, Briggs weighting is used (intermediate between natural and uniform weighting), with a default robust factor of 0.5 (which corresponds to something between natural and uniform weighting).
  • pbcor=False : by default pbcor=False and a flat-noise image is produced. We can do the primary beam correction later (see below).
  • savemodel='modelcolumn' : We recommend here the use of a physical MODEL_DATA scratch column. This will save some time, as it can be faster in the case of complicated gridding to read data from disk instead of doing all of the computations on-the-fly. However, this has the unfortunate side effect of increasing the size of the MS on disk.
Figure 13: After the first approximately 300 iterations of multi-scale mfs clean

As mentioned above, we can guide the clean process by allowing it to find clean components only within a user-specified region. When tclean runs in interactive mode, an imview window will pop up as shown in Figure 12. First, you'll want to navigate to the green box and select "All Polarizations" rather than use the default "This Polarization"; this way the cleaning we are about to do will apply to all of the polarizations rather than just the one we are currently viewing. Similarly, select "All channels". To get a more detailed view of the central regions containing the emission, zoom in by first left clicking on the zoom button (leftmost button in third row) and tracing out a rectangle with the left mouse button and double-clicking inside the zoom box you just made. Play with the color scale to bring out the emission better by holding down the middle mouse button and moving it around. To create a clean box (a region within which components may be found), hold down the right mouse button and trace out a rectangle around the source, then double-click inside that rectangle to set it as a box. Note that the clean box must turn white for it to be registered - if the box is not white, it has not been set. Alternatively, you can trace out a more custom shape to better enclose the irregular outline of the radio galaxy jets. To do this, right-click on the closed polygonal icon then trace out a shape by right-clicking where you want the corners of that shape. Once you have come full circle, the shape will be traced out in green, with small squares at the corners. Double-click inside this region and the green outline will turn white. You have now set the clean region. If you have made a mistake with your clean box, click on the Erase button, trace out a rectangle around your erroneous region, and double-click inside that rectangle. You can also set multiple clean regions.

At any stage in the cleaning, you can adjust the number of iterations that tclean will do before returning to the GUI (cycleniter). This is set to 1000 (see the iterations field in mid-upper left of panel), values from 500 to 1000 later on seem to work. Note that this will override the cycleniter value that you might had set before starting tclean. tclean will keep going until it reaches threshold or runs out of cycles (the cycles field to the right of the iterations).

Figure 14: Interactive residuals after about 13000 iterations of multi-scale mfs clean

When you are happy with the clean regions, press the green circular arrow button on the far right to continue deconvolution. After completing a cycle, a revised image will come up. As the brightest points are removed from the image (cleaned off), fainter emission may show up. You can adjust the clean boxes each cycle, to enclose all real emission. After many cycles, when only noise is left, you can hit the red-and-white stop-sign icon to stop cleaning. Figure 13 shows the interactive viewer panel later in the process, after cleaning about 500 iterations. We have used the polygon tool to add to the clean region, drawing around emission that shows up in the residual image outside of the original clean region. After about 13000 iterations (Figure 14) the residuals were looking good (similar noise level inside and outside of the cleaned mask region). As mentioned before, restarting tclean with different multiscale=[...] choices can help also. You see that there is a significant amount of residual structure (the various spikes and streaks throughout the image), these are most likely due to calibration errors which we will try to correct for in the next section during self-calibration.

Task tclean will make several output files, all named with the prefix given as imagename. These include:

  • .image: final restored image(s) with the clean components convolved with a restoring beam and added to the remaining residuals at the end of the imaging process, one for each Taylor Term (.tt0 and .tt1)
  • .pb.tt0: effective response of the telescope (the primary beam)
  • .mask: areas where tclean has been allowed to search for emission
  • .model: sum of all the clean components, which also has been stored as the MODEL_DATA column in the measurement set, one for each Taylor Term (.tt0 and .tt1)
  • .psf: dirty beam, which is being deconvolved from the true sky brightness during the clean process, one for each Taylor Term (.tt0, .tt1, .tt2)
  • .residual: what is left at the end of the deconvolution process; this is useful to diagnose whether or not to clean more deeply, one for each Taylor Term (.tt0, .tt1)
  • .sumwt: a single pixel image containing sum of weights per plane, one for each Taylor Term (.tt0, .tt1, .tt2)
Figure 15A: Viewer panel of final restored Stokes I image (using viridis colormap, linear scale, 99.9%)
Figure 15B: Viewer panel of final restored Stokes Q image (using viridis colormap, linear scale, 99.9%)
Figure 15C: Viewer panel of final restored Stokes U image (using viridis colormap, linear scale, 99.9%)
Figure 15D: Viewer panel of final restored Stokes V image (using viridis colormap, linear scale, 99.9%)

After the imaging and deconvolution process has finished, you can use CARTA to look at your image.

Take some time to play with the color scale to better emphasize the faint emission and to see the underlying noise patterns. For the figures above we selected the viridis color map, the linear scale function, and the 99.9% data range on the histogram. You can also use the Animators slider/buttons to switch between the four different Stokes parameter images that were computed. If you are unfamiliar with CARTA then take some time to look over its extensive built in documentation and help features. You can find its searchable online manual via the "Help" button at the top or to get more information on a particular widget you can click the corresponding "?" button near it. If you click the Animator tab you'll also notice that CARTA attempts to create total polarization, linear polarization, fractional total polarization, fractional linear polarization, and linear polarization angle images for you. This can be quite convenient, but we'll show how to create these yourself later in this guide.

The tclean task naturally operates in a flat noise image, i.e., an image where the effective weighting across the field of view is set so that the noise is constant. This is so that the clean threshold has a uniform meaning for the stopping criterion and that the image fed into the minor cycles has uniform noise levels. This means, however, that the image does not take into account the primary beam response fall-off in the edges. In principle, tclean produces primary beam response image, and if we had set parameter pbcor=True tclean would had saved a primary beam corrected restored image of our target. Since we used deconvolver='mtmfs' and nterms=2, the calculation of the primary beam response requires special treatment. To perform wideband primary beam correction, we will use task widebandpbcor. In the future this task will be incorporated into tclean, but until then this separate task needs to be used.

# In CASA
widebandpbcor(vis='3C75.ms',imagename='3C75_initial',nterms=2, action='pbcor',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])

The task will produce primary beam corrected images of our target (3C75_initial.pbcor.image.tt0, 3C75_initial.pbcor.image.tt1, 3C75_initial.pbcor.image.alpha, 3C75_initial.pbcor.image.alpha.error). You can open image 3C75_initial.pbcor.image.tt0 in CARTA, and compare it to screenshots in Figure 15. You will see noise (and signal) at the edges of the image has indeed increased.

Self-Calibration

Before we get started with self-calibration, it might be good to check whether we need to perform additional flagging on the target data. Since we have established an image model in the previous section, we can use it to look at the residuals by dividing out the model. We can make a similar plot to Figure 11 above, however, we will divide the image model that was created. The division will help us to see low level interfrence we might not otherwise notice by just looking at the data column. Since we performed full-polarization imaging, we can also do the same to the cross-hand data RL,LR. Figures 16A & B shows example plots. You should also have a look at time plotted against amplitude and frequency against amplitude to see if there are any obvious times of interference.

# In CASA
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
       ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RR',
       plotfile='plotms_3c75-uvdist_resid_RR.png',avgspw=False,overwrite=True)

# If you made a mistake above and didn't clean the polarization as well, then this plot will be empty.
plotms(vis='3C75.ms',xaxis='uvdist',yaxis='amp',plotrange=[0,0,0,20],
       ydatacolumn='data/model_vector', field='3C75',avgtime='30',correlation='RL',
       plotfile='plotms_3c75-uvdist_resid_RL.png',avgspw=False,overwrite=True)
Figure 16A: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RR correlations.
Figure 16B: plotms plot showing Amplitude vs UV Distance residuals in wavelengths for 3C75 for RL correlations.

Since we are seeing a significant amount of weak residual interference, we will take a few steps to reduce these.

# In CASA

# tfcrop
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RR,ABS_LL',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
flagdata(vis='3C75.ms',mode='tfcrop',correlation='ABS_RL,ABS_LR',freqfit='line',extendflags=False,flagbackup=False,datacolumn='residual_data',flagdimension='freq',ntime='scan')
# rflag
flagdata(vis='3C75.ms',mode='rflag',correlation='RR,LL',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
flagdata(vis='3C75.ms',mode='rflag',correlation='RL,LR',extendflags=False,flagbackup=False,datacolumn='residual_data',ntime='scan')
# extend flags
flagdata(vis='3C75.ms',mode='extend',flagbackup=False)

This should have gotten rid of the worst remaining outliers, but will leave some residual weak RFI on certain baseline lengths. Since we are not trying to win any records on high dynamic range imaging, this additional flagging should suffice for our dataset.

In addition to residual RFI, even after calibration using the amplitude calibrator and the phase calibrator, there are likely to be residual phase and/or amplitude errors in the data. Self-calibration uses an existing model, often constructed from imaging the data itself, provided that sufficient visibility data have been obtained. This is essentially always the case with data: the system of equations is wildly over-constrained for the number of unknowns.


For an array of [math]\displaystyle{ N }[/math] antennas there are at any given instant only [math]\displaystyle{ N }[/math] gain factors, but how many visibilities?

Answer

[math]\displaystyle{ {N(N-1) \over 2} }[/math]

Since we are only considering one instance of time (i.e. one integration) this is also the number of baselines in the array. For a typical 27 antenna VLA observation that comes out to 351.


For an array with a reasonable number of antennas, [math]\displaystyle{ N }[/math] >~ 8, solutions to this set of coupled equations converge quickly. There is some discussion in the old CASA Reference Manual on self calibration (see Section 5.11), but more detailed discussion can be found in lectures on Self-calibration given at NRAO community days.

In self-calibrating data, it is useful to keep in mind the structure of a Measurement Set. There are three columns of interest for an MS: the DATA column, the MODEL column, and the CORRECTED_DATA column. In normal usage, as part of the initial split, the DATA column of the new MS is set to be equal the previous MS's CORRECTED_DATA column. The self-calibration procedure is then:

  • Produce an image (tclean) using the (corrected copy) DATA column.
  • Derive a series of gain corrections (gaincal) by comparing the DATA columns and the Fourier transform of the image, which is stored in the MODEL column. These corrections are stored in an external table.
    • Optionally, we can also derive a bandpass correction—which is also referred to as bandpass self calibration—to correct for global amplitude errors.
  • Apply these corrections (applycal) to the DATA column to form a new CORRECTED_DATA column overwriting the previous contents of CORRECTED_DATA should it exist.

The following example begins with the standard data set, 3C75.ms (resulting from the steps above). We have previously generated an IQUV multiscale image cube. We discard it for this step and create a new Stokes I image, which we will use to generate a series of gain corrections (phase only self-calibration) that will be stored in 3C75.ScG0. With this solution, we then perform bandpass self-calibration to remove any amplitude slope that might be present. Next, we apply the derived phase and amplitude corrections to the data to form a set of self-calibrated data, and then re-image the dataset (3C75_selfcal.image). For the purpose of self-calibration, note that in the clean before the self-calibration, it is important that we only use the Stokes I model so that any cleaned polarization does not affect the gaincal. We first use delmod on the MS to get rid of the previous polarized model, and run tclean to generate Stokes I-only image.

#In CASA
delmod('3C75.ms')

tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="data",
       imagename="3C75_initial_I",
       imsize=480,
       cell="3.4arcsec",
       phasecenter="",
       stokes="I",
       projection="SIN",
       specmode="mfs",
       reffreq="3.0GHz",
       nchan=-1,
       start="",
       width="",
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=0.0001,
       normtype="flatnoise",
       deconvolver="mtmfs",
       scales=[0, 6, 18],
       nterms=2,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=3500,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=750,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)

As discussed, this tclean call will ignore the polarized structure. You should not clean very deeply at this point. You want to be sure to capture as much of the source's total flux density as possible, but not include low level questionable features or sub-structures (ripples) that might be due to calibration or deconvolution artifacts. We modified the two parameters controlling tclean's minor and major cycles to the following values cycleniter=750 and niter=3500 to reflect this, but you may find that you don't even need 3500 iterations for this first tclean pass.

If you are happy with the new image, perform the following self-calibration steps:

#In CASA
gaincal(vis='3C75.ms', caltable='3C75.ScG0', field='', solint='inf', refant='ea10', 
           spw='',minsnr=3.0, gaintype='G', parang=False, calmode='p')

bandpass(vis='3C75.ms', caltable='3C75.ScB0', field='', solint='inf', refant='ea10', minsnr=3.0, spw='',
                parang = False, gaintable=['3C75.ScG0'], interp=[])

applycal(vis='3C75.ms', gaintable=['3C75.ScG0','3C75.ScB0'], spw='', applymode='calflagstrict', parang=False)

The CORRECTED_DATA column of the MS now contains the self-calibrated visibilities which will be used by next execution of tclean. The gaincal step will report a number of solutions with insufficient SNR. By default, with parameter applymode='calflag', data with no good solutions will be flagged by applycal which may or may not be a good thing. You can control the action of applycal by changing the value of parameter applymode. Setting applymode='calflagstrict' will be more stringent about flagging data points without valid calibration, while applymode='calonly' will calibrate those with solutions while passing unchanged the data without solutions. You can see ahead of time what applycal will do by executing it with applymode='trial' which will do the reporting but nothing else. In our example we used applymode='calflagstrict' , but you will notice that the reported flagged fraction has not changed much, only increasing by 0.6%. This is a good thing.

Having applied these gain and bandpass solutions, we will once again image the target measurement set which we now expect to have better gain solutions and consequently produce a better image. We do this by invoking the tclean command once again.

#In CASA
tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="corrected",
       imagename="3C75_selfcal_1",
       imsize=480,
       cell="3.4arcsec",
       phasecenter="",
       stokes="I",
       projection="SIN",
       specmode="mfs",
       reffreq="3.0GHz",
       nchan=-1,
       start="",
       width="",
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=0.0001,
       normtype="flatnoise",
       deconvolver="mtmfs",
       scales=[0, 6, 18],
       nterms=2,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=3500,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=750,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)

Commonly this self-calibration procedure is applied multiple times. In Figures 17A & B you can see a comparison of the shallow Stokes I image before self-calibration and after two self-calibration steps. The first self-calibration round was done as instructed in this section, while the second round was executed with solint='120s' and new solution tables were created (3C75.ScG1, 3C75.ScB1). You are encouraged to think about what parameters should and should not differ between the round 1 and round 2 self calibration stages, but they are provided below.


Round 2 of Self Cal
#In CASA
gaincal(vis='3C75.ms', caltable='3C75.ScG1', field='', solint='120s', refant='ea10', 
           spw='',minsnr=3.0, gaintype='G', parang=False, calmode='p')

bandpass(vis='3C75.ms', caltable='3C75.ScB1', field='', solint='inf', refant='ea10', minsnr=3.0, spw='',
                parang = False, gaintable=['3C75.ScG1'], interp=[])

applycal(vis='3C75.ms', gaintable=['3C75.ScG1','3C75.ScB1'], spw='', applymode='calflagstrict', parang=False)

#Producing the Figure 17B image
tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="corrected",
       imagename="3C75_selfcal_2",
       imsize=480,
       cell="3.4arcsec",
       phasecenter="",
       stokes="I",
       projection="SIN",
       specmode="mfs",
       reffreq="3.0GHz",
       nchan=-1,
       start="",
       width="",
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=0.0001,
       normtype="flatnoise",
       deconvolver="mtmfs",
       scales=[0, 6, 18],
       nterms=2,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=3500,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=750,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)

Note that only the gaincal call used the 120s solint. The bandpass of the VLA antennas are generally stable in time so it is relatively rare to have a case for using a time variable bandpass. Also note that the new solution interval is not the only difference between these round 2 calls. Since our previous tclean call (imagename="3C75_selfcal_1") also used savemodel='modelcolumn' these calls will be making use of an improved model.

Figure 17A: Shallow Stokes I image before self-calibration.
Figure 17B: Stokes I image after two rounds of self-calibration.

The number of iterations is determined by a combination of the data quality, the number of antennas in the array, the structure of the source, the extent to which the original self-calibration assumptions are valid, and the user's patience. A not uncommon limitation for moderately high dynamic range imaging is that there may be baseline-based factors that modify the true visibility. If the corruptions to the true visibility cannot be modeled as antenna-based self-calibration won't help.

Self-calibration requires experimentation. Do not be afraid to remove an image, or even a set of gain corrections, change something and try again. Having said that, here are several guidelines to consider:

  • Bookkeeping is important! Suppose one conducts 9 iterations of self-calibration. Will it be possible to remember one month later (or maybe even one week later!) which set of gain corrections and images are which? In the example above, the descriptor 'selfcal_1' is attached to various files to help keep straight what is what. Successive iterations of self-cal could then be 'selfcal_2' , 'selfcal_3' , etc.
  • Care is required in setting imagename. If one has an image that already exists, CASA will continue cleaning it (if it can), which is almost certainly not what one wants during self-calibration. Rather, use a unique imagename for each pass of self-calibration.
  • A common metric for self-calibration is whether the dynamic range (= peak flux density/rms) of the image has improved. An improvement of 10% is quite acceptable.
  • Be careful when making images and setting clean regions or masks; self-calibration assumes that the model is perfect. If one cleans a noise bump, self-calibration will quite happily try to adjust the gains so that the CORRECTED_DATA describe a source at the location of the noise bump. It is far better to exclude some features of a source, or a weak source, from initial cleaning and conduct another round of self-calibration than to create an artificial source. If a real source is excluded from initial cleaning, it will continue to be present in subsequent iterations of self-calibration; if it's not a real source, one probably isn't interested in it anyway.
  • Start self-calibration with phase-only solutions (parameter calmode='p' in gaincal). As discussed in the High Dynamic Range Imaging lecture, a phase error of 20 deg is as bad as an amplitude error of 10%.
  • In initial rounds of self-calibration, consider solution intervals longer than the nominal sampling time (parameter solint in gaincal) and/or lower signal-to-noise ratio thresholds (parameter minsnr in gaincal). Depending upon the frequency and configuration and fidelity of the model image, it can be quite reasonable to start with solint='30s' or solint='60s' and/or minsnr=3. One may also want to consider specifying a uvrange, if, for example, the field has structure on large scales (small [math]\displaystyle{ u }[/math]-[math]\displaystyle{ v }[/math]) that is not well represented by the current image.
  • The task applycal will flag data with no good calibration solutions. During the initial self-calibration steps, this flagging may be excessive. If so, one can restore the flags to the state right before running applycal by using the task flagmanager.
  • You can track the agreement between the DATA, CORRECTED_DATA, and MODEL in plotms. The options in Axes tab allows one to select which column is to be plotted. If the MODEL agrees well with the CORRECTED_DATA, one can use shorter solint and/or higher minsnr values.
  • You should consider examining the solutions from gaincal by using plotms in order to assure that the corrections are sensible. Smoothly varying phases are good, jumps are usually not. (However, because the phases are often plotted ±180 degrees, there can be apparent jumps if the phases are very near +180 deg or −180 deg.)

Final Polarization Images

At this point, satisfied with the results of self-calibration, it might be a good idea to recalculate the visibility weights since some additional flagging was performed. After this, we get right to full-polarization imaging. We also suspect that there is a bright source outside of the masked field causing some imaging artifacts due to not being cleaned. We thus set the parameter pbmask value to 0.0 in order to disable masking of areas beyond the primary beam, and make the image larger to incorporate the bright source into our model in this tclean execution.

# In CASA
statwt(vis='3C75.ms', minsamp=8, datacolumn='corrected', flagbackup=True)

tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="corrected",
       imagename="3C75_final_large",
       imsize=800,
       cell="3.4arcsec",
       phasecenter="",
       stokes="IQUV",
       projection="SIN",
       specmode="mfs",
       reffreq="3.0GHz",
       nchan=-1,
       start="",
       width="",
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=-0.0001,
       pbmask=0.0,
       normtype="flatnoise",
       deconvolver="mtmfs",
       scales=[0, 6, 18],
       nterms=2,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=20000,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=1000,
       cyclefactor=1.0,
       restart=True,
       savemodel="modelcolumn",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=True)

The final restored Stokes I,Q,U, and V images are shown in Figures 18A–D. We've set the color scale to match between the images. Note that there is still a star like pattern in the residuals which are artifacts most likely due to the multi-scale multi-term multi-frequency synthesis. You can try on your own to improve upon the shown images by re-imaging and choosing a different set of multi-scale parameters that better match the scales found in the extended structure of 3C 75. Another issue to point out is looking at the Stokes V image. We do not expect a significant amount of Stokes V emission from this object, the emission you are seeing in Stokes V is most likely an effect of incorrectly solving for polarization leakages in the primary beam. In the above calibration we have only addressed leakage between the two polarization referring to the phase center. The extended beam itself, however, shows leakage which manifests itself spatially. The extended polarized emission we see in the Stokes Q and U images is not corrected for beam polarization during imaging. This, in turn, contains errors leading to polarization and de-polarization effects and causes changes to the polarization angle which increases the further away one gets from the beam center. Additionally, the two polarization beams do not sit on top of each other but are slightly offset, introducing a polarization squint. For correct and accurate polarization imaging, these two effects have to be taken into account. Imaging algorithms to address beam polarization are currently under development and will be discussed in this guide when they become available to the general user.

Figure 18A: Viewer panel of final restored Stokes I image.
Figure 18B: Viewer panel of final restored Stokes Q image.
Figure 18C: Viewer panel of final restored Stokes U image.
Figure 18D: Viewer panel of final restored Stokes V image.

Note, that these images are not yet primary beam corrected and are displayed on log scaling. You should play with the color scaling as well as the bias/contrast widget in CARTA to better see the faint emission.

Spectral & Polarization Maps

Note: If you are using CARTA then several of the next steps are actually unnecessary. If supplied a proper IQUV image CARTA will compute polarization intensity, linear polarization, fractional polarization intensity, fractional linear polarization intensity, and polarization angle maps for you. We show the steps one would have to take to manually create some of the images below for completeness. When possible the Figures shown will be using values/images that are generated soley by CARTA itself. You are encouraged though to still manually create your own set of images and then overlay them with the CARTA generated images to see that they match.

If you want to obtain a reasonable map of the in-band spectral index, like the one shown in Fig. 19A, we can compute it with the task widebandpbcor. As demonstrated earlier, the task can also correct the images for the telescope's primary beam response; this correction will make the images science ready. Parameter action='pbcor' will perform both actions (correct for the primary beam and calculate spectral index map) while parameter threshold sets minimum flux density above which the spectral index is calculated (this will allow us to mask all the noise regions).

# In CASA
widebandpbcor(vis='3C75.ms', imagename='3C75_final_large', nterms=2, threshold='1.0mJy/beam', action='pbcor',
              spwlist=[0,1,2,3,4,5,6,7], chanlist=[32,32,32,32,32,32,32,32], weightlist=[1,1,1,1,1,1,1,1])


For further study of polarization properties, you might want to convert the Stokes images into something more useful for scientific analysis. We will use CASA to calculate polarization intensity, [math]\displaystyle{ \sqrt{Q^2 + U^2 + V^2} }[/math], and polarization angle, [math]\displaystyle{ {atan2 (U,Q) \over 2} }[/math], maps from the final Stokes I,Q,U,V images. You can then look at those with CARTA. For example, Figure 19B shows the polarization intensity image. Since we've yet to apply any mask, the polarization angle image made in the next step will also contain values from low signal-to-noise data.

# In CASA

# Obtain image for the polarization intensity
immath(outfile='3C75_final.poli',mode='poli',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
# Obtain image for the polarization angle
immath(outfile='3C75_final.pola',mode='pola',imagename=['3C75_final_large.image.tt0'],sigma='0.0Jy/beam')
Figure 19A: CASA Computed spectral index map.
Figure 19B: CARTA Computed polarization intensity image.
Figure 19C: CARTA Computed polarized angles (vectors) superposed on the Stokes I raster image plane. We've selected an intensity threshold within CARTA to exclude low S/N points.

Note that for calculations of the polarization intensity and angle images you may — but do not need to — use primary beam corrected images; your results will be the same. This is because the primary beam correction cancels out in the equations for these two polarization quantities. If you want to visualize the polarization vectors on top of the Stokes I image, we need to add a mask for the low noise values.

# In CASA
!cp -r '3C75_final.poli' polimg

imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.Q.image',stokes='Q')
imsubimage(imagename='3C75_final_large.image.tt0',outfile='3C75_final.U.image',stokes='U')

subimPI='polimg'
ia.open(subimPI)
ia.calcmask(mask=subimPI+'>5e-4',name='mymask')
ia.done()

ia.open('3C75_final.Q.image')
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
ia.maskhandler('set','polithreshmask')
ia.done()

ia.open('3C75_final.U.image')
ia.maskhandler('copy',['polimg:mymask','polithreshmask'])
ia.maskhandler('set','polithreshmask')
ia.done()

immath(imagename=['3C75_final.Q.image', '3C75_final.U.image'], mode='pola', outfile='3C75_final.pola.masked')

These steps take the polarized intensity image calculated above (Figure 19B) and create a mask using a polarization intensity threshold of 5e-4 Jy/beam. This mask is then applied to the Q and U images from the image cube that was generated above. Then a new polarization angle image is calculated from the Q & U image planes, applying the mask created from the polarization intensity image. Finally, we can load the Stokes I as raster image into CARTA and add the polarization angle as vectors. You can do this by matching the final IQUV image, 3C75_final_large.image.tt0, and the newly created polarization angle image in WCS space by clicking the "XY" under the "Matching" column of the Image List widget. Then open the Vector Overlay Configuration widget to create the vectors. You can compare the vectors calculated with immath to the ones that CARTA generates for you. You may notice that there are some vectors that appear to disagree with each other. If so, it is likely caused by the pixel averaging being done within CARTA, which you can toggle off to confirm. Figure 19C shows the resulting image. One can clearly see that the linear polarization angle follows perpendicular to the extended structure. This indicates that the magnetic field lines are oriented along the extended structure, perpendicular to the linear polarization angles.

Rotation Measures

The plane of polarization of light is rotated by the magnetic fields present in the intervening plasma. The total rotation to the plane of polarization of light between the source and the user is called Faraday Rotation. Prior to the wide bandwidth capabilities, these rotation measures were computed by fitting a line to the polarization position angle as a function of the square of the wavelength of measurement. The slope of the resulting fit was deemed to be the RM of the source while the intercept would give the true polarization position angle of the source. With the wide bandwidths, it is now possible to determine the rotation measure of the source using the naive fitting approach by making images per spectral window in IQUV and fitting the data (polarization position angle vs lambda^2) with a line.

We show how to produce such images with one last tclean call using the following parameters. Since this is the last tclean call you'll need to perform to complete the guide we'll give you the opportunity to see if you can construct it yourself (Tip: using 'inp tclean' in CASA to see the inputs for the command will be quite useful). Remember two key differences in this call as compared to the previous:

- You are making a cube with one spectral window per plane

- You already know where the emission is (i.e. you have a mask)


The final tclean
# In CASA
tclean(vis='3C75.ms',
       field="3C75",
       spw="",timerange="",
       uvrange="",antenna="",scan="",observation="",intent="",
       datacolumn="corrected",
       imagename="3C75_chan8",
       imsize=800,
       cell="3.4arcsec",
       phasecenter="",
       stokes="IQUV",
       projection="SIN",
       specmode="cube",
       reffreq="",
       nchan=-1,
       start="",
       width=64,
       outframe="LSRK",
       veltype="radio",
       restfreq=[],
       interpolation="linear",
       gridder="standard",
       mosweight=True,
       cfcache="",
       computepastep=360.0,
       rotatepastep=360.0,
       pblimit=-0.0001,
       pbmask=0.0,
       mask='3C75_final_large.mask',
       normtype="flatnoise",
       deconvolver="multiscale",
       scales=[0, 6, 18],
       nterms=1,
       smallscalebias=0.6,
       restoration=True,
       restoringbeam=[],
       pbcor=False,
       outlierfile="",
       weighting="briggs",
       robust=0.5,
       npixels=0,
       uvtaper=[],
       niter=20000,
       gain=0.1,
       threshold=0.0,
       nsigma=0.0,
       cycleniter=1000,
       cyclefactor=1.0,
       restart=True,
       savemodel="none",
       calcres=True,
       calcpsf=True,
       parallel=False,
       interactive=False)

Here's the differences as compared to the previous tclean:

  • specmode="cube": This tells tclean we want a cube (i.e. separate images for separate frequencies) instead of a continuum image (specmode='mfs')
  • width=64: This tells tclean how wide in number of channels (i.e. frequency) each plane of the cube should be. We wanted one plane per spectral window and our spectral windows are 64 channels wide each.
  • mask='3C75_final_large.mask': We created this in our previous tclean call by interactively drawing it in the GUI. We call it again here to reuse it.
  • deconvolver="multiscale": Previously we used 'mtmfs' which stands for Multi-Term (Multi-scale) Multi-Frequency Synthesis. Since we are making per spectral window images this time were are no longer in the wideband regime and therefore drop the multi-frequency aspect.
  • nterms=1: Same reasoning as the change in deconvolver. Since we are making per spectral window images we need not worry about the spectral index of each image (i.e. we can assume each spectral window has a flat spectrum).
  • savemodel="none": This change is not strictly needed, but since we have no intention of changing our model with this run of tclean it is good form to make sure this is set. It would be a shame to overwrite your model this late into the process only to decide later that you wanted it for some reason.
  • interactive=False: Since we already have a mask we are happy with from the previous run there is no use in having tclean's GUI pop up again.


Now we use the CASA toolkit to access data for four pixels in the image cube to visualize and fit the rotation measure.

# In CASA
import matplotlib
# to display
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np

ia.open('3C75_chan8.image')

# number of channels/frequencies
nunr = 8 

tt = ia.getchunk()
nu = np.linspace(2.551e9,3.319e9,num=nunr)
c = 2.99792458e8

Q1 = tt[418,444,1,:nunr]
U1 = tt[418,444,2,:nunr]
Q2 = tt[376,419,1,:nunr]
U2 = tt[376,419,2,:nunr]
Q3 = tt[383,401,1,:nunr]
U3 = tt[383,401,2,:nunr]
Q4 = tt[395,398,1,:nunr]
U4 = tt[395,398,2,:nunr]

chi1 = 0.5*np.arctan2(U1,Q1)
chi2 = 0.5*np.arctan2(U2,Q2)
chi3 = 0.5*np.arctan2(U3,Q3)
chi4 = 0.5*np.arctan2(U4,Q4)

#locate the values that are nan and delete these indices from nu
indx1=np.argwhere(chi1==0)
indx2=np.argwhere(chi2==0)
indx3=np.argwhere(chi3==0)
indx4=np.argwhere(chi4==0)

nu1=np.delete(nu,indx1)
lam1 = c/nu1
lamsq1 = lam1*lam1

nu2=np.delete(nu,indx2)
lam2 = c/nu2
lamsq2 = lam2*lam2

nu3=np.delete(nu,indx3)
lam3 = c/nu3
lamsq3 = lam3*lam3

nu4=np.delete(nu,indx4)
lam4 = c/nu4
lamsq4 = lam4*lam4

#drop the zero values
chi1=np.delete(chi1,indx1)
chi2=np.delete(chi2,indx2)
chi3=np.delete(chi3,indx3)
chi4=np.delete(chi4,indx4)

fit1 = np.polyfit(lamsq1,chi1,1)
fit_fn1 = np.poly1d(fit1)
slope1 = fit1[0]
intercept1 = fit1[1]
fit2 = np.polyfit(lamsq2,chi2,1)
fit_fn2 = np.poly1d(fit2)
slope2 = fit2[0]
intercept2 = fit2[1]
fit3 = np.polyfit(lamsq3,chi3,1)
fit_fn3 = np.poly1d(fit3)
slope3 = fit3[0]
intercept3 = fit3[1]
fit4 = np.polyfit(lamsq4,chi4,1)
fit_fn4 = np.poly1d(fit4)
slope4 = fit4[0]
intercept4 = fit4[1]

plt.figure(1)
plt.title('Overall Title')
plt.subplot(221)
plt.title('Point 1: (418,444)')
plt.xlabel(r'$\lambda^{2}$')
plt.ylabel(r'$\chi1$')
plt.scatter(lamsq1,chi1,color='r')
plt.plot(lamsq1,fit_fn1(lamsq1),'r--',label='$\chi$ = {:.2f}$\lambda^2$ + {:.2f}'.format(slope1,intercept1))
plt.legend(loc=2)

plt.subplot(222)
plt.title('Point 2: (376,419)')
plt.xlabel(r'$\lambda^{2}$')
plt.ylabel(r'$\chi2$')
plt.scatter(lamsq2,chi2,color='b')
plt.plot(lamsq2,fit_fn2(lamsq2),'b--',label='$\chi$ = {:.2f}$\lambda^2$ + {:.2f}'.format(slope2,intercept2))
plt.legend(loc=1)

plt.subplot(223)
plt.title('Point 3: (383,401)')
plt.xlabel(r'$\lambda^{2}$')
plt.ylabel(r'$\chi3$')
plt.scatter(lamsq3,chi3,color='g')
plt.plot(lamsq3,fit_fn3(lamsq3),'g--',label='$\chi$ = {:.2f}$\lambda^2$ + {:.2f}'.format(slope3,intercept3))
plt.legend(loc=3)

plt.subplot(224)
plt.title('Point 4: (395,398)')
plt.xlabel(r'$\lambda^{2}$')
plt.ylabel(r'$\chi4$')
plt.scatter(lamsq4,chi4,color='m')
plt.plot(lamsq4,fit_fn4(lamsq4),'m--',label='$\chi$ = {:.2f}$\lambda^2$ + {:.2f}'.format(slope4,intercept4))
plt.legend(loc=1)
plt.tight_layout()

plt.show()
#Or to save the figure
plt.savefig('3C75_rmscript_8chan4px.png')

ia.close()

The resulting plots are shown in Figure 20A. Alternatively, there exists a CASA task rmfit which does this basic fitting for you while taking into account the [math]\displaystyle{ N \pi }[/math] ambiguity (refer to [3] for more info). The fits using rmfit for our case of 3C 75 by making images per spectral window is shown in Figure 20B. Here we set the maximum acceptable position angle error to 20 degrees. If larger, then no rotation measures are calculated.

# In CASA
rmfit('3C75_chan8.image',rm='3C75_chan8_rm.image',rmerr='3C75_chan8_rm.image.err',maxpaerr=0.35)
Figure 20A: Rotation measures extracted for 4 pixels from an 8 channel image cube of 3C75.
Figure 20B: RMFIT rotation measure image generated from 8 channel image cube.

The rmfit task has many more options; for example, you are able to provide a foreground rotation measure to subtract.

Now we can compare the rotation measures extracted for the 4 pixels from the 8 channel image cube with the values derived in the rmfit for the same pixels. In most cases the values are more or less comparable.

Point RM Lin. Fit. RM RMFIT
1 -65.46 -57.29
2 10.41 66.62
3 -71.71 -65.14
4 -7.30 -5.07

If time allows you can take this even further. As our source is rather bright, we can derive an IQUV image not just per averaged spectral window as we just did, but rather per channel. To achieve this you can change the above tclean parameter width from 64 to 1, which will result in 512 channels spanning all 8 spectral windows. Note when imaging each channel, the edge channels are flagged which results in the PSF being blank for channels sourrounding each spectral window and some of the images being blank. Don't forget to change the imagename parameter when re-running tclean. Due to the increased size of the cube you may find that your machine's avaliable memory struggles to keep up with the new tclean command. If so, then you can reduce the image size to lower the required memory. For our 512 channel cube we reduced the image size from 800x800 to 270x270. If you do reduce the image size as we have then you'll need to make use of imsubimage to first reduce your old image's mask size so it can be used again for your smaller image. Following the same steps as for the 8 channel image cube (adjusting for the new number of channels and new pixel indices for our points of interest), you would then obtain the results shown in Figure 21 where again the polarization position angle as a function of lambda square is shown together with the rmfit image. We can clearly see that the source exhibits complex structure beyond a simple linear fit we performed earlier. This suggests that deriving a single RM would be an oversimplification. We should ideally perform RM Synthesis (https://arxiv.org/pdf/astro-ph/0507349.pdf). At this point in time CASA does not have an RM synthesis task.


Figure 21A: Rotation measures extracted for 4 pixels from an 512 channel image cube of 3C75.
Figure 21B: Rotation measures extracted for 4 pixels from an 512 channel image cube of 3C75 with enforced limits on y axis for points 1 and 2 to exclude outlier points from the view and see better the variation of the data.
Figure 21C: RMFIT rotation measure image generated from 512 channel image cube.