ParselTongue Demo

Mark Kettenis

JIVE

Table of Contents

1. Starting an interactive ParselTongue session
2. Running AIPS tasks
3. Array Indexing
4. Accessing AIPS data
Headers
Tables
Convenience functions
Cleaning up
Catalogs
5. The AIPS TV
6. Scripts
7. Wizardry

Chapter 1. Starting an interactive ParselTongue session

For this tutorial we will use an interactive ParselTongue session:

$ ParselTongue
Python 2.3.4 (#1, Oct  5 2004, 00:17:14) 
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type "help", "copyright", "credits" or "license" for more information.

Welcome to ParselTongue
Please enter your AIPS user ID number: 3602
>>>

Chapter 2. Running AIPS tasks

Use the AIPSTask class to run AIPS tasks:

  1. Create an instance for the task you want to run

    >>> fitld = AIPSTask('fitld')
    

  2. Set attributes (adverbs)

    >>> fitld.infile = '/tmp/4C39.25.FITS'
    >>> fitld.clint = 0.33
    

  3. Go!

    >>> fitld.go()
    ...
    

Attributes are not shared between instances:

>>> fitld2 = AIPSTask('fitld')
>>> print fitld.clint
0.33
>>> print fitld2.clint
0.0

AIPS Tasks can return attributes:

>>> imean = AIPSTask('imean')
>>> imean.inname = '4C39.25'
>>> imean.inclass = 'ICL001'
>>> imean.indisk = 1
>>> imean.go()
...
>>> print imean.pixavg, imean.pixstd
0.00019473816792 0.00434004655108

Output is logged to AIPS.log if you set it to a file-like object:

>>> AIPS.log = open('/tmp/pt.log', 'w+')
>>> imean.go()
...
>>> for line in open('/tmp/pt.log'): print line,
...

The verbosity of the output is controlled by AIPSTask.msgkill:

  • > 0 - Reduce output on screen

  • < 0 - Reduce output on both screen and log

>>> imean.msgkill = 2
>>> imean.go()
...

Chapter 3. Array Indexing

There are different array indexing conventions around:

  • AIPS uses 1-based array indexing (like FORTRAN)

  • Python uses 0-based array indexing (like everyone else)

Unfortunately 0-based indexing is very confusing for things like APARM. Therefore ParselTongue arrays used for task attributes are a bit special and have element 0 hardwired to None.

>>> imean.trc = AIPSList([256, 256])
>>> imean.trc[1:] = [256, 256]
>>> print imean.trc
[None, 256.0, 256.0, 0.0, 0.0, 0.0, 0.0, 0.0]

>>> imean.trc[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/export/jive/kettenis/opt/ParselTongue/share/parseltongue/python/Task.py", line 131, in __setitem__
    raise ValueError, msg
ValueError: setting element '0' is prohibited

>>> print PythonList(imean.trc)
[256.0, 256.0, 0.0, 0.0, 0.0, 0.0, 0.0]

Chapter 4. Accessing AIPS data

Use the AIPSUVData and AIPSImage classes to access the metadata associated with AIPS UV data and images:

  1. Create an instance for the data set you want to access:

    >>> uvdata = AIPSUVData('N03L1', 'UVDATA', 1, 1)
    >>> image = AIPSImage('4C39.25', 'ICL001', 1, 1)
    

Note that we refer to data sets by their name, class, disk and sequence number and not by its catalog number.

It is easy to check whether the data set actually exists in the AIPS catalog:

>>> uvdata.exists()
False
>>> image.exists()
True

These ParselTongue data can be used conveniently when running AIPS tasks:

>>> fitld = AIPSTask('fitld')
>>> fitld.infile = '/tmp/N03L1.IDI'
>>> fitld.clint = 0.33
>>> fitld.outdata = uvdata
>>> fitld.go()
...
>>> uvdata.exists()
True

Headers

You can access the header through the header attribute:

>>> uvdata.header
...
>>> uvdata.header.telescop
'EVN     '
>>> image.header
...
>>> image.header.date_obs
'2005-03-01'

Keywords are the same as for the AIPS GETHEAD verb, but lower case with '-' replaced by '_'.

Tables

What tables do we have?

>>> uvdata.tables
[[1, 'AIPS HI'], [1, 'AIPS AT'], [1, 'AIPS NX'], [1, 'AIPS CL'], [1, 'AIPS FQ'], [1, 'AIPS AN'], [1, 'AIPS SU']]

These tables can be opened for further analysis:

>>> sutable = uvdata.table('SU', 1)
>>> for row in sutable:
...     print row.source, row.raapp, row.decapp
...
3C84             49.9489485008 41.513581044
DA193            88.8813073705 39.8151637728

It is also possible to access individual rows directly:

>>> cltable = uvdata.table('CL', 1)
>>> print cltable[0]
...

Convenience functions

ParselTongue includes some convenience functions that

>>> uvdata.antennas
['MC', 'WB', 'NT', 'JB']
>>> uvdata.sources
['3C84', 'DA193']
>>> uvdata.polarizations
['R', 'L']
>>> uvdata.stokes
['RR', 'LL', 'RL', 'LR']
>>> image.stokes
['I']

Cleaning up

Finally when you're done you should clean up. The following command removes the entire data set:

>>> image.zap()
>>> image.exists()
False

It is also possible to remove individual tables:

>>> uvdata.tables
[[1, 'AIPS HI'], [1, 'AIPS AT'], [1, 'AIPS NX'], [1, 'AIPS CL'], [1, 'AIPS FQ'], [1, 'AIPS AN'], [1, 'AIPS SU']]
>>> uvdata.table('NX', 1).zap()
>>> uvdata.tables
[[1, 'AIPS HI'], [1, 'AIPS AT'], [1, 'AIPS CL'], [1, 'AIPS FQ'], [1, 'AIPS AN'], [1, 'AIPS SU']]

Catalogs

Use the AIPSCat to access the AIPS catalog:

>>> AIPSCat()
{1: [{'name': '4C39.25', 'seq': 1, 'klass': 'ICL001', 'time': '15:53:17', 'date': '23-Nov-2006', 'cno': 1, 'type': 'MA'}, {'name': 'N03L1', 'seq': 1, 'klass': 'UVDATA', 'time': '15:54:23', 'date': '23-Nov-2006', 'cno': 2, 'type': 'UV'}], 2: [], 3: [], 4: []}

That perhaps is not terribly enlightening, but you can easily print it in a nicely formatted way:

>>> print AIPSCat()
Catalog on disk  1
 Cat Mapname      Class   Seq  Pt     Last access
   1 4C39.25     .ICL001.    1 MA 23-Nov-2006 15:53:17
   2 N03L1       .UVDATA.    1 UV 23-Nov-2006 15:54:23
Catalog on disk  2
 Cat Mapname      Class   Seq  Pt     Last access
Catalog on disk  3
 Cat Mapname      Class   Seq  Pt     Last access
Catalog on disk  4
 Cat Mapname      Class   Seq  Pt     Last access

If you're only interested in a particular disk:

>>> print AIPSCat(1)
Catalog on disk  1
 Cat Mapname      Class   Seq  Pt     Last access
   1 4C39.25     .ICL001.    1 MA 23-Nov-2006 15:53:17
   2 N03L1       .UVDATA.    1 UV 23-Nov-2006 15:54:23

It is possible to zap the entire AIPS catalog:

>>> AIPSCat().zap()
>>> AIPSCat()
{1: [], 2: [], 3: [], 4: []}

Chapter 5. The AIPS TV

If you have a (non local) AIPS TV running, ParselTongue will automatically use it. Otherwise, you can use the AIPSTV class to start one:

>>> tv = AIPSTV()
>>> tv.start()

Once the TV is running you can direct output to it:

>>> kntr = AIPSTask('kntr')
>>> kntr.indata = image
>>> kntr.docont = 0
>>> kntr.dovect = 0
>>> kntr.dotv = 1
>>> kntr.go()

Simple interaction with the TV is possible:

>>> tv.clear()
>>> tv.kill()

Chapter 6. Scripts

In order to use ParselTongue from scripts you'll need to import the appropriate ParselTongue modules and set your AIPS user number. For the examples we have seen before, something like the following will suffice:

from AIPS import AIPS
from AIPSTask import AIPSTask, AIPSList
from AIPSData import AIPSUVData, AIPSImage

AIPS.userno = 3602

Starting ParselTongue scripts is easiest done by using the ParselTongue command:

$ ParselTongue script.py

This will start Python with all the magic environment variables set.

Chapter 7. Wizardry

For Hogwarts graduates it is even possible to create new extension tables. The following bit of code creates a new CL table with a different amplitude calibration:

from AIPS import AIPS
from Wizardry.AIPSData import AIPSUVData

AIPS.userno = 3602

data = AIPSUVData('N03L1', 'UVDATA', 1, 1)
oldcl = data.table('CL', 1)

newcl = data.attach_table('CL', 2, no_term=oldcl.keywords['NO_TERM'])
newcl.keywords['NO_ANT'] = oldcl.keywords['NO_ANT']

for row in oldcl:
    row.real1 = [2 * x for x in row.real1]
    row.real2 = [2 * x for x in row.real2]
    newcl.append(row)

newcl.close()
oldcl.close()

Wizardry.AIPSUVData is very similar to the normal AIPSUVData but is in a different module because it doesn't support remote executaion like AIPSUVData does. Remote execution will be adressed later in this workshop.

It's also possible to get at the actual visibilities in a UV data set. Here is a little script that uses matplotlib to make a UV coverage plot:

from Wizardry.AIPSData import AIPSUVData
from AIPS import AIPS

from pylab import plot, show

AIPS.userno = 3602

data = AIPSUVData('MULTI', 'UVDATA', 1, 3)
u = []
v = []
for visibility in data:
    u.append(visibility.uvw[0])
    v.append(visibility.uvw[1])

plot(u, v, '.')
show()

And here is a script that makes a plot of the phase for a single channel on a randomly chosen baseline:

from Wizardry.AIPSData import AIPSUVData
from AIPS import AIPS

from pylab import plot, show
from math import atan2

AIPS.userno = 3602

data = AIPSUVData('MULTI', 'UVDATA', 1, 3)
phase = []
time = []
for visibility in data:
    if visibility.baseline == [1, 2]:
        re = visibility.visibility[0, 0, 0, 0]
        im = visibility.visibility[0, 0, 0, 1]
        phase.append(atan2(re, im))
        time.append(visibility.time)

plot(time, phase, '.')
show()