示例#1
0
 def setUp(self):
     random.seed(0)
     self.ImageSet = afwImage.ImagePcaF()
示例#2
0
def imagePca(mosaics,
             visits=None,
             nComponent=3,
             log=False,
             rng=30,
             showEigen=True,
             showResiduals=False,
             showOriginal=True,
             showRecon=False,
             normalizeEimages=True,
             scale=False,
             frame0=0,
             verbose=False):

    if showOriginal and showRecon:
        raise RuntimeError(
            "You may not specify both showOriginal and showRecon")

    try:
        rng[0]
    except TypeError:
        rng = [rng, rng]

    if not visits:
        visits = sorted(mosaics.keys())

    mosaics = mosaics.copy()
    for v in visits:
        mosaics[v] = mosaics[v].clone()

    pca = afwImage.ImagePcaF()
    mask = None
    for v in visits:
        im = mosaics[v]
        if not mask:
            mask = im.Factory(im.getDimensions())
            maska = mask.getArray()
            X, Y = np.meshgrid(np.arange(mask.getWidth()),
                               np.arange(mask.getHeight()))
            maska[np.where(np.hypot(X - 571, Y - 552) > 531)] = np.nan
            del maska

            mask[168:184, 701:838] = np.nan
            mask[667:733, 420:556] = np.nan
            mask[653:677, 548:570] = np.nan
            mask[1031:1047, 274:414] = np.nan

            if False:
                mask[866:931, 697:828] = np.nan
                mask[267:334, 145:276] = np.nan

        im += mask

        pca.addImage(im, afwMath.makeStatistics(im, afwMath.SUM).getValue())
    pca.analyze()

    eValues = np.array(pca.getEigenValues())
    eValues /= eValues[0]
    eImages = pca.getEigenImages()
    #
    # Fiddle eigen images (we don't care about orthogonality)
    #
    if False:
        f10 = 0.1
        f20 = -0.3
        f30 = 0.55
        eImages[1].getArray()[:] += f10 * eImages[0].getArray()
        eImages[2].getArray()[:] += f20 * eImages[0].getArray()
        eImages[3].getArray()[:] += f30 * eImages[0].getArray()

    if nComponent:
        eImages = eImages[:nComponent]
    else:
        nComponent = len(eImages)
    #
    # Normalize
    #
    good = np.where(np.isfinite(eImages[0].getArray()))
    if normalizeEimages:
        for eim in eImages:
            eima = eim.getArray()
            eima /= 1e-3 * np.sqrt(np.sum(eima[good]**2))
    #
    # Plot/display eigen values/images
    #
    frame = frame0
    if showEigen:
        for i in range(len(eImages)):
            ds9.mtv(eImages[i], frame=frame, title="%d %.2g" % (i, eValues[i]))
            ds9.ds9Cmd("scale linear; scale mode zscale")
            frame += 1

        pyplot.clf()
        if log:
            eValues = np.log10(eValues)
        pyplot.plot(eValues)
        pyplot.plot(eValues, marker='o')
        pyplot.xlim(-0.5, len(eValues))
        pyplot.ylim(max(-5, pyplot.ylim()[0]), 0.05 if log else 1.05)
        pyplot.xlabel("n")
        pyplot.ylabel(r"$lg(\lambda)$" if log else r"$\lambda$")
        pyplot.show()

    if showOriginal or showRecon or showResiduals:
        #
        # Expand input images in the (modified) eImages
        #
        A = np.empty(nComponent * nComponent).reshape((nComponent, nComponent))
        b = np.empty(nComponent)
        for v in visits:
            im = mosaics[v]
            if scale:
                im /= afwMath.makeStatistics(im, afwMath.MEANCLIP).getValue()

            for i in range(nComponent):
                b[i] = np.dot(eImages[i].getArray()[good], im.getArray()[good])

                for j in range(i, nComponent):
                    A[i, j] = np.dot(eImages[i].getArray()[good],
                                     eImages[j].getArray()[good])
                    A[j, i] = A[i, j]

            x = np.linalg.solve(A, b)
            #print v, A, b, x
            print "%d [%s] %s" % (v, ", ".join(["%9.2e" % _ for _ in x / x[0]
                                                ]), labels.get(v, ""))

            recon = eImages[0].clone()
            recon *= x[0]
            recona = recon.getArray()
            for i in range(1, nComponent):
                recona += x[i] * eImages[i].getArray()

            mtv = True
            if showOriginal or showRecon:
                if mtv:
                    ds9.mtv(im if showOriginal else recon,
                            frame=frame,
                            title=v)
                else:
                    ds9.erase(frame=frame)
                s0 = afwMath.makeStatistics(recon, afwMath.MEDIAN).getValue()
                s0 -= 0.5 * rng[0]
                ds9.ds9Cmd("scale linear; scale limits %g %g" %
                           (s0, s0 + rng[0]),
                           frame=frame)
                ds9.dot("%s %d" % ("orig" if showOriginal else "resid", v),
                        int(0.5 * im.getWidth()),
                        int(0.15 * im.getHeight()),
                        frame=frame,
                        ctype=ds9.RED)
                if labels.has_key(v):
                    ds9.dot(labels[v],
                            int(0.5 * im.getWidth()),
                            int(0.85 * im.getHeight()),
                            frame=frame,
                            ctype=ds9.RED)

                frame += 1

            if showResiduals:
                recon -= im
                if mtv:
                    ds9.mtv(recon, frame=frame)
                else:
                    ds9.erase(frame=frame)
                s0 = 0
                s0 -= 0.5 * rng[1]
                ds9.ds9Cmd("scale linear; scale limits %g %g" %
                           (s0, s0 + rng[1]),
                           frame=frame)

                frame += 1

    return eImages