예제 #1
0
def test_redundancy_finder():
    """
        Check that get_baseline_redundancies and get_antenna_redundancies return consistent
        redundant groups for a test file with the HERA19 layout.
    """
    uvd = pyuvdata.UVData()
    uvd.read_uvfits(
        os.path.join(
            DATA_PATH,
            'hera19_8hrs_uncomp_10MHz_000_05.003111-05.033750.uvfits'))
    uvd.select(times=uvd.time_array[0])
    uvd.unphase_to_drift(
        use_ant_pos=True)  # uvw_array is now equivalent to baseline positions

    tol = 0.05  # meters

    bl_positions = uvd.uvw_array

    nt.assert_raises(ValueError, uvutils.get_baseline_redundancies,
                     uvd.baseline_array, bl_positions[0:2, 0:1])
    baseline_groups, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol)

    baseline_groups, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol)

    for gi, gp in enumerate(baseline_groups):
        for bl in gp:
            bl_ind = np.where(uvd.baseline_array == bl)
            bl_vec = bl_positions[bl_ind]
            nt.assert_true(
                np.allclose(np.sqrt(np.dot(bl_vec, vec_bin_centers[gi])),
                            lens[gi],
                            atol=tol))

    # Now jostle the baselines around by up to 0.25m and see if we can recover the same redundancies to that tolerance.
    tol = 0.25  # meters. Less than the smallest baseline in the file.
    Nbls = uvd.Nbls
    shift_dists = np.random.uniform(low=0.0, high=tol / 2., size=Nbls)
    shift_angs = np.random.uniform(low=0.0, high=2 * np.pi, size=Nbls)
    shift_vecs = np.stack(
        (shift_dists * np.cos(shift_angs), shift_dists * np.sin(shift_angs),
         np.zeros(Nbls))).T

    bl_positions_new = uvd.uvw_array + shift_vecs

    baseline_groups_new, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions_new, tol=tol)

    for gi, gp in enumerate(baseline_groups_new):
        for bl in gp:
            bl_ind = np.where(uvd.baseline_array == bl)
            bl_vec = bl_positions[bl_ind]
            nt.assert_true(
                np.allclose(np.sqrt(np.abs(np.dot(bl_vec,
                                                  vec_bin_centers[gi]))),
                            lens[gi],
                            atol=tol))

    # Compare baseline groups:
    for c, blg in enumerate(baseline_groups):
        bl = blg[0]
        ind = np.sum(np.where([bl in gp for gp in baseline_groups_new]))
        nt.assert_equal(baseline_groups_new[ind], blg)

    tol = 0.05

    antpos, antnums = uvd.get_ENU_antpos()
    baseline_groups_ants, vec_bin_centers, lens = uvutils.get_antenna_redundancies(
        antnums, antpos, tol=tol, include_autos=True)
    # Under these conditions, should see 31 redundant groups in the file.
    nt.assert_equal(len(baseline_groups_ants), 31)

    # Check with conjugated baseline redundancies returned
    u16_0 = bl_positions[16, 0]
    bl_positions[
        16,
        0] = 0  # Ensure at least one baseline has u==0 and v!=0 (for coverage of this case)
    baseline_groups, vec_bin_centers, lens, conjugates = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol, with_conjugates=True)

    # restore baseline (16,0) and repeat to get correct groups
    bl_positions[16, 0] = u16_0
    baseline_groups, vec_bin_centers, lens, conjugates = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol, with_conjugates=True)

    # Should get the same groups as with the antenna method:
    baseline_groups_flipped = []
    for bgp in baseline_groups:
        bgp_new = []
        for bl in bgp:
            ai, aj = uvutils.baseline_to_antnums(bl, uvd.Nants_telescope)
            if bl in conjugates:
                bgp_new.append(
                    uvutils.antnums_to_baseline(aj, ai, uvd.Nants_telescope))
            else:
                bgp_new.append(
                    uvutils.antnums_to_baseline(ai, aj, uvd.Nants_telescope))
        bgp_new.sort()
        baseline_groups_flipped.append(bgp_new)
    baseline_groups = [sorted(bgp) for bgp in baseline_groups]
    nt.assert_true(
        np.all(
            sorted(baseline_groups_ants) == sorted(baseline_groups_flipped)))
    for gi, gp in enumerate(baseline_groups):
        for bl in gp:
            bl_ind = np.where(uvd.baseline_array == bl)
            bl_vec = bl_positions[bl_ind]
            if bl in conjugates:
                bl_vec *= (-1)
            nt.assert_true(
                np.isclose(np.sqrt(np.dot(bl_vec, vec_bin_centers[gi])),
                           lens[gi],
                           atol=tol))
예제 #2
0
def setup_uvdata(
    array_layout=None,
    telescope_location=None,
    telescope_name=None,
    Nfreqs=None,
    start_freq=None,
    bandwidth=None,
    freq_array=None,
    Ntimes=None,
    time_cadence=None,
    start_time=None,
    time_array=None,
    bls=None,
    anchor_ant=None,
    antenna_nums=None,
    no_autos=True,
    pols=["xx"],
    make_full=False,
    redundancy=None,
    run_check=True,
):
    """
    Setup a UVData object for simulating.

    Args:
        array_layout : str
            Filepath to array layout in ENU coordinates [meters]
        telescope_location : len-3 tuple
            Telescope location on Earth in LatLonAlt coordinates [deg, deg, meters]
        telescope_name : str
            Name of telescope
        Nfreqs : int
            Number of frequency channels
        start_freq : float
            Starting frequency [Hz]
        bandwidth : float
            Total frequency bandwidth of spectral window [Hz]
        freq_array : ndarray
            frequency array [Hz], cannot be specified if start_freq, Nfreqs or bandwidth is specified
        Ntimes : int
            Number of integration bins
        time_cadence : float
            Cadence of time bins [seconds]
        start_time : float
            Time of the first integration bin [Julian Date]
        time_array : ndarray
            time array [Julian Date], cannot be specified if start_time, Ntimes and time_cadence is specified
        bls : list
            List of antenna-pair tuples for baseline selection
        anchor_ant: int
            Selects baselines such that one of the pair is a specified antenna number
        redundancy: float
            Redundant baseline selection tolerance for selection
        antenna_nums : list
            List of antenna numbers to keep in array
        make_full : Generate the full UVData object, includes arrays of length Nblts.
                    Default behavior creates an invalid UVData object, where baseline_array has length Nbls, etc.
                    This is to avoid excessive memory usage up front when it's not necessary.

    Returns:
        UVData object with zeroed data_array
    """

    # get antenna information
    tele_dict = parse_telescope_params(
        dict(
            array_layout=array_layout,
            telescope_location=telescope_location,
            telescope_name=telescope_name,
        ))
    lat, lon, alt = uvutils.LatLonAlt_from_XYZ(tele_dict["telescope_location"])
    antpos = tele_dict["antenna_positions"]
    enu = uvutils.ENU_from_ECEF(
        tele_dict["antenna_positions"] + tele_dict["telescope_location"], lat,
        lon, alt)
    anums = tele_dict["antenna_numbers"]
    antnames = tele_dict["antenna_names"]
    Nants = tele_dict["Nants_data"]

    # setup object and fill in basic info
    uv_obj = UVData()
    uv_obj.telescope_location = tele_dict["telescope_location"]
    uv_obj.telescope_location_lat_lon_alt = (lat, lon, alt)
    uv_obj.telescope_location_lat_lon_alt_degrees = (
        np.degrees(lat),
        np.degrees(lon),
        alt,
    )
    uv_obj.antenna_numbers = anums
    uv_obj.antenna_names = antnames
    uv_obj.antenna_positions = antpos
    uv_obj.Nants_telescope = Nants

    # fill in frequency and time info: wait to fill in len-Nblts arrays until later
    if freq_array is not None:
        if Nfreqs is not None or start_freq is not None or bandwidth is not None:
            raise ValueError(
                "Cannot specify freq_array as well as Nfreqs, start_freq or bandwidth"
            )
        if freq_array.ndim == 1:
            freq_array = freq_array.reshape(1, -1)
            Nfreqs = freq_array.size
    else:
        freq_dict = parse_frequency_params(
            dict(Nfreqs=Nfreqs, start_freq=start_freq, bandwidth=bandwidth))
        freq_array = freq_dict["freq_array"]

    if time_array is not None:
        if Ntimes is not None or start_time is not None or time_cadence is not None:
            raise ValueError(
                "Cannot specify time_array as well as Ntimes, start_time or time_cadence"
            )
        Ntimes = time_array.size
    else:
        time_dict = parse_time_params(
            dict(Ntimes=Ntimes,
                 start_time=start_time,
                 time_cadence=time_cadence))
        time_array = time_dict["time_array"]

    uv_obj.freq_array = freq_array
    uv_obj.Nfreqs = Nfreqs
    uv_obj.Ntimes = Ntimes

    # fill in other attributes
    uv_obj.spw_array = np.array([0], dtype=int)
    uv_obj.Nspws = 1
    uv_obj.polarization_array = np.array(
        [uvutils.polstr2num(pol) for pol in pols], dtype=int)
    uv_obj.Npols = uv_obj.polarization_array.size
    if uv_obj.Nfreqs > 1:
        uv_obj.channel_width = np.diff(uv_obj.freq_array[0])[0]
    else:
        uv_obj.channel_width = 1.0
    uv_obj._set_drift()
    uv_obj.telescope_name = tele_dict["telescope_name"]
    uv_obj.instrument = "simulator"
    uv_obj.object_name = "zenith"
    uv_obj.vis_units = "Jy"
    uv_obj.history = ""

    if redundancy is not None:
        red_tol = redundancy
        reds, vec_bin_centers, lengths = uvutils.get_antenna_redundancies(
            anums, enu, tol=red_tol, include_autos=not bool(no_autos))
        bls = [r[0] for r in reds]
        bls = [uvutils.baseline_to_antnums(bl_ind, Nants) for bl_ind in bls]

    # Setup array and implement antenna/baseline selections.
    bl_array = []
    _bls = [(a1, a2) for a1 in anums for a2 in anums if a1 <= a2]
    if bls is not None:
        if isinstance(bls, str):
            bls = ast.literal_eval(bls)
        bls = [bl for bl in _bls if bl in bls]
    else:
        bls = _bls
    if anchor_ant is not None:
        bls = [bl for bl in bls if anchor_ant in bl]

    if bool(no_autos):
        bls = [bl for bl in bls if bl[0] != bl[1]]
    if antenna_nums is not None:
        if isinstance(antenna_nums, str):
            antenna_nums = ast.literal_eval(antenna_nums)
        if isinstance(antenna_nums, int):
            antenna_nums = [antenna_nums]
        bls = [(a1, a2) for (a1, a2) in bls
               if a1 in antenna_nums or a2 in antenna_nums]
    bls = sorted(bls)
    for (a1, a2) in bls:
        bl_array.append(uvutils.antnums_to_baseline(a1, a2, 1))
    bl_array = np.asarray(bl_array)
    print("Nbls: {}".format(bl_array.size))
    if bl_array.size == 0:
        raise ValueError("No baselines selected.")
    uv_obj.time_array = time_array  # Keep length Ntimes
    uv_obj.baseline_array = bl_array  # Length Nbls

    if make_full:
        uv_obj = complete_uvdata(uv_obj, run_check=run_check)

    return uv_obj
예제 #3
0
bls = [(a1, a2) for a2 in anums for a1 in anums if a1>a2]
if 'select' in param_dict:
    sel = param_dict['select']
    if 'bls' in sel:
        bls = eval(sel['bls'])
    if 'antenna_nums' in sel:
        antnums = sel['antenna_nums']
        if isinstance(antnums, str):
            antnums = eval(sel['antenna_nums'])
        if isinstance(antnums, int):
            antnums = [antnums]
        bls = [(a1, a2) for (a1, a2) in bls if a1 in antnums or a2 in antnums]
        uv_obj.antenna_nums = antnums
    if 'redundancy' in sel:
        red_tol = sel['redundancy']
        reds, vec_bin_centers, lengths = uvutils.get_antenna_redundancies(anums, enu, tol=red_tol, include_autos=False)
        bls = [r[0] for r in reds]
        bls = [uvutils.baseline_to_antnums(bl_ind, Nants) for bl_ind in bls]
uv_obj.Nants_data = np.unique(bls).size
for (a1, a2) in bls:
    i1, i2 = np.where(anums == a1), np.where(anums == a2)
    array.append(visibility.baseline(enu[i1], enu[i2]))
    bl_array.append(uvutils.antnums_to_baseline(a1, a2, Nants))
Nbls = len(bl_array)
uv_obj.Nbls = Nbls
uv_obj.Nblts = Nbls * Ntimes

bl_array = np.array(bl_array)
freqs = freq_dict['freq_array'][0]        #Hz
obs = visibility.observatory(np.degrees(lat), np.degrees(lon), array=array, freqs=freqs)
obs.set_fov(fov)
예제 #4
0
def test_redundancy_finder():
    """
    Check that get_baseline_redundancies and get_antenna_redundancies return consistent
    redundant groups for a test file with the HERA19 layout.
    """
    uvd = pyuvdata.UVData()
    uvd.read_uvfits(
        os.path.join(DATA_PATH,
                     'fewant_randsrc_airybeam_Nsrc100_10MHz.uvfits'))

    uvd.select(times=uvd.time_array[0])
    uvd.unphase_to_drift()  # uvw_array is now equivalent to baseline positions
    uvtest.checkWarnings(uvd.conjugate_bls,
                         func_kwargs={
                             'convention': 'u>0',
                             'use_enu': True
                         },
                         message=['The default for the `center`'],
                         nwarnings=1,
                         category=DeprecationWarning)

    tol = 0.05  # meters

    bl_positions = uvd.uvw_array

    pytest.raises(ValueError, uvutils.get_baseline_redundancies,
                  uvd.baseline_array, bl_positions[0:2, 0:1])
    baseline_groups, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol)

    baseline_groups, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol)

    for gi, gp in enumerate(baseline_groups):
        for bl in gp:
            bl_ind = np.where(uvd.baseline_array == bl)
            bl_vec = bl_positions[bl_ind]
            assert np.allclose(np.sqrt(np.dot(bl_vec, vec_bin_centers[gi])),
                               lens[gi],
                               atol=tol)

    # Shift the baselines around in a circle. Check that the same baselines are
    # recovered to the corresponding tolerance increase.
    # This moves one baseline at a time by a fixed displacement and checks that
    # the redundant groups are the same.

    hightol = 0.25  # meters. Less than the smallest baseline in the file.
    Nbls = uvd.Nbls
    Nshifts = 5
    shift_angs = np.linspace(0, 2 * np.pi, Nshifts)
    base_shifts = np.stack(
        ((hightol - tol) * np.cos(shift_angs),
         (hightol - tol) * np.sin(shift_angs), np.zeros(Nshifts))).T
    for sh in base_shifts:
        for bi in range(Nbls):
            # Shift one baseline at a time.
            bl_positions_new = uvd.uvw_array
            bl_positions_new[bi] += sh

            baseline_groups_new, vec_bin_centers, lens = uvutils.get_baseline_redundancies(
                uvd.baseline_array, bl_positions_new, tol=hightol)

            for gi, gp in enumerate(baseline_groups_new):
                for bl in gp:
                    bl_ind = np.where(uvd.baseline_array == bl)
                    bl_vec = bl_positions[bl_ind]
                    assert np.allclose(np.sqrt(
                        np.abs(np.dot(bl_vec, vec_bin_centers[gi]))),
                                       lens[gi],
                                       atol=hightol)

            # Compare baseline groups:
            a = [tuple(el) for el in baseline_groups]
            b = [tuple(el) for el in baseline_groups_new]
            assert set(a) == set(b)

    tol = 0.05

    antpos, antnums = uvtest.checkWarnings(
        uvd.get_ENU_antpos,
        message=['The default for the `center`'],
        category=DeprecationWarning,
        nwarnings=1)

    baseline_groups_ants, vec_bin_centers, lens = uvutils.get_antenna_redundancies(
        antnums, antpos, tol=tol, include_autos=False)
    # Under these conditions, should see 19 redundant groups in the file.
    assert len(baseline_groups_ants) == 19

    # Check with conjugated baseline redundancies returned
    u16_0 = bl_positions[16, 0]
    # Ensure at least one baseline has u==0 and v!=0 (for coverage of this case)
    bl_positions[16, 0] = 0
    baseline_groups, vec_bin_centers, lens, conjugates = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol, with_conjugates=True)

    # restore baseline (16,0) and repeat to get correct groups
    bl_positions[16, 0] = u16_0
    baseline_groups, vec_bin_centers, lens, conjugates = uvutils.get_baseline_redundancies(
        uvd.baseline_array, bl_positions, tol=tol, with_conjugates=True)

    # Should get the same groups as with the antenna method:
    baseline_groups_flipped = []
    for bgp in baseline_groups:
        bgp_new = []
        for bl in bgp:
            ai, aj = uvutils.baseline_to_antnums(bl, uvd.Nants_telescope)
            if bl in conjugates:
                bgp_new.append(
                    uvutils.antnums_to_baseline(aj, ai, uvd.Nants_telescope))
            else:
                bgp_new.append(
                    uvutils.antnums_to_baseline(ai, aj, uvd.Nants_telescope))
        bgp_new.sort()
        baseline_groups_flipped.append(bgp_new)
    baseline_groups = [sorted(bgp) for bgp in baseline_groups]
    assert np.all(
        sorted(baseline_groups_ants) == sorted(baseline_groups_flipped))
    for gi, gp in enumerate(baseline_groups):
        for bl in gp:
            bl_ind = np.where(uvd.baseline_array == bl)
            bl_vec = bl_positions[bl_ind]
            if bl in conjugates:
                bl_vec *= (-1)
            assert np.isclose(np.sqrt(np.dot(bl_vec, vec_bin_centers[gi])),
                              lens[gi],
                              atol=tol)