def test_gsm_pointing(): pytest.importorskip("pygsm") # test that PyGSM visibility sim peaks at times when galactic center transits ant1_enu = np.array([0.0, 0.0, 0.0]) ant2_enu = np.array([15.0, 0, 0]) bl = observatory.Baseline(ant1_enu, ant2_enu) freqs = np.linspace(100e6, 200e6, 2) # for 2458000, galactic center at RA of 266 degrees transits at 2458000.2272949447 times = np.linspace(2458000.2272949447 - 0.2, 2458000.2272949447 + 0.2, 11) fov = 20 # Deg nside = 64 gsm = sky_model.gsm_shell(nside, freqs)[None, :, :] obs = observatory.Observatory(latitude, longitude, array=[bl], freqs=freqs) obs.set_pointings(times) obs.set_fov(fov) obs.set_beam("airy", diameter=15) sky = sky_model.SkyModel(Nside=nside, freqs=freqs, data=gsm) visibs, times, bls = obs.make_visibilities(sky) # make sure peak is at time index 5, centered at transit time assert np.argmax(np.abs(visibs[:, 0, 0])) == 5
def test_pointings(): """ Test pointings In the ICRS, RAs should be close to the LST for times near J2000. This test checks that the pointing centers shift in RA at near the sky rotation rate, and that DEC stays close to the observatory latitude. """ t0 = Time("J2000").jd dt_min = 20.0 dt_days = dt_min * 1 / 60.0 * 1 / 24.0 # 20 minutes in days time_arr = np.arange(20) * dt_days + t0 obs = observatory.Observatory(latitude, longitude) obs.set_pointings(time_arr) ras = np.array([c[0] for c in obs.pointing_centers]) decs = np.array([c[1] for c in obs.pointing_centers]) if np.any(np.diff(ras) < 0): ind = np.where(np.diff(ras) < 0)[0][0] ras[ind + 1:] += 360.0 # Deal with 360 degree wrap degperhour_sidereal = 360.0 / 23.9344 dts = np.diff(ras) / degperhour_sidereal dts *= 60.0 # Minutes assert np.allclose(dts, dt_min, atol=1e-2) # Within half a second. assert np.allclose(decs, latitude, atol=1e-1) # Within 6 arcmin
def test_offzenith_vis(): # Construct a shell with a single point source a known position off from zenith. # Similar to test_vis_calc, but set the pointing center 5deg off from the zenith and adjust analytic calculation freqs = [1.0e8] Nfreqs = 1 fov = 60 ant1_enu = np.array([10.0, 0, 0]) ant2_enu = np.array([0.0, 140.6, 0]) bl = observatory.Baseline(ant1_enu, ant2_enu) # Set pointing center to ra/dec = 0/0 center = [0, 0] # Make a shell and place a 1 Jy/pix point source at ra/dec of 5/0 Nside = 128 Npix = Nside**2 * 12 shell = np.zeros((Npix, Nfreqs)) pix_area = 4 * np.pi / float(Npix) ind = hp.ang2pix(Nside, 5, 0.0, lonlat=True) shell[ind] = 1 # Jy/pix shell[ind] *= utils.jy2Tsr(freqs[0], bm=pix_area) # K obs = observatory.Observatory(0, 0, array=[bl], freqs=freqs) obs.pointing_centers = [center] obs.times_jd = np.array([1]) obs.set_fov(fov) obs.set_beam("uniform") sky = sky_model.SkyModel(Nside=Nside, freqs=np.array(freqs), data=shell) vis_calc, times, bls = obs.make_visibilities(sky) ra_deg, dec_deg = hp.pix2ang(Nside, ind, lonlat=True) src_az = np.radians(90.0) src_za = np.radians(ra_deg) src_l = np.sin(src_az) * np.sin(src_za) src_m = np.cos(src_az) * np.sin(src_za) src_n = np.cos(src_za) u, v, w = bl.get_uvw(freqs[0]) vis_analytic = (1) * np.exp(2j * np.pi * (u * src_l + v * src_m + w * src_n)) print(vis_analytic) print(vis_calc) print(vis_calc[0, 0, 0] - vis_analytic) vis_calc = vis_calc[0, 0, 0] assert np.isclose(vis_calc.real, vis_analytic.real) assert np.isclose(vis_calc.imag, vis_analytic.imag)
def test_az_za(): """ Check the calculated azimuth and zenith angle of a point exactly 5 deg east on the sphere (az = 90d, za = 5d) """ Nside = 128 obs = observatory.Observatory(latitude, longitude, fov=20, nside=Nside) center = [0, 0] lon, lat = [5, 0] ind0 = hp.ang2pix(Nside, lon, lat, lonlat=True) lon, lat = hp.pix2ang(Nside, ind0, lonlat=True) za, az, pix = obs.calc_azza(center, return_inds=True) ind = np.where(pix == ind0) # lon = longitude of the source, which is set to 5deg off zenith (hence, zenith angle) assert np.isclose(np.degrees(za[ind]), lon) assert np.isclose(np.degrees(az[ind]), 90.0)
def test_az_za_astropy(): """ Check the calculated azimuth and zenith angle for a selection of HEALPix pixels against the corresponding astropy calculation. """ Nside = 128 altitude = 0.0 loc = EarthLocation.from_geodetic(longitude, latitude, altitude) obs = observatory.Observatory(latitude, longitude, nside=Nside) t0 = Time(2458684.453187554, format="jd") obs.set_fov(180) zen = AltAz(alt=Angle("90d"), az=Angle("0d"), obstime=t0, location=loc) zen_radec = zen.transform_to(ICRS()) center = [zen_radec.ra.deg, zen_radec.dec.deg] northloc = EarthLocation.from_geodetic(lat="90.d", lon="0d", height=0.0) north_radec = AltAz(alt="90.0d", az="0.0d", obstime=t0, location=northloc).transform_to(ICRS()) yvec = np.array([north_radec.ra.deg, north_radec.dec.deg]) za, az, inds = obs.calc_azza(center, yvec, return_inds=True) ra, dec = hp.pix2ang(Nside, inds, lonlat=True) altaz_astropy = ICRS(ra=Angle(ra, unit="deg"), dec=Angle(dec, unit="deg")).transform_to( AltAz(obstime=t0, location=loc)) za0 = altaz_astropy.zen.rad az0 = altaz_astropy.az.rad if environ.get("VIS", False): hmap = np.zeros(12 * Nside**2) + hp.UNSEEN hmap[inds] = np.unwrap(az0 - az) import IPython IPython.embed() print(np.degrees(za0 - za)) assert np.allclose(za0, za, atol=1e-4) assert np.allclose( np.unwrap(az0 - az), 0.0, atol=3e-4 ) # About 1 arcmin precision. Worst is at the southern horizon.
def test_vis_calc(): """Construct a shell with a single point source at the zenith. Confirm against analytic calculation. """ ant1_enu = np.array([0, 0, 0]) ant2_enu = np.array([0.0, 14.6, 0]) bl = observatory.Baseline(ant1_enu, ant2_enu) freqs = np.array([1e8]) nfreqs = 1 fov = 20 # Deg # Longitude/Latitude in degrees. nside = 32 ind = 10 center = list(hp.pix2ang(nside, ind, lonlat=True)) centers = [center] npix = nside**2 * 12 shell = np.zeros((npix, nfreqs)) pix_area = 4 * np.pi / float(npix) shell[ind] = 1 # Jy/pix shell[ind] *= utils.jy2Tsr(freqs[0], bm=pix_area) # K obs = observatory.Observatory(latitude, longitude, array=[bl], freqs=freqs) obs.pointing_centers = centers obs.times_jd = np.array([1]) obs.set_fov(fov) obs.set_beam("uniform") sky = sky_model.SkyModel(Nside=nside, freqs=freqs, data=shell[np.newaxis, :, :]) visibs, times, bls = obs.make_visibilities(sky) assert np.isclose(np.real(visibs), 1.0).all() # Unit point source at zenith
def test_Observatory(): # setup ant1 = np.array([15.0, 0, 0]) ant2 = np.array([0.0, 0, 0]) bl = observatory.Baseline(ant1, ant2) Npix, Nfreqs = 10, 100 az = np.linspace(0, 2 * np.pi, Npix) za = np.linspace(0, np.pi, Npix) freqs = np.linspace(100e6, 200e6, Nfreqs) obs = observatory.Observatory(latitude, longitude, array=[bl], freqs=freqs) # test Analytic set beam for beam in ["uniform", "gaussian", "airy", beam_model.airy_disk]: obs.set_beam(beam, gauss_width=10, diameter=10) assert isinstance(obs.beam, beam_model.AnalyticBeam) b = obs.beam.beam_val(az, za, freqs, pol="xx") assert b.shape == (Npix, Nfreqs) # test Power set beam obs.set_beam(os.path.join(DATA_PATH, "HERA_NF_dipole_power.beamfits")) assert isinstance(obs.beam, beam_model.PowerBeam) b = obs.beam.beam_val(az, za, freqs, pol="xx") assert b.shape == (Npix, Nfreqs)
from healvis import observatory import pylab as pl latitude = -30.7215277777 longitude = 21.4283055554 fov = 2 # Deg ant1_enu = np.array([0, 0, 0]) ant2_enu = np.array([0.0, 14.6, 0]) bl = observatory.Baseline(ant1_enu, ant2_enu) # Time Ntimes = 100 t0 = 2451545.0 # Start at J2000 epoch dt_min_short = 30.0 / 60.0 dt_min_long = 10.0 dt_days_short = dt_min_short * 1 / 60.0 * 1 / 24.0 dt_days_long = dt_min_long * 1 / 60.0 * 1 / 24.0 time_arr_short = np.arange(Ntimes) * dt_days_short + t0 time_arr_long = np.arange(Ntimes) * dt_days_long + t0 time_arr = time_arr_short freqs = [1e8] obs = observatory.Observatory(latitude, longitude, array=[bl], freqs=freqs) obs.set_fov(fov) obs.set_pointings(time_arr) Nside = 128 pixels = obs.get_observed_region(Nside)
bls.append(r) break 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(observatory.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 = observatory.Observatory(np.degrees(lat), np.degrees(lon), array=array, freqs=freqs) obs.set_fov(fov) print("Observatory built.") print("Nbls: ", Nbls) print("Ntimes: ", Ntimes) sys.stdout.flush() # --------------------------- # Pointings # --------------------------- time_arr = time_dict["time_array"] obs.set_pointings(time_arr) print("Pointings set.") sys.stdout.flush()
def test_pspec_amp(): # Construct a flat-spectrum shell, simulate visibilities, # confirm power spectrum amplitude. ant1_enu = np.array([0, 0, 0]) ant2_enu = np.array([0.0, 14.6, 0]) bl = observatory.Baseline(ant1_enu, ant2_enu) Ntimes = 20 Nfreqs = 200 freqs = np.linspace(100e6, 150e6, Nfreqs) fov = 50 # Deg # Longitude/Latitude in degrees. nside = 64 obs = observatory.Observatory(latitude, longitude, array=[bl], freqs=freqs) t0 = Time("J2000").jd obs.times_jd = np.linspace(t0, t0 + 0.5, Ntimes) # Half a day obs.set_pointings(obs.times_jd) obs.set_fov(fov) obs.set_beam("gaussian", gauss_width=7.37) skysig = 0.031 sky = sky_model.SkyModel(Nside=nside, freqs=freqs, ref_chan=Nfreqs // 2) sky.make_flat_spectrum_shell(skysig, shared_memory=True) visibs, times, bls = obs.make_visibilities(sky, Nprocs=3) vis_jy = visibs[:, 0, :] # (Nblts, Nskies, Nfreqs) vis_Ksr = utils.jy2Tsr(freqs) * vis_jy _vis = np.fft.ifft(vis_Ksr, axis=1) Nkpar = Nfreqs // 2 _vis = _vis[:, :Nkpar] # Keeping only positive k_par modes dspec_instr = np.abs(_vis)**2 beam_sq_int = np.mean( obs.beam_sq_int(freqs, nside, obs.pointing_centers[0])) Bandwidth = freqs[-1] - freqs[0] scalar = cosmology.X2Y( sky.Z_array[sky.ref_chan]) * (Bandwidth / beam_sq_int) dspec_I = np.mean(dspec_instr * scalar, axis=0) # Theoretical pspec amp dnu = np.diff(freqs)[0] Z_sel = sky.Z_array[sky.ref_chan] amp_theor = skysig**2 * cosmology.comoving_voxel_volume( Z_sel, dnu, sky.pix_area_sr) tolerance = amp_theor / float(Ntimes) # assuming independent fields print(amp_theor, np.mean(dspec_I)) print(tolerance) assert np.isclose(amp_theor, np.mean(dspec_I), atol=2 * tolerance) # Close to within twice the sample variance