Table of Contents
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:3601
>>>
Use the AIPSTask
class to run AIPS tasks:
Create an instance for the task you want to run
>>>
fitld = AIPSTask('fitld')
Set attributes (adverbs)
>>>
fitld.infile = '/tmp/4C39.25.FITS'>>>
fitld.clint = 0.33
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', 'a')>>>
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 both screen and log
< 0 - Reduce output only on screen
>>>
imean.msgkill = 2>>>
imean.go() ...
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]
Table of Contents
Use the AIPSUVData
and
AIPSImage
classes to access the metadata
associated with AIPS UV data and images:
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
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 '_'.
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] ...
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']
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']]
There is an alternative way for zapping tables that might come handy if you want to zap all tables of a particular type:
>>>
uvdata.tables>>>
uvdata.zap_table('AT', -1)>>>
uvdata.tables [[1, 'AIPS HI'], [1, 'AIPS CL'], [1, 'AIPS FQ'], [1, 'AIPS AN'], [1, 'AIPS SU']]
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 = 3601
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.
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 = 3601 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 is also possible to change an existing table (although that is not very AIPS-ish):
from Wizardry.AIPSData import AIPSUVData from AIPS import AIPS AIPS.userno = 3602 data = AIPSUVData('N03L1', 'UVDATA', 1, 1) table = data.table('CL', 1) for row in table: row.real1 = [2 * x for x in row.real1] row.real2 = [2 * x for x in row.real2] row.update() table.close()
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 = 3601 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 = 3601 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()