def test_ghosts(lmax=700, mmax=5, fwhm=43, ra0=-10, dec0=-57.5, az_throw=50, scan_speed=2.8, rot_period=4.5 * 60 * 60, hwp_mode=None): ''' Similar test to `scan_bicep`, but includes reflected ghosts Simulates a 24h BICEP2-like scan strategy using a random LCDM realisation and a 3 x 3 grid of Gaussian beams pairs. Bins tods into maps and compares to smoothed input maps (no pair- differencing). MPI-enabled. Keyword arguments --------- lmax : int, bandlimit (default : 700) mmax : int, assumed azimuthal bandlimit beams (symmetric in this example so 2 would suffice) (default : 5) fwhm : float, The beam FWHM in arcmin (default : 40) ra0 : float, Ra coord of centre region (default : -10) dec0 : float, (default : -57.5) Ra coord of centre region az_throw : float, Scan width in azimuth (in degrees) (default : 50) scan_speed : float, Scan speed in deg/s (default : 1) rot_period : float, The instrument rotation period in sec (default : 600) hwp_mode : str, None HWP modulation mode, either "continuous", "stepped" or None. Use freq of 1 or 1/10800 Hz respectively (default : None) ''' mlen = 24 * 60 * 60 # hardcoded mission length # Create LCDM realization ell, cls = get_cls() np.random.seed(25) # make sure all MPI ranks use the same seed alm = hp.synalm(cls, lmax=lmax, new=True, verbose=True) # uK b2 = ScanStrategy( mlen, # mission duration in sec. sample_rate=12.01, # sample rate in Hz location='spole') # Instrument at south pole # Create a 3 x 3 square grid of Gaussian beams b2.create_focal_plane(nrow=3, ncol=3, fov=5, lmax=lmax, fwhm=fwhm) # Create reflected ghosts for every detector # We create two ghosts per detector. They overlap # but have different fwhm. First ghost is just a # scaled down version of the main beam, the second # has a much wider Gaussian shape. # After this initialization, the code takes # the ghosts into account without modifications b2.create_reflected_ghosts(b2.beams, amplitude=0.01, ghost_tag='ghost_1', dead=False) b2.create_reflected_ghosts(b2.beams, amplitude=0.01, fwhm=100, ghost_tag='ghost_2', dead=False) # calculate tods in two chunks b2.partition_mission(0.5 * b2.nsamp) # Allocate and assign parameters for mapmaking b2.allocate_maps(nside=256) # set instrument rotation b2.set_instr_rot(period=rot_period, angles=[68, 113, 248, 293]) # Set HWP rotation if hwp_mode == 'continuous': b2.set_hwp_mod(mode='continuous', freq=1.) elif hwp_mode == 'stepped': b2.set_hwp_mod(mode='stepped', freq=1 / (3 * 60 * 60.)) # Generate timestreams, bin them and store as attributes b2.scan_instrument_mpi(alm, verbose=1, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=256, max_spin=mmax) # Solve for the maps maps, cond = b2.solve_for_map(fill=np.nan) # Plotting if b2.mpi_rank == 0: print('plotting results') cart_opts = dict( rot=[ra0, dec0, 0], lonra=[-min(0.5 * az_throw, 90), min(0.5 * az_throw, 90)], latra=[-min(0.375 * az_throw, 45), min(0.375 * az_throw, 45)], unit=r'[$\mu K_{\mathrm{CMB}}$]') # plot rescanned maps plot_iqu(maps, '../scratch/img/', 'rescan_ghost', sym_limits=[250, 5, 5], plot_func=hp.cartview, **cart_opts) # plot smoothed input maps nside = hp.get_nside(maps[0]) hp.smoothalm(alm, fwhm=np.radians(fwhm / 60.), verbose=False) maps_raw = hp.alm2map(alm, nside, verbose=False) plot_iqu(maps_raw, '../scratch/img/', 'raw_ghost', sym_limits=[250, 5, 5], plot_func=hp.cartview, **cart_opts) # plot difference maps for arr in maps_raw: # replace stupid UNSEEN crap arr[arr == hp.UNSEEN] = np.nan diff = maps_raw - maps plot_iqu(diff, '../scratch/img/', 'diff_ghost', sym_limits=[1e+1, 1e-1, 1e-1], plot_func=hp.cartview, **cart_opts) # plot condition number map cart_opts.pop('unit', None) plot_map(cond, '../scratch/img/', 'cond_ghost', min=2, max=5, unit='condition number', plot_func=hp.cartview, **cart_opts) # plot input spectrum cls[3][cls[3] <= 0.] *= -1. dell = ell * (ell + 1) / 2. / np.pi plt.figure() for i, label in enumerate(['TT', 'EE', 'BB', 'TE']): plt.semilogy(ell, dell * cls[i], label=label) plt.legend() plt.ylabel(r'$D_{\ell}$ [$\mu K^2_{\mathrm{CMB}}$]') plt.xlabel(r'Multipole [$\ell$]') plt.savefig('../scratch/img/cls_ghost.png') plt.close()
def test_satellite_scan(lmax=700, mmax=2, fwhm=43, ra0=-10, dec0=-57.5, az_throw=50, scan_speed=2.8, hwp_mode=None, alpha=45., beta=45., alpha_period=5400., beta_period=600., delta_az=0., delta_el=0., delta_psi=0., jitter_amp=1.0): ''' Simulates a satellite scan strategy using a random LCDM realisation and a 3 x 3 grid of Gaussian beams pairs. Bins tods into maps and compares to smoothed input maps (no pair- differencing). MPI-enabled. Keyword arguments --------- lmax : int, bandlimit (default : 700) mmax : int, assumed azimuthal bandlimit beams (symmetric in this example so 2 would suffice) (default : 2) fwhm : float, The beam FWHM in arcmin (default : 40) ra0 : float, Ra coord of centre region (default : -10) dec0 : float, (default : -57.5) Ra coord of centre region az_throw : float, Scan width in azimuth (in degrees) (default : 50) scan_speed : float, Scan speed in deg/s (default : 1) hwp_mode : str, None HWP modulation mode, either "continuous", "stepped" or None. Use freq of 1 or 1/10800 Hz respectively (default : None) ''' print('Simulating a satellite...') mlen = 3 * 24 * 60 * 60 # hardcoded mission length # Create LCDM realization ell, cls = get_cls() np.random.seed(25) # make sure all MPI ranks use the same seed alm = hp.synalm(cls, lmax=lmax, new=True, verbose=True) # uK sat = ScanStrategy( mlen, # mission duration in sec. external_pointing=True, # Telling code to use non-standard scanning sample_rate=12.01, # sample rate in Hz location='space') # Instrument at south pole # Create a 3 x 3 square grid of Gaussian beams sat.create_focal_plane(nrow=7, ncol=7, fov=15, lmax=lmax, fwhm=fwhm) # calculate tods in two chunks sat.partition_mission(0.5 * sat.nsamp) # Allocate and assign parameters for mapmaking sat.allocate_maps(nside=256) scan_opts = dict(q_bore_func=sat.satellite_scan, ctime_func=sat.satellite_ctime, q_bore_kwargs=dict(), ctime_kwargs=dict()) # Generate timestreams, bin them and store as attributes sat.scan_instrument_mpi(alm, verbose=1, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=256, max_spin=mmax, **scan_opts) # Solve for the maps maps, cond, proj = sat.solve_for_map(fill=np.nan, return_proj=True) # Plotting if sat.mpi_rank == 0: print('plotting results') cart_opts = dict(unit=r'[$\mu K_{\mathrm{CMB}}$]') # plot rescanned maps plot_iqu(maps, '../scratch/img/', 'rescan_satellite', sym_limits=[250, 5, 5], plot_func=hp.mollview, **cart_opts) # plot smoothed input maps nside = hp.get_nside(maps[0]) hp.smoothalm(alm, fwhm=np.radians(fwhm / 60.), verbose=False) maps_raw = hp.alm2map(alm, nside, verbose=False) plot_iqu(maps_raw, '../scratch/img/', 'raw_satellite', sym_limits=[250, 5, 5], plot_func=hp.mollview, **cart_opts) # plot difference maps for arr in maps_raw: # replace stupid UNSEEN crap arr[arr == hp.UNSEEN] = np.nan diff = maps_raw - maps plot_iqu(diff, '../scratch/img/', 'diff_satellite', sym_limits=[1e-6, 1e-6, 1e-6], plot_func=hp.mollview, **cart_opts) # plot condition number map cart_opts.pop('unit', None) plot_map(cond, '../scratch/img/', 'cond_satellite', min=2, max=5, unit='condition number', plot_func=hp.mollview, **cart_opts) plot_map(proj[0], '../scratch/img/', 'hits_satellite', unit='Hits', plot_func=hp.mollview, **cart_opts)
def scan_atacama(lmax=700, mmax=5, fwhm=40, mlen=48 * 60 * 60, nrow=3, ncol=3, fov=5.0, ra0=[-10, 170], dec0=[-57.5, 0], el_min=45., cut_el_min=False, az_throw=50, scan_speed=1, rot_period=0, hwp_mode='continuous'): ''' Simulates 48h of an atacama-based telescope with a 3 x 3 grid of Gaussian beams pairs. Prefers to scan the bicep patch but will try to scan the ABS_B patch if the first is not visible. Keyword arguments --------- lmax : int bandlimit (default : 700) mmax : int assumed azimuthal bandlimit beams (symmetric in this example so 2 would suffice) (default : 5) fwhm : float The beam FWHM in arcmin (default : 40) mlen : int The mission length [seconds] (default : 48 * 60 * 60) nrow : int Number of detectors along row direction (default : 3) ncol : int Number of detectors along column direction (default : 3) fov : float The field of view in degrees (default : 5.0) ra0 : float, array-like Ra coord of centre region (default : [-10., 85.]) dec0 : float, array-like Ra coord of centre region (default : [-57.5, 0.]) el_min : float Minimum elevation range [deg] (default : 45) cut_el_min: bool If True, excludes timelines where el would be less than el_min az_throw : float Scan width in azimuth (in degrees) (default : 10) scan_speed : float Scan speed in deg/s (default : 1) rot_period : float The instrument rotation period in sec (default : 600) hwp_mode : str, None HWP modulation mode, either "continuous", "stepped" or None. Use freq of 1 or 1/10800 Hz respectively (default : continuous) ''' # hardcoded mission length # Create LCDM realization ell, cls = get_cls() np.random.seed(25) # make sure all MPI ranks use the same seed alm = hp.synalm(cls, lmax=lmax, new=True, verbose=True) # uK ac = ScanStrategy( mlen, # mission duration in sec. sample_rate=12.01, # sample rate in Hz location='atacama') # Instrument at south pole # Create a 3 x 3 square grid of Gaussian beams ac.create_focal_plane(nrow=nrow, ncol=ncol, fov=fov, lmax=lmax, fwhm=fwhm) # calculate tods in two chunks ac.partition_mission(0.5 * ac.mlen * ac.fsamp) # Allocate and assign parameters for mapmaking ac.allocate_maps(nside=256) # set instrument rotation ac.set_instr_rot(period=rot_period) # Set HWP rotation if hwp_mode == 'continuous': ac.set_hwp_mod(mode='continuous', freq=1.) elif hwp_mode == 'stepped': ac.set_hwp_mod(mode='stepped', freq=1 / (3 * 60 * 60.)) # Generate timestreams, bin them and store as attributes ac.scan_instrument_mpi(alm, verbose=2, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=256, el_min=el_min, cut_el_min=cut_el_min, create_memmap=True) # Solve for the maps maps, cond = ac.solve_for_map(fill=np.nan) # Plotting if ac.mpi_rank == 0: print('plotting results') img_out_path = '../scratch/img/' moll_opts = dict(unit=r'[$\mu K_{\mathrm{CMB}}$]') # plot rescanned maps plot_iqu(maps, img_out_path, 'rescan_atacama', sym_limits=[250, 5, 5], plot_func=hp.mollview, **moll_opts) # plot smoothed input maps nside = hp.get_nside(maps[0]) hp.smoothalm(alm, fwhm=np.radians(fwhm / 60.), verbose=False) maps_raw = hp.alm2map(alm, nside, verbose=False) plot_iqu(maps_raw, img_out_path, 'raw_atacama', sym_limits=[250, 5, 5], plot_func=hp.mollview, **moll_opts) # plot difference maps for arr in maps_raw: # replace stupid UNSEEN crap arr[arr == hp.UNSEEN] = np.nan diff = maps_raw - maps plot_iqu(diff, img_out_path, 'diff_atacama', sym_limits=[1e-6, 1e-6, 1e-6], plot_func=hp.mollview, **moll_opts) # plot condition number map moll_opts.pop('unit', None) plot_map(cond, img_out_path, 'cond_atacama', min=2, max=5, unit='condition number', plot_func=hp.mollview, **moll_opts) # plot input spectrum cls[3][cls[3] <= 0.] *= -1. dell = ell * (ell + 1) / 2. / np.pi plt.figure() for i, label in enumerate(['TT', 'EE', 'BB', 'TE']): plt.semilogy(ell, dell * cls[i], label=label) plt.legend() plt.ylabel(r'$D_{\ell}$ [$\mu K^2_{\mathrm{CMB}}$]') plt.xlabel(r'Multipole [$\ell$]') plt.savefig('../scratch/img/cls_atacama.png') plt.close() print("Results written to {}".format(os.path.abspath(img_out_path)))
def idea_jon(): nside_spin = 512 ra0 = 0 dec0 = -90 az_throw = 10 max_spin = 5 fwhm = 32.2 scan_opts = dict(verbose=1, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=nside_spin, max_spin=max_spin, binning=True) lmax = 800 alm = tools.gauss_blm(1e-5, lmax, pol=False) ell = np.arange(lmax + 1) fl = np.sqrt((2 * ell + 1) / 4. / np.pi) hp.almxfl(alm, fl, mmax=None, inplace=True) fm = (-1)**(hp.Alm.getlm(lmax)[1]) alm *= fm alm = tools.get_copol_blm(alm) # create Beam properties and pickle (this is just to test load_focal_plane) import tempfile import shutil import pickle opj = os.path.join blm_dir = os.path.abspath( opj(os.path.dirname(__file__), '../tests/test_data/example_blms')) po_file = opj(blm_dir, 'blm_hp_X1T1R1C8A_800_800.npy') eg_file = opj(blm_dir, 'blm_hp_eg_X1T1R1C8A_800_800.npy') tmp_dir = tempfile.mkdtemp() beam_file = opj(tmp_dir, 'beam_opts.pkl') beam_opts = dict(az=0, el=0, polang=0., btype='Gaussian', name='X1T1R1C8', fwhm=fwhm, lmax=800, mmax=800, amplitude=1., po_file=po_file, eg_file=eg_file) with open(beam_file, 'wb') as handle: pickle.dump(beam_opts, handle, protocol=pickle.HIGHEST_PROTOCOL) # init scan strategy and instrument ss = ScanStrategy( 1., # mission duration in sec. sample_rate=10000, location='spole') ss.allocate_maps(nside=1024) ss.load_focal_plane(tmp_dir, no_pairs=True) # remove tmp dir and contents shutil.rmtree(tmp_dir) ss.set_el_steps(0.01, steps=np.linspace(-10, 10, 100)) # Generate maps with Gaussian beams ss.scan_instrument_mpi(alm, **scan_opts) ss.reset_el_steps() # Solve for the maps maps_g, cond_g = ss.solve_for_map(fill=np.nan) # Generate maps with elliptical Gaussian beams ss.allocate_maps(nside=1024) ss.beams[0][0].btype = 'EG' ss.scan_instrument_mpi(alm, **scan_opts) ss.reset_el_steps() # Solve for the maps maps_eg, cond_eg = ss.solve_for_map(fill=np.nan) # Generate map with Physical Optics beams and plot them ss.allocate_maps(nside=1024) ss.beams[0][0].btype = 'PO' ss.scan_instrument_mpi(alm, **scan_opts) ss.reset_el_steps() # Solve for the maps maps_po, cond_po = ss.solve_for_map(fill=np.nan) # Plotting print('plotting results') cart_opts = dict( #rot=[ra0, dec0, 0], lonra=[-min(0.5 * az_throw, 10), min(0.5 * az_throw, 10)], latra=[-min(0.375 * az_throw, 10), min(0.375 * az_throw, 10)], unit=r'[$\mu K_{\mathrm{CMB}}$]') # plot smoothed input maps nside = hp.get_nside(maps_g[0]) hp.smoothalm(alm, fwhm=np.radians(fwhm / 60.), verbose=False) maps_raw = hp.alm2map(alm, nside, verbose=False) plot_iqu(maps_raw, '../scratch/img/', 'raw_delta', sym_limits=[1, 1, 1], plot_func=hp.cartview, **cart_opts)