Esempio n. 1
0
 def solve(self, maxiter=100, cg_tol=1e-7, verbose=False, dump_dir=None):
     if np.sum(self.highres_mask) == 0: return None
     solver = cg.CG(self.A, self.rhs.reshape(-1), M=self.M)
     for i in range(maxiter):
         t1 = time.time()
         solver.step()
         t2 = time.time()
         if verbose:
             print "%5d %15.7e %5.2f" % (solver.i, solver.err, t2 - t1)
         if dump_dir is not None and solver.i in [1, 2, 5, 10, 20, 50
                                                  ] + range(
                                                      100, 10000, 100):
             m = enmap.ndmap(solver.x.reshape(self.shape), self.wcs)
             enmap.write_map(dump_dir + "/step%04d.fits" % solver.i, m)
         if solver.err < cg_tol:
             if dump_dir is not None:
                 m = enmap.ndmap(solver.x.reshape(self.shape), self.wcs)
                 enmap.write_map(dump_dir + "/step_final.fits", m)
             break
     tot_map = self.highres_mask * solver.x.reshape(self.shape)
     tot_div = self.highres_mask * self.tot_div
     # Get rid of the fourier padding
     ny, nx = tot_map.shape[-2:]
     tot_map = tot_map[..., :ny - self.ffpad[0], :nx - self.ffpad[1]]
     tot_div = tot_div[..., :ny - self.ffpad[0], :nx - self.ffpad[1]]
     return bunch.Bunch(map=tot_map, div=tot_div)
Esempio n. 2
0
def calc_model_constrained(tod,
                           cut,
                           srate=400,
                           mask_scale=0.3,
                           lim=3e-4,
                           maxiter=50,
                           verbose=False):
    # First do some simple gapfilling to avoid messing up the noise model
    tod = sampcut.gapfill_linear(cut, tod, inplace=False)
    ft = fft.rfft(tod) * tod.shape[1]**-0.5
    iN = nmat_measure.detvecs_jon(ft, srate)
    del ft
    iV = iN.ivar * mask_scale

    def A(x):
        x = x.reshape(tod.shape)
        Ax = iN.apply(x.copy())
        Ax += sampcut.gapfill_const(cut, x * iV[:, None], 0, inplace=True)
        return Ax.reshape(-1)

    b = sampcut.gapfill_const(cut, tod * iV[:, None], 0,
                              inplace=True).reshape(-1)
    x0 = sampcut.gapfill_linear(cut, tod).reshape(-1)
    solver = cg.CG(A, b, x0)
    while solver.i < maxiter and solver.err > lim:
        solver.step()
        if verbose:
            print("%5d %15.7e" % (solver.i, solver.err))
    res = solver.x.reshape(tod.shape)
    res = smooth(res, srate)
    return res
Esempio n. 3
0
File: gibbs.py Progetto: jit9/enlib
    def solve(self, b, x0=None, verbose=False):
        """Solves the equation system (S"+N")x = b. This is done in
		a single step if S and N are in the same domain. Otherwise,
		conjugate gradients is used."""
        mode = self.mode.lower()
        if mode[0] == mode[1]:
            # Can solve directly
            return self.M(b)
        else:
            if x0 is None: x0 = b * 0
            dof = DOF(Arg(default=self.d))

            def wrap(fun):
                return lambda x: dof.zip(fun(*dof.unzip(x)))

            solver = cg.CG(wrap(self.A),
                           dof.zip(b),
                           x0=dof.zip(x0),
                           M=wrap(self.M))
            for i in range(50):
                #while solver.err > 1e-6:
                #while solver.err_true > 10:
                solver.step()
                if verbose:
                    print "%5d %15.7e %15.7e" % (solver.i, solver.err,
                                                 solver.err_true)
            return dof.unzip(solver.x)[0]
Esempio n. 4
0
 def cgsolve(Afun,
             rhs,
             x0=None,
             Mfun=None,
             tol=1e-14,
             maxiter=1000000,
             miniter=0,
             callback=None):
     if Mfun is None: Mfun = cg.default_M
     solver = cg.CG(Afun, rhs, x0=x0, M=Mfun)
     for i in range(maxiter):
         solver.step()
         if callback: callback(solver.err, solver.x)
         if solver.err < tol and i > miniter: break
     return solver.x
Esempio n. 5
0
            del tod
        omap = utils.allreduce(omap, comm)
        return np.concatenate([omap.reshape(-1), ojunk], 0)

    def M(x):
        map = x[:area.size].reshape(area.shape)
        junk = x[area.size:]
        omap = map * 0
        omap[:] = enmap.map_mul(idiv, map)
        ojunk = junk / jdiv
        return np.concatenate([omap.reshape(-1), ojunk], 0)

    def dot(x, y):
        mprod = np.sum(x[:area.size] * y[:area.size])
        jprod = np.sum(x[area.size:] * y[area.size:])
        return mprod + comm.allreduce(jprod)

    bin = enmap.map_mul(idiv, cg_rhs)
    enmap.write_map(args.odir + "/map_bin.fits", bin)

    b = np.concatenate([cg_rhs.reshape(-1), cg_rjunk], 0)
    solver = cg.CG(A, b, M=M, dot=dot)
    for i in range(nstep):
        solver.step()
        if comm.rank == 0:
            print "%5d %15.7e" % (solver.i, solver.err)
            if solver.i % args.ostep == 0:
                map = enmap.samewcs(solver.x[:area.size].reshape(area.shape),
                                    area)
                enmap.write_map(args.odir + "/map%04d.fits" % solver.i, map)
Esempio n. 6
0
def coadd_tile_data(datasets,
                    box,
                    odir,
                    ps_smoothing=10,
                    pad=0,
                    ref_beam=None,
                    cg_tol=1e-6,
                    dump=False,
                    verbose=False,
                    read_cache=False,
                    write_cache=False,
                    div_max_tol=100,
                    div_div_tol=1e-10):
    # Load data for this box for each dataset
    datasets, ffpad = read_data(datasets,
                                box,
                                odir,
                                pad=pad,
                                verbose=verbose,
                                read_cache=read_cache,
                                write_cache=write_cache)
    # We might not find any data
    if len(datasets) == 0: return None
    # Find the smallest beam size of the datasets
    bmin = np.min([beam_size(dataset.beam) for dataset in datasets])

    # Subtract mean map from each split to get noise maps. Our noise
    # model is HNH, where H is div**0.5 and N is the mean 2d noise spectrum
    # after some smoothing
    rhs, tot_div = None, None
    tot_iN, tot_udiv = None, 0
    for dataset in datasets:
        nsplit = 0
        dset_map, dset_div = None, None
        for split in dataset.splits:
            if dset_map is None:
                dset_map = split.data.map * 0
                dset_div = split.data.div * 0
            dset_map += split.data.map * split.data.div
            dset_div += split.data.div
        # Form the mean map for this dataset
        dset_map[:, dset_div > 0] /= dset_div[dset_div > 0]
        if tot_div is None: tot_div = dset_div * 0
        tot_div += dset_div
        tshape, twcs, tdtype = dset_map.shape, dset_div.wcs, dset_div.dtype
        # Then use it to build the diff maps and noise spectra
        dset_ps = None
        for split in dataset.splits:
            if split.data.empty: continue
            diff = split.data.map - dset_map
            wdiff = diff * split.data.H
            # What is the healthy area of wdiff? Wdiff should have variance
            # 1 or above. This tells us how to upweight the power spectrum
            # to take into account missing regions of the diff map.
            ndown = 10
            wvar = enmap.downgrade(wdiff**2, ndown)
            goodfrac = np.sum(wvar > 1e-3) / float(wvar.size)
            if goodfrac < 0.1: goodfrac = 0
            #opre  = odir + "/" + os.path.basename(split.map)[:-5]
            #enmap.write_map(opre + "_diff.fits", diff)
            #enmap.write_map(opre + "_wdiff.fits", wdiff)
            #enmap.write_map(opre + "_wvar.fits", wvar)
            ps = np.abs(map_fft(wdiff))**2
            #enmap.write_map(opre + "_ps1.fits", ps)
            # correct for unhit areas, which can't be whitened
            #print "A", dataset.name, np.median(ps[ps>0]), medloop(ps), goodfrac
            with utils.nowarn():
                ps /= goodfrac
            #print "B", dataset.name, np.median(ps[ps>0]), medloop(ps), goodfrac
            #enmap.write_map(opre + "_ps2.fits", ps)
            #enmap.write_map(opre + "_ps2d.fits", ps)
            if dset_ps is None:
                dset_ps = enmap.zeros(ps.shape, ps.wcs, ps.dtype)
            dset_ps += ps
            nsplit += 1
        if nsplit < 2: continue
        # With n splits, mean map has var 1/n, so diff has var (1-1/n) + (n-1)/n = 2*(n-1)/n
        # Hence tot-ps has var 2*(n-1)
        dset_ps /= 2 * (nsplit - 1)
        #enmap.write_map(opre + "_ps2d_tot.fits", dset_ps)
        dset_ps = smooth_pix(dset_ps, ps_smoothing)
        #enmap.write_map(opre + "_ps2d_smooth.fits", dset_ps)
        if np.all(np.isfinite(dset_ps)):
            # Super-low values of the spectrum are not realistic. These appear
            # due to beam/pixel smoothing in the planck maps. This will be
            # mostly taken care of when processing the beams, as long as we don't
            # let them get too small
            dset_ps = np.maximum(dset_ps, 1e-7)
            # Optionally cap the max dset_ps, this is mostly to speed up convergence
            if args.max_ps:
                dset_ps = np.minimum(dset_ps, args.max_ps)

            # Our fourier-space inverse noise matrix is based on the inverse noise spectrum
            iN = 1 / dset_ps
            #enmap.write_map(opre + "_iN_raw.fits", iN)
        else:
            print "Setting weight of dataset %s to zero" % dataset.name
            #print np.all(np.isfinite(dset_ps)), np.all(dset_ps>0)
            iN = enmap.zeros(dset_ps.shape, dset_ps.wcs, dset_ps.dtype)

        # Add any fourier-space masks to this
        ly, lx = enmap.laxes(tshape, twcs)
        lr = (ly[:, None]**2 + lx[None, :]**2)**0.5
        if dataset.highpass:
            kxmask = butter(lx, args.kxrad, -3)
            kxmask = 1 - (1 - kxmask[None, :]) * (
                np.abs(ly) < bmin * args.kx_ymax_scale)[:, None]
            highpass = butter(lr, args.highpass, -10)
            filter = highpass * kxmask
            #print "filter weighting", dataset.name
            del kxmask, highpass
        else:
            filter = 1

        if not args.filter: iN *= filter

        # We should deconvolve the relative beam from the maps,
        # but that's numerically nasty. But it can be handled
        # inversely. We want (BiNB + ...)x = (BiNB iB m + ...)
        # where iB is the beam deconvolution operation in map space.
        # Instead of actually doing that operation, we can compute two
        # inverse noise matrixes: iN_A = BiNB for the left hand
        # side and iN_b = BiN for the right hand side. That way we
        # avoid dividing by any huge numbers.

        # Add the relative beam
        iN_A = iN.copy()
        iN_b = iN.copy()
        if ref_beam is not None:
            rel_beam = beam_ratio(dataset.beam, ref_beam)
            bspec = eval_beam(rel_beam, lr)
            iN_A *= bspec**2
            iN_b *= bspec
        #moo = iN*0+filter
        #enmap.write_map(opre + "_filter.fits", moo)
        # Add filter to noise model if we're downweighting
        # rather than filtering.
        dataset.iN_A = iN_A
        dataset.iN_b = iN_b
        dataset.filter = filter
        #print "A", opre
        #enmap.write_map(opre + "_iN_A.fits", iN_A)
        #enmap.write_map(opre + "_iN.fits", iN)

    # Cap to avoid single crazy pixels
    tot_div = np.maximum(tot_div, np.median(tot_div[tot_div > 0]) * 0.01)
    tot_idiv = tot_div * 0
    tot_idiv[tot_div > div_div_tol] = 1 / tot_div[tot_div > div_div_tol]

    # Build the right-hand side. The right-hand side is
    # sum(HNHm)
    if rhs is None: rhs = enmap.zeros(tshape, twcs, tdtype)
    for dataset in datasets:
        i = 0
        for split in dataset.splits:
            if split.data.empty: continue
            #print "MOO", dataset.name, np.max(split.data.map), np.min(split.data.map), np.max(split.data.div), np.min(split.data.div)
            w = split.data.H * split.data.map
            fw = map_fft(w)
            fw *= dataset.iN_b
            if args.filter: fw *= dataset.filter
            w = map_ifft(fw) * split.data.H
            #enmap.write_map(odir + "/%s_%02d_rhs.fits" % (dataset.name, i), w)
            rhs += w
            i += 1
    del w, iN, iN_A, iN_b, filter

    # Now solve the equation
    def A(x):
        global times
        m = enmap.samewcs(x.reshape(rhs.shape), rhs)
        res = m * 0
        times[:] = 0
        ntime = 0
        for dataset in datasets:
            for split in dataset.splits:
                if split.data.empty: continue
                t = [time.time()]
                w = split.data.H * m
                t.append(time.time())
                fw = map_fft(w)
                t.append(time.time())
                fw *= dataset.iN_A
                t.append(time.time())
                w = map_ifft(fw)
                t.append(time.time())
                w *= split.data.H
                t.append(time.time())
                res += w
                for i in range(1, len(t)):
                    times[i - 1] += t[i] - t[i - 1]
                ntime += 1
                #w  = enmap.harm2map(dataset.iN_A*enmap.map2harm(w))
                #w *= split.data.H
                #res += w
                del w
        times /= ntime
        return res.reshape(-1)

    def M(x):
        m = enmap.samewcs(x.reshape(rhs.shape), rhs)
        res = m * tot_idiv
        return res.reshape(-1)

    solver = cg.CG(A, rhs.reshape(-1), M=M)
    for i in range(1000):
        t1 = time.time()
        solver.step()
        t2 = time.time()
        if verbose:
            print "%5d %15.7e %5.2f: %4.2f %4.2f %4.2f %4.2f %4.2f" % (
                solver.i, solver.err, t2 - t1, times[0], times[1], times[2],
                times[3], times[4]), np.std(solver.x)
        if dump and solver.i in [1, 2, 5, 10, 20, 50] + range(100, 10000, 100):
            m = enmap.samewcs(solver.x.reshape(rhs.shape), rhs)
            enmap.write_map(odir + "/step%04d.fits" % solver.i, m)
        if solver.err < cg_tol:
            if dump:
                m = enmap.samewcs(solver.x.reshape(rhs.shape), rhs)
                enmap.write_map(odir + "/step_final.fits", m)
            break
    tot_map = enmap.samewcs(solver.x.reshape(rhs.shape), rhs)
    # Get rid of the fourier padding
    ny, nx = tot_map.shape[-2:]
    tot_map = tot_map[..., :ny - ffpad[0], :nx - ffpad[1]]
    tot_div = tot_div[..., :ny - ffpad[0], :nx - ffpad[1]]
    return bunch.Bunch(map=tot_map, div=tot_div)