File: cass2fits.py

package info (click to toggle)
cassbeam 1.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 920 kB
  • sloc: ansic: 8,483; python: 231; sh: 171; makefile: 48
file content (103 lines) | stat: -rwxr-xr-x 4,354 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python
"""
Convert cassbeam output Jones dat files into FITS beams for meqtrees

Assumes cassbeam output files contain freq information in the filename of the form <prefix>-<freq>MHz.jones.dat
"""

import sys,os
import datetime
import pyfits as pf
import numpy as n

if __name__ == '__main__':
    from optparse import OptionParser
    o = OptionParser()
    o.set_usage('%prog [options] <CASSBEAM DAT FILES>')
    o.set_description(__doc__)
    o.add_option('-c','--clobber',dest='clobber',action='store_true',
        help='Clobber/overwrite output FITS files if they exist')
    o.add_option('-o','--output',dest='output',default='cassBeam_',
        help='Output FITS filename prefix')
    o.add_option('-p','--pixel',dest='pixel',type='float',default=0.01,
        help='Pixel scale factor in radians, this is the beampixelscale in the cassbeam output parameter file, default: 0.01')
    opts, args = o.parse_args(sys.argv[1:])

    freqs=[]
    beamCube=[]
    for fid,fn in enumerate(args):
        print 'Reading %s (%i of %i)'%(fn,fid+1,len(args))
        freq=float(fn.split('/')[-1].split('-')[1].split('MHz')[0]) #parse filename for frequency
        freqs.append(freq)
        data=n.fromfile(fn,dtype=float,sep=' ')
        data=data.reshape((data.shape[0]/8,8))
        beamCube.append(data)
    freqs=n.array(freqs)*1e6
    beamCube=n.array(beamCube)

    dim=n.sqrt(beamCube.shape[1])
    beamCube=beamCube.reshape((beamCube.shape[0],dim,dim,8))

    #normalize cube so that peak value is 1.0, is this legit or required?
    beamCube/=n.max(n.abs(beamCube))
    
    #generate a fits beam header
    templateCube=n.zeros((1,beamCube.shape[0],dim,dim),dtype=float)
    hdu=pf.PrimaryHDU(templateCube)

    ctime=datetime.datetime.today()
    hdu.header.update('DATE','%s'%ctime)
    hdu.header.update('DATE-OBS','%s'%ctime)
    hdu.header.update('ORIGIN', 'GFOSTER')
    hdu.header.update('TELESCOP', 'VLA')
    hdu.header.update('OBJECT', 'beam')
    hdu.header.update('EQUINOX', 2000.0)

    print 'Using pixel scale factor: %f radians'%opts.pixel
    # note: defining M as the fastest moving axis (FITS uses
    # FORTRAN-style indexing) produces an image that when
    # viewed with kview / ds9 etc looks correct on the sky 
    # with M increasing to left and L increasing toward top
    # of displayed image
    if beamCube.shape[1]%2==0: crpixVal=int(beamCube.shape[1]/2)
    else: crpixVal=int(((beamCube.shape[1]-1)/2)+1)

    hdu.header.update('CTYPE1', 'M')
    hdu.header.update('CDELT1', (-1.0) * opts.pixel, 'in radians')
    hdu.header.update('CRPIX1', crpixVal, 'reference pixel (one relative)')
    hdu.header.update('CRVAL1', 0.0, 'M = 0 at beam peak')
    hdu.header.update('CTYPE2', 'L')
    hdu.header.update('CDELT2', opts.pixel, 'in radians')
    hdu.header.update('CRPIX2', crpixVal, 'reference pixel (one relative)')
    hdu.header.update('CRVAL2', 0.0, 'L = 0 at beam peak')

    #determine frequency step by assuming equal frequency steps and taking the difference of the first two frequencies
    sortFreqs=n.sort(freqs)
    if freqs.shape[0]>1: freqStep=(sortFreqs[-1]-sortFreqs[0])/freqs.shape[0];
    else: freqStep=1.
    hdu.header.update('CTYPE3', 'FREQ')
    hdu.header.update('CDELT3', freqStep, 'frequency step in Hz')
    hdu.header.update('CRPIX3', 1, 'reference frequency postion')
    hdu.header.update('CRVAL3', sortFreqs[0], 'reference frequency')
    hdu.header.update('CTYPE4', 'STOKES')
    hdu.header.update('CDELT4', 1) 
    hdu.header.update('CRPIX4', 1)
    hdu.header.update('CRVAL4', -5)
    
    # in case the frequency range is irregularly sampled, add keywords giving the actual frequency values
    for i,fq in enumerate(sortFreqs):
      hdu.header.update('GFREQ%d'%(i+1),fq);

    # create initial HDUList
    hdulist = pf.HDUList([hdu])

    #for XX,XY,YX,YY,real,imag: write a fits file
    for pid,pol in enumerate(['rr','lr','rl','ll']):
    #for pid,pol in enumerate(['xx','xy','yx','yy']):
        for cid,cmplx in enumerate(['re','im']):
            #write data to FITS data
            hdu.data=beamCube[:,:,:,2*pid+cid]
            ofn=opts.output+pol+'_'+cmplx+'.fits'
            if opts.clobber or not os.path.isfile(ofn): hdulist.writeto(ofn,clobber=opts.clobber)
            else: print 'File: %s exists, and clobber parameter not set, skipping'%ofn