Quick and Dirty ATNF Spectra line Analysis Package Cookbook


The following "cookbook" is intended to help asap testers get up and
running. It is not intended to be a comprehensive user guide. If
anything is not clear please get in contact with
Chris.Phillips@csiro.au or Malte.Marquarding@csiro.au.

***********
* General *
***********

The asap user interface is the python scripting language (ipython to
be exact). It currently uses an object oriented approach for the user
interface. One job of the testers is to give feed back to how they
like this or what they would prefer as the command line interface.

The main object in use is a scantable which initially contains the
scans from a set of observations as individual correlator
cycles. There are currently some limitations on how this data can be
averaged. For practical purposes at the moment each scan has to be
copied from the initial scan table before averaging or other
reduction.

Asap comes with built in help (help functionname), see the examples
further down in this document. ipython allows you to run shell
built-ins (ls, pwd, cd, etc). It also allows tab completion of function
names etc, so if you cannot remember full command name you can just
type the first few characters and type tab (eg pol<tab>).

Asap unses "zero-based" indexing. This means the first scan in a
scantable is scan 0. The first IF, polarisation and beam would have
index [0,0,0].

****************
* Running asap *
****************

Currently in the testing phase, asap only runs on Linux at the ATNF.

Ssh onto brage or vulcan at Epping.

 > source /nfs/aips++/weekly/aipsinit.csh  # Tempory measure
 > asap

This will start up the asap ipython interpretor.

****************
* Reading data *
****************

To read data from disk, a reader object needs to be created then the
scans copied into a scan table. This scan table will contain the
averaged (!) correlator cycles for every scan in the rpfits file.

 ASAP> scans = scantable('2003-03-16_082048_t0002.rpf')

The scantable contains all the data from the rpfits file. To reduce
the data you need to separate the individual scans. Before you do this
is is advisable to set the restfrequency etc on all scans.

 ASAP> scans.set_restfreqs([1665.4018], 'MHz')
 ASAP> scans.set_freqframe('LSRK')

This will set the rest frequency and tell asap to use LSR velocity
reference.


********************************************
* Extract scans and make a quotient spectra *
********************************************

 ASAP> q = scans.get_scan(0)
 ASAP> s = scans.get_scan(1)

 This copies the data for the first and second scan.

 ASAP> scan = quotient(s, q)

 "scan" now contains the quotient spectrum, which you might want to look at.
 The default display is to have polarisation colour stacked and scans across panels.

  ASAP> plotter.plot(scan)

 *******************************
* Time average separate scans *
*******************************

If you have observed the source with multiple source/reference cycles you
will want to average the quotient spectra together.
**Note** - You have to have time_averaged the individual scans before you
           average different scans. But you had to time average the individual
           scans before you do the quotient spectra, so you should be OK.
          - When time averaging multiple scans, asap uses rms weighting.
            Generally you have to set a mask so it can calculate the rms.
          - The default setting for a mask it to specify the channel
            range you want to *include* in the fit. The "invert=True" option
            below lets to choose the range you want to exclude (rather than
            include).

 ASAP> msk = s1.create_mask([0,100],[450,550],[900,1024]) # Include these
 ASAP> msk = s1.create_mask([250,450],[550,750],invert=True) # or exclude these

 ASAP> av = average_time(s1, s2, s3, mask=msk)

*******************
* Baseline fitting *
********************

To make a baseline fit, you must first create a mask of channels to
use in the baseline fit. Remember that the default is the range to
exclude, not include.

 ASAP> msk = scan.create_mask([1600,1700],[1900,2000])
 ASAP> scan2 = poly_baseline(scan, msk, 1)

This will fit and subtract a first order polynomial to the masked region

*****************************
* Average the polarisations *
*****************************

If you are just interested in highest SNR for total intensity you
want to average the parallel polarisations together.

 ASAP> iav = average_pol(s)


*********************
* Plotting the data *
*********************

You can plot the data at any time.
 ASAP> plotter.plot(s)

This will bring up a plot window (a separate one for each scantable at
the moment).

The plot window has 6 buttons on the bottom left hand side.

- Home: This will unzoom the window to the original zoom factor. A current
        bug means that if you change the axis units (say from channel
        to velocity) strange things happen

- Plot history (left ad right arrow). The left arrow sets the plot zoom
        to the previous value. The right arrow returns it. This allows you
        to zoom in on one feature then return the plot to how it was
        previously.

- Pan: The Cross sets the cursor to pan, or scroll mode allowing you to shift
       the plot within the window. Useful when zoomed in on a feature.

- Zoom (the letter with the magnifying glass) lets you draw a rectangle around
       a region of interest then zooms in on that region. Use the plot
       history to unzoom again.
       plotter.set_range(100,500)
       sets a permanent viewing window on the abcissa between in the range 100 to 500 in the current unit.
       plotter.set_range()
       resets this

- Save (floppy disk). Save the plot as a postscript or .png file.
       plotter.save('myfile.ps') doers the same from the command line


***********
* Fitting *
***********

Currently multicomponent Gaussian function is available. This is done
by creating a fitting object, setting up the fit and actually fitting
the data.

 ASAP> f = fitter()
 ASAP> f.set_function(gauss=1)
 ASAP> f.set_scan(s)
 ASAP> f.fit()
 ASAP> f.plot()
 ASAP> f.get_parameters()

If you want to confine the fitting to a smaller range (e.g. to avoid
band edge effects or RFI

 ASAP> f = fitter()
 ASAP> f.set_function(gauss=2)
 ASAP> msk = s.create_mask([2000,2100])
 ASAP> f.set_scan(s,msk)
 ASAP> f.fit()
 ASAP> f.plot()
 ASAP> f.get_parameters()

If you want to set the initial paramter guesses and fix specific parameters:

 ASAP> f = fitter()
 ASAP> f.set_function(gauss=2)
 ASAP> f.set_scan(s,msk)
 ASAP> f.fit()
 ASAP> p = [1.2,160.,50.,0.7,280.,100]
       # order is: [peak0,centre0,FWHM0,peak1,centre1,FWHM1]
 ASAP> fxd = [0,1,0,0,1,0] # fix the centres
 ASAP> f.set_parameters(p,fxd) # set the parameters
 ASAP> f.fit()

*********
* Units *
*********

Restfrequency, preferred velocity frame and active units need to be set
for plotting etc to give sensible velocity units.

* Set the rest frequency of the transition (in MHz, GHz etc).

 ASAP> s.set_restfreqs([1666.4018], 'MHz')

* Set the preferred velocity reference frame ('REST', 'TOPO', 'LSRD',
'LSRK', 'BARY', 'GEO', 'GALACTO', 'LGROUP', 'CMB')

 ASAP> s.set_freqframe('LSRK')

* Set the units for plotting, mask selection etc ('km/s', 'channel', 'MHz')

 ASAP> s.set_unit('km/s')

**NOTE** When the unit has been set to, say, km/s then this is the unit used
         for the create_mask function etc, ie give the mask range in km/s
         and not channels.

***************************
* Miscellaneous reduction *
***************************

* Scale a spectra by a fixed amount

 ASAP> ss = scale(s, 1.2)

* Hanning smooth the spectrum

 ASAP> ss = hanning(s)

* Bin average the spectrum and reduce the number of spectral points

 ASAP> ss = bin(s, 4)

* Save a scan

 ASAP> s.save('scan.asap')

* Read a saved scan from disk

ASAP> s = scantable('scan.asap')

* Execute a python script named 'myscript'

 ASAP> execfile('myscript')

* To see a summary of a individual or set of scans

 ASAP> print s

  or alternatively:

 ASAP> s.summary()

* Get all (reference) scans which match the pattern '*_R':

 ASAP> s = scans.get_scan('*_R')

* Or just and individual:

 ASAP> s = scans.get_scan('232p621_S')


*******************
* Object clean up *
*******************

A asap session has the potential to create a lot of scantable
objects. To list the current objects and remove unneeded ones use the
list_scan and del functions. Overwriting deletes the old one automatically

 ASAP> list_scan
----> list_scans()
The user created scantables are:
['av', 'q1', 's2', 'scans', 'q2', 's', 'ss', 'r1', 'r2', 's1']

 ASAP> del s1
 ASAP> del s2
 ASAP> del q1
 ASAP> del q2

****************
* Builtin help *
****************

All asap functions have built-in documentation. To get a summary of
all functions use

 ASAP> commands

To get help on individual tasks use the help command. For the Maths
functions do this as:

 ASAP> help quotient

For the scantable or fitter functions use the syntax

 ASAP> help scantable.set_freqframe
 ASAP> help fitter.set_scan

**NOTE** If you type "help" only, you get ipython help. To exit this mode
         you need to type ^-d (control-d).

* Notes

- Only does one IF/Pol/Beam. Need to change cursor


******************
* Worked example *
******************

commands
scans = scantable('2001-10-07_0337.rpf')
# data is auto-averaged
print scans
scans.set_restfreqs([90.663543], 'GHz')
scans.set_freqframe('LSRK')
r1 = scans.get_scan(0)
s1 = scans.get_scan(1)
r2 = scans.get_scan(2)
s2 = scans.get_scan(3)
q1 = quotient(s1,r1)
q2 = quotient(s2,r2)
del s1,s2
del r1,r2
plotter.plot(q1)
msk = q1.create_mask([100,500],[620,1024])
help scantable.average_time
av = average_time(q1, q2, mask=msk)
plotter.plot(av)
# reuse the old mask as data range hasn't changed
s = poly_baseline(av,msk,1)
plotter.plot(s)
ss = average_pol(s)
plotter.plot(ss)
ss.save('asap.test')

f = fitter()
f.set_function(gauss=1)
f.set_scan(ss)
f.fit()
f.plot()
f.get_parameters()
^d
