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))
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
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)
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)