run_woden¶
Tests for the functions in WODEN/src/run_woden.py. These functions handle:
parsing user arguments; calculating astronomical constants;
reading in variables from an MWA metafits if requested; writing out a .json
file to input into the woden executable; calling the woden executable;
reading the binary file written out by woden; creating a uvfits file;
tidying up after the simulator.
In the following, rw is short for run_woden.py, and so rw.calc_jdcal
means the function calc_jdcal in run_woden.py.
test_command.py¶
Tests the rw.command function, which should call things on the command line
from within python. Test by running the command:
$ echo cheese > example.txt
and then reading the word “cheese” out of the file “example.txt” that should have been created.
test_calc_jdcal.py¶
Tests the rw.calc_jdcal function, which should calculate the Julian Date and
split into a integer day and fractional day values. Just test by calling
rw.calc_jdcal with two known date strings, and checking the output values
match expectations.
test_get_uvfits_date_and_position_constants.py¶
Tests the rw.get_uvfits_date_and_position_constants function,
which should calculate the LST, GST0 (greenwich sidereal time at 0 hours
of the given date), DEGPDY (rotational speed of the Earth) and UT1UTC (
difference between UT1 and UTC) for a given Long/Lat/Height array location and
UTC date. Test with two combinations of different UTC/Long/Lat/Height and
check the returned values are as expected.
test_RTS_encoding.py¶
Tests the rw.RTS_encode_baseline function, which should take two antenna
numbers and create the BASELINE number as per AIPS uvfits file convention.
Tests by running with four antenna pairs, and ensuring the output values match
expectation.
Secondly, tests the function rw.RTS_decode_baseline, which should separate
the encoded BASELINE number back into two antenna numbers. Test by decoding the
same four BASELINE numbers and ensuring the correct antenna numbers are found.
test_make_antenna_table.py¶
Tests the rw.make_antenna_table function, which should create
the antenna table that goes into a uvfits file. Test by giving it a
known set of input parameters and checking those values end up in
the correct location and format of output antenna table. The following parameters
are tested as correct:
ant_table.data['ANNAME']
ant_table.data['STABXYZ']
ant_table.data['ORBPARM']
ant_table.data['NOSTA']
ant_table.data['MNTSTA']
ant_table.data['STAXOF']
ant_table.data['POLTYA']
ant_table.data['POLAA']
ant_table.data['POLCALA']
ant_table.data['POLTYB']
ant_table.data['POLAB']
ant_table.data['POLCALB']
ant_table.header['ARRAYX']
ant_table.header['ARRAYY']
ant_table.header['ARRAYZ']
ant_table.header['FREQ']
ant_table.header['GSTIA0']
ant_table.header['DEGPDY']
ant_table.header['UT1UTC']
ant_table.header['XYZHAND']
ant_table.header['FRAME']
ant_table.header['RDATE']
ant_table.header['TIMSYS']
ant_table.header['ARRNAM']
ant_table.header['NUMORB']
ant_table.header['NOPCAL']
ant_table.header['POLTYPE']
ant_table.header['CREATOR']
test_create_uvfits.py¶
Tests the rw.create_uvfits function, which should take a whole
heap of inputs and write out a uvfits. Test by running function with a known
set of inputs, reading in the created file, and checking contents match
expectations. Along checking all the same parameters in the antenna table as
checked by test_make_antenna_table.py, the following parameters are
checked against the inputs:
data_table.data['UU']
data_table.data['VV']
data_table.data['WW']
data_table.data['BASELINE']
##Astropy automatically adds the header value to the DATE array,
##so need to subtract before comparison
data_table.data['DATE'] - data_table.header['PZERO4']
##Check the actual visisbility values are correct
data_table.data.data
data_table.header['CTYPE2']
data_table.header['CRVAL2']
data_table.header['CRPIX2']
data_table.header['CDELT2']
data_table.header['CTYPE3']
data_table.header['CRVAL3']
data_table.header['CRPIX3']
data_table.header['CDELT3']
data_table.header['CTYPE4']
data_table.header['CRVAL4']
data_table.header['CRPIX4']
data_table.header['CDELT4']
data_table.header['CTYPE5']
data_table.header['CRVAL5']
data_table.header['CRPIX5']
data_table.header['CDELT5']
data_table.header['CTYPE6']
data_table.header['CRVAL6']
data_table.header['CRPIX6']
data_table.header['CDELT6']
data_table.header['PSCAL1']
data_table.header['PZERO1']
data_table.header['PSCAL2']
data_table.header['PZERO2']
data_table.header['PSCAL3']
data_table.header['PZERO3']
data_table.header['PSCAL4']
data_table.header['PZERO4']
data_table.header['PSCAL5']
data_table.header['PZERO5']
data_table.header['OBJECT']
data_table.header['OBSRA']
data_table.header['OBSDEC']
data_table.header['GITLABEL']
data_table.header['TELESCOP']
data_table.header['LAT']
data_table.header['LON']
data_table.header['ALT']
data_table.header['INSTRUME']
test_enh2xyz.py¶
Tests the rw.enh2xyz function, which should calculate the local X,Y,Z coords
using the local east, north, height. Test using the cases where latitude is 0
and -30 deg, which have analytically predictable outcomes. This runs the same
test as descibred in test_RTS_ENH2XYZ_local.c.
test_load_data.py¶
Tests the rw.load_data function, which should read in a binary
file as output by woden_float or woden_double, into various arrays.
Test by writing out a binary file with known input params, reading in that
binary file using rw.load_data, and comparing the inputs to outputs. The
test is run in both 32 and 64 bit precision.
test_write_json.py¶
Test the rw.write_json function, which writes an input file to feed into
either woden_float or woden_double. A number of tests are run, all of
which call rw.write_json using a minimum set of example input arguments.
The resulting .json is then read back in, and the following parameters are
checked as correct:
json_data['ra0']
json_data['dec0']
json_data['num_freqs']
json_data['num_time_steps']
json_data['cat_filename']
json_data['time_res']
json_data['frequency_resolution']
json_data['chunking_size']
json_data['jd_date']
json_data['LST']
json_data['array_layout']
json_data['lowest_channel_freq']
json_data['latitude']
json_data['coarse_band_width']
json_data['band_nums']
The following tests run with the following optional arguments:
test_write_gaussian_beam: checks that extra arguments that control the Gaussian primary beam are written correctly
test_write_MWA_FEE_beam: checks that extra arguments that control the MWA FEE beam are written correctly
test_write_MWA_FEE_beam_interp: checks that extra arguments that control the interpolated MWA FEE beam are written correctly
test_write_MWA_analy_beam: checks that extra arguments that control analytic MWA beam are written correctly
test_write_EDA2_beam: checks that extra arguments that control the EDA2 beam are written correctly
test_write_no_precession: checks that the option to turn off precession is added when asked for
test_make_baseline_date_arrays.py¶
Tests the rw.make_baseline_date_arrays function, which should make
the DATE and BASELINE arrays that are needed to populate a uvfits file. Test
by giving the function a known date string, number of antennas, number of time
steps, and time resolution, and checking the output arrays match expectations.
test_remove_phase_tracking.py¶
Tests the rw.remove_phase_tracking function, which should remove
the phase tracking applied to visibilities. The original MWA correlator
did not phase track, so the RTS expects no phase tracking on the data, so
to input WODEN simulations into the RTS, have to undo the phase-tracking.
The RTS calculates it’s own u,v,w, so I only fiddle the visibilities
here so be warned.
This test starts by creating a random array layout via:
num_antennas = 50
##Make a random array layout
east = np.random.uniform(-1000, 1000, num_antennas)
north = np.random.uniform(-1000, 1000, num_antennas)
height = np.random.uniform(0, 10, num_antennas)
These coordinates can then be used the calculate u,v,w coodinates for a given array location (I’m using the MWA site) and phase-centre.
First of all, for 10 frequency channels (100MHz to 190MHz at 10MHz resolution), and for 10 time steps (at a 2s resolution), calculate the phase-tracked measurement equation:
where the \(u,v,w\) and \(l,m,n\) are calculated with a phase centre of RA, Dec = \(40^\circ, -50^\circ\), and I calculate a single \(l,m,n\) for a source at RA, Dec = \(10^\circ, -15^\circ\) (so in this setup, \(u,v,w\) change with time, and \(l,m,n\) are constant).
I also calculate the measurement equation without phase tracking, where I calculate \(u_{\mathrm{zen}},v_{\mathrm{zen}},w_{\mathrm{zen}}\) and \(l_{\mathrm{zen}},m_{\mathrm{zen}},n_{\mathrm{zen}}\), using the zenith of the instrument as a coordinate system centre, and use the following equation:
(in this setup, \(u_{\mathrm{zen}},v_{\mathrm{zen}},w_{\mathrm{zen}}\) are constant with time, and \(l_{\mathrm{zen}},m_{\mathrm{zen}},n_{\mathrm{zen}}\) change with time).
I then use \(V_{\textrm{phased}}\) as an input to rw.remove_phase_tracking
along with \(w\), and use that to unwrap the phase tracking. I then assert
that the output of rw.remove_phase_tracking matches \(V_{\textrm{unphased}}\).
test_argument_inputs.py¶
These tests run rw.get_parser, which runs the command line parser, and
rw.check_args, which checks the args collected by rw.get_parser
are parsed correctly. It also does sanity checks on certain combinations of args
such that we don’t feed WODEN arguments that won’t work. The following tests are run
with the expected outcomes:
test_parser_fails: There are three required arguments,--ra0,--dec0, and--cat_filename. Check the parser errors if missing.
test_missing_args_without_metafits_fails: If the user doesn’t supply the--metafitsarg, there are a minimum set of arguments that must be input. Checkrw.check_argserrors if they are missing
test_metafits_read_fails: Checkrw.check_argserrors if there is a bad path to a metafits file
test_read_metafits_succeeds: Check the correct values are read in from a known metafits file
test_EDA2_args_work: Check the correct arguments are selected for an EDA2 beam simulation
test_GaussBeam_args_work: Check that Gaussian beam related arguments work as expected. Iteratively check that if arguments with defaults are not given (e.g.--gauss_ra_point) that they are set to their defaults, and if they are supplied, that they match the given value.
test_MWAFEEBeam_args_work: Checks that the MWA FEE primary beam is handled byra.check_argscorrectly. The function should error out if certain paths to the hdf5 file that holds the spherical harmonic information is missing, and if the delays have been specified incorrectly. Check that things work when the correct arguments are given.
test_MWAFEEBeamInterp_args_work: Same astest_MWAFEEBeam_args_work, but for the interpolated FEE beam.
test_MWAAnalyBeam_args_work: Checks for the analytic MWA beam. Same astest_MWAFEEBeam_args_work, but only checking the delays are set correctly, as no need for an hdf5 file for this model
test_read_uvfits_into_pyuvdata.py¶
This tests the absolute minimal compliance with pyuvdata. The test calls
rw.create_uvfits with a set of dummy input variables to make a file
called unittest_example.uvfits. It then simply checks that the following
lines don’t throw an error:
from pyuvdata import UVData
UV = UVData()
UV.read('unittest_example.uvfits')
This really only tests that the correct keywords and arrays are present in the
output unittest_example.uvfits to a level that appeases pyuvdata.
The test is setup to skip if the user has not installed pyuvdata.