def __init__(self, scan, template, sys=None): sys = config.get("map_sys", sys) downsamp = config.get("pmat_moby_downsamp", 20) bore = scan.boresight.copy() bore[:, 0] += utils.mjd2ctime(scan.mjd0) opoint = get_moby_pointing(scan.entry, bore, scan.dets, downgrade=downsamp) # We will fit a polynomial to the pointing for each detector box = np.array([[np.min(a), np.max(a)] for a in scan.boresight.T]).T def scale(a, r): return 2 * (a - r[0]) / (r[1] - r[0]) - 1 t = scale(scan.boresight[::downsamp, 0], box[:, 0]) az = scale(scan.boresight[::downsamp, 1], box[:, 1]) el = scale(scan.boresight[::downsamp, 2], box[:, 2]) basis = np.array( [az**4, az**3, az**2, az**1, az**0, el**2, el, t**2, t, t * az]).T denom = basis.T.dot(basis) e, v = np.linalg.eigh(denom) if (np.min(e) < 1e-8 * np.max(e)): basis = np.concatenate([basis[:, :5], basis[:, 6:]], 1) denom = basis.T.dot(basis) # Convert from ra/dec to pixels, since we've confirmed that # our ra/dec is the same as ninkasi to 0.01". t1 = time.time() pix = template.sky2pix(opoint[1::-1], safe=True) t2 = time.time() #rafit = np.linalg.solve(denom, basis.T.dot(opoint[0].T)) #decfit = np.linalg.solve(denom, basis.T.dot(opoint[1].T)) yfit = np.linalg.solve(denom, basis.T.dot(pix[0].T)) xfit = np.linalg.solve(denom, basis.T.dot(pix[1].T)) # Just use the same az and t as before for simplicity. The # coefficients will be different, but the result will be # the same. basis = np.array([az**0, az**1, az**2, az**3, t]).T denom = basis.T.dot(basis) cosfit = np.linalg.solve(denom, basis.T.dot(opoint[2].T)) sinfit = np.linalg.solve(denom, basis.T.dot(opoint[3].T)) # Parameters for pmat self.posfit = np.concatenate([yfit[:, :, None], xfit[:, :, None]], 2) self.polfit = np.concatenate([cosfit[:, :, None], sinfit[:, :, None]], 2) self.box = box self.pixbox = np.array([[0, 0], template.shape[-2:]]) self.scan = scan self.dtype = template.dtype self.core = get_core(self.dtype)
scan = enscan.Scan( boresight=bore, offsets=np.concatenate([np.zeros(d.ndet)[:, None], d.point_offset], 1), comps=np.concatenate([np.ones(d.ndet)[:, None], np.zeros((d.ndet, 3))], 1), mjd0=utils.ctime2mjd(d.boresight[0, 0]), sys="hor", site=d.site) scan.hwp_phase = np.zeros([len(bore), 2]) bore_box = np.array([np.min(d.boresight, 1), np.max(d.boresight, 1)]) bore_corners = utils.box2corners(bore_box) scan.entry = d.entry # Is the source above the horizon? If not, it doesn't matter how close # it is. mjd = utils.ctime2mjd( utils.mjd2ctime(scan.mjd0) + scan.boresight[::100, 0]) object_pos = coordinates.interpol_pos("cel", "hor", args.objname, mjd, site=scan.site) visible = np.any(object_pos[1] >= margin) if not visible: cut = rangelist.zeros((d.ndet, d.nsamp)) else: pmap = pmat.PmatMap(scan, mask, sys="hor:%s" % args.objname) # Build a tod to project onto. tod = np.zeros((d.ndet, d.nsamp), dtype=dtype) # And project pmap.forward(tod, mask) # Any nonzero samples should be cut
trhs = P.backward(scan.tod, ncomp=1) # We want the standard deviation too scan.tod[:] = scan.boresight[None, :, 0]**2 N.white(scan.tod) t2rhs = P.backward(scan.tod, ncomp=1) # Get the div and hits scan.tod[:] = 1 N.white(scan.tod) tdiv = P.backward(scan.tod, ncomp=1) scan.tod[:] = 1 hits = P.backward(scan.tod, ncomp=1) with utils.nowarn(): t = trhs / tdiv t2 = t2rhs / tdiv trms = (t2 - t**2)**0.5 t0 = utils.mjd2ctime(scan.mjd0) t += t0 # Get rid of nans to make future calculations easier with utils.nowarn(): bad = ~np.isfinite(flux) | ~np.isfinite(dflux) | ~(dflux > 0) | ~(hits > 0) flux[bad] = t[bad] = hits[bad] = tdiv[bad] = 0 dflux[bad] = np.inf # Cut any sources that aren't hit by anything, and also get rid of useless indices good = np.any(np.isfinite(dflux), (1, 2, 3)) sids = np.array(sids)[good] flux, dflux, t, hits, trms, tdiv = [ a[good, 0, :, 0] for a in [flux, dflux, t, hits, trms, tdiv] ]
# annoying that scan and data objects aren't compatible. bore = d.boresight.T.copy() bore[:,0] -= bore[0,0] scan = enscan.Scan( boresight = bore, offsets = np.concatenate([np.zeros(d.ndet)[:,None],d.point_offset],1), comps = np.concatenate([np.ones(d.ndet)[:,None],np.zeros((d.ndet,3))],1), mjd0 = utils.ctime2mjd(d.boresight[0,0]), sys = "hor", site = d.site) scan.hwp_phase = np.zeros([len(bore),2]) bore_box = np.array([np.min(d.boresight,1),np.max(d.boresight,1)]) bore_corners = utils.box2corners(bore_box) scan.entry = d.entry # Is the source above the horizon? If not, it doesn't matter how close # it is. mjd = utils.ctime2mjd(utils.mjd2ctime(scan.mjd0)+scan.boresight[::100,0]) try: object_pos = coordinates.interpol_pos("cel","hor", args.objname, mjd, site=scan.site) except AttributeError as e: print("Unexpected error in interpol_pos for %s. mid time was %.5f. message: %s. skipping" % (id, mjd[len(mjd)//2], e)) continue visible = np.any(object_pos[1] >= -margin) if not visible: cut = sampcut.empty(d.ndet, d.nsamp) else: pmap = pmat.PmatMap(scan, mask, sys="sidelobe:%s" % args.objname) # Build a tod to project onto. tod = np.zeros((d.ndet, d.nsamp), dtype=dtype) # And project pmap.forward(tod, mask) # Any nonzero samples should be cut
args.corr_spacing * utils.degree) if args.inject: inject_params = np.loadtxt(args.inject, ndmin=2) # [:,{ra0,dec0,R,vx,vy,flux}] asteroids = planet9.get_asteroids(args.asteroid_file, args.asteroid_list) # How to parallelize? Could do it over chunks. Usually there will be more chunks than # mpi tasks. But there will still be many tods per chunk too (about 6 tods per hour # and 72 hours per chunk gives 432 tods per chunk). That's quite a bit for one mpi # task to do. Could paralellize over both... No, keep things simple. Parallelize over tods # in a chunk, and make sure that nothing breaks if some tasks don't have anything to do. L.info("Processing %d chunks" % len(chunks)) for ci, chunk in enumerate(chunks): ctime0 = int(utils.mjd2ctime(mjd[chunk[0]] // args.dt * args.dt)) if only and ctime0 not in only: continue cdir = root + str(ctime0) if args.cont and os.path.exists(cdir + "/info.hdf"): continue #### 1. Distribute and read in all our scans chunk_ids = ids[chunk] chunk_mjd = mjd[chunk] L.info("Scanning chunk %3d/%d with %4d tods from %s" % (ci + 1, len(chunks), len(chunk), ids[chunk[0]])) myinds = np.arange(len(chunk))[comm.rank::comm.size] myinds, myscans = scanutils.read_scans( chunk_ids, myinds, actscan.ACTScan, filedb.data, downsample=config.get("downsample"))
continue else: print(f"found {len(sids)} sources") # insert source into tod entry = filedb.data[id] try: scan = actscan.ACTScan(entry, verbose=verbose>=2) if scan.ndet < 2 or scan.nsamp < 1: raise errors.DataMissing("no data in tod") except errors.DataMissing as e: print("%s skipped: %s" % (id, e)) continue scan = scan[:,::down] scan.tod = scan.get_samples() # build source lists # ra, dec, T, Q, U, omg, phi t0 = u.mjd2ctime(scan.mjd0) phi0 = np.mod(phi+t0*omg, 2*np.pi) srcs = np.array([srcpos[0], srcpos[1], amps, amps*0, amps*0, omg, phi0, D]) # srcs = np.array([srcpos[0], srcpos[1], amps, amps*0, amps*0]) # build pointing matrix P = lib.PmatTotVar(scan, srcs, perdet=False, sys=sys) # P = lib.PmatTot(scan, srcpos[:,sids], perdet=False, sys=sys) # project pulsar into the given tod # prepare source parameter: [T,Q,U,omega_c,phi_c] tod = P.forward(scan.tod*0, amps) # scan.tod = P.forward(scan.tod*0, amps) # plot tod for debugging if 1: sel = slice(70350,70850) plt.figure() plt.plot(tod[:,sel].T, 'k-', alpha=0.5)