The AIPY Cookbook
This page is for posting examples of how AIPY is used to accomplish various tasks. Examples should be fully functional (i.e. they should run), but should not have too much extraneous code.
Writing a Calibration File
A calibration file is a Python module that is imported by AIPY scripts to get deployment-specific information about your instrument. A calibration file should implement 2 functions: `get_aa(...)` and `get_catalog(...)`. These functions should return, respectively, an `AntennaArray` object representing your array, and a `SrcCatalog` containing sources to use for simulation. A bare-minimum calibration file would be something like:
import aipy as a def get_aa(freqs): # Define the location of your instrument lat, lon = '45:00', '90:00' # Create a model of the primary beam. BeamFlat is a minimal model that has unity # gain in all directions. beam = a.fit.BeamFlat(freqs) # Make a list of antennas with requisite nanosecond locations, primary beams, and # any other calibration parameters you wish to provide. ants = [ a.fit.Antenna( 0, 0, 0, beam), a.fit.Antenna( 0, 100, 0, beam), a.fit.Antenna(100, 0, 0, beam), a.fit.Antenna(100, 100, 0, beam), ] # Create an AntennaArray at the specified location with the listed antennas aa = a.fit.AntennaArray((lat,lon), ants) return aa def get_catalog(srcs=None, cutoff=None): # Pass off the request for sources to the AIPY source catalog. If desired, you can # substitute your own sources or source calibrations. return a.src.get_catalog(srcs=srcs, cutoff=cutoff)
This code can be saved as a module (named, say, `my_cal.py`), and imported into AIPY scripts that need location-specific calibrations using `-l my_cal`. Note that `my_cal.py` must be in a location where Python can find and import it. Your current working directory should suffice most of the time.
Starting a new UV File
Starting a brand-new UV file takes a bit of setup work. This example shows a bare-bones UV file setup; more detailed code for setting up a UV file is in the script `mdlvis.py`. This example creates a UV file filled with constant data. In most applications, you would probably want to import an `AntennaArray` at the beginning of a script, and you would use data from that object to fill in various fields (`latitud`, `longitud`, `antpos`, `lst`, etc.) and to simulate data.
import aipy as a uv = a.miriad.UV('new.uv', status='new') # Start a new UV file uv._wrhd('obstype','mixed-auto-cross') # Miriad header item indicating data type uv._wrhd('history','Started new file') # Record file creation for posterity # Create and initialize UV variables # a dict of variable data type is in a.miriad.data_types # This is not a complete list of variables, see MIRIAD programmer reference uv.add_var('epoch' ,'r') # Make a variable 'epoch', data type = real uv['epoch'] = 2000. # Set epoch to 2000. uv.add_var('source' ,'a') # Source we are tracking, as a string uv['source'] = 'zenith' uv.add_var('latitud' ,'d') # Latitude of our array, as a double uv['latitud'] = 0.00 uv.add_var('longitu' ,'d') # Longitude of our array, as double uv['longitu'] = 3.1415 uv.add_var('npol' ,'i') # Number of recorded polarizations, as int uv['npol'] = 1 uv.add_var('nspect' ,'i') # Number of spectra recorded per antenna/baseline uv['nspect'] = 1 uv.add_var('nants' ,'i') # Number of antennas in array uv['nants'] = 4 uv.add_var('antpos' ,'d') # Positions (uvw) of antennas. Expected to be 3*nants in length antpos = n.array([ [ 0, 0, 0], [100, 0, 0], [ 0, 100, 0], [100, 100, 0]], dtype=n.double) uv['antpos'] = antpos.transpose().flatten() # Transposition is a MIRIAD convention. You can follow it or not. uv.add_var('sfreq' ,'d') # Freq of first channel in spectra (GHz) uv['sfreq'] = .100 uv.add_var('sdf' ,'d') # Delta freq between channels uv['sdf'] = .001 uv.add_var('nchan' ,'i') # Number of channels in spectrum uv['nchan'] = 256 uv.add_var('nschan' ,'i') # Number of channels in bandpass cal spectra uv['nschan'] = 256 uv.add_var('inttime' ,'r') # Integration time (seconds) uv['inttime'] = 10 # These variables will get updated every spectrum uv.add_var('time' ,'d') uv.add_var('lst' ,'d') uv.add_var('ra' ,'d') uv.add_var('obsra' ,'d') uv.add_var('baseline','r') uv.add_var('pol' ,'i') # Now start generating data # Time steps in julian date times = n.arange(2454500., 2454501, uv['inttime']/a.const.s_per_day) for cnt,t in enumerate(times): uv['lst'] = 0. # Should be sidereal time from AntennaArray uv['ra'] = 0. # RA of source you're pointing at for i,ai in enumerate(antpos): for j,aj in enumerate(antpos): if j < i: continue crd = ai - aj # Find uvw coordinate of baseline preamble = (crd, t, (i,j)) # Set preamble to (uvw, julian date, baseline) uv['pol'] = a.miriad.str2pol['xx'] # Fix polarization as 'xx' data = n.ones((uv['nchan'],), dtype=n.complex64) # Generate some data flag = n.zeros((uv['nchan'],), dtype=n.int32) # Generate some flags (zero = valid) uv.write(preamble, data, flags) # Write this entry to the UV file del(uv) # Close the file