예제 #1
0
    def test_create_groupdata(self):
        """
        Basic test for creating GroupData from scratch.
        """

        imdata = np.arange(100.0)
        imdata.shape = (10, 1, 1, 2, 5)
        pdata1 = np.arange(10, dtype=np.float32) + 0.1
        pdata2 = 42.0
        x = fits.hdu.groups.GroupData(imdata,
                                      parnames=['abc', 'xyz'],
                                      pardata=[pdata1, pdata2],
                                      bitpix=-32)
        assert x.parnames == ['abc', 'xyz']
        assert (x.par('abc') == pdata1).all()
        assert (x.par('xyz') == ([pdata2] * len(x))).all()
        assert (x.data == imdata).all()

        # Test putting the data into a GroupsHDU and round-tripping it
        ghdu = fits.GroupsHDU(data=x)
        ghdu.writeto(self.temp('test.fits'))

        with fits.open(self.temp('test.fits')) as h:
            hdr = h[0].header
            assert hdr['GCOUNT'] == 10
            assert hdr['PCOUNT'] == 2
            assert hdr['NAXIS'] == 5
            assert hdr['NAXIS1'] == 0
            assert hdr['NAXIS2'] == 5
            assert hdr['NAXIS3'] == 2
            assert hdr['NAXIS4'] == 1
            assert hdr['NAXIS5'] == 1
            assert h[0].data.parnames == ['abc', 'xyz']
            assert comparerecords(h[0].data, x)
예제 #2
0
    def gen_vis_table(self):
        """Generate visibility table and fill payload."""

        baselines = []
        ant_pos = self.config.get_antenna_positions()
        loc = self.config.get_loc()
        for cal_vis in self.v_array:
            ra, dec = self.phase_center.radec(cal_vis.vis.timestamp)
            # v.rotate(skyloc.Skyloc(ra, dec))
            uu_a, vv_a, ww_a = cal_vis.get_all_uvw()
            bls = cal_vis.get_baselines()
            datestamp = tart_util.get_julian_date(cal_vis.vis.timestamp) - int(
                tart_util.get_julian_date(cal_vis.vis.timestamp) + 0.5
            )
            for uu, vv, ww, b in zip(uu_a, vv_a, ww_a, bls):
                baseline = {}
                [i, j] = b
                # print((np.array(a1.enu) - np.array(a0.enu)), uu, vv, ww)
                # arcane units of UVFITS require u,v,w in nanoseconds
                baseline["UU"] = uu * constants.L1_WAVELENGTH / constants.V_LIGHT
                baseline["VV"] = vv * constants.L1_WAVELENGTH / constants.V_LIGHT
                baseline["WW"] = ww * constants.L1_WAVELENGTH / constants.V_LIGHT
                baseline["BASELINE"] = encode_baseline(i + 1, j + 1)
                baseline["DATE"] = datestamp
                # DATE FIXME ?
                baselines.append(baseline)

        freqs = np.array([1545.0])
        pols = np.array(["+"])

        data = np.zeros(
            (len(self.v_array) * self.n_baselines, 1, 1, len(freqs), len(pols), 3)
        )

        for i, v in enumerate(self.v_array):
            for k, b in enumerate(cal_vis.get_baselines()):
                for l, _ in enumerate(freqs):
                    for j, _ in enumerate(pols):
                        vis = v.get_visibility(b[0], b[1])
                        re = vis.real
                        img = vis.imag
                        w = np.ones(1)
                        data[i * self.n_baselines + k, 0, 0, l, j, :] = [re, img, w]

        hdu = fits.GroupsHDU(
            fits.GroupData(
                data,
                parnames=["UU", "VV", "WW", "BASELINE", "DATE"],
                bitpix=-32,
                pardata=[
                    [b["UU"] for b in baselines],
                    [b["VV"] for b in baselines],
                    [b["WW"] for b in baselines],
                    [b["BASELINE"] for b in baselines],
                    [b["DATE"] for b in baselines],
                ],
            )
        )
        return hdu
예제 #3
0
    def test_append_groupshdu_to_non_empty_list(self):
        """Tests appending a Simple GroupsHDU to an empty HDUList."""

        hdul = fits.HDUList()
        hdu = fits.PrimaryHDU(np.arange(100, dtype=np.int32))
        hdul.append(hdu)
        hdu = fits.GroupsHDU()
        hdul.append(hdu)
예제 #4
0
def test_select_read_nospw_pol(casa_uvfits, tmp_path):
    # this requires writing a new file because the no spw file we have has only 1 pol

    with fits.open(casa_tutorial_uvfits, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data
        raw_data_array = raw_data_array[:, :, :, 0, :, :, :]

        vis_hdr["NAXIS"] = 6

        vis_hdr["NAXIS5"] = vis_hdr["NAXIS6"]
        vis_hdr["CTYPE5"] = vis_hdr["CTYPE6"]
        vis_hdr["CRVAL5"] = vis_hdr["CRVAL6"]
        vis_hdr["CDELT5"] = vis_hdr["CDELT6"]
        vis_hdr["CRPIX5"] = vis_hdr["CRPIX6"]
        vis_hdr["CROTA5"] = vis_hdr["CROTA6"]

        vis_hdr["NAXIS6"] = vis_hdr["NAXIS7"]
        vis_hdr["CTYPE6"] = vis_hdr["CTYPE7"]
        vis_hdr["CRVAL6"] = vis_hdr["CRVAL7"]
        vis_hdr["CDELT6"] = vis_hdr["CDELT7"]
        vis_hdr["CRPIX6"] = vis_hdr["CRPIX7"]
        vis_hdr["CROTA6"] = vis_hdr["CROTA7"]

        vis_hdr.pop("NAXIS7")
        vis_hdr.pop("CTYPE7")
        vis_hdr.pop("CRVAL7")
        vis_hdr.pop("CDELT7")
        vis_hdr.pop("CRPIX7")
        vis_hdr.pop("CROTA7")

        par_names = vis_hdu.data.parnames

        group_parameter_list = [
            vis_hdu.data.par(ind) for ind in range(len(par_names))
        ]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        write_file = str(tmp_path / "outtest_casa.uvfits")
        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    pols_to_keep = [-1, -2]
    uvfits_uv = UVData()
    uvfits_uv.read(write_file, polarizations=pols_to_keep)
    uvfits_uv2 = casa_uvfits
    uvfits_uv2.select(polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2
예제 #5
0
def test_multisource_error(tmp_path):
    # make a file with multiple sources to test error condition
    uv_in = UVData()
    testfile = os.path.join(DATA_PATH,
                            "day2_TDEM0003_10s_norx_1src_1spw.uvfits")
    write_file = str(tmp_path / "outtest_casa.uvfits")
    uv_in.read(testfile)
    uv_in.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = vis_hdu.data.parnames
        group_parameter_list = []

        lst_ind = 0
        for index, name in enumerate(par_names):
            par_value = vis_hdu.data.par(name)
            # lst_array needs to be split in 2 parts to get high enough accuracy
            if name.lower() == "lst":
                if lst_ind == 0:
                    # first lst entry, par_value has full lst value
                    # (astropy adds the 2 values)
                    lst_array_1 = np.float32(par_value)
                    lst_array_2 = np.float32(par_value -
                                             np.float64(lst_array_1))
                    par_value = lst_array_1
                    lst_ind = 1
                else:
                    par_value = lst_array_2

            # need to account for PZERO values
            group_parameter_list.append(par_value -
                                        vis_hdr["PZERO" + str(index + 1)])

        par_names.append("SOURCE")
        source_array = np.ones_like(vis_hdu.data.par("BASELINE"))
        mid_index = source_array.shape[0] // 2
        source_array[mid_index:] = source_array[mid_index:] * 2
        group_parameter_list.append(source_array)

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr
        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    with pytest.raises(ValueError) as cm:
        uv_in.read(write_file)
    assert str(cm.value).startswith("This file has multiple sources")
예제 #6
0
def test_source_group_params():
    # make a file with a single source to test that it works
    uv_in = UVData()
    testfile = os.path.join(DATA_PATH,
                            'day2_TDEM0003_10s_norx_1src_1spw.uvfits')
    write_file = os.path.join(DATA_PATH, 'test/outtest_casa.uvfits')
    uvtest.checkWarnings(uv_in.read, [testfile],
                         message='Telescope EVLA is not')
    uv_in.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = vis_hdu.data.parnames
        group_parameter_list = []

        lst_ind = 0
        for index, name in enumerate(par_names):
            par_value = vis_hdu.data.par(name)
            # lst_array needs to be split in 2 parts to get high enough accuracy
            if name.lower() == 'lst':
                if lst_ind == 0:
                    # first lst entry, par_value has full lst value (astropy adds the 2 values)
                    lst_array_1 = np.float32(par_value)
                    lst_array_2 = np.float32(par_value -
                                             np.float64(lst_array_1))
                    par_value = lst_array_1
                    lst_ind = 1
                else:
                    par_value = lst_array_2

            # need to account for PZERO values
            group_parameter_list.append(par_value -
                                        vis_hdr['PZERO' + str(index + 1)])

        par_names.append('SOURCE')
        source_array = np.ones_like(vis_hdu.data.par('BASELINE'))
        group_parameter_list.append(source_array)

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr
        ant_hdu = hdu_list[hdunames['AIPS AN']]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    uv_out = UVData()
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out
예제 #7
0
def test_readwriteread_error_single_time(tmp_path, casa_uvfits):
    uv_in = casa_uvfits
    uv_out = UVData()
    write_file = str(tmp_path / "outtest_casa.uvfits")
    write_file2 = str(tmp_path / "outtest_casa2.uvfits")

    # check error if one time & no inttime specified
    uv_singlet = uv_in.select(times=uv_in.time_array[0], inplace=False)
    uv_singlet.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = np.array(vis_hdu.data.parnames)
        pars_use = np.where(par_names != "INTTIM")[0]
        par_names = par_names[pars_use].tolist()

        group_parameter_list = [vis_hdu.data.par(name) for name in par_names]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file2, overwrite=True)

    with pytest.raises(ValueError) as cm:
        uvtest.checkWarnings(
            uv_out.read,
            func_args=[write_file2],
            message=[
                "Telescope EVLA is not",
                'ERFA function "utcut1" yielded 1 of "dubious year (Note 3)"',
                'ERFA function "utctai" yielded 1 of "dubious year (Note 3)"',
                "LST values stored in this file are not self-consistent",
            ],
            nwarnings=4,
            category=[
                UserWarning,
                astropy._erfa.core.ErfaWarning,
                astropy._erfa.core.ErfaWarning,
                UserWarning,
            ],
        )
    assert str(cm.value).startswith(
        "integration time not specified and only one time present")

    return
예제 #8
0
    def test_insert_groupshdu_to_begin_of_hdulist_with_groupshdu(self):
        """
        Tests inserting a Simple GroupsHDU to the beginning of an HDUList
        that that already contains a GroupsHDU.
        """

        hdul = fits.HDUList()
        hdu = fits.GroupsHDU()
        hdul.insert(0, hdu)
        hdul.insert(0, hdu)
예제 #9
0
def test_source_group_params(casa_uvfits, tmp_path):
    # make a file with a single source to test that it works
    uv_in = casa_uvfits
    write_file = str(tmp_path / "outtest_casa.uvfits")
    write_file2 = str(tmp_path / "outtest_casa2.uvfits")
    uv_in.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = vis_hdu.data.parnames
        group_parameter_list = []

        lst_ind = 0
        for index, name in enumerate(par_names):
            par_value = vis_hdu.data.par(name)
            # lst_array needs to be split in 2 parts to get high enough accuracy
            if name.lower() == "lst":
                if lst_ind == 0:
                    # first lst entry, par_value has full lst value
                    # (astropy adds the 2 values)
                    lst_array_1 = np.float32(par_value)
                    lst_array_2 = np.float32(par_value -
                                             np.float64(lst_array_1))
                    par_value = lst_array_1
                    lst_ind = 1
                else:
                    par_value = lst_array_2

            # need to account for PZERO values
            group_parameter_list.append(par_value -
                                        vis_hdr["PZERO" + str(index + 1)])

        par_names.append("SOURCE")
        source_array = np.ones_like(vis_hdu.data.par("BASELINE"))
        group_parameter_list.append(source_array)

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr
        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file2, overwrite=True)
        hdulist.close()

    uv_out = UVData()
    uv_out.read(write_file2)
    assert uv_in == uv_out
예제 #10
0
 def test_groups_hdu_data(self):
     imdata = np.arange(100.0)
     imdata.shape = (10, 1, 1, 2, 5)
     pdata1 = np.arange(10) + 0.1
     pdata2 = 42
     x = fits.hdu.groups.GroupData(imdata, parnames=[str('abc'), str('xyz')],
                                   pardata=[pdata1, pdata2], bitpix=-32)
     hdu = fits.GroupsHDU(x)
     hdu.writeto(self.temp('tmp.fits'), overwrite=True, checksum=True)
     with fits.open(self.temp('tmp.fits'), checksum=True) as hdul:
         assert comparerecords(hdul[0].data, hdu.data)
         assert 'CHECKSUM' in hdul[0].header
         assert hdul[0].header['CHECKSUM'] == '3eDQAZDO4dDOAZDO'
         assert 'DATASUM' in hdul[0].header
         assert hdul[0].header['DATASUM'] == '2797758084'
예제 #11
0
    def test_insert_groupshdu_to_empty_list(self):
        """Tests inserting a Simple GroupsHDU to an empty HDUList."""

        hdul = fits.HDUList()
        hdu = fits.GroupsHDU()
        hdul.insert(0, hdu)

        info = [(0, 'PRIMARY', 1, 'GroupsHDU', 8, (), '',
                 '1 Groups  0 Parameters')]

        assert hdul.info(output=False) == info

        hdul.writeto(self.temp('test-insert.fits'))

        assert fits.info(self.temp('test-insert.fits'), output=False) == info
예제 #12
0
    def test_duplicate_parameter(self):
        """
        Tests support for multiple parameters of the same name, and ensures
        that the data in duplicate parameters are returned as a single summed
        value.
        """

        imdata = np.arange(100.0)
        imdata.shape = (10, 1, 1, 2, 5)
        pdata1 = np.arange(10, dtype=np.float32) + 1
        pdata2 = 42.0
        x = fits.hdu.groups.GroupData(imdata,
                                      parnames=['abc', 'xyz', 'abc'],
                                      pardata=[pdata1, pdata2, pdata1],
                                      bitpix=-32)

        assert x.parnames == ['abc', 'xyz', 'abc']
        assert (x.par('abc') == pdata1 * 2).all()
        assert x[0].par('abc') == 2

        # Test setting a parameter
        x[0].setpar(0, 2)
        assert x[0].par('abc') == 3
        pytest.raises(ValueError, x[0].setpar, 'abc', 2)
        x[0].setpar('abc', (2, 3))
        assert x[0].par('abc') == 5
        assert x.par('abc')[0] == 5
        assert (x.par('abc')[1:] == pdata1[1:] * 2).all()

        # Test round-trip
        ghdu = fits.GroupsHDU(data=x)
        ghdu.writeto(self.temp('test.fits'))

        with fits.open(self.temp('test.fits')) as h:
            hdr = h[0].header
            assert hdr['PCOUNT'] == 3
            assert hdr['PTYPE1'] == 'abc'
            assert hdr['PTYPE2'] == 'xyz'
            assert hdr['PTYPE3'] == 'abc'
            assert x.parnames == ['abc', 'xyz', 'abc']
            assert x.dtype.names == ('abc', 'xyz', '_abc', 'DATA')
            assert x.par('abc')[0] == 5
            assert (x.par('abc')[1:] == pdata1[1:] * 2).all()
예제 #13
0
    def test_insert_groupshdu_to_non_empty_list(self):
        """Tests inserting a Simple GroupsHDU to an empty HDUList."""

        hdul = fits.HDUList()
        hdu = fits.PrimaryHDU(np.arange(100, dtype=np.int32))
        hdul.insert(0, hdu)
        hdu = fits.GroupsHDU()

        with pytest.raises(ValueError):
            hdul.insert(1, hdu)

        info = [(0, 'PRIMARY', 1, 'GroupsHDU', 8, (), '',
                 '1 Groups  0 Parameters'),
                (1, '', 1, 'ImageHDU', 6, (100, ), 'int32', '')]

        hdul.insert(0, hdu)

        assert hdul.info(output=False) == info

        hdul.writeto(self.temp('test-insert.fits'))

        assert fits.info(self.temp('test-insert.fits'), output=False) == info
예제 #14
0
def save_obs_uvfits(obs, fname):
    """Save observation data to uvfits.
    """

    # Open template UVFITS
    dir_path = os.path.dirname(os.path.realpath(__file__))
    #hdulist = fits.open(dir_path+'/template.UVP')

    hdulist_new = fits.HDUList()
    hdulist_new.append(fits.GroupsHDU())

    ########################################################################
    # Data table
    # Data header (based on the BU format)
    #header = fits.Header()
    #header = hdulist[0].header
    header = hdulist_new['PRIMARY'].header
    header['OBSRA'] = obs.ra * 180. / 12.
    header['OBSDEC'] = obs.dec
    header['OBJECT'] = obs.source
    header['MJD'] = float(obs.mjd)
    header['BUNIT'] = 'JY'
    header['VELREF'] = 3  # !AC TODO ??
    header['ALTRPIX'] = 1.e0
    header['TELESCOP'] = 'ALMA'  # !AC TODO Can we change this field?
    header['INSTRUME'] = 'ALMA'
    header['CTYPE2'] = 'COMPLEX'
    header['CRVAL2'] = 1.e0
    header['CDELT2'] = 1.e0
    header['CRPIX2'] = 1.e0
    header['CROTA2'] = 0.e0
    header['CTYPE3'] = 'STOKES'
    header['CRVAL3'] = -1.e0
    header['CDELT3'] = -1.e0
    header['CRPIX3'] = 1.e0
    header['CROTA3'] = 0.e0
    header['CTYPE4'] = 'FREQ'
    header['CRVAL4'] = obs.rf
    header['CDELT4'] = obs.bw
    header['CRPIX4'] = 1.e0
    header['CROTA4'] = 0.e0
    header['CTYPE6'] = 'RA'
    header['CRVAL6'] = header['OBSRA']
    header['CDELT6'] = 1.e0
    header['CRPIX6'] = 1.e0
    header['CROTA6'] = 0.e0
    header['CTYPE7'] = 'DEC'
    header['CRVAL7'] = header['OBSDEC']
    header['CDELT7'] = 1.e0
    header['CRPIX7'] = 1.e0
    header['CROTA7'] = 0.e0
    header['PTYPE1'] = 'UU---SIN'
    header['PSCAL1'] = 1.0 / obs.rf
    header['PZERO1'] = 0.e0
    header['PTYPE2'] = 'VV---SIN'
    header['PSCAL2'] = 1.0 / obs.rf
    header['PZERO2'] = 0.e0
    header['PTYPE3'] = 'WW---SIN'
    header['PSCAL3'] = 1.0 / obs.rf
    header['PZERO3'] = 0.e0
    header['PTYPE4'] = 'BASELINE'
    header['PSCAL4'] = 1.e0
    header['PZERO4'] = 0.e0
    header['PTYPE5'] = 'DATE'
    header['PSCAL5'] = 1.e0
    header['PZERO5'] = 0.e0
    header['PTYPE6'] = 'DATE'
    header['PSCAL6'] = 1.e0
    header['PZERO6'] = 0.0
    header['PTYPE7'] = 'INTTIM'
    header['PSCAL7'] = 1.e0
    header['PZERO7'] = 0.e0
    header['PTYPE8'] = 'TAU1'
    header['PSCAL8'] = 1.e0
    header['PZERO8'] = 0.e0
    header['PTYPE9'] = 'TAU2'
    header['PSCAL9'] = 1.e0
    header['PZERO9'] = 0.e0

    # Get data
    obsdata = obs.unpack([
        'time', 'tint', 'u', 'v', 'vis', 'qvis', 'uvis', 'vvis', 'sigma',
        'qsigma', 'usigma', 'vsigma', 't1', 't2', 'tau1', 'tau2'
    ])
    ndat = len(obsdata['time'])

    # times and tints
    #jds = (obs.mjd + 2400000.5) * np.ones(len(obsdata))
    #fractimes = (obsdata['time'] / 24.0)
    jds = (2400000.5 + obs.mjd) * np.ones(len(obsdata))
    fractimes = (obsdata['time'] / 24.0)
    #jds = jds + fractimes
    #fractimes = np.zeros(len(obsdata))
    tints = obsdata['tint']

    # Baselines
    t1 = [obs.tkey[scope] + 1 for scope in obsdata['t1']]
    t2 = [obs.tkey[scope] + 1 for scope in obsdata['t2']]
    bl = 256 * np.array(t1) + np.array(t2)

    # opacities
    tau1 = obsdata['tau1']
    tau2 = obsdata['tau2']

    # uv are in lightseconds
    u = obsdata['u']
    v = obsdata['v']

    # rr, ll, lr, rl, weights
    rr = obsdata['vis'] + obsdata['vvis']
    ll = obsdata['vis'] - obsdata['vvis']
    rl = obsdata['qvis'] + 1j * obsdata['uvis']
    lr = obsdata['qvis'] - 1j * obsdata['uvis']

    weightrr = 1.0 / (obsdata['sigma']**2 + obsdata['vsigma']**2)
    weightll = 1.0 / (obsdata['sigma']**2 + obsdata['vsigma']**2)
    weightrl = 1.0 / (obsdata['qsigma']**2 + obsdata['usigma']**2)
    weightlr = 1.0 / (obsdata['qsigma']**2 + obsdata['usigma']**2)

    # Data array
    outdat = np.zeros((ndat, 1, 1, 1, 1, 4, 3))
    outdat[:, 0, 0, 0, 0, 0, 0] = np.real(rr)
    outdat[:, 0, 0, 0, 0, 0, 1] = np.imag(rr)
    outdat[:, 0, 0, 0, 0, 0, 2] = weightrr
    outdat[:, 0, 0, 0, 0, 1, 0] = np.real(ll)
    outdat[:, 0, 0, 0, 0, 1, 1] = np.imag(ll)
    outdat[:, 0, 0, 0, 0, 1, 2] = weightll
    outdat[:, 0, 0, 0, 0, 2, 0] = np.real(rl)
    outdat[:, 0, 0, 0, 0, 2, 1] = np.imag(rl)
    outdat[:, 0, 0, 0, 0, 2, 2] = weightrl
    outdat[:, 0, 0, 0, 0, 3, 0] = np.real(lr)
    outdat[:, 0, 0, 0, 0, 3, 1] = np.imag(lr)
    outdat[:, 0, 0, 0, 0, 3, 2] = weightlr

    # Save data

    pars = [
        'UU---SIN', 'VV---SIN', 'WW---SIN', 'BASELINE', 'DATE', 'DATE',
        'INTTIM', 'TAU1', 'TAU2'
    ]
    x = fits.GroupData(
        outdat,
        parnames=pars,
        pardata=[u, v,
                 np.zeros(ndat), bl, jds, fractimes, tints, tau1, tau2],
        bitpix=-32)

    #hdulist[0].data = x
    #hdulist[0].header = header
    hdulist_new['PRIMARY'].data = x
    hdulist_new[
        'PRIMARY'].header = header  # TODO necessary, or is it a pointer?

    ########################################################################
    # Antenna table

    # Load the array data
    tarr = obs.tarr
    tnames = tarr['site']
    tnums = np.arange(1, len(tarr) + 1)
    xyz = np.array([[tarr[i]['x'], tarr[i]['y'], tarr[i]['z']]
                    for i in np.arange(len(tarr))])
    sefd = tarr['sefdr']

    nsta = len(tnames)
    col1 = fits.Column(name='ANNAME', format='8A', array=tnames)
    col2 = fits.Column(name='STABXYZ', format='3D', unit='METERS', array=xyz)
    col3 = fits.Column(name='NOSTA', format='1J', array=tnums)
    colfin = fits.Column(name='SEFD', format='1D', array=sefd)

    #!AC TODO these antenna fields+header are questionable - look into them

    col4 = fits.Column(name='MNTSTA', format='1J', array=np.zeros(nsta))
    col5 = fits.Column(name='STAXOF',
                       format='1E',
                       unit='METERS',
                       array=np.zeros(nsta))
    col6 = fits.Column(name='POLTYA',
                       format='1A',
                       array=np.array(['R' for i in range(nsta)], dtype='|S1'))
    col7 = fits.Column(name='POLAA',
                       format='1E',
                       unit='DEGREES',
                       array=np.zeros(nsta))
    col8 = fits.Column(name='POLCALA', format='3E', array=np.zeros((nsta, 3)))
    col9 = fits.Column(name='POLTYB',
                       format='1A',
                       array=np.array(['L' for i in range(nsta)], dtype='|S1'))
    col10 = fits.Column(name='POLAB',
                        format='1E',
                        unit='DEGREES',
                        array=(90. * np.ones(nsta)))
    col11 = fits.Column(name='POLCALB', format='3E', array=np.zeros((nsta, 3)))
    col25 = fits.Column(name='ORBPARM', format='1E', array=np.zeros(0))

    #Antenna Header params - do I need to change more of these??
    #head = fits.Header()
    tbhdu = fits.BinTableHDU.from_columns(fits.ColDefs([
        col1, col2, col25, col3, col4, col5, col6, col7, col8, col9, col10,
        col11, colfin
    ]),
                                          name='AIPS AN')
    hdulist_new.append(tbhdu)

    #head = hdulist['AIPS AN'].header
    head = hdulist_new['AIPS AN'].header

    head['EXTNAME'] = 'AIPS AN'
    head['EXTVER'] = 1
    head['RDATE'] = '2000-01-01T00:00:00.0'
    head['GSTIA0'] = 114.38389781355  # !AC TODO ?? for jan 1 2000
    head['UT1UTC'] = 0.e0
    head['DATUTC'] = 0.e0
    head['TIMESYS'] = 'UTC'
    head['DEGPDY'] = 360.9856

    head['FREQ'] = obs.rf
    head['FREQID'] = 1

    head['ARRNAM'] = 'ALMA'  #!AC TODO Can we change this field?
    head['XYZHAND'] = 'RIGHT'
    head['ARRAYX'] = 0.e0
    head['ARRAYY'] = 0.e0
    head['ARRAYZ'] = 0.e0
    head['POLARX'] = 0.e0
    head['POLARY'] = 0.e0

    head['NUMORB'] = 0
    head['NO_IF'] = 1
    head['NOPCAL'] = 0  #!AC changed from 1
    head['POLTYPE'] = 'APPROX'

    hdulist_new['AIPS AN'].header = head  # TODO necessary, or is it a pointer?

    #tbhdu = fits.BinTableHDU.from_columns(fits.ColDefs([col1,col2,col25,col3,col4,col5,col6,col7,col8,col9,col10,col11,colfin]), name='AIPS AN', header=head)
    #hdulist['AIPS AN'] = tbhdu

    ##################################################################################
    # AIPS FQ TABLE -- Thanks to Kazu
    # Convert types & columns

    nif = 1
    col1 = np.array(1, dtype=np.int32).reshape([nif])  #frqsel
    col2 = np.array(0.0, dtype=np.float64).reshape([nif])  #iffreq
    col3 = np.array([obs.bw], dtype=np.float32).reshape([nif])  #chwidth
    col4 = np.array([obs.bw], dtype=np.float32).reshape([nif])  #bw
    col5 = np.array([1], dtype=np.int32).reshape([nif])  #sideband

    col1 = fits.Column(name="FRQSEL", format="1J", array=col1)
    col2 = fits.Column(name="IF FREQ", format="%dD" % (nif), array=col2)
    col3 = fits.Column(name="CH WIDTH", format="%dE" % (nif), array=col3)
    col4 = fits.Column(name="TOTAL BANDWIDTH",
                       format="%dE" % (nif),
                       array=col4)
    col5 = fits.Column(name="SIDEBAND", format="%dJ" % (nif), array=col5)
    cols = fits.ColDefs([col1, col2, col3, col4, col5])

    # create table
    tbhdu = fits.BinTableHDU.from_columns(cols)

    # add header information
    tbhdu.header.append(("NO_IF", nif, "Number IFs"))
    tbhdu.header.append(("EXTNAME", "AIPS FQ"))
    #hdulist.append(tbhdu)
    hdulist_new.append(tbhdu)

    # Write final HDUList to file
    #hdulist.writeto(fname, overwrite=True)
    hdulist_new.writeto(fname, overwrite=True)

    return
예제 #15
0
파일: uv_comb.py 프로젝트: phanicode/eat
def uvf_combine(uvf_list, outp='merged.uvfits', mode='normal'):

    uvf_list = check_uvf_antab(uvf_list)
    r_bands, if_pos = check_uvf_ifs(uvf_list)
    Nif = len(r_bands)

    Nuvf = len(uvf_list)
    # UU, VV and WW, BASELINE, DATE, DATE, INTTIM AND DATA
    exp_keys = ['UU', 'VV', 'WW', 'BASELINE', 'DATE', 'INTTIM']
    comb_data = [[] for i in range(8)]
    uvf_hdul = [0 for i in range(Nuvf)]
    for (i, uvf) in enumerate(uvf_list):
        uvf_hdul[i] = pyfits.open(uvf)

    # GET THE TIMESTAMPS
    print('Computing time and baseline stamps ...')
    all_rjds = []
    for i in range(Nuvf):
        data = uvf_hdul[i][0].data
        keys = data.parnames
        idx, iek = index_uvf_keys(keys, exp_keys)
        jds = np.float64(data.par(idx[4])) + np.float64(data.par(idx[5]))
        all_rjds += list(set(jds))

    all_rjds = list(set(all_rjds))
    all_rjds.sort()  # SORTED UNION OF TIMESTAMPS
    Ntime = len(all_rjds)
    print('T-B stamps done!')

    # GET THE BASELINES AT ALL TIMESTAMPS
    print('Segmenting datasets ...')
    all_bsls = [0 for i in range(Ntime)]
    for (i, rjd) in enumerate(all_rjds):
        # ST_BSLS: BASELINES AT A SINGLE TIMESTAMP (FOR EACH UVFIT, LIST OF LIST).
        # THIS LIST WILL BE USED TO GET THE UVW AND INTTIM
        st_bsls = []
        # T_BSLS: BASELINES AT A SINGLE TIMESTAMP (FOR ALL UVFITS)
        t_bsls = []
        st_intts = []
        st_uus, st_vvs, st_wws = [], [], []
        st_data = []

        for j in range(Nuvf):
            data = uvf_hdul[j][0].data
            keys = data.parnames
            idx, iek = index_uvf_keys(keys, exp_keys)
            jds = np.float64(data.par(idx[4])) + np.float64(data.par(idx[5]))
            flt = jds == rjd

            bsl = list(data.par(idx[3])[flt])
            t_bsls += bsl
            st_bsls.append(bsl)
            # THE ORDER OF BSL DOES NOT EFFECT THE ORDER OF U, V, W AND INTTS
            st_uus.append(list(data.par(idx[0])[flt]))
            st_vvs.append(list(data.par(idx[1])[flt]))
            st_wws.append(list(data.par(idx[2])[flt]))
            st_intts.append(list(data.par(idx[6])[flt]))
            st_data.append(data.par(idx[7])[flt])
            #      print data.par(idx[7])[flt].shape
            if mode == 'check_scan':
                st_data[-1][:, :, :, :, :, :, 0] = j + 1.0
                st_data[-1][:, :, :, :, :, :, 1] = 0.0
                st_data[-1][:, :, :, :, :, :, 2] = 2.0

        t_bsls = list(set(t_bsls))
        t_bsls.sort()  # SORTED UNION BASELINES AT A GIVEN TIME

        # PREPARE THE UVW AND INTTIM
        for t_bsl in t_bsls:
            filled = False
            _arr_st_data = np.zeros((1, 1, Nif, 1, 4, 3), dtype=np.float64)
            # ITERATE ON UVFITS
            for (j, st_bsl) in enumerate(st_bsls):
                if t_bsl in st_bsl:
                    k = st_bsl.index(t_bsl)
                    if not filled:
                        comb_data[0].append(st_uus[j][k])
                        comb_data[1].append(st_vvs[j][k])
                        comb_data[2].append(st_wws[j][k])
                        comb_data[6].append(st_intts[j][k])
                        filled = True
                    # NOW IT IS TIME TO WORK ON IFS !!!
                    for (l, ip) in enumerate(if_pos[j]):
                        _arr_st_data[:, :,
                                     ip, :, :, :] = st_data[j][k][:, :,
                                                                  l, :, :, :]
            comb_data[7].append(_arr_st_data)
            del _arr_st_data

        all_bsls[i] = t_bsls
        del data, jds, bsl, flt, st_bsls, st_intts, t_bsls,
        del t_bsl, st_bsl, st_uus, st_vvs, st_wws
    print('Segmenting done!')

    print('Merging datasets ...')
    Nvis = len(comb_data[0])
    # WHEN TIMESTAMPS, BASELINES AND INTTIM ARE READY
    for (i, rjd) in enumerate(all_rjds):
        t_nbsl = len(all_bsls[i])
        comb_data[3] += all_bsls[i]
        comb_data[4] += [int(rjd)] * t_nbsl
        comb_data[5] += [rjd - int(rjd)] * t_nbsl

    # DATA IS READY
    for i in range(len(iek)):
        comb_data[i] = np.array(comb_data[i], dtype=np.float64)

    gdata = pyfits.GroupData(input=comb_data[-1],
                             parnames=iek[:-1],
                             pardata=comb_data[:-1],
                             bscale=1.0,
                             bzero=0.0,
                             bitpix=-32)
    ghdu = pyfits.GroupsHDU(gdata)

    # FORMATTING THE FITS HEADER. FOR SOME CASES THE KEY-VALUES FROM ORIGINAL
    # HEADER ARE BORROWED. NORMALLY THIS SHOULD BE FINE, IF NOT, PLEASE JUST LOAD
    # THE ORIGINAL DATASET INTO DIFMAP AND THEN SAVE IT OUT. SO THAT THE HEADERS
    # ARE AUTOMATICALLY FORMATTED.
    print('Formatting FITS header ...')
    hdr0 = uvf_hdul[0][0].header
    cards = []
    # Complex
    cards.append(('CTYPE2', 'COMPLEX', ''))
    cards.append(('CRPIX2', 1.0, ''))
    cards.append(('CRVAL2', 1.0, ''))
    cards.append(('CDELT2', 1.0, ''))
    cards.append(('CROTA2', 0.0, ''))
    # Stokes
    cards.append(('CTYPE3', 'STOKES', ''))
    cards.append(('CRPIX3', 1.0, ''))
    cards.append(('CRVAL3', hdr0['CRVAL3'], ''))
    cards.append(('CDELT3', hdr0['CDELT3'], ''))
    cards.append(('CROTA3', 0.0, ''))
    # FREQ
    if_freq = (r_bands.real + r_bands.imag) * 0.5
    ch_width = (r_bands.imag - r_bands.real)
    cards.append(('CTYPE4', 'FREQ', ''))
    cards.append(('CRPIX4', 1.0, ''))
    cards.append(('CRVAL4', if_freq[0], ''))
    cards.append(('CDELT4', ch_width[0], ''))
    cards.append(('CROTA4', 0.0, ''))
    del if_freq, ch_width
    # IF
    cards.append(('CTYPE5', 'IF', ''))
    cards.append(('CRPIX5', 1.0, ''))
    cards.append(('CRVAL5', 1.0, ''))
    cards.append(('CDELT5', 1.0, ''))
    cards.append(('CROTA5', 0.0, ''))
    # RA & Dec
    cards.append(('CTYPE6', 'RA', ''))
    cards.append(('CRPIX6', 1.0, ''))
    cards.append(('CRVAL6', hdr0['CRVAL6'], ''))
    cards.append(('CDELT6', 1.0, ''))
    cards.append(('CROTA6', 0.0, ''))
    cards.append(('CTYPE7', 'DEC', ''))
    cards.append(('CRPIX7', 1.0, ''))
    cards.append(('CRVAL7', hdr0['CRVAL7'], ''))
    cards.append(('CDELT7', 1.0, ''))
    cards.append(('CROTA7', 0.0, ''))
    for card in cards:
        ghdu.header.append(card)

    # PTYPE HEADER
    cards = []
    pcount = 7  # DIFMAP DEFAULTS, SHOULD NOT BE A PROBLEM FOR MOST CASES
    for i in range(1, pcount + 1):
        pk = 'PTYPE%d' % i
        cards.append((pk, hdr0[pk]))
        cards.append(('PSCAL%d' % i, 1.0))
        cards.append(('PZERO%d' % i, 0.0))
    for card in cards:
        ghdu.header.append(card)

    # Other Header
    utc = Time(all_rjds[0], scale='utc', format='jd')
    cards = []
    cards.append(('DATE-OBS', utc.isot[:10]))

    brr_keys = ['TELESCOP', 'INSTRUME', 'OBSERVER', 'OBJECT', 'BUNIT']
    for bk in brr_keys:
        cards.append((bk, borrow_cards(hdr0, bk)))

    eq_keys = ['EQUINOX', 'EPOCH']
    eq_keys = [ek for ek in eq_keys if ek in hdr0.keys()]
    if len(eq_keys) >= 1:
        ek = eq_keys[0]
        try:
            cards.append(('EPOCH', float(hdr0[ek])))
        except:
            cards.append(('EPOCH', 2000.0))
    else:
        cards.append(('EPOCH', 2000.0))

    cards.append(('BSCALE', 1.0))
    cards.append(('BSZERO', 0.0))
    cards.append(('VELREF', 3))
    cards.append(('ALTRVAL', 0.0))
    cards.append(('ALTRPIX', 1.0))
    cards.append(('OBSRA', hdr0['CRVAL6'], ''))
    cards.append(('OBSDEC', hdr0['CRVAL7'], ''))
    cards.append(('RESTFREQ', 0.0))
    for card in cards:
        ghdu.header.append(card)

    # THE VISIBILITIES SHOULD BE ALREADY TB SORTED.
    # ADD IT TO HISTORY SO THAT AIPS CAN RECOGNIZE IT.
    ghdu.header['HISTORY'] = "AIPS   SORT ORDER = 'TB'"

    # REFORMAT AN AND FQ TABLE
    # IN THE CASE OF SINGLE IF, THE ARRAY HAS TO BE TRANSPOSED
    print('Appending AN and FQ Tables ...')
    antab = uvf_hdul[0]['AIPS AN']

    if_freq = (r_bands.real + r_bands.imag) * 0.5
    if_freq = (if_freq - if_freq[0])[np.newaxis]
    ch_width = (r_bands.imag - r_bands.real)[np.newaxis]
    tot_bw = ch_width * 1.0
    sb = np.ones_like(tot_bw)

    fq_keys = ['FRQSEL', 'IF FREQ', 'CH WIDTH', 'TOTAL BANDWIDTH', 'SIDEBAND']
    fq_formats = ['1J', '%dD' % Nif, '%dE' % Nif, '%dE' % Nif, '%dJ' % Nif]
    fq_data = [np.array([1]), if_freq, ch_width, tot_bw, sb]

    cols = [pyfits.Column(name=fq_keys[k], format=fq_formats[k], \
            array=fq_data[k]) for k in range(len(fq_keys))]
    fqtab = pyfits.BinTableHDU.from_columns(cols, name='AIPS FQ')
    fh = fqtab.header
    fh['NO_IF'] = Nif

    comb_hdu = pyfits.HDUList([ghdu, antab, fqtab])
    comb_hdu.writeto(outp, output_verify='silentfix', overwrite=True)

    for uvf in uvf_list:
        os.system('rm -rf %s' % uvf)
    print('Done!!! \nMerged visibility data: %s' % outp)
예제 #16
0
def save_obs_uvfits(obs, fname, force_singlepol=None, polrep_out='circ'):
    """Save observation data to uvfits.
       To save Stokes I as a single polarization (e.g., only RR) set force_singlepol='R' or 'L'
    """

    # output times must be in utc
    obs = obs.switch_timetype(timetype_out='UTC')

    if polrep_out == 'circ':
        obs = obs.switch_polrep('circ')
    elif polrep_out == 'stokes':
        obs = obs.switch_polrep('stokes')
    else:
        raise Exception(
            "'polrep_out' in 'save_obs_uvfits' must be 'circ' or 'stokes'!")

    hdulist_new = fits.HDUList()
    hdulist_new.append(fits.GroupsHDU())

    #####################
    # AIPS Data TABLE
    #####################

    # Data header (based on the BU format)
    MJD_0 = 2400000.5
    header = hdulist_new['PRIMARY'].header
    header['OBSRA'] = obs.ra * 180. / 12.
    header['OBSDEC'] = obs.dec
    header['OBJECT'] = obs.source
    header['MJD'] = float(obs.mjd)
    header['DATE-OBS'] = Time(obs.mjd + MJD_0,
                              format='jd',
                              scale='utc',
                              out_subfmt='date').iso
    header['BSCALE'] = 1.0
    header['BZERO'] = 0.0
    header['BUNIT'] = 'JY'
    header['VELREF'] = 3  # TODO ??
    header['EQUINOX'] = 'J2000'
    header['ALTRPIX'] = 1.e0
    header['ALTRVAL'] = 0.e0
    header['TELESCOP'] = 'VLBA'  # TODO Can we change this field?
    header['INSTRUME'] = 'VLBA'
    header['OBSERVER'] = 'EHT'

    header['CTYPE2'] = 'COMPLEX'
    header['CRVAL2'] = 1.e0
    header['CDELT2'] = 1.e0
    header['CRPIX2'] = 1.e0
    header['CROTA2'] = 0.e0
    header['CTYPE3'] = 'STOKES'
    if polrep_out == 'circ':
        header['CRVAL3'] = -1.e0
        header['CDELT3'] = -1.e0
    elif polrep_out == 'stokes':
        header['CRVAL3'] = 1.e0
        header['CDELT3'] = 1.e0
    header['CRPIX3'] = 1.e0
    header['CROTA3'] = 0.e0
    header['CTYPE4'] = 'FREQ'
    header['CRVAL4'] = obs.rf
    header['CDELT4'] = obs.bw
    header['CRPIX4'] = 1.e0
    header['CROTA4'] = 0.e0
    header['CTYPE6'] = 'RA'
    header['CRVAL6'] = header['OBSRA']
    header['CDELT6'] = 1.e0
    header['CRPIX6'] = 1.e0
    header['CROTA6'] = 0.e0
    header['CTYPE7'] = 'DEC'
    header['CRVAL7'] = header['OBSDEC']
    header['CDELT7'] = 1.e0
    header['CRPIX7'] = 1.e0
    header['CROTA7'] = 0.e0
    header['PTYPE1'] = 'UU---SIN'
    header['PSCAL1'] = 1.0 / obs.rf
    header['PZERO1'] = 0.e0
    header['PTYPE2'] = 'VV---SIN'
    header['PSCAL2'] = 1.0 / obs.rf
    header['PZERO2'] = 0.e0
    header['PTYPE3'] = 'WW---SIN'
    header['PSCAL3'] = 1.0 / obs.rf
    header['PZERO3'] = 0.e0
    header['PTYPE4'] = 'BASELINE'
    header['PSCAL4'] = 1.e0
    header['PZERO4'] = 0.e0
    header['PTYPE5'] = 'DATE'
    header['PSCAL5'] = 1.e0
    header['PZERO5'] = 0.e0
    header['PTYPE6'] = 'DATE'
    header['PSCAL6'] = 1.e0
    header['PZERO6'] = 0.0
    header['PTYPE7'] = 'INTTIM'
    header['PSCAL7'] = 1.e0
    header['PZERO7'] = 0.e0
    header['PTYPE8'] = 'TAU1'
    header['PSCAL8'] = 1.e0
    header['PZERO8'] = 0.e0
    header['PTYPE9'] = 'TAU2'
    header['PSCAL9'] = 1.e0
    header['PZERO9'] = 0.e0
    header['history'] = "AIPS SORT ORDER='TB'"

    # Get data

    if polrep_out == 'circ':
        obsdata = obs.unpack([
            'time', 'tint', 'u', 'v', 'rrvis', 'llvis', 'rlvis', 'lrvis',
            'rrsigma', 'llsigma', 'rlsigma', 'lrsigma', 't1', 't2', 'tau1',
            'tau2'
        ])
    elif polrep_out == 'stokes':
        obsdata = obs.unpack([
            'time', 'tint', 'u', 'v', 'vis', 'qvis', 'uvis', 'vvis', 'sigma',
            'qsigma', 'usigma', 'vsigma', 't1', 't2', 'tau1', 'tau2'
        ])

    ndat = len(obsdata['time'])

    # times and tints
    jds = (2400000.5 + obs.mjd) * np.ones(len(obsdata))
    fractimes = (obsdata['time'] / 24.0)
    tints = obsdata['tint']

    # Baselines
    t1 = [obs.tkey[scope] + 1 for scope in obsdata['t1']]
    t2 = [obs.tkey[scope] + 1 for scope in obsdata['t2']]
    bl = 256 * np.array(t1) + np.array(t2)

    # opacities
    tau1 = obsdata['tau1']
    tau2 = obsdata['tau2']

    # uv are in lightseconds
    u = obsdata['u']
    v = obsdata['v']

    # rr, ll, lr, rl, weights

    if polrep_out == 'circ':
        rr = obsdata['rrvis']
        ll = obsdata['llvis']
        rl = obsdata['rlvis']
        lr = obsdata['lrvis']
        weightrr = 1.0 / (obsdata['rrsigma']**2)
        weightll = 1.0 / (obsdata['llsigma']**2)
        weightrl = 1.0 / (obsdata['rlsigma']**2)
        weightlr = 1.0 / (obsdata['lrsigma']**2)

        # If necessary, enforce single polarization
        if force_singlepol == 'L':
            if obs.polrep == 'stokes':
                raise Exception(
                    "force_singlepol only works with obs.polrep=='stokes'!")
            print(
                "force_singlepol='L': treating Stokes 'I' as LL and ignoring Q,U,V!!"
            )
            ll = obsdata['vis']
            rr = rr * 0.0
            rl = rl * 0.0
            lr = lr * 0.0
            weightrr = weightrr * 0.0
            weightrl = weightrl * 0.0
            weightlr = weightlr * 0.0
        elif force_singlepol == 'R':
            if obs.polrep == 'stokes':
                raise Exception(
                    "force_singlepol only works with obs.polrep=='stokes'!")
            print(
                "force_singlepol='R': treating Stokes 'I' as RR and ignoring Q,U,V!!"
            )
            rr = obsdata['vis']
            ll = rr * 0.0
            rl = rl * 0.0
            lr = lr * 0.0
            weightll = weightll * 0.0
            weightrl = weightrl * 0.0
            weightlr = weightlr * 0.0

        dat1 = rr
        dat2 = ll
        dat3 = rl
        dat4 = lr
        weight1 = weightrr
        weight2 = weightll
        weight3 = weightrl
        weight4 = weightlr

    elif polrep_out == 'stokes':
        dat1 = obsdata['vis']
        dat2 = obsdata['qvis']
        dat3 = obsdata['uvis']
        dat4 = obsdata['vvis']
        weight1 = 1.0 / (obsdata['sigma']**2)
        weight2 = 1.0 / (obsdata['qsigma']**2)
        weight3 = 1.0 / (obsdata['usigma']**2)
        weight4 = 1.0 / (obsdata['vsigma']**2)

    # Replace nans by zeros (including zero weights)
    dat1 = np.nan_to_num(dat1)
    dat2 = np.nan_to_num(dat2)
    dat3 = np.nan_to_num(dat3)
    dat4 = np.nan_to_num(dat4)
    weight1 = np.nan_to_num(weight1)
    weight2 = np.nan_to_num(weight2)
    weight3 = np.nan_to_num(weight3)
    weight4 = np.nan_to_num(weight4)

    # Data array
    outdat = np.zeros((ndat, 1, 1, 1, 1, 4, 3))
    outdat[:, 0, 0, 0, 0, 0, 0] = np.real(dat1)
    outdat[:, 0, 0, 0, 0, 0, 1] = np.imag(dat1)
    outdat[:, 0, 0, 0, 0, 0, 2] = weight1
    outdat[:, 0, 0, 0, 0, 1, 0] = np.real(dat2)
    outdat[:, 0, 0, 0, 0, 1, 1] = np.imag(dat2)
    outdat[:, 0, 0, 0, 0, 1, 2] = weight2
    outdat[:, 0, 0, 0, 0, 2, 0] = np.real(dat3)
    outdat[:, 0, 0, 0, 0, 2, 1] = np.imag(dat3)
    outdat[:, 0, 0, 0, 0, 2, 2] = weight3
    outdat[:, 0, 0, 0, 0, 3, 0] = np.real(dat4)
    outdat[:, 0, 0, 0, 0, 3, 1] = np.imag(dat4)
    outdat[:, 0, 0, 0, 0, 3, 2] = weight4

    # Save data
    pars = [
        'UU---SIN', 'VV---SIN', 'WW---SIN', 'BASELINE', 'DATE', 'DATE',
        'INTTIM', 'TAU1', 'TAU2'
    ]
    x = fits.GroupData(
        outdat,
        parnames=pars,
        pardata=[u, v,
                 np.zeros(ndat), bl, jds, fractimes, tints, tau1, tau2],
        bitpix=-32)

    hdulist_new['PRIMARY'].data = x
    hdulist_new['PRIMARY'].header = header  # TODO necessary ??

    #####################
    # AIPS AN TABLE
    #####################

    # Load the array data
    tarr = obs.tarr
    tnames = tarr['site']
    tnums = np.arange(1, len(tarr) + 1)
    xyz = np.array([[tarr[i]['x'], tarr[i]['y'], tarr[i]['z']]
                    for i in np.arange(len(tarr))])
    sefd = tarr['sefdr']

    nsta = len(tnames)
    col1 = fits.Column(name='ANNAME', format='8A', array=tnames)
    col2 = fits.Column(name='STABXYZ', format='3D', unit='METERS', array=xyz)
    col3 = fits.Column(name='NOSTA', format='1J', array=tnums)
    colfin = fits.Column(name='SEFD', format='1D', array=sefd)

    # TODO these antenna fields+header are questionable - look into them
    col4 = fits.Column(name='MNTSTA', format='1J', array=np.zeros(nsta))
    col5 = fits.Column(name='STAXOF',
                       format='1E',
                       unit='METERS',
                       array=np.zeros(nsta))
    col6 = fits.Column(name='POLTYA',
                       format='1A',
                       array=np.array(['R' for i in range(nsta)], dtype='|S1'))
    col7 = fits.Column(name='POLAA',
                       format='1E',
                       unit='DEGREES',
                       array=np.zeros(nsta))
    col8 = fits.Column(name='POLCALA', format='3E', array=np.zeros((nsta, 3)))
    col9 = fits.Column(name='POLTYB',
                       format='1A',
                       array=np.array(['L' for i in range(nsta)], dtype='|S1'))
    col10 = fits.Column(name='POLAB',
                        format='1E',
                        unit='DEGREES',
                        array=(90. * np.ones(nsta)))
    col11 = fits.Column(name='POLCALB', format='3E', array=np.zeros((nsta, 3)))
    col25 = fits.Column(name='ORBPARM', format='1E', array=np.zeros(0))

    # Antenna Header params
    # TODO do we need to change more of these??
    collist = [
        col1, col2, col25, col3, col4, col5, col6, col7, col8, col9, col10,
        col11, colfin
    ]
    tbhdu = fits.BinTableHDU.from_columns(fits.ColDefs(collist),
                                          name='AIPS AN')
    hdulist_new.append(tbhdu)

    head = hdulist_new['AIPS AN'].header

    head['EXTVER'] = 1
    head['ARRAYX'] = 0.e0
    head['ARRAYY'] = 0.e0
    head['ARRAYZ'] = 0.e0

    # TODO change the reference date
    rdate_tt_new = Time(obs.mjd + MJD_0,
                        format='jd',
                        scale='utc',
                        out_subfmt='date')
    rdate_out = rdate_tt_new.iso
    rdate_tt_new.out_subfmt = 'float'  # TODO -- needed to fix subformat issue in astropy 4.0
    rdate_jd_out = rdate_tt_new.jd
    rdate_gstiao_out = rdate_tt_new.sidereal_time('apparent',
                                                  'greenwich').degree
    rdate_offset_out = (rdate_tt_new.ut1.datetime.second -
                        rdate_tt_new.utc.datetime.second)
    rdate_offset_out += 1.e-6 * (rdate_tt_new.ut1.datetime.microsecond -
                                 rdate_tt_new.utc.datetime.microsecond)

    head['RDATE'] = rdate_out
    head['GSTIA0'] = rdate_gstiao_out
    head['DEGPDY'] = 360.9856
    head['UT1UTC'] = rdate_offset_out  # difference between UT1 and UTC ?
    head['DATUTC'] = 0.e0
    head['TIMESYS'] = 'UTC'

    head['FREQ'] = obs.rf
    head['POLARX'] = 0.e0
    head['POLARY'] = 0.e0

    head['ARRNAM'] = 'VLBA'  # TODO must be recognized by aips/casa
    head['XYZHAND'] = 'RIGHT'
    head['FRAME'] = '????'
    head['NUMORB'] = 0
    head['NO_IF'] = 1  # TODO nchan
    head['NOPCAL'] = 0  # TODO add pol cal information
    head['POLTYPE'] = 'VLBI'
    head['FREQID'] = 1

    hdulist_new['AIPS AN'].header = head  # TODO necessary, or is it a pointer?

    #####################
    # AIPS FQ TABLE
    #####################
    # Convert types & columns

    nif = 1
    col1 = np.array(1, dtype=np.int32).reshape([nif])  # frqsel
    col2 = np.array(0.0, dtype=np.float64).reshape([nif])  # iffreq
    col3 = np.array([obs.bw], dtype=np.float32).reshape([nif])  # chwidth
    col4 = np.array([obs.bw], dtype=np.float32).reshape([nif])  # bw
    col5 = np.array([1], dtype=np.int32).reshape([nif])  # sideband

    col1 = fits.Column(name="FRQSEL", format="1J", array=col1)
    col2 = fits.Column(name="IF FREQ", format="%dD" % (nif), array=col2)
    col3 = fits.Column(name="CH WIDTH", format="%dE" % (nif), array=col3)
    col4 = fits.Column(name="TOTAL BANDWIDTH",
                       format="%dE" % (nif),
                       array=col4)
    col5 = fits.Column(name="SIDEBAND", format="%dJ" % (nif), array=col5)
    cols = fits.ColDefs([col1, col2, col3, col4, col5])

    # create table
    tbhdu = fits.BinTableHDU.from_columns(cols)

    # add header information
    tbhdu.header.append(("NO_IF", nif, "Number IFs"))
    tbhdu.header.append(("EXTNAME", "AIPS FQ"))
    tbhdu.header.append(("EXTVER", 1))
    hdulist_new.append(tbhdu)

    #####################
    # AIPS NX TABLE
    #####################

    scan_times = []
    scan_time_ints = []
    start_vis = []
    stop_vis = []

    # TODO make sure jds AND scan_info MUST be time sorted!!
    jj = 0

    ROUND_SCAN_INT = 5
    comp_fac = 3600 * 24 * 100  # compare to 100th of a second
    scan_arr = obs.scans
    print('Building NX table')
    if (scan_arr is None or len(scan_arr) == 0):
        print("No NX table in saved uvfits")
    else:
        try:
            scan_arr = scan_arr / 24.
            for scan in scan_arr:
                scan_start = round(scan[0], ROUND_SCAN_INT)
                scan_stop = round(scan[1], ROUND_SCAN_INT)
                scan_dur = (scan_stop - scan_start)

                if jj >= len(fractimes):
                    # print start_vis, stop_vis
                    break

                # print ("%.12f %.12f %.12f" % (fractimes[jj], scan_start, scan_stop))
                jd = round(fractimes[jj],
                           ROUND_SCAN_INT) * comp_fac  # TODO precision??

                if ((np.floor(jd) >= np.floor(scan_start * comp_fac))
                        and (np.ceil(jd) <= np.ceil(comp_fac * scan_stop))):
                    start_vis.append(jj)

                    # TODO AIPS MEMO 117 says scan_times should be midpoint!
                    # but AIPS data looks likes it's at the start?
                    scan_times.append(scan_start +
                                      0.5 * scan_dur)  # - rdate_jd_out)
                    scan_time_ints.append(scan_dur)
                    ceilcut = np.ceil(comp_fac * scan_stop)
                    while ((jj < len(fractimes) and np.floor(
                            round(fractimes[jj], ROUND_SCAN_INT) * comp_fac) <=
                            ceilcut)):
                        jj += 1
                    stop_vis.append(jj - 1)
                else:
                    continue

            if jj < len(fractimes):
                print(scan_arr[-1])
                print(round(scan_arr[-1][0], ROUND_SCAN_INT),
                      round(scan_arr[-1][1], ROUND_SCAN_INT))
                print(jj, len(jds), round(jds[jj], ROUND_SCAN_INT))
                print(
                    "WARNING!!!: in save_uvfits NX table, " +
                    "didn't get to all entries when computing scan start/stop!"
                )
                print(scan_times)
            time_nx = fits.Column(name="TIME",
                                  format="1D",
                                  unit='DAYS',
                                  array=np.array(scan_times))
            timeint_nx = fits.Column(name="TIME INTERVAL",
                                     format="1E",
                                     unit='DAYS',
                                     array=np.array(scan_time_ints))
            sourceid_nx = fits.Column(name="SOURCE ID",
                                      format="1J",
                                      unit='',
                                      array=np.ones(len(scan_times)))
            subarr_nx = fits.Column(name="SUBARRAY",
                                    format="1J",
                                    unit='',
                                    array=np.ones(len(scan_times)))
            freqid_nx = fits.Column(name="FREQ ID",
                                    format="1J",
                                    unit='',
                                    array=np.ones(len(scan_times)))
            startvis_nx = fits.Column(name="START VIS",
                                      format="1J",
                                      unit='',
                                      array=np.array(start_vis) + 1)
            endvis_nx = fits.Column(name="END VIS",
                                    format="1J",
                                    unit='',
                                    array=np.array(stop_vis) + 1)
            cols = fits.ColDefs([
                time_nx, timeint_nx, sourceid_nx, subarr_nx, freqid_nx,
                startvis_nx, endvis_nx
            ])

            tbhdu = fits.BinTableHDU.from_columns(cols)

            # header information
            tbhdu.header.append(("EXTNAME", "AIPS NX"))
            tbhdu.header.append(("EXTVER", 1))

            hdulist_new.append(tbhdu)
        except TypeError:
            print("No NX table in saved uvfits")

    # Write final HDUList to file
    hdulist_new.writeto(fname, overwrite=True)

    return
예제 #17
0
def test_select_read(tmp_path):
    uvfits_uv = UVData()
    uvfits_uv2 = UVData()
    uvfits_file = os.path.join(DATA_PATH,
                               "day2_TDEM0003_10s_norx_1src_1spw.uvfits")

    # select on antennas
    ants_to_keep = np.array([0, 19, 11, 24, 3, 23, 1, 20, 21])
    uvfits_uv.read(uvfits_file, antenna_nums=ants_to_keep)
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on frequency channels
    chans_to_keep = np.arange(12, 22)
    uvfits_uv.read(uvfits_file, freq_chans=chans_to_keep)
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(freq_chans=chans_to_keep)
    assert uvfits_uv == uvfits_uv2

    # check writing & reading single frequency files
    uvfits_uv.select(freq_chans=[0])
    testfile = str(tmp_path / "outtest_casa.uvfits")
    uvfits_uv.write_uvfits(testfile)
    uvfits_uv2.read(testfile)
    assert uvfits_uv == uvfits_uv2

    # select on pols
    pols_to_keep = [-1, -2]
    uvfits_uv.read(uvfits_file, polarizations=pols_to_keep)
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on read using time_range
    unique_times = np.unique(uvfits_uv.time_array)
    uvfits_uv.read(uvfits_file, time_range=[unique_times[0], unique_times[1]])
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(times=unique_times[0:2])
    assert uvfits_uv == uvfits_uv2

    # now test selecting on multiple axes
    # frequencies first
    uvfits_uv.read(
        uvfits_file,
        antenna_nums=ants_to_keep,
        freq_chans=chans_to_keep,
        polarizations=pols_to_keep,
    )
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # baselines first
    ants_to_keep = np.array([0, 1])
    uvfits_uv.read(
        uvfits_file,
        antenna_nums=ants_to_keep,
        freq_chans=chans_to_keep,
        polarizations=pols_to_keep,
    )
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # polarizations first
    ants_to_keep = np.array([0, 1, 2, 3, 6, 7, 8, 11, 14, 18, 19, 20, 21, 22])
    chans_to_keep = np.arange(12, 64)
    uvfits_uv.read(
        uvfits_file,
        antenna_nums=ants_to_keep,
        freq_chans=chans_to_keep,
        polarizations=pols_to_keep,
    )
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # repeat with no spw file
    uvfitsfile_no_spw = os.path.join(DATA_PATH,
                                     "zen.2456865.60537.xy.uvcRREAAM.uvfits")

    # select on antennas
    ants_to_keep = np.array([2, 4, 5])
    uvfits_uv.read(uvfitsfile_no_spw, antenna_nums=ants_to_keep)
    uvfits_uv2.read(uvfitsfile_no_spw)
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on frequency channels
    chans_to_keep = np.arange(4, 8)
    uvfits_uv.read(uvfitsfile_no_spw, freq_chans=chans_to_keep)
    uvfits_uv2.read(uvfitsfile_no_spw)
    uvfits_uv2.select(freq_chans=chans_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on pols
    # this requires writing a new file because the no spw file we have has only 1 pol
    with fits.open(uvfits_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data
        raw_data_array = raw_data_array[:, :, :, 0, :, :, :]

        vis_hdr["NAXIS"] = 6

        vis_hdr["NAXIS5"] = vis_hdr["NAXIS6"]
        vis_hdr["CTYPE5"] = vis_hdr["CTYPE6"]
        vis_hdr["CRVAL5"] = vis_hdr["CRVAL6"]
        vis_hdr["CDELT5"] = vis_hdr["CDELT6"]
        vis_hdr["CRPIX5"] = vis_hdr["CRPIX6"]
        vis_hdr["CROTA5"] = vis_hdr["CROTA6"]

        vis_hdr["NAXIS6"] = vis_hdr["NAXIS7"]
        vis_hdr["CTYPE6"] = vis_hdr["CTYPE7"]
        vis_hdr["CRVAL6"] = vis_hdr["CRVAL7"]
        vis_hdr["CDELT6"] = vis_hdr["CDELT7"]
        vis_hdr["CRPIX6"] = vis_hdr["CRPIX7"]
        vis_hdr["CROTA6"] = vis_hdr["CROTA7"]

        vis_hdr.pop("NAXIS7")
        vis_hdr.pop("CTYPE7")
        vis_hdr.pop("CRVAL7")
        vis_hdr.pop("CDELT7")
        vis_hdr.pop("CRPIX7")
        vis_hdr.pop("CROTA7")

        par_names = vis_hdu.data.parnames

        group_parameter_list = [
            vis_hdu.data.par(ind) for ind in range(len(par_names))
        ]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        write_file = str(tmp_path / "outtest_casa.uvfits")
        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    pols_to_keep = [-1, -2]
    uvfits_uv.read(write_file, polarizations=pols_to_keep)
    uvfits_uv2.read(uvfits_file)
    uvfits_uv2.select(polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2
예제 #18
0
def test_readwriteread(tmp_path):
    """
    CASA tutorial uvfits loopback test.

    Read in uvfits file, write out new uvfits file, read back in and check for
    object equality.
    """
    uv_in = UVData()
    uv_out = UVData()
    testfile = os.path.join(DATA_PATH,
                            "day2_TDEM0003_10s_norx_1src_1spw.uvfits")
    write_file = str(tmp_path / "outtest_casa.uvfits")
    uv_in.read(testfile)
    uv_in.write_uvfits(write_file)
    uv_out.read(write_file)
    assert uv_in == uv_out

    # test that it works with write_lst = False
    uv_in.write_uvfits(write_file, write_lst=False)
    uv_out.read(write_file)
    assert uv_in == uv_out

    # check that if x_orientation is set, it's read back out properly
    uv_in.x_orientation = "east"
    uv_in.write_uvfits(write_file)
    uv_out.read(write_file)
    assert uv_in == uv_out

    # check that if antenna_diameters is set, it's read back out properly
    uv_in.read(testfile)
    uv_in.antenna_diameters = np.zeros(
        (uv_in.Nants_telescope, ), dtype=np.float) + 14.0
    uv_in.write_uvfits(write_file)
    uv_out.read(write_file)
    assert uv_in == uv_out

    # check that if antenna_numbers are > 256 everything works
    uv_in.read(testfile)
    uv_in.antenna_numbers = uv_in.antenna_numbers + 256
    uv_in.ant_1_array = uv_in.ant_1_array + 256
    uv_in.ant_2_array = uv_in.ant_2_array + 256
    uv_in.baseline_array = uv_in.antnums_to_baseline(uv_in.ant_1_array,
                                                     uv_in.ant_2_array)
    uvtest.checkWarnings(
        uv_in.write_uvfits,
        [write_file],
        message=
        "antnums_to_baseline: found > 256 antennas, using 2048 baseline",
    )
    uv_out.read(write_file)
    assert uv_in == uv_out

    # check missing telescope_name, timesys vs timsys spelling, xyz_telescope_frame=????
    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()

        vis_hdr.pop("TELESCOP")

        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames["AIPS AN"]]
        ant_hdr = ant_hdu.header.copy()

        time_sys = ant_hdr.pop("TIMSYS")
        ant_hdr["TIMESYS"] = time_sys
        ant_hdr["FRAME"] = "????"

        ant_hdu.header = ant_hdr

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    uv_out.read(write_file)
    assert uv_out.telescope_name == "EVLA"
    assert uv_out.timesys == time_sys

    # check error if timesys is 'IAT'
    uv_in.read(testfile)
    uv_in.timesys = "IAT"
    with pytest.raises(ValueError) as cm:
        uv_in.write_uvfits(write_file)
    assert str(cm.value).startswith(
        "This file has a time system IAT. "
        'Only "UTC" time system files are supported')
    uv_in.timesys = "UTC"

    # check error if one time & no inttime specified
    uv_singlet = uv_in.select(times=uv_in.time_array[0], inplace=False)
    uv_singlet.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = np.array(vis_hdu.data.parnames)
        pars_use = np.where(par_names != "INTTIM")[0]
        par_names = par_names[pars_use].tolist()

        group_parameter_list = [vis_hdu.data.par(name) for name in par_names]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames["AIPS AN"]]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    with pytest.raises(ValueError) as cm:
        uvtest.checkWarnings(
            uv_out.read,
            func_args=[write_file],
            message=[
                "Telescope EVLA is not",
                'ERFA function "utcut1" yielded 1 of "dubious year (Note 3)"',
                'ERFA function "utctai" yielded 1 of "dubious year (Note 3)"',
                "LST values stored in this file are not self-consistent",
            ],
            nwarnings=4,
            category=[
                UserWarning,
                astropy._erfa.core.ErfaWarning,
                astropy._erfa.core.ErfaWarning,
                UserWarning,
            ],
        )
    assert str(cm.value).startswith(
        "integration time not specified and only one time present")

    # check that unflagged data with nsample = 0 will cause warnings
    uv_in.nsample_array[list(range(11, 22))] = 0
    uv_in.flag_array[list(range(11, 22))] = False
    uvtest.checkWarnings(uv_in.write_uvfits, [write_file],
                         message="Some unflagged data has nsample = 0")
예제 #19
0
파일: uvfits.py 프로젝트: tammojan/pyuvdata
    def write_uvfits(self,
                     filename,
                     spoof_nonessential=False,
                     force_phase=False,
                     run_check=True,
                     check_extra=True,
                     run_check_acceptability=True):
        """
        Write the data to a uvfits file.

        Args:
            filename: The uvfits file to write to.
            spoof_nonessential: Option to spoof the values of optional
                UVParameters that are not set but are required for uvfits files.
                Default is False.
            force_phase: Option to automatically phase drift scan data to
                zenith of the first timestamp. Default is False.
            run_check: Option to check for the existence and proper shapes of
                parameters before writing the file. Default is True.
            check_extra: Option to check optional parameters as well as required
                ones. Default is True.
            run_check_acceptability: Option to check acceptable range of the values of
                parameters before writing the file. Default is True.
        """
        if run_check:
            self.check(check_extra=check_extra,
                       run_check_acceptability=run_check_acceptability)

        if self.phase_type == 'phased':
            pass
        elif self.phase_type == 'drift':
            if force_phase:
                print('The data are in drift mode and do not have a '
                      'defined phase center. Phasing to zenith of the first '
                      'timestamp.')
                phase_time = Time(self.time_array[0], format='jd')
                self.phase_to_time(phase_time)
            else:
                raise ValueError('The data are in drift mode. '
                                 'Set force_phase to true to phase the data '
                                 'to zenith of the first timestamp before '
                                 'writing a uvfits file.')
        else:
            raise ValueError('The phasing type of the data is unknown. '
                             'Set the phase_type to drift or phased to '
                             'reflect the phasing status of the data')

        if self.Nfreqs > 1:
            freq_spacing = self.freq_array[0, 1:] - self.freq_array[0, :-1]
            if not np.isclose(np.min(freq_spacing),
                              np.max(freq_spacing),
                              rtol=self._freq_array.tols[0],
                              atol=self._freq_array.tols[1]):
                raise ValueError(
                    'The frequencies are not evenly spaced (probably '
                    'because of a select operation). The uvfits format '
                    'does not support unevenly spaced frequencies.')
            if not np.isclose(freq_spacing[0],
                              self.channel_width,
                              rtol=self._freq_array.tols[0],
                              atol=self._freq_array.tols[1]):
                raise ValueError(
                    'The frequencies are separated by more than their '
                    'channel width (probably because of a select operation). '
                    'The uvfits format does not support frequencies '
                    'that are spaced by more than their channel width.')
            freq_spacing = freq_spacing[0]
        else:
            freq_spacing = self.channel_width

        if self.Npols > 1:
            pol_spacing = np.diff(self.polarization_array)
            if np.min(pol_spacing) < np.max(pol_spacing):
                raise ValueError(
                    'The polarization values are not evenly spaced (probably '
                    'because of a select operation). The uvfits format '
                    'does not support unevenly spaced polarizations.')
            pol_spacing = pol_spacing[0]
        else:
            pol_spacing = 1

        for p in self.extra():
            param = getattr(self, p)
            if param.name in self.uvfits_required_extra:
                if param.value is None:
                    if spoof_nonessential:
                        # spoof extra keywords required for uvfits
                        if isinstance(param, uvp.AntPositionParameter):
                            param.apply_spoof(self, 'Nants_telescope')
                        else:
                            param.apply_spoof()
                        setattr(self, p, param)
                    else:
                        raise ValueError(
                            'Required attribute {attribute} '
                            'for uvfits not defined. Define or '
                            'set spoof_nonessential to True to '
                            'spoof this attribute.'.format(attribute=p))

        # check for unflagged data with nsample = 0. Warn if any found
        wh_nsample0 = np.where(self.nsample_array == 0)
        if np.any(~self.flag_array[wh_nsample0]):
            warnings.warn('Some unflagged data has nsample = 0. Flags and '
                          'nsamples are combined in uvfits files such that '
                          'these data will appear to be flagged.')

        weights_array = self.nsample_array * \
            np.where(self.flag_array, -1, 1)
        # FITS uvw direction convention is opposite ours and Miriad's.
        # So conjugate the visibilities and flip the uvws:
        data_array = np.conj(self.data_array[:, np.newaxis,
                                             np.newaxis, :, :, :, np.newaxis])
        weights_array = weights_array[:, np.newaxis, np.newaxis, :, :, :,
                                      np.newaxis]
        # uvfits_array_data shape will be  (Nblts,1,1,[Nspws],Nfreqs,Npols,3)
        uvfits_array_data = np.concatenate(
            [data_array.real, data_array.imag, weights_array], axis=6)

        # FITS uvw direction convention is opposite ours and Miriad's.
        # So conjugate the visibilities and flip the uvws:
        uvw_array_sec = -1 * self.uvw_array / const.c.to('m/s').value
        # jd_midnight = np.floor(self.time_array[0] - 0.5) + 0.5
        tzero = np.float32(self.time_array[0])

        # uvfits convention is that time_array + relevant PZERO = actual JD
        # We are setting PZERO4 = float32(first time of observation)
        time_array = np.float32(self.time_array - np.float64(tzero))

        int_time_array = self.integration_time

        baselines_use = self.antnums_to_baseline(self.ant_1_array,
                                                 self.ant_2_array,
                                                 attempt256=True)
        # Set up dictionaries for populating hdu
        # Note that uvfits antenna arrays are 1-indexed so we add 1
        # to our 0-indexed arrays
        group_parameter_dict = {
            'UU      ': uvw_array_sec[:, 0],
            'VV      ': uvw_array_sec[:, 1],
            'WW      ': uvw_array_sec[:, 2],
            'DATE    ': time_array,
            'BASELINE': baselines_use,
            'ANTENNA1': self.ant_1_array + 1,
            'ANTENNA2': self.ant_2_array + 1,
            'SUBARRAY': np.ones_like(self.ant_1_array),
            'INTTIM': int_time_array
        }
        pscal_dict = {
            'UU      ': 1.0,
            'VV      ': 1.0,
            'WW      ': 1.0,
            'DATE    ': 1.0,
            'BASELINE': 1.0,
            'ANTENNA1': 1.0,
            'ANTENNA2': 1.0,
            'SUBARRAY': 1.0,
            'INTTIM': 1.0
        }
        pzero_dict = {
            'UU      ': 0.0,
            'VV      ': 0.0,
            'WW      ': 0.0,
            'DATE    ': tzero,
            'BASELINE': 0.0,
            'ANTENNA1': 0.0,
            'ANTENNA2': 0.0,
            'SUBARRAY': 0.0,
            'INTTIM': 0.0
        }

        # list contains arrays of [u,v,w,date,baseline];
        # each array has shape (Nblts)
        if (np.max(self.ant_1_array) < 255 and np.max(self.ant_2_array) < 255):
            # if the number of antennas is less than 256 then include both the
            # baseline array and the antenna arrays in the group parameters.
            # Otherwise just use the antenna arrays
            parnames_use = [
                'UU      ', 'VV      ', 'WW      ', 'DATE    ', 'BASELINE',
                'ANTENNA1', 'ANTENNA2', 'SUBARRAY', 'INTTIM'
            ]
        else:
            parnames_use = [
                'UU      ', 'VV      ', 'WW      ', 'DATE    ', 'ANTENNA1',
                'ANTENNA2', 'SUBARRAY', 'INTTIM'
            ]

        group_parameter_list = [
            group_parameter_dict[parname] for parname in parnames_use
        ]
        hdu = fits.GroupData(uvfits_array_data,
                             parnames=parnames_use,
                             pardata=group_parameter_list,
                             bitpix=-32)
        hdu = fits.GroupsHDU(hdu)

        for i, key in enumerate(parnames_use):
            hdu.header['PSCAL' + str(i + 1) + '  '] = pscal_dict[key]
            hdu.header['PZERO' + str(i + 1) + '  '] = pzero_dict[key]

        # ISO string of first time in self.time_array
        hdu.header['DATE-OBS'] = Time(self.time_array[0],
                                      scale='utc',
                                      format='jd').isot

        hdu.header['CTYPE2  '] = 'COMPLEX '
        hdu.header['CRVAL2  '] = 1.0
        hdu.header['CRPIX2  '] = 1.0
        hdu.header['CDELT2  '] = 1.0

        # Note: This axis is called STOKES to comply with the AIPS memo 117
        # However, this confusing because it is NOT a true Stokes axis,
        #   it is really the polarization axis.
        hdu.header['CTYPE3  '] = 'STOKES  '
        hdu.header['CRVAL3  '] = self.polarization_array[0]
        hdu.header['CRPIX3  '] = 1.0
        hdu.header['CDELT3  '] = pol_spacing

        hdu.header['CTYPE4  '] = 'FREQ    '
        hdu.header['CRVAL4  '] = self.freq_array[0, 0]
        hdu.header['CRPIX4  '] = 1.0
        hdu.header['CDELT4  '] = freq_spacing

        hdu.header['CTYPE5  '] = 'IF      '
        hdu.header['CRVAL5  '] = 1.0
        hdu.header['CRPIX5  '] = 1.0
        hdu.header['CDELT5  '] = 1.0

        hdu.header['CTYPE6  '] = 'RA'
        hdu.header['CRVAL6  '] = self.phase_center_ra_degrees

        hdu.header['CTYPE7  '] = 'DEC'
        hdu.header['CRVAL7  '] = self.phase_center_dec_degrees

        hdu.header['BUNIT   '] = self.vis_units
        hdu.header['BSCALE  '] = 1.0
        hdu.header['BZERO   '] = 0.0

        hdu.header['OBJECT  '] = self.object_name
        hdu.header['TELESCOP'] = self.telescope_name
        hdu.header['LAT     '] = self.telescope_location_lat_lon_alt_degrees[0]
        hdu.header['LON     '] = self.telescope_location_lat_lon_alt_degrees[1]
        hdu.header['ALT     '] = self.telescope_location_lat_lon_alt[2]
        hdu.header['INSTRUME'] = self.instrument
        hdu.header['EPOCH   '] = float(self.phase_center_epoch)
        if self.phase_center_frame is not None:
            hdu.header['PHSFRAME'] = self.phase_center_frame

        if self.x_orientation is not None:
            hdu.header['XORIENT'] = self.x_orientation

        for line in self.history.splitlines():
            hdu.header.add_history(line)

        # end standard keywords; begin user-defined keywords
        for key, value in self.extra_keywords.items():
            # header keywords have to be 8 characters or less
            if len(str(key)) > 8:
                warnings.warn(
                    'key {key} in extra_keywords is longer than 8 '
                    'characters. It will be truncated to 8 as required '
                    'by the uvfits file format.'.format(key=key))
            keyword = key[:8].upper()
            if isinstance(value, (dict, list, np.ndarray)):
                raise TypeError('Extra keyword {keyword} is of {keytype}. '
                                'Only strings and numbers are '
                                'supported in uvfits.'.format(
                                    keyword=key, keytype=type(value)))

            if keyword == 'COMMENT':
                for line in value.splitlines():
                    hdu.header.add_comment(line)
            else:
                hdu.header[keyword] = value

        # ADD the ANTENNA table
        staxof = np.zeros(self.Nants_telescope)

        # 0 specifies alt-az, 6 would specify a phased array
        mntsta = np.zeros(self.Nants_telescope)

        # beware, X can mean just about anything
        poltya = np.full((self.Nants_telescope), 'X', dtype=np.object_)
        polaa = [90.0] + np.zeros(self.Nants_telescope)
        poltyb = np.full((self.Nants_telescope), 'Y', dtype=np.object_)
        polab = [0.0] + np.zeros(self.Nants_telescope)

        col1 = fits.Column(name='ANNAME',
                           format='8A',
                           array=self.antenna_names)
        # AIPS memo #117 says that antenna_positions should be relative to
        # the array center, but in a rotated ECEF frame so that the x-axis
        # goes through the local meridian.
        longitude = self.telescope_location_lat_lon_alt[1]
        rot_ecef_positions = uvutils.rotECEF_from_ECEF(self.antenna_positions,
                                                       longitude)
        col2 = fits.Column(name='STABXYZ',
                           format='3D',
                           array=rot_ecef_positions)
        # convert to 1-indexed from 0-indexed indicies
        col3 = fits.Column(name='NOSTA',
                           format='1J',
                           array=self.antenna_numbers + 1)
        col4 = fits.Column(name='MNTSTA', format='1J', array=mntsta)
        col5 = fits.Column(name='STAXOF', format='1E', array=staxof)
        col6 = fits.Column(name='POLTYA', format='1A', array=poltya)
        col7 = fits.Column(name='POLAA', format='1E', array=polaa)
        # col8 = fits.Column(name='POLCALA', format='3E', array=polcala)
        col9 = fits.Column(name='POLTYB', format='1A', array=poltyb)
        col10 = fits.Column(name='POLAB', format='1E', array=polab)
        # col11 = fits.Column(name='POLCALB', format='3E', array=polcalb)
        # note ORBPARM is technically required, but we didn't put it in
        col_list = [col1, col2, col3, col4, col5, col6, col7, col9, col10]

        if self.antenna_diameters is not None:
            col12 = fits.Column(name='DIAMETER',
                                format='1E',
                                array=self.antenna_diameters)
            col_list.append(col12)

        cols = fits.ColDefs(col_list)

        ant_hdu = fits.BinTableHDU.from_columns(cols)

        ant_hdu.header['EXTNAME'] = 'AIPS AN'
        ant_hdu.header['EXTVER'] = 1

        # write XYZ coordinates if not already defined
        ant_hdu.header['ARRAYX'] = self.telescope_location[0]
        ant_hdu.header['ARRAYY'] = self.telescope_location[1]
        ant_hdu.header['ARRAYZ'] = self.telescope_location[2]
        ant_hdu.header['FRAME'] = 'ITRF'
        ant_hdu.header['GSTIA0'] = self.gst0
        ant_hdu.header['FREQ'] = self.freq_array[0, 0]
        ant_hdu.header['RDATE'] = self.rdate
        ant_hdu.header['UT1UTC'] = self.dut1

        ant_hdu.header['TIMSYS'] = self.timesys
        if self.timesys != 'UTC':
            raise ValueError(
                'This file has a time system {tsys}. '
                'Only "UTC" time system files are supported'.format(
                    tsys=self.timesys))
        ant_hdu.header['ARRNAM'] = self.telescope_name
        ant_hdu.header['NO_IF'] = self.Nspws
        ant_hdu.header['DEGPDY'] = self.earth_omega
        # ant_hdu.header['IATUTC'] = 35.

        # set mandatory parameters which are not supported by this object
        # (or that we just don't understand)
        ant_hdu.header['NUMORB'] = 0

        # note: Bart had this set to 3. We've set it 0 after aips 117. -jph
        ant_hdu.header['NOPCAL'] = 0

        ant_hdu.header['POLTYPE'] = 'X-Y LIN'

        # note: we do not support the concept of "frequency setups"
        # -- lists of spws given in a SU table.
        ant_hdu.header['FREQID'] = -1

        # if there are offsets in images, this could be the culprit
        ant_hdu.header['POLARX'] = 0.0
        ant_hdu.header['POLARY'] = 0.0

        ant_hdu.header['DATUTC'] = 0  # ONLY UTC SUPPORTED

        # we always output right handed coordinates
        ant_hdu.header['XYZHAND'] = 'RIGHT'

        # ADD the FQ table
        # skipping for now and limiting to a single spw

        # write the file
        hdulist = fits.HDUList(hdus=[hdu, ant_hdu])
        if float(astropy.__version__[0:3]) < 1.3:  # pragma: no cover
            hdulist.writeto(filename, clobber=True)
        else:
            hdulist.writeto(filename, overwrite=True)
예제 #20
0
def test_readwriteread():
    """
    CASA tutorial uvfits loopback test.

    Read in uvfits file, write out new uvfits file, read back in and check for
    object equality.
    """
    uv_in = UVData()
    uv_out = UVData()
    testfile = os.path.join(DATA_PATH,
                            'day2_TDEM0003_10s_norx_1src_1spw.uvfits')
    write_file = os.path.join(DATA_PATH, 'test/outtest_casa.uvfits')
    uvtest.checkWarnings(uv_in.read, [testfile],
                         message='Telescope EVLA is not')
    uv_in.write_uvfits(write_file)
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out

    # test that it works with write_lst = False
    uv_in.write_uvfits(write_file, write_lst=False)
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out

    # check that if x_orientation is set, it's read back out properly
    uv_in.x_orientation = 'east'
    uv_in.write_uvfits(write_file)
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out

    # check that if antenna_diameters is set, it's read back out properly
    uvtest.checkWarnings(uv_in.read, [testfile],
                         message='Telescope EVLA is not')
    uv_in.antenna_diameters = np.zeros(
        (uv_in.Nants_telescope, ), dtype=np.float) + 14.0
    uv_in.write_uvfits(write_file)
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out

    # check that if antenna_numbers are > 256 everything works
    uvtest.checkWarnings(uv_in.read, [testfile],
                         message='Telescope EVLA is not')
    uv_in.antenna_numbers = uv_in.antenna_numbers + 256
    uv_in.ant_1_array = uv_in.ant_1_array + 256
    uv_in.ant_2_array = uv_in.ant_2_array + 256
    uv_in.baseline_array = uv_in.antnums_to_baseline(uv_in.ant_1_array,
                                                     uv_in.ant_2_array)
    uvtest.checkWarnings(
        uv_in.write_uvfits, [write_file],
        message='antnums_to_baseline: found > 256 antennas, using 2048 baseline'
    )
    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_in == uv_out

    # check missing telescope_name, timesys vs timsys spelling, xyz_telescope_frame=????
    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()

        vis_hdr.pop('TELESCOP')

        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames['AIPS AN']]
        ant_hdr = ant_hdu.header.copy()

        time_sys = ant_hdr.pop('TIMSYS')
        ant_hdr['TIMESYS'] = time_sys
        ant_hdr['FRAME'] = '????'

        ant_hdu.header = ant_hdr

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    uvtest.checkWarnings(uv_out.read, [write_file],
                         message='Telescope EVLA is not')
    assert uv_out.telescope_name == 'EVLA'
    assert uv_out.timesys == time_sys

    # check error if timesys is 'IAT'
    uvtest.checkWarnings(uv_in.read, [testfile],
                         message='Telescope EVLA is not')
    uv_in.timesys = 'IAT'
    pytest.raises(ValueError, uv_in.write_uvfits, write_file)
    uv_in.timesys = 'UTC'

    # check error if one time & no inttime specified
    uv_singlet = uv_in.select(times=uv_in.time_array[0], inplace=False)
    uv_singlet.write_uvfits(write_file)

    with fits.open(write_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data

        par_names = np.array(vis_hdu.data.parnames)
        pars_use = np.where(par_names != 'INTTIM')[0]
        par_names = par_names[pars_use].tolist()

        group_parameter_list = [vis_hdu.data.par(name) for name in par_names]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames['AIPS AN']]

        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    uvtest.checkWarnings(
        pytest.raises, [ValueError, uv_out.read, write_file],
        message=[
            'Telescope EVLA is not',
            'ERFA function "utcut1" yielded 1 of "dubious year (Note 3)"',
            'ERFA function "utctai" yielded 1 of "dubious year (Note 3)"',
            'LST values stored in this file are not self-consistent'
        ],
        nwarnings=4,
        category=[
            UserWarning, astropy._erfa.core.ErfaWarning,
            astropy._erfa.core.ErfaWarning, UserWarning
        ])

    # check that unflagged data with nsample = 0 will cause warnings
    uv_in.nsample_array[list(range(11, 22))] = 0
    uv_in.flag_array[list(range(11, 22))] = False
    uvtest.checkWarnings(uv_in.write_uvfits, [write_file],
                         message='Some unflagged data has nsample = 0')

    del (uv_in)
    del (uv_out)
예제 #21
0
    v_slice[0, 0, :, 1, 2] = 1.0
    v_container[i] = v_slice

#uvparnames = ['UU','VV','WW','BASELINE_ARR','TIME']
uvparnames = ['UU', 'VV', 'WW', 'BASELINE_ARR', 'DATE']
parvals = [uu, vv, ww, baseline, date]
#pzeros = [0.0,0.0,0.0,0.0,date_0]
#pscales = [1.0] * 5

hdu10 = fits.GroupData(v_container,
                       parnames=uvparnames,
                       pardata=parvals,
                       bitpix=-32)

#
hdu10 = fits.GroupsHDU(hdu10)

hdu10.header['CTYPE2'] = 'COMPLEX '
hdu10.header['CRVAL2'] = 1.0
hdu10.header['CRPIX2'] = 1.0
hdu10.header['CDELT2'] = 1.0

hdu10.header['CTYPE3'] = 'STOKES '
hdu10.header['CRVAL3'] = -5.0
hdu10.header['CRPIX3'] = 1.0
hdu10.header['CDELT3'] = -1.0

# Write header information. Not sure about central frequency value as
# it differs between ngas header and fhd value.
hdu10.header['CTYPE4'] = 'FREQ'
#hdu10.header['CRVAL4'] = xx_data.obs['FREQ_CENTER'][0]
예제 #22
0
def test_select_read():
    uvfits_uv = UVData()
    uvfits_uv2 = UVData()
    uvfits_file = os.path.join(DATA_PATH,
                               'day2_TDEM0003_10s_norx_1src_1spw.uvfits')

    # select on antennas
    ants_to_keep = np.array([0, 19, 11, 24, 3, 23, 1, 20, 21])
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file],
                         {'antenna_nums': ants_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # select on frequency channels
    chans_to_keep = np.arange(12, 22)
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file],
                         {'freq_chans': chans_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(freq_chans=chans_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # select on pols
    pols_to_keep = [-1, -2]
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file],
                         {'polarizations': pols_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(polarizations=pols_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # now test selecting on multiple axes
    # frequencies first
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # baselines first
    ants_to_keep = np.array([0, 1])
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # polarizations first
    ants_to_keep = np.array([0, 1, 2, 3, 6, 7, 8, 11, 14, 18, 19, 20, 21, 22])
    chans_to_keep = np.arange(12, 64)
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # repeat with no spw file
    uvfitsfile_no_spw = os.path.join(DATA_PATH,
                                     'zen.2456865.60537.xy.uvcRREAAM.uvfits')

    # select on antennas
    ants_to_keep = np.array([2, 4, 5])
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfitsfile_no_spw],
                         {'antenna_nums': ants_to_keep},
                         known_warning='paper_uvfits')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfitsfile_no_spw],
                         known_warning='paper_uvfits')
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # select on frequency channels
    chans_to_keep = np.arange(4, 8)
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [uvfitsfile_no_spw],
                         {'freq_chans': chans_to_keep},
                         known_warning='paper_uvfits')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [uvfitsfile_no_spw],
                         known_warning='paper_uvfits')
    uvfits_uv2.select(freq_chans=chans_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)

    # select on pols
    # this requires writing a new file because the no spw file we have has only 1 pol
    hdu_list = fits.open(uvfits_file)
    hdunames = uvutils.fits_indexhdus(hdu_list)
    vis_hdu = hdu_list[0]
    vis_hdr = vis_hdu.header.copy()
    raw_data_array = vis_hdu.data.data
    raw_data_array = raw_data_array[:, :, :, 0, :, :, :]

    vis_hdr['NAXIS'] = 6

    vis_hdr['NAXIS5'] = vis_hdr['NAXIS6']
    vis_hdr['CTYPE5'] = vis_hdr['CTYPE6']
    vis_hdr['CRVAL5'] = vis_hdr['CRVAL6']
    vis_hdr['CDELT5'] = vis_hdr['CDELT6']
    vis_hdr['CRPIX5'] = vis_hdr['CRPIX6']
    vis_hdr['CROTA5'] = vis_hdr['CROTA6']

    vis_hdr['NAXIS6'] = vis_hdr['NAXIS7']
    vis_hdr['CTYPE6'] = vis_hdr['CTYPE7']
    vis_hdr['CRVAL6'] = vis_hdr['CRVAL7']
    vis_hdr['CDELT6'] = vis_hdr['CDELT7']
    vis_hdr['CRPIX6'] = vis_hdr['CRPIX7']
    vis_hdr['CROTA6'] = vis_hdr['CROTA7']

    vis_hdr.pop('NAXIS7')
    vis_hdr.pop('CTYPE7')
    vis_hdr.pop('CRVAL7')
    vis_hdr.pop('CDELT7')
    vis_hdr.pop('CRPIX7')
    vis_hdr.pop('CROTA7')

    par_names = vis_hdu.data.parnames

    group_parameter_list = [
        vis_hdu.data.par(ind) for ind in range(len(par_names))
    ]

    vis_hdu = fits.GroupData(raw_data_array,
                             parnames=par_names,
                             pardata=group_parameter_list,
                             bitpix=-32)
    vis_hdu = fits.GroupsHDU(vis_hdu)
    vis_hdu.header = vis_hdr

    ant_hdu = hdu_list[hdunames['AIPS AN']]

    write_file = os.path.join(DATA_PATH, 'test/outtest_casa.uvfits')
    hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
    if float(astropy.__version__[0:3]) < 1.3:
        hdulist.writeto(write_file, clobber=True)
    else:
        hdulist.writeto(write_file, overwrite=True)

    pols_to_keep = [-1, -2]
    uvtest.checkWarnings(uvfits_uv.read_uvfits, [write_file],
                         {'polarizations': pols_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read_uvfits, [write_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(polarizations=pols_to_keep)
    nt.assert_equal(uvfits_uv, uvfits_uv2)
예제 #23
0
def test_select_read():
    uvfits_uv = UVData()
    uvfits_uv2 = UVData()
    uvfits_file = os.path.join(DATA_PATH,
                               'day2_TDEM0003_10s_norx_1src_1spw.uvfits')

    # select on antennas
    ants_to_keep = np.array([0, 19, 11, 24, 3, 23, 1, 20, 21])
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file],
                         {'antenna_nums': ants_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on frequency channels
    chans_to_keep = np.arange(12, 22)
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file],
                         {'freq_chans': chans_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(freq_chans=chans_to_keep)
    assert uvfits_uv == uvfits_uv2

    # check writing & reading single frequency files
    uvfits_uv.select(freq_chans=[0])
    testfile = os.path.join(DATA_PATH, 'test/outtest_casa.uvfits')
    uvfits_uv.write_uvfits(testfile)
    uvtest.checkWarnings(uvfits_uv2.read, [testfile],
                         message='Telescope EVLA is not')
    assert uvfits_uv == uvfits_uv2

    # select on pols
    pols_to_keep = [-1, -2]
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file],
                         {'polarizations': pols_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on read using time_range
    unique_times = np.unique(uvfits_uv.time_array)
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file],
                         {'time_range': [unique_times[0], unique_times[1]]},
                         nwarnings=2,
                         message=[
                             'Warning: "time_range" keyword is set',
                             'Telescope EVLA is not'
                         ])
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(times=unique_times[0:2])
    assert uvfits_uv == uvfits_uv2

    # now test selecting on multiple axes
    # frequencies first
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # baselines first
    ants_to_keep = np.array([0, 1])
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # polarizations first
    ants_to_keep = np.array([0, 1, 2, 3, 6, 7, 8, 11, 14, 18, 19, 20, 21, 22])
    chans_to_keep = np.arange(12, 64)
    uvtest.checkWarnings(uvfits_uv.read, [uvfits_file], {
        'antenna_nums': ants_to_keep,
        'freq_chans': chans_to_keep,
        'polarizations': pols_to_keep
    },
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfits_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(antenna_nums=ants_to_keep,
                      freq_chans=chans_to_keep,
                      polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2

    # repeat with no spw file
    uvfitsfile_no_spw = os.path.join(DATA_PATH,
                                     'zen.2456865.60537.xy.uvcRREAAM.uvfits')

    # select on antennas
    ants_to_keep = np.array([2, 4, 5])
    uvtest.checkWarnings(uvfits_uv.read, [uvfitsfile_no_spw],
                         {'antenna_nums': ants_to_keep},
                         known_warning='paper_uvfits')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfitsfile_no_spw],
                         known_warning='paper_uvfits')
    uvfits_uv2.select(antenna_nums=ants_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on frequency channels
    chans_to_keep = np.arange(4, 8)
    uvtest.checkWarnings(uvfits_uv.read, [uvfitsfile_no_spw],
                         {'freq_chans': chans_to_keep},
                         known_warning='paper_uvfits')
    uvtest.checkWarnings(uvfits_uv2.read, [uvfitsfile_no_spw],
                         known_warning='paper_uvfits')
    uvfits_uv2.select(freq_chans=chans_to_keep)
    assert uvfits_uv == uvfits_uv2

    # select on pols
    # this requires writing a new file because the no spw file we have has only 1 pol
    with fits.open(uvfits_file, memmap=True) as hdu_list:
        hdunames = uvutils._fits_indexhdus(hdu_list)
        vis_hdu = hdu_list[0]
        vis_hdr = vis_hdu.header.copy()
        raw_data_array = vis_hdu.data.data
        raw_data_array = raw_data_array[:, :, :, 0, :, :, :]

        vis_hdr['NAXIS'] = 6

        vis_hdr['NAXIS5'] = vis_hdr['NAXIS6']
        vis_hdr['CTYPE5'] = vis_hdr['CTYPE6']
        vis_hdr['CRVAL5'] = vis_hdr['CRVAL6']
        vis_hdr['CDELT5'] = vis_hdr['CDELT6']
        vis_hdr['CRPIX5'] = vis_hdr['CRPIX6']
        vis_hdr['CROTA5'] = vis_hdr['CROTA6']

        vis_hdr['NAXIS6'] = vis_hdr['NAXIS7']
        vis_hdr['CTYPE6'] = vis_hdr['CTYPE7']
        vis_hdr['CRVAL6'] = vis_hdr['CRVAL7']
        vis_hdr['CDELT6'] = vis_hdr['CDELT7']
        vis_hdr['CRPIX6'] = vis_hdr['CRPIX7']
        vis_hdr['CROTA6'] = vis_hdr['CROTA7']

        vis_hdr.pop('NAXIS7')
        vis_hdr.pop('CTYPE7')
        vis_hdr.pop('CRVAL7')
        vis_hdr.pop('CDELT7')
        vis_hdr.pop('CRPIX7')
        vis_hdr.pop('CROTA7')

        par_names = vis_hdu.data.parnames

        group_parameter_list = [
            vis_hdu.data.par(ind) for ind in range(len(par_names))
        ]

        vis_hdu = fits.GroupData(raw_data_array,
                                 parnames=par_names,
                                 pardata=group_parameter_list,
                                 bitpix=-32)
        vis_hdu = fits.GroupsHDU(vis_hdu)
        vis_hdu.header = vis_hdr

        ant_hdu = hdu_list[hdunames['AIPS AN']]

        write_file = os.path.join(DATA_PATH, 'test/outtest_casa.uvfits')
        hdulist = fits.HDUList(hdus=[vis_hdu, ant_hdu])
        hdulist.writeto(write_file, overwrite=True)

    pols_to_keep = [-1, -2]
    uvtest.checkWarnings(uvfits_uv.read, [write_file],
                         {'polarizations': pols_to_keep},
                         message='Telescope EVLA is not')
    uvtest.checkWarnings(uvfits_uv2.read, [write_file],
                         message='Telescope EVLA is not')
    uvfits_uv2.select(polarizations=pols_to_keep)
    assert uvfits_uv == uvfits_uv2
예제 #24
0
def create_uvfits(template_uvfits=None,
                  freq_cent=None,
                  ra_point=None,
                  dec_point=None,
                  oskar_vis_tag=None,
                  output_uvfits_name=None,
                  date=None):
    '''Takes OSKAR uv data and converts into a uvfits file'''
    int_jd, float_jd = calc_jdcal(date)

    template_file = fits.open(template_uvfits)
    template_data = template_file[0].data
    antenna_table = template_file[1].data

    # Create uv structure by hand, probably there is a better way of doing this but the uvfits structure is kind of finicky
    n_freq = 1  # only one frequency per uvfits file as read by the RTS

    n_data = len(template_data)

    v_container = zeros((n_data, 1, 1, 1, n_freq, 4, 3))
    uu = zeros(n_data)
    vv = zeros(n_data)
    ww = zeros(n_data)
    baseline = zeros(n_data)
    date_array = zeros(n_data)

    xx_us, xx_vs, xx_ws, xx_res, xx_ims = get_osk_data(
        oskar_vis_tag=oskar_vis_tag, polarisation='XX')
    yy_us, yy_vs, yy_ws, yy_res, yy_ims = get_osk_data(
        oskar_vis_tag=oskar_vis_tag, polarisation='YY')
    xy_us, xy_vs, xy_ws, xy_res, xy_ims = get_osk_data(
        oskar_vis_tag=oskar_vis_tag, polarisation='XY')
    yx_us, yx_vs, yx_ws, yx_res, yx_ims = get_osk_data(
        oskar_vis_tag=oskar_vis_tag, polarisation='YX')

    for i in range(len(template_data)):
        xx_list = [xx_res[i], xx_ims[i], 1.0]
        yy_list = [yy_res[i], yy_ims[i], 1.0]
        xy_list = [xy_res[i], xy_ims[i], 1.0]
        yx_list = [yx_res[i], yx_ims[i], 1.0]

        uvdata = [xx_list, yy_list, xy_list, yx_list]
        uvdata = array(uvdata)
        uvdata.shape = (4, 3)

        v_container[i] = uvdata
        uu[i] = xx_us[i] / freq_cent
        vv[i] = xx_vs[i] / freq_cent
        ww[i] = xx_ws[i] / freq_cent
        baseline[i] = template_data[i][3]
        date_array[i] = float_jd
        rotate_phase(xx_ws[i], v_container[i][0, 0, 0, 0, :, :])

    ##UU, VV, WW don't actually get read in by RTS - might be an issue with
    ##miriad/wsclean however, as it looks like oskar w = negative maps w
    uvparnames = ['UU', 'VV', 'WW', 'BASELINE', 'DATE']
    parvals = [uu, vv, ww, baseline, date_array]

    uvhdu = fits.GroupData(v_container,
                           parnames=uvparnames,
                           pardata=parvals,
                           bitpix=-32)
    uvhdu = fits.GroupsHDU(uvhdu)

    ###Try to copy MAPS as sensibly as possible
    uvhdu.header['CTYPE2'] = 'COMPLEX '
    uvhdu.header['CRVAL2'] = 1.0
    uvhdu.header['CRPIX2'] = 1.0
    uvhdu.header['CDELT2'] = 1.0

    ##This means it's linearly polarised
    uvhdu.header['CTYPE3'] = 'STOKES '
    uvhdu.header['CRVAL3'] = -5.0
    uvhdu.header['CRPIX3'] = 1.0
    uvhdu.header['CDELT3'] = -1.0

    uvhdu.header['CTYPE4'] = 'FREQ'
    ###Oskar/CASA for some reason adds half of the frequency specified in the
    ###simulation setup. I think this is happens because CASA is unsure
    ###what 'channel' the data is - when you run with multiple channels, they
    ###are all set to spw = 0, but the output freq is correct. Somethig funky anyway
    ###For one channel, set by hand
    uvhdu.header['CRVAL4'] = freq_cent  ##(sim freq + half channel width)
    uvhdu.header['CRPIX4'] = template_file[0].header['CRPIX4']
    uvhdu.header['CDELT4'] = template_file[0].header['CDELT4']

    uvhdu.header['CTYPE5'] = template_file[0].header['CTYPE5']
    uvhdu.header['CRVAL5'] = template_file[0].header['CRVAL5']
    uvhdu.header['CRPIX5'] = template_file[0].header['CRPIX5']
    uvhdu.header['CDELT5'] = template_file[0].header['CDELT5']

    uvhdu.header['CTYPE6'] = template_file[0].header['CTYPE6']
    uvhdu.header['CRVAL6'] = template_file[0].header['CRVAL6']
    uvhdu.header['CRPIX6'] = template_file[0].header['CRPIX6']
    uvhdu.header['CDELT6'] = template_file[0].header['CDELT6']

    uvhdu.header['CTYPE7'] = template_file[0].header['CTYPE7']
    uvhdu.header['CRVAL7'] = template_file[0].header['CRVAL7']
    uvhdu.header['CRPIX7'] = template_file[0].header['CRPIX7']
    uvhdu.header['CDELT7'] = template_file[0].header['CDELT7']

    ## Write the parameters scaling explictly because they are omitted if default 1/0

    uvhdu.header['PSCAL1'] = 1.0
    uvhdu.header['PZERO1'] = 0.0
    uvhdu.header['PSCAL2'] = 1.0
    uvhdu.header['PZERO2'] = 0.0
    uvhdu.header['PSCAL3'] = 1.0
    uvhdu.header['PZERO3'] = 0.0
    uvhdu.header['PSCAL4'] = 1.0
    uvhdu.header['PZERO4'] = 0.0
    uvhdu.header['PSCAL5'] = 1.0

    uvhdu.header['PZERO5'] = float(int_jd)

    uvhdu.header['OBJECT'] = 'Undefined'
    uvhdu.header['OBSRA'] = ra_point
    uvhdu.header['OBSDEC'] = dec_point

    ##ANTENNA TABLE MODS======================================================================

    template_file[1].header['FREQ'] = freq_cent

    ##MAJICK uses this date to set the LST
    dmy, hms = date.split()
    day, month, year = map(int, dmy.split('-'))
    hour, mins, secs = map(float, hms.split(':'))

    rdate = "%d-%02d-%2dT%2d:%2d:%.2f" % (year, month, day, hour, mins, secs)

    template_file[1].header['RDATE'] = rdate

    ## Create hdulist and write out file
    hdulist = fits.HDUList(hdus=[uvhdu, template_file[1]])
    hdulist.writeto(output_uvfits_name, clobber=True)
    template_file.close()
    hdulist.close()
예제 #25
0
def create_uvfits(v_container=None,freq_cent=None, ra_point=None, dec_point=None,
                  output_uvfits_name=None,uu=None,vv=None,ww=None,
                  baselines_array=None,date_array=None,date=None,
                  central_freq_chan=None,ch_width=None,template_uvfits=None,
                  int_jd=None):
    '''Takes visibility date and writes out a uvfits format file'''

    ##UU, VV, WW don't actually get read in by RTS - might be an issue with
    ##miriad/wsclean however, as it looks like oskar w = negative maps w
    uvparnames = ['UU','VV','WW','BASELINE','DATE']
    parvals = [uu,vv,ww,baselines_array,date_array]

    uvhdu = fits.GroupData(v_container,parnames=uvparnames,pardata=parvals,bitpix=-32)
    uvhdu = fits.GroupsHDU(uvhdu)

    ###Try to copy MAPS as sensibly as possible
    uvhdu.header['CTYPE2'] = 'COMPLEX '
    uvhdu.header['CRVAL2'] = 1.0
    uvhdu.header['CRPIX2'] = 1.0
    uvhdu.header['CDELT2'] = 1.0

    ##This means it's linearly polarised
    uvhdu.header['CTYPE3'] = 'STOKES '
    uvhdu.header['CRVAL3'] = -5.0
    uvhdu.header['CRPIX3'] =  1.0
    uvhdu.header['CDELT3'] = -1.0

    uvhdu.header['CTYPE4'] = 'FREQ'
    uvhdu.header['CRVAL4'] = freq_cent  ##Middle pixel value in Hz
    uvhdu.header['CRPIX4'] = int(central_freq_chan) + 1 ##Middle pixel number
    uvhdu.header['CDELT4'] = ch_width

    uvhdu.header['CTYPE5'] = template_uvfits[0].header['CTYPE5']
    uvhdu.header['CRVAL5'] = template_uvfits[0].header['CRVAL5']
    uvhdu.header['CRPIX5'] = template_uvfits[0].header['CRPIX5']
    uvhdu.header['CDELT5'] = template_uvfits[0].header['CDELT5']

    uvhdu.header['CTYPE6'] = template_uvfits[0].header['CTYPE6']
    uvhdu.header['CRVAL6'] = ra_point
    uvhdu.header['CRPIX6'] = template_uvfits[0].header['CRPIX6']
    uvhdu.header['CDELT6'] = template_uvfits[0].header['CDELT6']

    uvhdu.header['CTYPE7'] = template_uvfits[0].header['CTYPE7']
    uvhdu.header['CRVAL7'] = dec_point
    uvhdu.header['CRPIX7'] = template_uvfits[0].header['CRPIX7']
    uvhdu.header['CDELT7'] = template_uvfits[0].header['CDELT7']

    ## Write the parameters scaling explictly because they are omitted if default 1/0
    uvhdu.header['PSCAL1'] = 1.0
    uvhdu.header['PZERO1'] = 0.0
    uvhdu.header['PSCAL2'] = 1.0
    uvhdu.header['PZERO2'] = 0.0
    uvhdu.header['PSCAL3'] = 1.0
    uvhdu.header['PZERO3'] = 0.0
    uvhdu.header['PSCAL4'] = 1.0
    uvhdu.header['PZERO4'] = 0.0
    uvhdu.header['PSCAL5'] = 1.0

    uvhdu.header['PZERO5'] = float(int_jd)

    uvhdu.header['OBJECT']  = 'Undefined'
    uvhdu.header['OBSRA']   = ra_point
    uvhdu.header['OBSDEC']  = dec_point

    ##ANTENNA TABLE MODS======================================================================

    template_uvfits[1].header['FREQ'] = freq_cent
    template_uvfits[1].header['ARRNAM'] = 'MWA'

    ##MAJICK uses this date to set the LST
    dmy, hms = date.split()
    day,month,year = map(int,dmy.split('-'))
    hour,mins,secs = map(float,hms.split(':'))

    rdate = "%d-%02d-%02dT%02d:%02d:%.2f" %(year,month,day,hour,mins,secs)

    template_uvfits[1].header['RDATE'] = rdate

    ## Create hdulist and write out file
    hdulist = fits.HDUList(hdus=[uvhdu,template_uvfits[1]])
    hdulist.writeto(output_uvfits_name,overwrite=True)
    hdulist.close()
예제 #26
0
파일: uv_comb.py 프로젝트: phanicode/eat
def uvf_if_flatten(uvf, outp='merged.uvfits'):

    # THIS IS TO ADD NEW MERGING MODE: IF_FLATTEN
    # ASSUMING THE SINGLE UVF IS WELL BEHAVED
    uvf_hdul = pyfits.open(uvf)
    f0 = uvf_hdul[0].header['CRVAL4']
    freqs = uvf_hdul['AIPS FQ'].data['IF FREQ'].flatten() + f0
    bw = freqs[-1] - freqs[0]
    Nif = len(freqs)
    freq0 = freqs.mean()

    data = uvf_hdul[0].data
    exp_keys = ['UU', 'VV', 'WW', 'BASELINE', 'DATE', 'INTTIM']
    keys = data.parnames
    idx, iek = index_uvf_keys(keys, exp_keys)
    comb_data = [[] for i in range(7)]
    comb_data.append(np.empty((0, 1, 1, 1, 1, 4, 3)))
    for i in range(Nif):
        for j in range(7):
            # FILLINF UU, VV and WW, BASELINE, DATE, DATE, INTTIM AND DATA
            if j == 5:  # ADD A ONE-SEC OFFSET TO TIMESTAMPS
                comb_data[j].append(data.par(idx[j]) + i * 1.0 / 86400)
            else:
                comb_data[j].append(data.par(idx[j]))
        comb_data[7] = np.append(comb_data[7],
                                 data.data[:, :, :, [i], :, :, :],
                                 axis=0)

    # DATA IS READY
    for i in range(len(iek) - 1):
        comb_data[i] = np.array(comb_data[i], dtype=np.float64).flatten()
    mjd = comb_data[4] + comb_data[5]
    idx_tsort = mjd.argsort()
    for i in range(len(iek)):
        comb_data[i] = comb_data[i][idx_tsort]

    print(comb_data[-1].shape)
    gdata = pyfits.GroupData(input=comb_data[-1],
                             parnames=iek[:-1],
                             pardata=comb_data[:-1],
                             bscale=1.0,
                             bzero=0.0,
                             bitpix=-32)
    ghdu = pyfits.GroupsHDU(gdata)
    ghdu.header = uvf_hdul[0].header
    ghdu.header['CRVAL4'] = freq0
    ghdu.header['CDELT4'] = bw

    antab = uvf_hdul['AIPS AN']
    fq_keys = ['FRQSEL', 'IF FREQ', 'CH WIDTH', 'TOTAL BANDWIDTH', 'SIDEBAND']
    fq_formats = ['1J', '1D', '1E', '1E', '1J']
    fq_data = [np.array([1]), [0], [bw], [bw], [1]]

    cols = [pyfits.Column(name=fq_keys[k], format=fq_formats[k], \
            array=fq_data[k]) for k in range(len(fq_keys))]
    fqtab = pyfits.BinTableHDU.from_columns(cols, name='AIPS FQ')
    fh = fqtab.header
    fh['NO_IF'] = 1

    comb_hdu = pyfits.HDUList([ghdu, antab, fqtab])
    comb_hdu.writeto(outp, output_verify='silentfix', overwrite=True)
예제 #27
0
    def write_uvfits(
        self,
        filename,
        spoof_nonessential=False,
        write_lst=True,
        force_phase=False,
        run_check=True,
        check_extra=True,
        run_check_acceptability=True,
    ):
        """
        Write the data to a uvfits file.

        Parameters
        ----------
        filename : str
            The uvfits file to write to.
        spoof_nonessential : bool
            Option to spoof the values of optional UVParameters that are not set
            but are required for uvfits files.
        write_lst : bool
            Option to write the LSTs to the metadata (random group parameters).
        force_phase : bool
            Option to automatically phase drift scan data to zenith of the first
            timestamp.
        run_check : bool
            Option to check for the existence and proper shapes of parameters
            before writing the file.
        check_extra : bool
            Option to check optional parameters as well as required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of parameters before
            writing the file.

        Raises
        ------
        ValueError
            The `phase_type` of the object is "drift" and the `force_phase`
            keyword is not set.
            The `phase_type` of the object is "unknown".
            If the frequencies are not evenly spaced or are separated by more
            than their channel width.
            The polarization values are not evenly spaced.
            Any of ['antenna_positions', 'gst0', 'rdate', 'earth_omega', 'dut1',
            'timesys'] are not set on the object and `spoof_nonessential` is False.
            If the `timesys` parameter is not set to "UTC".
        TypeError
            If any entry in extra_keywords is not a single string or number.

        """
        if run_check:
            self.check(
                check_extra=check_extra,
                run_check_acceptability=run_check_acceptability,
                check_freq_spacing=True,
            )

        if self.phase_type == "phased":
            pass
        elif self.phase_type == "drift":
            if force_phase:
                print(
                    "The data are in drift mode and do not have a "
                    "defined phase center. Phasing to zenith of the first "
                    "timestamp."
                )
                phase_time = Time(self.time_array[0], format="jd")
                self.phase_to_time(phase_time)
            else:
                raise ValueError(
                    "The data are in drift mode. "
                    "Set force_phase to true to phase the data "
                    "to zenith of the first timestamp before "
                    "writing a uvfits file."
                )
        else:
            raise ValueError(
                "The phasing type of the data is unknown. "
                "Set the phase_type to drift or phased to "
                "reflect the phasing status of the data"
            )

        if self.Nfreqs > 1:
            freq_spacing = np.diff(self.freq_array, axis=1)
            freq_spacing = freq_spacing[0, 0]
        else:
            freq_spacing = self.channel_width

        if self.Npols > 1:
            pol_spacing = np.diff(self.polarization_array)
            if np.min(pol_spacing) < np.max(pol_spacing):
                raise ValueError(
                    "The polarization values are not evenly spaced (probably "
                    "because of a select operation). The uvfits format "
                    "does not support unevenly spaced polarizations."
                )
            pol_spacing = pol_spacing[0]
        else:
            pol_spacing = 1

        for p in self.extra():
            param = getattr(self, p)
            if param.name in self.uvfits_required_extra:
                if param.value is None:
                    if spoof_nonessential:
                        param.apply_spoof()
                        setattr(self, p, param)
                    else:
                        raise ValueError(
                            "Required attribute {attribute} "
                            "for uvfits not defined. Define or "
                            "set spoof_nonessential to True to "
                            "spoof this attribute.".format(attribute=p)
                        )

        # check for unflagged data with nsample = 0. Warn if any found
        wh_nsample0 = np.where(self.nsample_array == 0)
        if np.any(~self.flag_array[wh_nsample0]):
            warnings.warn(
                "Some unflagged data has nsample = 0. Flags and "
                "nsamples are combined in uvfits files such that "
                "these data will appear to be flagged."
            )

        weights_array = self.nsample_array * np.where(self.flag_array, -1, 1)
        # FITS uvw direction convention is opposite ours and Miriad's.
        # So conjugate the visibilities and flip the uvws:
        data_array = np.conj(
            self.data_array[:, np.newaxis, np.newaxis, :, :, :, np.newaxis]
        )
        weights_array = weights_array[:, np.newaxis, np.newaxis, :, :, :, np.newaxis]
        # uvfits_array_data shape will be  (Nblts,1,1,[Nspws],Nfreqs,Npols,3)
        uvfits_array_data = np.concatenate(
            [data_array.real, data_array.imag, weights_array], axis=6
        )

        # FITS uvw direction convention is opposite ours and Miriad's.
        # So conjugate the visibilities and flip the uvws:
        uvw_array_sec = -1 * self.uvw_array / const.c.to("m/s").value
        # jd_midnight = np.floor(self.time_array[0] - 0.5) + 0.5
        tzero = np.float32(self.time_array[0])

        # uvfits convention is that time_array + relevant PZERO = actual JD
        # We are setting PZERO4 = float32(first time of observation)
        time_array = np.float32(self.time_array - np.float64(tzero))

        int_time_array = self.integration_time

        baselines_use = self.antnums_to_baseline(
            self.ant_1_array, self.ant_2_array, attempt256=True
        )
        # Set up dictionaries for populating hdu
        # Note that uvfits antenna arrays are 1-indexed so we add 1
        # to our 0-indexed arrays
        group_parameter_dict = {
            "UU      ": uvw_array_sec[:, 0],
            "VV      ": uvw_array_sec[:, 1],
            "WW      ": uvw_array_sec[:, 2],
            "DATE    ": time_array,
            "BASELINE": baselines_use,
            "ANTENNA1": self.ant_1_array + 1,
            "ANTENNA2": self.ant_2_array + 1,
            "SUBARRAY": np.ones_like(self.ant_1_array),
            "INTTIM  ": int_time_array,
        }

        pscal_dict = {
            "UU      ": 1.0,
            "VV      ": 1.0,
            "WW      ": 1.0,
            "DATE    ": 1.0,
            "BASELINE": 1.0,
            "ANTENNA1": 1.0,
            "ANTENNA2": 1.0,
            "SUBARRAY": 1.0,
            "INTTIM  ": 1.0,
        }
        pzero_dict = {
            "UU      ": 0.0,
            "VV      ": 0.0,
            "WW      ": 0.0,
            "DATE    ": tzero,
            "BASELINE": 0.0,
            "ANTENNA1": 0.0,
            "ANTENNA2": 0.0,
            "SUBARRAY": 0.0,
            "INTTIM  ": 0.0,
        }

        if write_lst:
            # lst is a non-standard entry (it's not in the AIPS memo)
            # but storing it can be useful (e.g. can avoid recalculating it on read)
            # need to store it in 2 parts to get enough accuracy
            # angles in uvfits files are stored in degrees, so first convert to degrees
            lst_array_deg = np.rad2deg(self.lst_array)
            lst_array_1 = np.float32(lst_array_deg)
            lst_array_2 = np.float32(lst_array_deg - np.float64(lst_array_1))
            group_parameter_dict["LST     "] = lst_array_1
            pscal_dict["LST     "] = 1.0
            pzero_dict["LST     "] = 0.0

        # list contains arrays of [u,v,w,date,baseline];
        # each array has shape (Nblts)
        parnames_use = ["UU      ", "VV      ", "WW      ", "DATE    "]
        if np.max(self.ant_1_array) < 255 and np.max(self.ant_2_array) < 255:
            # if the number of antennas is less than 256 then include both the
            # baseline array and the antenna arrays in the group parameters.
            # Otherwise just use the antenna arrays
            parnames_use.append("BASELINE")

        parnames_use += ["ANTENNA1", "ANTENNA2", "SUBARRAY", "INTTIM  "]

        if write_lst:
            parnames_use.append("LST     ")

        group_parameter_list = [
            group_parameter_dict[parname] for parname in parnames_use
        ]

        if write_lst:
            # add second LST array part
            parnames_use.append("LST     ")
            group_parameter_list.append(lst_array_2)

        hdu = fits.GroupData(
            uvfits_array_data,
            parnames=parnames_use,
            pardata=group_parameter_list,
            bitpix=-32,
        )
        hdu = fits.GroupsHDU(hdu)

        for i, key in enumerate(parnames_use):
            hdu.header["PSCAL" + str(i + 1) + "  "] = pscal_dict[key]
            hdu.header["PZERO" + str(i + 1) + "  "] = pzero_dict[key]

        # ISO string of first time in self.time_array
        hdu.header["DATE-OBS"] = Time(self.time_array[0], scale="utc", format="jd").isot

        hdu.header["CTYPE2  "] = "COMPLEX "
        hdu.header["CRVAL2  "] = 1.0
        hdu.header["CRPIX2  "] = 1.0
        hdu.header["CDELT2  "] = 1.0

        # Note: This axis is called STOKES to comply with the AIPS memo 117
        # However, this confusing because it is NOT a true Stokes axis,
        #   it is really the polarization axis.
        hdu.header["CTYPE3  "] = "STOKES  "
        hdu.header["CRVAL3  "] = self.polarization_array[0]
        hdu.header["CRPIX3  "] = 1.0
        hdu.header["CDELT3  "] = pol_spacing

        hdu.header["CTYPE4  "] = "FREQ    "
        hdu.header["CRVAL4  "] = self.freq_array[0, 0]
        hdu.header["CRPIX4  "] = 1.0
        hdu.header["CDELT4  "] = freq_spacing

        hdu.header["CTYPE5  "] = "IF      "
        hdu.header["CRVAL5  "] = 1.0
        hdu.header["CRPIX5  "] = 1.0
        hdu.header["CDELT5  "] = 1.0

        hdu.header["CTYPE6  "] = "RA"
        hdu.header["CRVAL6  "] = self.phase_center_ra_degrees

        hdu.header["CTYPE7  "] = "DEC"
        hdu.header["CRVAL7  "] = self.phase_center_dec_degrees

        hdu.header["BUNIT   "] = self.vis_units
        hdu.header["BSCALE  "] = 1.0
        hdu.header["BZERO   "] = 0.0

        hdu.header["OBJECT  "] = self.object_name
        hdu.header["TELESCOP"] = self.telescope_name
        hdu.header["LAT     "] = self.telescope_location_lat_lon_alt_degrees[0]
        hdu.header["LON     "] = self.telescope_location_lat_lon_alt_degrees[1]
        hdu.header["ALT     "] = self.telescope_location_lat_lon_alt[2]
        hdu.header["INSTRUME"] = self.instrument
        hdu.header["EPOCH   "] = float(self.phase_center_epoch)
        if self.phase_center_frame is not None:
            hdu.header["PHSFRAME"] = self.phase_center_frame

        if self.x_orientation is not None:
            hdu.header["XORIENT"] = self.x_orientation

        if self.blt_order is not None:
            blt_order_str = ", ".join(self.blt_order)
            hdu.header["BLTORDER"] = blt_order_str

        for line in self.history.splitlines():
            hdu.header.add_history(line)

        # end standard keywords; begin user-defined keywords
        for key, value in self.extra_keywords.items():
            # header keywords have to be 8 characters or less
            if len(str(key)) > 8:
                warnings.warn(
                    "key {key} in extra_keywords is longer than 8 "
                    "characters. It will be truncated to 8 as required "
                    "by the uvfits file format.".format(key=key)
                )
            keyword = key[:8].upper()
            if isinstance(value, (dict, list, np.ndarray)):
                raise TypeError(
                    "Extra keyword {keyword} is of {keytype}. "
                    "Only strings and numbers are "
                    "supported in uvfits.".format(keyword=key, keytype=type(value))
                )

            if keyword == "COMMENT":
                for line in value.splitlines():
                    hdu.header.add_comment(line)
            else:
                hdu.header[keyword] = value

        # ADD the ANTENNA table
        staxof = np.zeros(self.Nants_telescope)

        # 0 specifies alt-az, 6 would specify a phased array
        mntsta = np.zeros(self.Nants_telescope)

        # beware, X can mean just about anything
        poltya = np.full((self.Nants_telescope), "X", dtype=np.object_)
        polaa = [90.0] + np.zeros(self.Nants_telescope)
        poltyb = np.full((self.Nants_telescope), "Y", dtype=np.object_)
        polab = [0.0] + np.zeros(self.Nants_telescope)

        col1 = fits.Column(name="ANNAME", format="8A", array=self.antenna_names)
        # AIPS memo #117 says that antenna_positions should be relative to
        # the array center, but in a rotated ECEF frame so that the x-axis
        # goes through the local meridian.
        longitude = self.telescope_location_lat_lon_alt[1]
        rot_ecef_positions = uvutils.rotECEF_from_ECEF(
            self.antenna_positions, longitude
        )
        col2 = fits.Column(name="STABXYZ", format="3D", array=rot_ecef_positions)
        # convert to 1-indexed from 0-indexed indicies
        col3 = fits.Column(name="NOSTA", format="1J", array=self.antenna_numbers + 1)
        col4 = fits.Column(name="MNTSTA", format="1J", array=mntsta)
        col5 = fits.Column(name="STAXOF", format="1E", array=staxof)
        col6 = fits.Column(name="POLTYA", format="1A", array=poltya)
        col7 = fits.Column(name="POLAA", format="1E", array=polaa)
        # col8 = fits.Column(name='POLCALA', format='3E', array=polcala)
        col9 = fits.Column(name="POLTYB", format="1A", array=poltyb)
        col10 = fits.Column(name="POLAB", format="1E", array=polab)
        # col11 = fits.Column(name='POLCALB', format='3E', array=polcalb)
        # note ORBPARM is technically required, but we didn't put it in
        col_list = [col1, col2, col3, col4, col5, col6, col7, col9, col10]

        if self.antenna_diameters is not None:
            col12 = fits.Column(
                name="DIAMETER", format="1E", array=self.antenna_diameters
            )
            col_list.append(col12)

        cols = fits.ColDefs(col_list)

        ant_hdu = fits.BinTableHDU.from_columns(cols)

        ant_hdu.header["EXTNAME"] = "AIPS AN"
        ant_hdu.header["EXTVER"] = 1

        # write XYZ coordinates if not already defined
        ant_hdu.header["ARRAYX"] = self.telescope_location[0]
        ant_hdu.header["ARRAYY"] = self.telescope_location[1]
        ant_hdu.header["ARRAYZ"] = self.telescope_location[2]
        ant_hdu.header["FRAME"] = "ITRF"
        ant_hdu.header["GSTIA0"] = self.gst0
        ant_hdu.header["FREQ"] = self.freq_array[0, 0]
        ant_hdu.header["RDATE"] = self.rdate
        ant_hdu.header["UT1UTC"] = self.dut1

        ant_hdu.header["TIMSYS"] = self.timesys
        if self.timesys != "UTC":
            raise ValueError(
                "This file has a time system {tsys}. "
                'Only "UTC" time system files are supported'.format(tsys=self.timesys)
            )
        ant_hdu.header["ARRNAM"] = self.telescope_name
        ant_hdu.header["NO_IF"] = self.Nspws
        ant_hdu.header["DEGPDY"] = self.earth_omega
        # ant_hdu.header['IATUTC'] = 35.

        # set mandatory parameters which are not supported by this object
        # (or that we just don't understand)
        ant_hdu.header["NUMORB"] = 0

        # note: Bart had this set to 3. We've set it 0 after aips 117. -jph
        ant_hdu.header["NOPCAL"] = 0

        ant_hdu.header["POLTYPE"] = "X-Y LIN"

        # note: we do not support the concept of "frequency setups"
        # -- lists of spws given in a SU table.
        ant_hdu.header["FREQID"] = -1

        # if there are offsets in images, this could be the culprit
        ant_hdu.header["POLARX"] = 0.0
        ant_hdu.header["POLARY"] = 0.0

        ant_hdu.header["DATUTC"] = 0  # ONLY UTC SUPPORTED

        # we always output right handed coordinates
        ant_hdu.header["XYZHAND"] = "RIGHT"

        # ADD the FQ table
        # skipping for now and limiting to a single spw

        # write the file
        hdulist = fits.HDUList(hdus=[hdu, ant_hdu])
        hdulist.writeto(filename, overwrite=True)