Difference between revisions of "Simulating ngVLA Data-CASA5.4.1"

tbd simobserve

The following tutorial shows how to simulate next generation very large array (ngVLA) data. The ngVLA is composed of different subarrays that are part of the current reference design. The configuration files are found in the "ngVLA Configuration Tools" and can be used for simulations and calculations that investigate the scientific capabilities of the ngVLA. A configuration (.cfg) file contains the information of the name of the observatory, the coordinate system which in this case is in WCS, the x, y, z antenna positions, antenna diameters in meters and the pad names of each antenna. CASA has two simulation tools available: the simobserve task and the sm toolkit. With these methods we can generate measurement sets, add thermal noise and predict model visibilities, from which one can explore the ngVLA’s imaging capabilities. The simobserve task is very user friendly but it is important to be aware that at the moment it has several limitations for making simulations for observatories other than ALMA and EVLA. For this reason, our suggested method for making simulations, specifically for advanced capabilities, is using the sm toolkit which provides a great deal of flexibility in the use of parameters even for observatories unknown by CASA.

In this tutorial we show how to properly estimate the scaling factor needed to add thermal noise to the visibilities and we present three examples for making the simulations: (i) simobserve using a model image, (ii) simobserve using a component list, and (iii) sm toolkit simulation. For more information about component lists see "this CASA guide" and "this other guide". The model image use in this guide can be found here [add link]. All our examples are at 93 GHz, single channel, 4 h of total observation, and 60 s integration time (in order to make the measurement set (ms) files small) with added thermal noise and no deconvolution. In this guide we will make a measurement set using the Main ngVLA subarray which is composed of 214 18 m antennas and that extends over a maximum baseline of 1005.4 km. The configuration file that we will use through this tutorial is called ngvla-main-revC.cfg and it is found "here".

Estimating the scaling parameter for adding thermal noise

Simobserve's parameter to corrupt the simulated data is called thermalnoise and for interferometric data the allowed values are 'tsys-atm', 'tsys-manual' or False (see more in "this CASA guide"). The option 'tsys-atm' is applicable predominantly to ALMA since it uses gain corrections, atmospheric corrections, etc for that observatory. If using the 'tsys-manual' many parameters are neccesary in order to construct the atmospheric model. Therefore, to have more flexibility and control we recommend to corrupt the simulated data using the sm toolkit, specifically the "sm.setnoise" function which in addition of 'tsys-atm' and 'tsys-manual' it also allows the option of 'simplenoise'. As the name indicates, 'simplenoise' calculate random Gaussian numbers and adds to the visibilities this noise uniformly to each antenna of the same diameter. In order to estimate the scaling factor for the 'simplenoise' parameter in sm.setnoise we use the following procedure:

The point source rms noise ($\sigma_{NA}$) in a Stokes I image is (see "setnoise function")

     $\sigma_{NA} \sim \frac{\sigma}{ \sqrt{n_{tot\,ch}\,n_{pol}\,n_{baselines}\,n_{integrations} }}$   (1)


where $\sigma$ is the simplenoise parameter in sm.setnoise and corresponds to the noise in amplitude per visibility, $n_{tot\,ch}$ is the total number of channels, $n_{pol}$ are the number of polarizations in the measurement set (typically 2) and $n_{integrations}$ are the number of correlator integration times in the measurement set (~ track time / int. time). For this example, the track time is 4 h, the integration time is 60 s and the total number of channels is 1, thus $n_{integrations}=240$. The number of baselines $n_{baselines}$ is estimated by $N(N-1)/2$ where N is the number of antennas in the array. In this case, N=214 thus $n_{baselines}= 22791$.

If we know the rms that we want for our resulting image, we can solve for $\sigma$ which is the scaling parameter of the simplenoise parameter in sm.setnoise.

If instead you want to calculate the expected rms noise for an ngVLA image we suggest the below procedure. Following is an example for a simulation at 93 GHz, single channel, 60 s integration time and 4 h of total observation:

(i) Calculate the expected naturally weighted point source sensitivity in a ngVLA performance table. The "ngVLA memo #55 " in Appendix D have key performance metrics for 6 subarrays including the Main interferometric array of the ngVLA where we can find the noise performance values as a function of frequency. For our example, we find in the ngVLA memo #55 Table 10 that the naturally weighted rms at 93 GHz for 1 hour is 0.83 uJy/beam.

(ii) Scale that number to the desired track time, in this case $t_{track}=4\,h$. Therefore, $0.83/\sqrt{(t_{track}/1\,hour)} = 0.415\,\text{uJy/beam}$.

(iii) Use the desired image noise into the above equation 1 to solve for the simplenoise parameter $\sigma$. In this case, $\sigma=0.415*\sqrt{1*2*240*22791} = 1.4\,\text{mJy}$.

We run sm.setnoise and corrupt the visibilities of the noise-free measurement set using the derived simplenoise parameter $\sigma$ as follows:

# In CASA
!cp noise_free.ms noisy.ms
sm.openfromms('noisy.ms')
sm.setnoise(mode = ’simplenoise’, simplenoise = sigma)
sm.corrupt()
sm.done()


and your resulting image will have a rms ~ point source noise. Below we present examples of how to make noise-free ms and how to corrupt those visibilities using sm.setnoise.

Simobserve using a model image

We start by making a noise-free ms.

# In CASA
## Using the configuration file obtained from the ngVLA's website
conf_file = 'ngvla-main-revC.cfg'
proj_name = 'ngVLA_214_ant_60s_noise_free'

simobserve(project = proj_name,
skymodel = 'my_model.fits',
inbright = '',
incenter = '93GHz',
inwidth = '1GHz' ,
setpointings = True,
integration = '60s',
direction = '',
mapsize = '',
obsmode = 'int',
antennalist = conf_file,
hourangle = 'transit',
totaltime = '14400',
thermalnoise = '',
graphics = 'none',
overwrite = True)


project: Simobserve will generate a folder with the project name which will contain all the resulting files including the noise-free ms.

skymodel: The input model image in Jy/pixel units. %We overwrite the fits header to assume that the model is valid for 93 GHz with the incenter parameter and the bandwidth to 1 MHz with inwidth.

%setpointings: allows simobserve to derive the pointing positions by its own algorithm. Given that the primary beam at Q-band is about 1 arcminutes (see the VLA observational status summary (OSS)), and the size of the model is less than an arcsecond, a single pointing will be adequate.

integration: To avoid time smearing, we follow the guidance for data rates in the VLA OSS and assume 2s integration time per visibility.

direction: the center of the map. For a single pointing this is equivalent to the pointing center. Should we specify?

obsmode: int is used for interferometric data.

antennalist: the ngVLA configuration antenna position file in this case it corresponds to the ngVLA Main interferometric array. The files are available in the "ngVLA's website". Alternatively, the configuration files can be found in CASA in this path: casa.values()[0]['data']+'/alma/simmos/'.

hourangle: is used to simulate observations at a specific hour angle. We use 'transit' for culmination.

totaltime: This is the total track time, in this case the time on source.

thermalnoise: We leave this parameter empty for this noise-free simulation.

graphics: 'both' will show graphics on the screen such as and save them as png files in the project directory. However, at the moment is not implemented for baselines larger than a few hundred of km. For this reason for our example we use graphics: 'none'.

sm toolkit using either a model image or a component list

# In CASA
## Using the configuration file obtained from the ngVLA's website
conf_file = 'ngvla-main-revC.cfg'

## If the configuration file is already part of CASA use:
## configdir = casa.values()[0]['data']+'/alma/simmos/'

## Use simutil to read the .cfg file
from simutil import simutil
u = simutil()
## or use this if the .cfg file is already part of CASA:

##############################################################
## Setting the observation framework  making the resources,
## similar to what we would do in the OPT when setting up
## our observations.
##############################################################

## Simulate measurement set using the simulation utilities sm tool
ms_name = 'ngVLA_214_ant_60s_noise_free.ms'     ## Name of your measurement set
sm.open( ms_name )

## Get the position of the ngVLA using the measures utilities (me)
pos_ngVLA = me.observatory('ngvla')

## set the antenna configuration using the sm tool using the positions,
## diameter and names of the antennas as read from the configuration file
sm.setconfig(telescopename = telescope, x = xx, y = yy, z = zz,
dishdiameter = diam.tolist(), mount = 'alt-az',
coordsystem = 'global', referencelocation = pos_ngVLA)

## set the spectral windows, in this case is a single channel
## simulation with a channel resolution of 1 MHz and bandwidth of 1 MHz
sm.setspwindow(spwname = 'Band6', freq = '93GHz', deltafreq = '1MHz',
freqresolution = '1MHz', nchannels = 1, stokes = 'RR RL LR LL')

## set feed parameters for the antennas
sm.setfeed('perfect R L')

## set the field of observation that we are going to simulate
## (where the telescope is pointing), in this example we are using
## a Dec of +24deg
sm.setfield(sourcename = 'My source',
sourcedirection = ['J2000','00h0m0.0','+24.0.0.000'])

## set the limit of the observation for the antennas
sm.setlimits(shadowlimit = 0.001, elevationlimit = '8.0deg')

## weight to assign autocorrelation
sm.setauto(autocorrwt = 0.0)

## integration time or how often the array writes one visibility
integrationtime = '60s'
sm.settimes(integrationtime = integrationtime, usehourangle = True,
referencetime = me.epoch('utc', 'today'))

## setting the observation time, which for our example is 4 h
starttime = '-2h'
stoptime = '2h'
sm.observe('My source', 'Band6', starttime = starttime, stoptime = stoptime)


Now we are going to write a scan of a source using the resource made above. Set the model either using a .fits model or a component list. After that we can predict the visibilities using sm.predict tool function. If using a component list follow the steps below:

# In CASA
## Position of the source that we are observing. In this case  the source is in the same location where  the telescope is pointing
direction = me.direction(rf = 'J2000', v0 = qa.unit('00h0m0.0'), v1 = qa.unit('+24.0.0.000'))

## component list cl to make a model centered at the direction given above, and with a source of flux=3.2 Jy
cl.addcomponent(dir = direction, flux = 3.2, freq = '93GHz')

## name of the component list model
cl.rename(filename = 'my_component.cl')

## close the component list
cl.done()

## predicts the visibility of the source
sm.predict( complist = 'my_component.cl')


# In CASA
## To export the .fits file to .image
importfits( fitsimage = 'my_model.fits', imagename = 'my_model.image')

## To predict the model visibilities
sm.predict( imagename = 'my_model.image')


Note: the model image should have units of Jy/pixel and not Jy/beam which in that case will be the restored image.

Finally, in order to add thermal noise we do the following:

# In CASA
## set the noise level using the simplenoise parameter estimated in section 1
sigma = '1.4mJy'
!cp ngVLA_214_ant_60s_noise_free.ms ngVLA_214_ant_60s_noisy.ms
sm.openfromms('ngVLA_214_ant_1s_noisy.ms')
sm.setnoise(mode = ’simplenoise’, simplenoise = sigma)
## adds the noise: calculate random Gaussian numbers and add to visibilities
sm.corrupt()
sm.done()


Last checked on CASA Version 5.4.1.