def test_scan_ghosts(self): ''' Perform a (low resolution) scan with two detectors, compare to detector + ghost. ''' mlen = 10 * 60 rot_period = 120 mmax = 2 ra0=-10 dec0=-57.5 fwhm = 200 nside = 128 az_throw = 10 scs = ScanStrategy(duration=mlen, sample_rate=10, location='spole') # Create two Gaussian (main) beams. beam_opts = dict(az=0, el=0, polang=0, fwhm=fwhm, lmax=self.lmax, symmetric=True) ghost_opts = dict(az=-4, el=10, polang=34, fwhm=fwhm, lmax=self.lmax, symmetric=True, amplitude=0.1) scs.add_to_focal_plane(Beam(**beam_opts)) scs.add_to_focal_plane(Beam(**ghost_opts)) # Allocate and assign parameters for mapmaking. scs.allocate_maps(nside=nside) # Set HWP rotation. scs.set_hwp_mod(mode='continuous', freq=3.) # Generate timestreams, bin them and store as attributes. scs.scan_instrument_mpi(self.alm, verbose=0, ra0=ra0, dec0=dec0, az_throw=az_throw, scan_speed=2., binning=False, nside_spin=nside, max_spin=mmax, save_tod=True) tod = scs.data(scs.chunks[0], beam=scs.beams[0][0], data_type='tod') tod += scs.data(scs.chunks[0], beam=scs.beams[1][0], data_type='tod') tod = tod.copy() # Repeat with single beam + ghost. scs.remove_from_focal_plane(scs.beams[1][0]) scs.beams[0][0].create_ghost(**ghost_opts) scs.reset_hwp_mod() scs.scan_instrument_mpi(self.alm, verbose=0, ra0=ra0, dec0=dec0, az_throw=az_throw, scan_speed=2., binning=False, nside_spin=nside, max_spin=mmax, save_tod=True) tod_w_ghost = scs.data(scs.chunks[0], beam=scs.beams[0][0], data_type='tod') # Sum TOD of two beams must match TOD of single beam + ghost. np.testing.assert_array_almost_equal(tod, tod_w_ghost, decimal=10)
def test_load_blm(self): ''' Test loading up a blm array ''' beam = Beam(**self.beam_opts) # test if unpolarized beam is loaded and scaled np.testing.assert_array_almost_equal(beam.blm[0], beam.amplitude * self.blm) # test if copol parts are correct blmm2_expd = self.blmm2_expd * beam.amplitude blmp2_expd = self.blmp2_expd * beam.amplitude np.testing.assert_array_almost_equal(blmm2_expd, beam.blm[1]) np.testing.assert_array_almost_equal(blmp2_expd, beam.blm[2]) # test if you can also load up the full beam beam.delete_blm() beam.po_file = self.blm_cross_name np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[0]) np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[1]) np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[2])
def test_remove_from_focal_plane(self): instr = instrument.Instrument() beam1 = Beam() beam2 = Beam() beam3 = Beam() beam4 = Beam() # Add single beam per pair. instr.add_to_focal_plane([beam1, beam2, beam3, beam4], combine=True) self.assertEqual(instr.ndet, 4) instr.remove_from_focal_plane([beam1, beam2, beam3, beam4]) self.assertEqual(instr.ndet, 0) self.assertEqual(instr.beams, []) # Add pairs. instr.add_to_focal_plane([[beam1, beam2], [beam3, beam4]], combine=True) self.assertEqual(instr.ndet, 4) instr.remove_from_focal_plane([beam1, beam2, beam3]) self.assertEqual(instr.ndet, 1) self.assertEqual(instr.beams, [[None, beam4]])
def test_init_detpair(self): ''' Check if spinmaps are correctly created. ''' mmax = 3 nside = 16 scs = ScanStrategy(duration=1, sample_rate=10) beam_a = Beam(fwhm=0., btype='Gaussian', mmax=mmax) beam_b = Beam(fwhm=0., btype='Gaussian', mmax=mmax) init_spinmaps_opts = dict(max_spin=5, nside_spin=nside) scs.init_detpair(self.alm, beam_a, beam_b=beam_b, **init_spinmaps_opts) # We expect a spinmaps attribute (dict) with # main_beam key that contains a list of [func, func_c] # where func has shape (mmax + 1, 12nside**2) and # func_c has shape (2 mmax + 1, 12nside**2). # We expect an empty list for the ghosts. # Note empty lists evaluate to False self.assertFalse(scs.spinmaps['ghosts']) func = scs.spinmaps['main_beam']['s0a0']['maps'] func_c = scs.spinmaps['main_beam']['s2a4']['maps'] self.assertEqual(func.shape, (mmax + 1, 12 * nside ** 2)) self.assertEqual(func_c.shape, (2 * mmax + 1, 12 * nside ** 2)) # Since we have a infinitely narrow Gaussian the convolved # maps should just match the input (up to healpix quadrature # wonkyness). input_map = hp.alm2map(self.alm, nside, verbose=False) # I, Q, U zero_map = np.zeros_like(input_map[0]) np.testing.assert_array_almost_equal(input_map[0], func[0], decimal=6) # s = 2 Pol map should be Q \pm i U np.testing.assert_array_almost_equal(input_map[1] + 1j * input_map[2], func_c[mmax + 2], decimal=6) # Test if rest of maps are zero. for i in range(1, mmax + 1): np.testing.assert_array_almost_equal(zero_map, func[i], decimal=6) for i in range(1, 2 * mmax + 1): if i == mmax + 2: continue print(i) np.testing.assert_array_almost_equal(zero_map, func_c[i], decimal=6)
def test_init(self): ''' Test initializing a Beam object. ''' beam = Beam(fwhm=0.) self.assertEqual(0, beam.fwhm)
def test_init_detpair2(self): ''' Check if function works with only A beam. ''' mmax = 3 nside = 16 scs = ScanStrategy() beam_a = Beam(fwhm=0., btype='Gaussian', mmax=mmax) beam_b = None init_spinmaps_opts = dict(max_spin=5, nside_spin=nside, verbose=False) scs.init_detpair(self.alm, beam_a, beam_b=beam_b, **init_spinmaps_opts) # Test for correct shapes. # Note empty lists evaluate to False self.assertFalse(scs.spinmaps['ghosts']) func, func_c = scs.spinmaps['main_beam']['maps'] self.assertEqual(func.shape, (mmax + 1, 12 * nside ** 2)) self.assertEqual(func_c.shape, (2 * mmax + 1, 12 * nside ** 2))
def test_add_to_focal_plane(self): instr = instrument.Instrument() beam = Beam() # Add single beam. instr.add_to_focal_plane(beam, combine=True) self.assertEqual(instr.ndet, 1) for pair in instr.beams: self.assertEqual(pair[0], beam) self.assertEqual(pair[1], None) # Add three more individual beam. instr.add_to_focal_plane([beam, beam, beam], combine=True) self.assertEqual(instr.ndet, 4) for pair in instr.beams: self.assertEqual(pair[0], beam) self.assertEqual(pair[1], None) # Add a pair. instr.add_to_focal_plane([[beam, beam]], combine=True) self.assertEqual(instr.ndet, 6) for n, pair in enumerate(instr.beams): self.assertEqual(pair[0], beam) if n > 3: self.assertEqual(pair[1], beam) # Add two pair. instr.add_to_focal_plane([[beam, beam], [beam, beam]], combine=True) self.assertEqual(instr.ndet, 10) for n, pair in enumerate(instr.beams): self.assertEqual(pair[0], beam) if n > 3: self.assertEqual(pair[1], beam) # Start new focal plane with pair. instr.add_to_focal_plane([[beam, beam]], combine=False) self.assertEqual(instr.ndet, 2) for pair in instr.beams: self.assertEqual(pair[0], beam) self.assertEqual(pair[1], beam)
def test_load_blm_mmax_fits(self): ''' Test loading up a blm .fits array that has mmax < lmax ''' if int(hp.__version__.replace('.', '')) < 1101: return beam = Beam(**self.beam_opts) beam.po_file = self.blm_name_mmax_fits # test if unpolarized beam is loaded and scaled blm_expd = beam.amplitude * self.blm blm_expd[-1] = 0 np.testing.assert_array_almost_equal(beam.blm[0], blm_expd) # After loading we expect mmax to be equal to the truncated value. self.assertEqual(beam.mmax, 2) # Test if you can also load up the full beam, note that these # are just 3 copies of main beam, but truncated. beam.delete_blm() beam.po_file = self.blm_cross_name_mmax_fits np.testing.assert_array_almost_equal(blm_expd, beam.blm[0]) np.testing.assert_array_almost_equal(blm_expd, beam.blm[1]) np.testing.assert_array_almost_equal(blm_expd, beam.blm[2])
def test_load_blm_fits(self): ''' Test loading up a blm .fits array ''' if int(hp.__version__.replace('.', '')) < 1101: return beam = Beam(**self.beam_opts) beam.po_file = self.blm_name_fits # test if unpolarized beam is loaded and scaled np.testing.assert_array_almost_equal(beam.blm[0], beam.amplitude * self.blm) # test if copol parts are correct blmm2_expd = self.blmm2_expd * beam.amplitude blmp2_expd = self.blmp2_expd * beam.amplitude np.testing.assert_array_almost_equal(blmm2_expd, beam.blm[1]) np.testing.assert_array_almost_equal(blmp2_expd, beam.blm[2]) # test if you can also load up the full beam beam.delete_blm() beam.po_file = self.blm_cross_name_fits np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[0]) np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[1]) np.testing.assert_array_almost_equal(self.blm * beam.amplitude, beam.blm[2])
def test_polang_error(self): ''' Test wheter polang_truth = polang + polang_error and correctly updates. ''' beam = Beam(**self.beam_opts) # Default Value. self.assertEqual(beam.polang_error, 0.) self.assertEqual(beam.polang_truth, beam.polang + beam.polang_error) beam.polang = 40 self.assertEqual(beam.polang_truth, beam.polang + beam.polang_error) beam.polang_error = 40 self.assertEqual(beam.polang_truth, beam.polang + beam.polang_error) # User cannot change polang_truth directly. try: beam.polang_truth = 42 except: AttributeError self.assertEqual(beam.polang_truth, beam.polang + beam.polang_error)
def Scan_maps(nside, alms, lmax, Freq, Own_Stack=True, ideal_hwp=False): ''' Scanning simulation, store the output map, the blm, the tod, and the condition number in the output directory. --------- nside: int the nside of the map alms : array-like array of alm arrays that share lmax and mmax. For each frequency we have three healpy alm array lmax: int The bandlmit. Freq: array-like frequency at which one want to compute the sky Keyword arguments ----------------- ideal_hwp : bool If True: it is considered an ideal HWP, if Flase: it is considered a real HWP. (default : False) ''' po_file = opj(blm_dir, 'pix0000_90_hwpproj_v5_f1p6_6p0mm_mfreq_lineard_hdpe.npy') #eg_file = opj(blm_dir, 'blm_hp_eg_X1T1R1C8A_800_800.npy') beam_file = 'pix0000_90_hwpproj_v5_f1p6_6p0mm_mfreq_lineard_hdpe.pkl' hwp = Beam().hwp() if Own_Stack: thicknesses = np.array([0.427, 4.930, 0.427]) indices = np.array([[1., 1.], [1.02, 1.02], [1., 1.]]) losses = np.array([[0., 0.], [1e-4, 1e-4], [0., 0.]]) angles = np.array([0., 0., 0.]) hwp.stack_builder(thicknesses=thicknesses, indices=indices, losses=losses, angles=angles) else: hwp.choose_HWP_model('SPIDER_95') beam_opts = dict( az=0, el=0, polang=0., btype='PO', fwhm=32.2, lmax=lmax, mmax=4, amplitude=1., po_file=po_file, #eg_file=eg_file, deconv_q=True, # blm are SH coeff from hp.alm2map normalize=True, hwp=hwp) with open(beam_file, 'wb') as handle: pickle.dump(beam_opts, handle, protocol=pickle.HIGHEST_PROTOCOL) beam = Beam(**beam_opts) ### SCAN OPTIONS # duration = nsamp/sample_rate nsamp = 864000 fsamp = 10 mlen = nsamp / fsamp lmax = lmax mmax = 4 ra0 = -10 dec0 = -57.5 az_throw = 50 scan_speed = 2.8 rot_period = 4.5 * 60 * 60 nside_spin = nside # scan the given sky and return the results as maps; filefolder = opj(dir_out, 'Output_maps/') for freq, alm in zip(Freq, alms): ss = ScanStrategy(mlen, sample_rate=fsamp, location='atacama') # Add the detectors to the focal plane; 9 detector pairs used in this case ss.create_focal_plane(nrow=4, ncol=4, fov=3, **beam_opts) # Use a half-wave plate. Other options one can use is to add an elevation # pattern or a periodic instrument rotation as, for example: # ss.set_instr_rot(period=rot_period, angles=[68, 113, 248, 293]) # and ss.set_el_steps(step_period, steps=[-4, -3, -2, -1, 0, 1, 2, 3, 4, 4]) ss.set_hwp_mod(mode='continuous', freq=1.) # scan the given sky and return the results as maps; ss.allocate_maps(nside=nside) if ideal_hwp: ss.scan_instrument_mpi(alm, verbose=1, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=nside_spin, max_spin=mmax, binning=True, hwp_status='ideal') else: ss.scan_instrument_mpi(alm, verbose=1, ra0=ra0, dec0=dec0, az_throw=az_throw, nside_spin=nside_spin, max_spin=mmax, binning=True) tod = ss.tod maps, cond = ss.solve_for_map(fill=np.nan) blm = np.asarray(beam.blm).copy() # We need to divide out sqrt(4pi / (2 ell + 1)) to get # correctly normlized spherical harmonic coeffients. ell = np.arange(hp.Alm.getlmax(blm[0].size)) q_ell = np.sqrt(4. * np.pi / (2 * ell + 1)) blm[0] = hp.almxfl(blm[0], 1 / q_ell) blm[1] = hp.almxfl(blm[1], 1 / q_ell) blm[2] = hp.almxfl(blm[2], 1 / q_ell) # print(np.shape(alm)) # print(np.shape(alms)) # print(np.shape(maps)) # print(np.shape(cond)) # maps = [maps[0], maps[1], maps[2]] hp.write_map(opj(dir_out, 'Output_maps/Bconv_' + str(freq) + 'GHz.fits'), maps, overwrite=True) hp.write_map(opj(dir_out, 'Output_maps/Cond_Numb_' + str(freq) + 'GHz.fits'), cond, overwrite=True) np.save(os.path.join(dir_out, 'blms/blm_' + str(freq) + 'GHz.npy'), blm) np.save(os.path.join(dir_out, 'tods/tod_' + str(freq) + 'GHz.npy'), tod)
def scan(lmax=500, nside=512, mmax=2): '''Time scanning single detector.''' os.environ["OMP_NUM_THREADS"] = "10" import numpy as np import healpy as hp from beamconv import ScanStrategy from beamconv import Beam ndays_range = np.logspace(np.log10(0.001), np.log10(50), 15) lmax = lmax nside = nside freq = 100. timings = np.ones((ndays_range.size), dtype=float) timings_cpu = np.ones((ndays_range.size), dtype=float) S = ScanStrategy(duration=24 * 3600, sample_rate=freq) beam_opts = dict(az=1, el=1, polang=10., fwhm=40, btype='Gaussian', lmax=lmax, symmetric=mmax == 0) beam = Beam(**beam_opts) S.add_to_focal_plane(beam) alm = np.zeros((3, hp.Alm.getsize(lmax=lmax)), dtype=np.complex128) print('init detpair...') S.init_detpair(alm, beam, beam_b=None, nside_spin=nside, max_spin=mmax, verbose=True) print('...done') spinmaps = copy.deepcopy(S.spinmaps) # Calculate q_bore for 0.1 day of scanning and reuse this. const_el_opts = dict(az_throw=50., scan_speed=10., dec0=-70.) S.partition_mission() print('cons_el_scan...') const_el_opts.update(dict(start=0, end=int(24 * 3600 * 100 * 0.1))) S.constant_el_scan(**const_el_opts) print('...done') q_bore_day = S.q_bore ctime_day = S.ctime for nidx, ndays in enumerate(ndays_range): duration = ndays * 24 * 3600 nsamp = duration * freq S = ScanStrategy(duration=duration, sample_rate=freq, external_pointing=True) S.add_to_focal_plane(beam) S.partition_mission() q_bore = np.repeat(q_bore_day, np.ceil(10 * ndays), axis=0) ctime = np.repeat(q_bore_day, np.ceil(10 * ndays)) def q_bore_func(start=None, end=None, q_bore=None): return q_bore[int(start):int(end), :] def ctime_func(start=None, end=None, ctime=None): return ctime[int(start):int(end)] S.spinmaps = spinmaps t0 = time.time() t0c = time.clock() S.scan_instrument_mpi(alm, binning=False, reuse_spinmaps=True, interp=False, q_bore_func=q_bore_func, ctime_func=ctime_func, q_bore_kwargs={'q_bore': q_bore}, ctime_kwargs={'ctime': ctime}, start=0, end=int(nsamp), cidx=0) t1 = time.time() t1c = time.clock() print t1 - t0 print t1c - t0c timings[nidx] = t1 - t0 timings_cpu[nidx] = t1c - t0c np.save( './scan_timing_lmax{}_nside{}_mmax{}.npy'.format(lmax, nside, mmax), timings) np.save( './scan_timing_cpu_lmax{}_nside{}_mmax{}.npy'.format( lmax, nside, mmax), timings_cpu) np.save('./scan_ndays_lmax{}_nside{}_mmax{}.npy'.format(lmax, nside, mmax), ndays_range)
def t_lmax(): '''Time init_detpair as function of lmax, mmax.''' os.environ["OMP_NUM_THREADS"] = "1" import numpy as np import healpy as hp from beamconv import ScanStrategy from beamconv import Beam scan_opts = dict(duration=3600, sample_rate=100) mmax_range = np.array([0, 2, 5, 8], dtype=int) lmax_range = np.logspace(np.log10(500), np.log10(3000), 8, dtype=int) nsides = np.ones_like(lmax_range) * np.nan nside_range = 2**np.arange(15) timings = np.ones((mmax_range.size, lmax_range.size)) * np.nan timings_cpu = np.ones((mmax_range.size, lmax_range.size)) * np.nan alm = np.zeros((3, hp.Alm.getsize(lmax=4000)), dtype=np.complex128) S = ScanStrategy(**scan_opts) for lidx, lmax in enumerate(lmax_range): nside = nside_range[np.digitize(0.5 * lmax, nside_range)] nsides[lidx] = nside for midx, mmax in enumerate(mmax_range): beam_opts = dict(az=0, el=0, polang=0, fwhm=40, btype='Gaussian', lmax=lmax, symmetric=mmax == 0) beam = Beam(**beam_opts) beam.blm t0 = time.time() t0c = time.clock() S.init_detpair(alm, beam, beam_b=None, nside_spin=nside, max_spin=mmax, verbose=False) t1 = time.time() t1c = time.clock() print('{}, {}, {}: {}'.format(lmax, mmax, nside, t1 - t0)) print('{}, {}, {}: {}'.format(lmax, mmax, nside, t1c - t0c)) timings[midx, lidx] = t1 - t0 timings_cpu[midx, lidx] = t1c - t0c np.save('./timings.npy', timings) np.save('./timings_cpu.npy', timings_cpu) np.save('./lmax_range.npy', lmax_range) np.save('./mmax_range.npy', mmax_range) np.save('./nsides.npy', nsides)