uv.Nbls = 1 uv.Ntimes = Ntimes uv.spw_array = [0] uv.Nfreqs = Nfreqs uv.freq_array = freqs[np.newaxis, :] uv.Nblts = uv.Ntimes * uv.Nbls uv.ant_1_array = np.zeros(uv.Nblts, dtype=int) uv.ant_2_array = np.ones(uv.Nblts, dtype=int) uv.baseline_array = uv.antnums_to_baseline(uv.ant_1_array, uv.ant_2_array) uv.time_array = time_arr uv.Npols = 1 uv.polarization_array=np.array([1]) uv.Nants_telescope = 2 uv.Nants_data = 2 uv.antenna_positions = uvutils.ECEF_from_ENU(np.stack([ant1_enu, ant2_enu]), latitude, longitude, altitude) uv.Nspws = 1 uv.antenna_numbers = np.array([0,1]) uv.antenna_names = ['ant0', 'ant1'] #uv.channel_width = np.ones(uv.Nblts) * np.diff(freqs)[0] uv.channel_width = np.diff(freqs)[0] uv.integration_time = np.ones(uv.Nblts) * np.diff(time_arr)[0] * 24 * 3600. # Seconds uv.uvw_array = np.tile(ant1_enu - ant2_enu, uv.Nblts).reshape(uv.Nblts, 3) uv.history = 'Eorsky simulated' uv.set_drift() uv.telescope_name = 'Eorsky gaussian' uv.instrument = 'simulator' uv.object_name = 'zenith' uv.vis_units = 'Jy' uv.telescope_location_lat_lon_alt_degrees = (latitude, longitude, altitude) uv.set_lsts_from_time_array() uv.extra_keywords = {'bsq_int': beam_sq_int[0], 'skysig': sig, 'bm_fwhm' : fwhm, 'nside': Nside}
def apply_bda( uv, max_decorr, pre_fs_int_time, corr_fov_angle, max_time, corr_int_time=None ): """Apply baseline dependent averaging to a UVData object. For each baseline in the UVData object, the expected decorrelation from averaging in time is computed. Baselines are averaged together in powers- of-two until the specified level of decorrelation is reached (rounded down). Parameters ---------- uv : UVData object The UVData object to apply BDA to. No changes are made to this object, and instead a copy is returned. max_decorr : float The maximum decorrelation fraction desired in the output object. Must be between 0 and 1. pre_fs_int_time : astropy Quantity The pre-finge-stopping integration time inside of the correlator. The quantity should be compatible with units of time. corr_fov_angle : astropy Angle The opening angle at which the maximum decorrelation is to be calculated. Because a priori it is not known in which direction the decorrelation will be largest, the expected decorrelation is computed in all 4 cardinal directions at `corr_fov_angle` degrees off of zenith, and the largest one is used. This is a "worst case scenario" decorrelation. max_time : astropy Quantity The maximum amount of time that spectra from different times should be combined for. The ultimate integration time for a given baseline will be for max_time or the integration time that is smaller than the specified decorrelation level, whichever is smaller. The quantity should be compatible with units of time. corr_int_time : astropy Quantity, optional The output time of the correlator. If not specified, the smallest integration_time in the UVData object is used. If specified, the quantity should be compatible with units of time. Returns ------- uv2 : UVData object The UVData object with BDA applied. Raises ------ ValueError This is raised if the input parameters are not the appropriate type or in the appropriate range. It is also raised if the input UVData object is not in drift mode (the BDA code does rephasing within an averaged set of baselines). AssertionError This is raised if the baselines of the UVData object are not time- ordered. """ if not isinstance(uv, UVData): raise ValueError( "apply_bda must be passed a UVData object as its first argument" ) if not isinstance(corr_fov_angle, Angle): raise ValueError( "corr_fov_angle must be an Angle object from astropy.coordinates" ) if not isinstance(pre_fs_int_time, units.Quantity): raise ValueError("pre_fs_int_time must be an astropy.units.Quantity") try: pre_fs_int_time.to(units.s) except UnitConversionError: raise ValueError("pre_fs_int_time must be a Quantity with units of time") if ( corr_fov_angle.to(units.deg).value < 0 or corr_fov_angle.to(units.deg).value > 90 ): raise ValueError("corr_fov_angle must be between 0 and 90 degrees") if max_decorr < 0 or max_decorr > 1: raise ValueError("max_decorr must be between 0 and 1") if not isinstance(max_time, units.Quantity): raise ValueError("max_time must be an astropy.units.Quantity") try: max_time.to(units.s) except UnitConversionError: raise ValueError("max_time must be a Quantity with units of time") if corr_int_time is None: # assume the correlator integration time is the smallest int_time of the # UVData object corr_int_time = np.unique(uv.integration_time)[0] * units.s else: if not isinstance(corr_int_time, units.Quantity): raise ValueError("corr_int_time must be an astropy.units.Quantity") try: corr_int_time.to(units.s) except UnitConversionError: raise ValueError("corr_int_time must be a Quantity with units of time") if uv.phase_type != "drift": raise ValueError("UVData object must be in drift mode to apply BDA") # get relevant bits of metadata freq = np.amax(uv.freq_array[0, :]) * units.Hz chan_width = uv.channel_width * units.Hz antpos_enu, ants = uv.get_ENU_antpos() lat, lon, alt = uv.telescope_location_lat_lon_alt antpos_ecef = uvutils.ECEF_from_ENU(antpos_enu, lat, lon, alt) telescope_location = EarthLocation.from_geocentric( uv.telescope_location[0], uv.telescope_location[1], uv.telescope_location[2], unit="m", ) # make a new UVData object to put BDA baselines in uv2 = UVData() # copy over metadata uv2.Nbls = uv.Nbls uv2.Nfreqs = uv.Nfreqs uv2.Npols = uv.Npols uv2.vis_units = uv.vis_units uv2.Nspws = uv.Nspws uv2.spw_array = uv.spw_array uv2.freq_array = uv.freq_array uv2.polarization_array = uv.polarization_array uv2.channel_width = uv.channel_width uv2.object_name = uv.object_name uv2.telescope_name = uv.telescope_name uv2.instrument = uv.instrument uv2.telescope_location = uv.telescope_location history = uv.history + " Baseline dependent averaging applied." uv2.history = history uv2.Nants_data = uv.Nants_data uv2.Nants_telescope = uv.Nants_telescope uv2.antenna_names = uv.antenna_names uv2.antenna_numbers = uv.antenna_numbers uv2.x_orientation = uv.x_orientation uv2.extra_keywords = uv.extra_keywords uv2.antenna_positions = uv.antenna_positions uv2.antenna_diameters = uv.antenna_diameters uv2.gst0 = uv.gst0 uv2.rdate = uv.rdate uv2.earth_omega = uv.earth_omega uv2.dut1 = uv.dut1 uv2.timesys = uv.timesys uv2.uvplane_reference_time = uv.uvplane_reference_time # initialize place-keeping variables and Nblt-sized metadata start_index = 0 uv2.Nblts = 0 uv2.uvw_array = np.zeros_like(uv.uvw_array) uv2.time_array = np.zeros_like(uv.time_array) uv2.lst_array = np.zeros_like(uv.lst_array) uv2.ant_1_array = np.zeros_like(uv.ant_1_array) uv2.ant_2_array = np.zeros_like(uv.ant_2_array) uv2.baseline_array = np.zeros_like(uv.baseline_array) uv2.integration_time = np.zeros_like(uv.integration_time) uv2.data_array = np.zeros_like(uv.data_array) uv2.flag_array = np.zeros_like(uv.flag_array) uv2.nsample_array = np.zeros_like(uv.nsample_array) # iterate over baselines for key in uv.get_antpairs(): print("averaging baseline ", key) ind1, ind2, indp = uv._key2inds(key) if len(ind2) != 0: raise AssertionError( "ind2 from _key2inds() is not 0--exiting. This should not happen, " "please contact the package maintainers." ) data = uv._smart_slicing( uv.data_array, ind1, ind2, indp, squeeze="none", force_copy=True ) flags = uv._smart_slicing( uv.flag_array, ind1, ind2, indp, squeeze="none", force_copy=True ) nsamples = uv._smart_slicing( uv.nsample_array, ind1, ind2, indp, squeeze="none", force_copy=True ) # get lx and ly for baseline ant1 = np.where(ants == key[0])[0][0] ant2 = np.where(ants == key[1])[0][0] x1, y1, z1 = antpos_ecef[ant1, :] x2, y2, z2 = antpos_ecef[ant2, :] lx = np.abs(x2 - x1) * units.m ly = np.abs(y2 - y1) * units.m # figure out how many time samples we can combine together if key[0] == key[1]: # autocorrelation--don't average n_two_foldings = 0 else: n_two_foldings = dc.bda_compression_factor( max_decorr, freq, lx, ly, corr_fov_angle, chan_width, pre_fs_int_time, corr_int_time, ) # convert from max_time to max_samples max_samples = (max_time / corr_int_time).to(units.dimensionless_unscaled) max_two_foldings = int(np.floor(np.log2(max_samples))) n_two_foldings = min(n_two_foldings, max_two_foldings) n_int = 2 ** (n_two_foldings) print("averaging {:d} time samples...".format(n_int)) # figure out how many output samples we're going to have n_in = len(ind1) n_out = n_in // n_int + min(1, n_in % n_int) # get relevant metdata uvw_array = uv.uvw_array[ind1, :] times = uv.time_array[ind1] if not np.all(times == np.sort(times)): raise AssertionError( "times of uvdata object are not monotonically increasing; " "throwing our hands up" ) lsts = uv.lst_array[ind1] int_time = uv.integration_time[ind1] # do the averaging input_shape = data.shape assert input_shape == (n_in, 1, uv.Nfreqs, uv.Npols) output_shape = (n_out, 1, uv.Nfreqs, uv.Npols) data_out = np.empty(output_shape, dtype=np.complex128) flags_out = np.empty(output_shape, dtype=np.bool_) nsamples_out = np.empty(output_shape, dtype=np.float32) uvws_out = np.empty((n_out, 3), dtype=np.float64) times_out = np.empty((n_out,), dtype=np.float64) lst_out = np.empty((n_out,), dtype=np.float64) int_time_out = np.empty((n_out,), dtype=np.float64) if n_out == n_in: # we don't need to average current_index = start_index + n_out uv2.data_array[start_index:current_index, :, :, :] = data uv2.flag_array[start_index:current_index, :, :, :] = flags uv2.nsample_array[start_index:current_index, :, :, :] = nsamples uv2.uvw_array[start_index:current_index, :] = uvw_array uv2.time_array[start_index:current_index] = times uv2.lst_array[start_index:current_index] = lsts uv2.integration_time[start_index:current_index] = int_time uv2.ant_1_array[start_index:current_index] = key[0] uv2.ant_2_array[start_index:current_index] = key[1] uv2.baseline_array[start_index:current_index] = uvutils.antnums_to_baseline( ant1, ant2, None ) start_index = current_index else: # rats, we actually have to do work... # phase up the data along each chunk of times for i in range(n_out): # compute zenith of the desired output time i1 = i * n_int i2 = min((i + 1) * n_int, n_in) assert i2 - i1 > 0 t0 = Time((times[i1] + times[i2 - 1]) / 2, scale="utc", format="jd") zenith_coord = SkyCoord( alt=Angle(90 * units.deg), az=Angle(0 * units.deg), obstime=t0, frame="altaz", location=telescope_location, ) obs_zenith_coord = zenith_coord.transform_to("icrs") zenith_ra = obs_zenith_coord.ra zenith_dec = obs_zenith_coord.dec # get data, flags, and nsamples of slices data_chunk = data[i1:i2, :, :, :] flags_chunk = flags[i1:i2, :, :, :] nsamples_chunk = nsamples[i1:i2, :, :, :] # actually phase now # compute new uvw coordinates icrs_coord = SkyCoord( ra=zenith_ra, dec=zenith_dec, unit="radian", frame="icrs" ) uvws = np.float64(uvw_array[i1:i2, :]) itrs_telescope_location = SkyCoord( x=uv.telescope_location[0] * units.m, y=uv.telescope_location[1] * units.m, z=uv.telescope_location[2] * units.m, representation_type="cartesian", frame="itrs", obstime=t0, ) itrs_lat_lon_alt = uv.telescope_location_lat_lon_alt frame_telescope_location = itrs_telescope_location.transform_to("icrs") frame_telescope_location.representation_type = "cartesian" uvw_ecef = uvutils.ECEF_from_ENU(uvws, *itrs_lat_lon_alt) itrs_uvw_coord = SkyCoord( x=uvw_ecef[:, 0] * units.m, y=uvw_ecef[:, 1] * units.m, z=uvw_ecef[:, 2] * units.m, representation_type="cartesian", frame="itrs", obstime=t0, ) frame_uvw_coord = itrs_uvw_coord.transform_to("icrs") frame_rel_uvw = ( frame_uvw_coord.cartesian.get_xyz().value.T - frame_telescope_location.cartesian.get_xyz().value ) new_uvws = uvutils.phase_uvw( icrs_coord.ra.rad, icrs_coord.dec.rad, frame_rel_uvw ) # average these uvws together to get the "average" position in # the uv-plane avg_uvws = np.average(new_uvws, axis=0) # calculate and apply phasor w_lambda = ( new_uvws[:, 2].reshape((i2 - i1), 1) / const.c.to("m/s").value * uv.freq_array.reshape(1, uv.Nfreqs) ) phs = np.exp(-1j * 2 * np.pi * w_lambda[:, None, :, None]) data_chunk *= phs # sum data, propagate flag array, and adjusting nsample accordingly data_slice = np.sum(data_chunk, axis=0) flag_slice = np.sum(flags_chunk, axis=0) nsamples_slice = np.sum(nsamples_chunk, axis=0) / (i2 - i1) data_out[i, :, :, :] = data_slice flags_out[i, :, :, :] = flag_slice nsamples_out[i, :, :, :] = nsamples_slice # update metadata uvws_out[i, :] = avg_uvws times_out[i] = (times[i1] + times[i2 - 1]) / 2 lst_out[i] = (lsts[i1] + lsts[i2 - 1]) / 2 int_time_out[i] = np.average(int_time[i1:i2]) * (i2 - i1) # update data and metadata when we're done with this baseline current_index = start_index + n_out uv2.data_array[start_index:current_index, :, :, :] = data_out uv2.flag_array[start_index:current_index, :, :, :] = flags_out uv2.nsample_array[start_index:current_index, :, :, :] = nsamples_out uv2.uvw_array[start_index:current_index, :] = uvws_out uv2.time_array[start_index:current_index] = times_out uv2.lst_array[start_index:current_index] = lst_out uv2.integration_time[start_index:current_index] = int_time_out uv2.ant_1_array[start_index:current_index] = key[0] uv2.ant_2_array[start_index:current_index] = key[1] uv2.baseline_array[start_index:current_index] = uvutils.antnums_to_baseline( ant1, ant2, None ) start_index = current_index # clean up -- shorten all arrays to actually be size nblts nblts = start_index uv2.Nblts = nblts uv2.data_array = uv2.data_array[:nblts, :, :, :] uv2.flag_array = uv2.flag_array[:nblts, :, :, :] uv2.nsample_array = uv2.nsample_array[:nblts, :, :, :] uv2.uvw_array = uv2.uvw_array[:nblts, :] uv2.time_array = uv2.time_array[:nblts] uv2.lst_array = uv2.lst_array[:nblts] uv2.integration_time = uv2.integration_time[:nblts] uv2.ant_1_array = uv2.ant_1_array[:nblts] uv2.ant_2_array = uv2.ant_2_array[:nblts] uv2.baseline_array = uv2.baseline_array[:nblts] uv2.Ntimes = len(np.unique(uv2.time_array)) # set phasing info uv2.phase_type = "phased" uv2.phase_center_ra = zenith_ra.rad uv2.phase_center_dec = zenith_dec.rad uv2.phase_center_frame = 2000.0 # fix up to correct old phasing method uv2.phase(zenith_ra.rad, zenith_dec.rad, epoch="J2000", fix_old_proj=True) # run a check uv2.check() return uv2
def initialize_uvdata(uvtask_list, source_list_name, uvdata_file=None, obs_param_file=None, telescope_config_file=None, antenna_location_file=None): """ Initialize an empty uvdata object to fill with simulation. Args: uvtask_list: List of uvtasks to simulate. source_list_name: Name of source list file or mock catalog. uvdata_file: Name of input UVData file or None if initializing from config files. obs_param_file: Name of observation parameter config file or None if initializing from a UVData file. telescope_config_file: Name of telescope config file or None if initializing from a UVData file. antenna_location_file: Name of antenna location file or None if initializing from a UVData file. """ if not isinstance(source_list_name, str): raise ValueError('source_list_name must be a string') if uvdata_file is not None: if not isinstance(uvdata_file, str): raise ValueError('uvdata_file must be a string') if (obs_param_file is not None or telescope_config_file is not None or antenna_location_file is not None): raise ValueError('If initializing from a uvdata_file, none of ' 'obs_param_file, telescope_config_file or ' 'antenna_location_file can be set.') elif (obs_param_file is None or telescope_config_file is None or antenna_location_file is None): if not isinstance(obs_param_file, str): raise ValueError('obs_param_file must be a string') if not isinstance(telescope_config_file, str): raise ValueError('telescope_config_file must be a string') if not isinstance(antenna_location_file, str): raise ValueError('antenna_location_file must be a string') raise ValueError('If not initializing from a uvdata_file, all of ' 'obs_param_file, telescope_config_file or ' 'antenna_location_file must be set.') # Version string to add to history history = get_version_string() history += ' Sources from source list: ' + source_list_name + '.' if uvdata_file is not None: history += ' Based on UVData file: ' + uvdata_file + '.' else: history += (' Based on config files: ' + obs_param_file + ', ' + telescope_config_file + ', ' + antenna_location_file) history += ' Npus = ' + str(Npus) + '.' task_freqs = [] task_bls = [] task_times = [] task_antnames = [] task_antnums = [] task_antpos = [] task_uvw = [] ant_1_array = [] ant_2_array = [] telescope_name = uvtask_list[0].telescope.telescope_name telescope_location = uvtask_list[0].telescope.telescope_location.geocentric source_0 = uvtask_list[0].source freq_0 = uvtask_list[0].freq for task in uvtask_list: if not task.source == source_0: continue task_freqs.append(task.freq) if task.freq == freq_0: task_bls.append(task.baseline) task_times.append(task.time) task_antnames.append(task.baseline.antenna1.name) task_antnames.append(task.baseline.antenna2.name) ant_1_array.append(task.baseline.antenna1.number) ant_2_array.append(task.baseline.antenna2.number) task_antnums.append(task.baseline.antenna1.number) task_antnums.append(task.baseline.antenna2.number) task_antpos.append(task.baseline.antenna1.pos_enu) task_antpos.append(task.baseline.antenna2.pos_enu) task_uvw.append(task.baseline.uvw) antnames, ant_indices = np.unique(task_antnames, return_index=True) task_antnums = np.array(task_antnums) task_antpos = np.array(task_antpos) antnums = task_antnums[ant_indices] antpos = task_antpos[ant_indices] freqs = np.unique(task_freqs) uv_obj = UVData() # add pyuvdata version info history += uv_obj.pyuvdata_version_str uv_obj.telescope_name = telescope_name uv_obj.telescope_location = np.array( [tl.to('m').value for tl in telescope_location]) uv_obj.instrument = telescope_name uv_obj.Nfreqs = freqs.size uv_obj.Ntimes = np.unique(task_times).size uv_obj.Nants_data = antnames.size uv_obj.Nants_telescope = uv_obj.Nants_data uv_obj.Nblts = len(ant_1_array) uv_obj.antenna_names = antnames.tolist() uv_obj.antenna_numbers = antnums antpos_ecef = uvutils.ECEF_from_ENU( antpos, * uv_obj.telescope_location_lat_lon_alt) - uv_obj.telescope_location uv_obj.antenna_positions = antpos_ecef uv_obj.ant_1_array = np.array(ant_1_array) uv_obj.ant_2_array = np.array(ant_2_array) uv_obj.time_array = np.array(task_times) uv_obj.uvw_array = np.array(task_uvw) uv_obj.baseline_array = uv_obj.antnums_to_baseline(ant_1_array, ant_2_array) uv_obj.Nbls = np.unique(uv_obj.baseline_array).size if uv_obj.Nfreqs == 1: uv_obj.channel_width = 1. # Hz else: uv_obj.channel_width = np.diff(freqs)[0] if uv_obj.Ntimes == 1: uv_obj.integration_time = np.ones_like(uv_obj.time_array, dtype=np.float64) # Second else: # Note: currently only support a constant spacing of times uv_obj.integration_time = ( np.ones_like(uv_obj.time_array, dtype=np.float64) * np.diff(np.unique(task_times))[0]) uv_obj.set_lsts_from_time_array() uv_obj.zenith_ra = uv_obj.lst_array uv_obj.zenith_dec = np.repeat(uv_obj.telescope_location_lat_lon_alt[0], uv_obj.Nblts) # Latitude uv_obj.object_name = 'zenith' uv_obj.set_drift() uv_obj.vis_units = 'Jy' uv_obj.polarization_array = np.array([-5, -6, -7, -8]) uv_obj.spw_array = np.array([0]) uv_obj.freq_array = np.array([freqs]) uv_obj.Nspws = uv_obj.spw_array.size uv_obj.Npols = uv_obj.polarization_array.size uv_obj.data_array = np.zeros( (uv_obj.Nblts, uv_obj.Nspws, uv_obj.Nfreqs, uv_obj.Npols), dtype=np.complex) uv_obj.flag_array = np.zeros( (uv_obj.Nblts, uv_obj.Nspws, uv_obj.Nfreqs, uv_obj.Npols), dtype=bool) uv_obj.nsample_array = np.ones_like(uv_obj.data_array, dtype=float) uv_obj.history = history uv_obj.check() return uv_obj
# Run simulation # --------------------------- print("Running simulation") sys.stdout.flush() visibs, time_array, baseline_inds = obs.make_visibilities(shell0, Nprocs=Nprocs) uv_obj.time_array = time_array uv_obj.set_lsts_from_time_array() uv_obj.baseline_array = bl_array[baseline_inds] uv_obj.ant_1_array, uv_obj.ant_2_array = uv_obj.baseline_to_antnums(uv_obj.baseline_array) uv_obj.spw_array = np.array([0]) uv_obj.Npols = 1 uv_obj.polarization_array=np.array([1]) uv_obj.Nspws = 1 uv_obj.set_uvws_from_antenna_positions() uv_obj.channel_width = np.diff(freqs)[0] uv_obj.integration_time = np.ones(uv_obj.Nblts) * np.diff(time_arr)[0] * 24 * 3600. # Seconds uv_obj.history = 'eorsky' uv_obj.set_drift() uv_obj.telescope_name = 'eorsky' uv_obj.instrument = 'simulator' uv_obj.object_name = 'zenith' uv_obj.vis_units = 'Jy' if sjob_id is None: sjob_id = '' if beam_type == 'gaussian': fwhm = beam_attr['sigma'] * 2.355
uvfile = or_xx_files[0] uvd = UVData() uvd.read_miriad(uvfile) # create uvdata object uvd = UVData() uvd.Nants_telescope = self.Nants uvd.Nants_data = len(np.unique(bl_array)) uvd.Nbls = Nbls uvd.Ntimes = Ntimes uvd.Nblts = Nbls * Ntimes uvd.Nfreqs = self.Nfreqs uvd.Npols = self.Nxpols uvd.Nspws = 1 uvd.antenna_numbers = self.ant_nums uvd.antenna_names = np.array(self.ant_nums, dtype=str) uvd.ant_1_array = np.concatenate( [map(lambda x: x[0], bl_array) for i in range(Ntimes)]) uvd.ant_2_array = np.concatenate( [map(lambda x: x[1], bl_array) for i in range(Ntimes)]) uvd.baseline_array = np.concatenate( [np.arange(Nbls) for i in range(Ntimes)]) uvd.freq_array = (self.freqs * 1e6).reshape(1, -1) uvd.time_array = np.repeat(np.array(JD_array)[:, np.newaxis], Nbls, axis=1).ravel() uvd.channel_width = (self.freqs * 1e6)[1] - (self.freqs * 1e6)[0] uvd.data_array = self.vis_data.reshape(uvd.Nblts, 1, self.Nfreqs, self.Nxpols) uvd.flag_array = np.ones_like(uvd.data_array, dtype=np.bool)
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
def fake_data_generator(): """Generate a fake dataset as a module-level fixture.""" # generate a fake data file for testing BDA application uvd = UVData() t0 = 2459000.0 dt = (2 * units.s).to(units.day) t1 = t0 + dt.value t2 = t0 + 2 * dt.value # define baseline-time spacing uvd.ant_1_array = np.asarray([0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=np.int_) uvd.ant_2_array = np.asarray([0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=np.int_) uvd.time_array = np.asarray([t0, t0, t0, t1, t1, t1, t2, t2, t2], dtype=np.float64) uvd.Ntimes = 3 uvd.Nbls = 3 uvd.Nblts = uvd.Ntimes * uvd.Nbls # define frequency array nfreqs = 1024 freq_array = np.linspace(50e6, 250e6, num=nfreqs) uvd.freq_array = freq_array[np.newaxis, :] uvd.spw_array = [0] uvd.Nfreqs = nfreqs uvd.Nspws = 1 # define polarization array uvd.polarization_array = [-5] uvd.Npols = 1 # make random data for data array data_shape = (uvd.Nblts, 1, uvd.Nfreqs, uvd.Npols) uvd.data_array = np.zeros(data_shape, dtype=np.complex128) rng = default_rng() uvd.data_array += rng.standard_normal(data_shape) uvd.data_array += 1j * rng.standard_normal(data_shape) uvd.flag_array = np.zeros_like(uvd.data_array, dtype=np.bool_) uvd.nsample_array = np.ones_like(uvd.data_array, dtype=np.float32) # set telescope and antenna positions hera_telescope = pyuvdata.telescopes.get_telescope("HERA") uvd.telescope_location_lat_lon_alt = hera_telescope.telescope_location_lat_lon_alt antpos0 = np.asarray([0, 0, 0], dtype=np.float64) antpos1 = np.asarray([14, 0, 0], dtype=np.float64) antpos2 = np.asarray([28, 0, 0], dtype=np.float64) antpos_enu = np.vstack((antpos0, antpos1, antpos2)) antpos_xyz = uvutils.ECEF_from_ENU(antpos_enu, *uvd.telescope_location_lat_lon_alt) uvd.antenna_positions = antpos_xyz - uvd.telescope_location uvw_array = np.zeros((uvd.Nblts, 3), dtype=np.float64) uvw_array[::3, :] = antpos0 - antpos0 uvw_array[1::3, :] = antpos1 - antpos0 uvw_array[2::3, :] = antpos2 - antpos0 uvd.uvw_array = uvw_array uvd.antenna_numbers = np.asarray([0, 1, 2], dtype=np.int_) uvd.antenna_names = np.asarray(["H0", "H1", "H2"], dtype=np.str_) uvd.Nants_data = 3 uvd.Nants_telescope = 3 # set other metadata uvd.vis_units = "uncalib" uvd.channel_width = 5e4 # 50 kHz uvd.phase_type = "drift" uvd.baseline_array = uvd.antnums_to_baseline(uvd.ant_1_array, uvd.ant_2_array) uvd.history = "BDA test file" uvd.instrument = "HERA" uvd.telescope_name = "HERA" uvd.object_name = "zenith" uvd.integration_time = 2 * np.ones_like(uvd.baseline_array, dtype=np.float64) uvd.set_lsts_from_time_array() # run a check uvd.check() yield uvd # clean up when done del uvd return
def uvdata_from_sim_data( array_lat, array_lon, array_height, jd_axis, nu_axis, r_axis, ant_pairs, V_sim, integration_time="derived", channel_width="derived", antenna_numbers="derived", antenna_names="derived", instrument="left blank by user", telescope_name="left blank by user", history="left blank by user", object_name="left blank by user", ): HERA_LAT = array_lat HERA_LON = array_lon HERA_HEIGHT = array_height HERA_LAT_LON_ALT = (HERA_LAT, HERA_LON, HERA_HEIGHT) HERA_LOC = coord.EarthLocation( lat=HERA_LAT * units.rad, lon=HERA_LON * units.rad, height=HERA_HEIGHT * units.meter, ) jd_obj = Time(jd_axis, format="jd", location=HERA_LOC) lst_axis = jd_obj.sidereal_time("apparent").radian if integration_time == "derived": del_jd = jd_obj[1] - jd_obj[0] integration_time = del_jd.sec uvd = UVData() uvd.telescope_location = HERA_LOC.value uvd.telescope_location_lat_lon_alt = HERA_LAT_LON_ALT if antenna_numbers == "derived": uvd.antenna_numbers = np.arange(r_axis.shape[0], dtype=np.int64) ant_num_pairs = ant_pairs else: uvd.antenna_numbers = antenna_numbers ant_num_pairs = np.array([(antenna_numbers[ap[0]], antenna_numbers[ap[1]]) for ap in ant_pairs]) if antenna_names == "derived": uvd.antenna_names = [str(ant_ind) for ant_ind in uvd.antenna_numbers] else: uvd.antenna_names = antenna_names ant_pos_ECEF = pyuvdata.utils.ECEF_from_ENU(r_axis, HERA_LOC.lat.rad, HERA_LOC.lon.rad, HERA_LOC.height.value) uvd.antenna_positions = ant_pos_ECEF - uvd.telescope_location bls = [ uvd.antnums_to_baseline(ant_num_pair[0], ant_num_pair[1]) for ant_num_pair in ant_num_pairs ] uvd.freq_array = nu_axis.reshape((1, nu_axis.size)) pols = ["xx", "yy", "xy", "yx"] uvd.polarization_array = np.array( [polstr2num(pol_str) for pol_str in pols]) uvd.x_orientation = "east" if channel_width == "derived": uvd.channel_width = nu_axis[1] - nu_axis[0] else: uvd.channel_width = channel_width uvd.Nfreqs = nu_axis.size uvd.Nspws = 1 uvd.Npols = len(pols) bl_arr, lst_arr = np.meshgrid(np.array(bls), lst_axis) uvd.baseline_array = bl_arr.flatten() uvd.lst_array = lst_arr.flatten() _, time_arr = np.meshgrid(np.array(bls), jd_axis) uvd.time_array = time_arr.flatten() ant1_arr, _ = np.meshgrid(ant_num_pairs[:, 0], lst_axis) ant2_arr, _ = np.meshgrid(ant_num_pairs[:, 1], lst_axis) uvd.ant_1_array = ant1_arr.flatten() uvd.ant_2_array = ant2_arr.flatten() # Nants_data might be less than r_axis.shape[0] for redundant arrays uvd.Nants_data = len( np.unique(np.r_[ant1_arr.flatten(), ant2_arr.flatten()])) uvd.Nants_telescope = r_axis.shape[0] uvd.set_uvws_from_antenna_positions() uvd.Nbls = len(bls) uvd.Ntimes = lst_axis.size uvd.Nblts = bl_arr.size uvd.data_array = np.zeros((uvd.Nblts, uvd.Nspws, uvd.Nfreqs, uvd.Npols), dtype=np.complex128) uvd.flag_array = np.zeros_like(uvd.data_array, dtype=np.bool) uvd.nsample_array = np.ones((uvd.Nblts, uvd.Nspws, uvd.Nfreqs, uvd.Npols), dtype=np.float64) uvd.spw_array = np.ones(1, dtype=np.int64) uvd.integration_time = integration_time * np.ones(uvd.Nblts) uvd.phase_type = "drift" # (0,0) <-> 'xx' <-> East-East, etc. # matches order of uvd.polarization_array pol_map = {(0, 0): 0, (1, 1): 1, (0, 1): 2, (1, 0): 3} for i_a in range(2): for i_b in range(2): i_p = pol_map[(i_a, i_b)] for k in range(ant_num_pairs.shape[0]): a_i, a_j = ant_num_pairs[k] bl_num = uvd.antnums_to_baseline(a_i, a_j) bl_ind = np.where(uvd.baseline_array == bl_num)[0] uvd.data_array[bl_ind, 0, :, i_p] = np.copy(V_sim[:, :, k, i_a, i_b]) uvd.vis_units = "Jy" uvd.instrument = instrument uvd.telescope_name = telescope_name uvd.history = history uvd.object_name = object_name uvd.check() return uvd
logger.info('Getting baseline pair: (%d, %d)..' % (a1, a2)) times.append(time.time()) if a1 == a2: bram.imag = 0 bram.real = bram.real / float( feng.corr.acc_len * feng.corr.spec_per_acc) else: bram = bram / float( feng.corr.acc_len * feng.corr.spec_per_acc) c.append(bram) poco.append(np.transpose(c)) # Write output to pyuvdata file data = UVData() data.Nfreqs = len(fqs) data.Nspws = 1 data.Npols = 1 data.Nbls = len(bls) data.Ntimes = len(times) data.Nblts = data.Ntimes # Init flag array with no flags data.flag_array = np.empty( (data.Nblts, data.Nspws, data.Nfreqs, data.Npols), dtype=bool) data.flag_array[:] = False # Init nsamples array with unity weights data.nsample_array = np.ones( (data.Nblts, data.Nspws, data.Nfreqs, data.Npols), dtype=float) # Create frequency array
def sim_obs(self, bl_array, JD_array, pool=None, write_miriad=False, fname=None, clobber=False, one_beam_model=True, interp=True, Tnoise=None, fast_noise=False): """ Simulate a visibility observation of the sky Input: ------ bl_array : list, shape=(Nbls, 2), entry_format=tuple(int, int) list of baselines (antenna pairs) in (ant1, ant2) with type(ant1) == int JD_array : list, shape=(Ntimes,), dtype=float list of Julian Dates for observations """ # get array info Nbls = len(bl_array) str_bls = [(str(x[0]), str(x[1])) for x in bl_array] Ntimes = len(JD_array) rel_ants = np.unique(np.concatenate(bl_array)) # relevant antennas rel_ant2ind = OrderedDict( zip(np.array(rel_ants, str), np.arange(len(rel_ants)))) # get antenna indices ant_inds = map(lambda x: self.ant2ind[str(x)], rel_ants) # get antenna positions for each baseline ant1_pos = np.array(map(lambda x: self.ant_pos[x[0]], str_bls)) ant2_pos = np.array(map(lambda x: self.ant_pos[x[1]], str_bls)) # get vector in u-v plane wavelengths = 2.9979e8 / (self.freqs * 1e6) self.uv_vecs = (ant2_pos - ant1_pos).reshape(Nbls, 3, -1) / wavelengths # Get direction unit vector, s-hat x, y, z = hp.pix2vec(self.beam_nside, np.arange(self.beam_npix)) self.s_hat = np.array([y, x, z]) # get phase map in topocentric frame (sqrt of full phase term) self.phase = np.exp(-1j * np.pi * np.einsum('ijk,jl->ikl', self.uv_vecs, self.s_hat)) # build beams for each antenna in topocentric coordinates self.build_beams(ant_inds=ant_inds, one_beam_model=one_beam_model) # create phase and beam product maps (Npol, Nbl, Nfreqs, Npix) self.beam_phs = self.ant_beam_models.reshape( self.Npols, -1, self.Nfreqs, self.beam_npix) * self.phase # loop over JDs self.vis_data = [] for jd in JD_array: # map through each antenna and project polarized, multi-frequency beam model onto sky if one_beam_model == True: self.proj_beam_phs = self.project_beams( jd, self.sky_theta, self.sky_phi, beam_models=self.beam_phs, output=True, interp=interp) else: #proj_ant_beam_models = self.project_beams(JD, self.sky_theta, self.sky_phi, #beam_models=np.array(map(lambda x: self.ant_beam_models[str(x)], self.ant_nums)), output=True) self.proj_beam_phs = self.project_beams( jd, self.sky_theta, self.sky_phi, beam_models=self.beam_phs, output=True, interp=interp) # calculate visibility if pool is None: M = map else: M = pool.map # add noise if Tnoise is None or fast_noise is True: sky_models = self.sky_models else: sky_models = self.sky_models + self.generate_noise_map( Tnoise, self.sky_models.shape) if one_beam_model is True: if self.onepol is True: vis = np.einsum("ijkl, ikl -> ijk", self.proj_beam_phs**2, sky_models) else: vis = np.einsum("ijkl, imkl, mjkl -> imjk", self.proj_beam_phs, sky_models, self.proj_beam_phs) else: vis = np.array( map( lambda x: np.einsum( "ijk, jk, ljk -> ilj", self.proj_beam_phs[ rel_ant2ind[x[1][0]]], sky_models, self. proj_beam_phs[rel_ant2ind[x[1][1]]]), enumerate(str_bls))) self.vis_data.append(vis) if self.onepol is True: self.vis_data = np.moveaxis(np.array(self.vis_data), 0, 2) else: self.vis_data = np.moveaxis(np.array(self.vis_data), 0, 3) # normalize by the effective-beam solid angle if one_beam_model == True: self.ant_beam_sa = np.repeat( np.einsum('ijk,ijk->ij', self.ant_beam_models, self.ant_beam_models)[:, np.newaxis, :], Nbls, 1) else: self.ant_beam_sa = np.array( map( lambda x: np.einsum( 'ijk,ljk->ilj', self.proj_ant_beam_models[rel_ant2ind[ x[1][0]]], self.proj_ant_beam_models[rel_ant2ind[x[ 1][1]]]), enumerate(str_bls))) if self.onepol is True: self.vis_data /= self.ant_beam_sa[:, :, np.newaxis, :] self.vis_data_shape = "(1, Nbls, Ntimes, Nfreqs)" else: self.vis_data /= self.ant_beam_sa[:, :, :, np.newaxis, :] self.vis_data_shape = "(2, 2, Nbls, Ntimes, Nfreqs)" if fast_noise is True and Tnoise is not None: self.vis_data += self.generate_vis_noise( Tnoise, self.freqs * 1e6, self.ant_beam_sa.squeeze(), self.vis_data.shape, bandwidth=self.bandwidth * 1e6, int_time=10.7) # write to file if write_miriad == True: # create uvdata object uvd = UVData() uvd.Nants_telescope = self.Nants uvd.Nants_data = len(np.unique(bl_array)) uvd.Nbls = Nbls uvd.Ntimes = Ntimes uvd.Nblts = Nbls * Ntimes uvd.Nfreqs = self.Nfreqs uvd.Npols = self.Nxpols uvd.Nspws = 1 uvd.antenna_numbers = self.ant_nums uvd.antenna_names = np.array(self.ant_nums, dtype=str) uvd.ant_1_array = np.concatenate( [map(lambda x: x[0], bl_array) for i in range(Ntimes)]) uvd.ant_2_array = np.concatenate( [map(lambda x: x[1], bl_array) for i in range(Ntimes)]) uvd.baseline_array = np.concatenate( [np.arange(Nbls) for i in range(Ntimes)]) uvd.freq_array = (self.freqs * 1e6).reshape(1, -1) uvd.time_array = np.repeat(np.array(JD_array)[:, np.newaxis], Nbls, axis=1).ravel() uvd.channel_width = (self.freqs * 1e6)[1] - (self.freqs * 1e6)[0] uvd.data_array = self.vis_data.reshape(uvd.Nblts, 1, self.Nfreqs, self.Nxpols) uvd.flag_array = np.ones_like(uvd.data_array, dtype=np.bool) uvd.history = " " uvd.instrument = " " uvd.integration_time = 10.7 uvd.lst_array = np.repeat(np.array( map(lambda x: self.JD2LST(self.loc, x), JD_array))[:, np.newaxis], Nbls, axis=1).ravel() uvd.nsample_array = np.ones_like(uvd.data_array, dtype=np.float) uvd.object_name = "" uvd.phase_type = "drift" uvd.polarization_array = np.array( map(lambda x: { "XX": -5, "YY": -6, "XY": -7, "YX": -8 }[x], self.xpols)) uvd.spw_array = np.array([0]) uvd.telescope_location = np.array([ 6378137. * np.cos(self.loc.lon) * np.cos(self.loc.lat), 6378137. * np.sin(self.loc.lon) * np.cos(self.loc.lat), 6378137. * np.sin(self.loc.lat) ]) uvd.telescope_name = " " uvd.uvw_array = np.ones((uvd.Nblts, 3)) uvd.vis_units = "Jy" zen_dec, zen_ra = self.loc.radec_of(0, np.pi / 2) uvd.zenith_dec = np.ones(uvd.Nblts) * zen_dec uvd.zenith_ra = np.ones(uvd.Nblts) * zen_ra uvd.write_miriad(fname, clobber=clobber)