Example #1
0
    def setUp(self):
        self.imgVal1, self.varVal1 = 100.0, 10.0
        self.imgVal2, self.varVal2 = 200.0, 15.0
        self.mimage = afwImage.MaskedImageF(100, 200)

        self.mimage.getImage().set(self.imgVal1)
        #
        # Set center of mask to 0, with 2 pixel border set to EDGE
        #
        self.BAD = afwImage.MaskU_getPlaneBitMask("BAD")
        self.EDGE = afwImage.MaskU_getPlaneBitMask("EDGE")

        self.mimage.getMask().set(self.EDGE)
        centre = afwImage.MaskU(
            self.mimage.getMask(),
            afwGeom.Box2I(afwGeom.Point2I(2, 2),
                          self.mimage.getDimensions() - afwGeom.Extent2I(4)),
            afwImage.LOCAL)
        centre.set(0x0)
        #
        self.mimage.getVariance().set(self.varVal1)
        #
        # Second MaskedImage
        #
        self.mimage2 = afwImage.MaskedImageF(self.mimage.getDimensions())
        self.mimage2.getImage().set(self.imgVal2)
        self.mimage2.getVariance().set(self.varVal2)
        #
        # a Function2
        #
        self.function = afwMath.PolynomialFunction2D(2)
        self.function.setParameters(range(self.function.getNParameters()))
    def get_inverse_variance(self, masked_image):
        mask_bits = afwImage.MaskU_getPlaneBitMask("BAD")
        mask_bits = mask_bits | afwImage.MaskU_getPlaneBitMask("CR")
        mask_bits = mask_bits | afwImage.MaskU_getPlaneBitMask("INTRP")

        iv_img = afwImage.ImageD(masked_image.getWidth(),
                                 masked_image.getHeight())
        iv_img.setXY0(masked_image.getXY0())

        iv_img.getArray()[:, :] = np.where(
            (masked_image.getMask().getArray() & mask_bits) == 0,
            1.0 / masked_image.getVariance().getArray(), 0.0)

        return iv_img
    def __init__(self, config):
        self.config = config

        self.bitMask = 0
        srcBadMaskPlanes = self.config.srcBadMaskPlanes
        for maskPlane in srcBadMaskPlanes:
            self.bitMask |= afwImage.MaskU_getPlaneBitMask(maskPlane)
Example #4
0
    def testStackBadPixels(self):
        """Check that we properly ignore masked pixels, and set noGoodPixelsMask where there are
        no good pixels"""
        mimgVec = afwImage.vectorMaskedImageF()

        DETECTED = afwImage.MaskU_getPlaneBitMask("DETECTED")
        EDGE = afwImage.MaskU_getPlaneBitMask("EDGE")
        INTRP = afwImage.MaskU_getPlaneBitMask("INTRP")
        SAT = afwImage.MaskU_getPlaneBitMask("SAT")

        sctrl = afwMath.StatisticsControl()
        sctrl.setNanSafe(False)
        sctrl.setAndMask(INTRP | SAT)
        sctrl.setNoGoodPixelsMask(EDGE)

        edgeBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(
            20, 20))  # set these pixels to EDGE
        width, height = 512, 512
        dim = afwGeom.Extent2I(width, height)
        val, maskVal = 10, DETECTED
        for i in range(4):
            mimg = afwImage.MaskedImageF(dim)
            mimg.set(val, maskVal, 1)
            #
            # Set part of the image to NaN (with the INTRP bit set)
            #
            llc = afwGeom.Point2I(width // 2 * (i // 2), height // 2 * (i % 2))
            bbox = afwGeom.Box2I(llc, dim // 2)

            smimg = mimg.Factory(mimg, bbox, afwImage.LOCAL)
            del smimg
            #
            # And the bottom corner to SAT
            #
            smask = mimg.getMask().Factory(mimg.getMask(), edgeBBox,
                                           afwImage.LOCAL)
            smask |= SAT
            del smask

            mimgVec.push_back(mimg)

            if display > 1:
                ds9.mtv(mimg, frame=i, title=str(i))

        mimgStack = afwMath.statisticsStack(mimgVec, afwMath.MEAN, sctrl)

        if display:
            i += 1
            ds9.mtv(mimgStack, frame=i, title="Stack")
            i += 1
            ds9.mtv(mimgStack.getVariance(), frame=i, title="var(Stack)")
        #
        # Check the output, ignoring EDGE pixels
        #
        sctrl = afwMath.StatisticsControl()
        sctrl.setAndMask(afwImage.MaskU_getPlaneBitMask("EDGE"))

        stats = afwMath.makeStatistics(mimgStack, afwMath.MIN | afwMath.MAX,
                                       sctrl)
        self.assertEqual(stats.getValue(afwMath.MIN), val)
        self.assertEqual(stats.getValue(afwMath.MAX), val)
        #
        # We have to clear EDGE in the known bad corner to check the mask
        #
        smask = mimgStack.getMask().Factory(mimgStack.getMask(), edgeBBox,
                                            afwImage.LOCAL)
        self.assertEqual(smask.get(edgeBBox.getMinX(), edgeBBox.getMinY()),
                         EDGE)
        smask &= ~EDGE
        del smask

        self.assertEqual(
            afwMath.makeStatistics(mimgStack.getMask(), afwMath.SUM,
                                   sctrl).getValue(), maskVal)
    def fitPsf(self, psfCandidateList):
        print >> sys.stderr, 'FIXME: resolve issue of proper bitmask (also in evalPsfDeterminer?)'
        mask_bits = afwImage.MaskU_getPlaneBitMask("BAD")
        mask_bits = mask_bits | afwImage.MaskU_getPlaneBitMask("CR")
        mask_bits = mask_bits | afwImage.MaskU_getPlaneBitMask("INTRP")

        cs = hscpsfLib.HscCandidateSet(mask_bits, self.kernelSize,
                                       self.kernelSize)

        for (i, cand) in enumerate(psfCandidateList):
            cs.add(
                cand, i, 0.0, 0.0
            )  # FIXME use real values of flux/size here, for completeness

        # FIXME rethink this
        for i in xrange(cs.getNcand()):
            (x0, y0) = (cs.getX0(i), cs.getY0(i))
            cs.setXY(i, x0 + 0.5 * (cs.getNx() - 1),
                     y0 + 0.5 * (cs.getNy() - 1))

        clipPsf = hscpsfLib.HscClipPsf(cs, 15, 1.0)
        for n in xrange(5):
            clipPsf.optimize()

        cs = clipPsf.getTrimmedCandidateSet()

        gsPsf = hscpsfLib.HscGlobalSplinePsf(cs, 15, 1.0, 1.0)
        for n in xrange(5):
            gsPsf.optimize()

        for icand in xrange(gsPsf.getNcand()):
            if gsPsf.displacement_is_maximized(
                    icand) or gsPsf.gamma_is_maximized(
                        icand) or gsPsf.kappa_is_maximized(icand):
                gsPsf.setBad(icand)

        cs = gsPsf.getTrimmedCandidateSet()

        assert self.kernelSize % 2 == 1
        nside = (self.kernelSize - 1) // 2

        pcaPsf = hscpsfLib.HscPcaPsfNoSM(cs, nside,
                                         self.config.nEigenComponents,
                                         self.config.lanczosInterpolationOrder)
        for n in xrange(5):
            pcaPsf.optimize()

        if self.config.nEigenComponents > 1:
            xvec = [pcaPsf.getX(icand) for icand in xrange(pcaPsf.getNcand())]
            yvec = [pcaPsf.getY(icand) for icand in xrange(pcaPsf.getNcand())]

            spatialModel = hscpsfLib.HscSpatialModelPolynomial(
                self.config.spatialOrder, min(xvec), max(xvec), min(yvec),
                max(yvec))
            pcaPsf = hscpsfLib.HscPcaPsf(pcaPsf, spatialModel)

            for n in xrange(5):
                pcaPsf.optimize()

        # The next 2 loops mark bad candidates
        bad = np.ones(len(psfCandidateList), dtype=bool)
        for icand in xrange(cs.getNcand()):
            bad[cs.getId(icand)] = False

        for i in xrange(len(psfCandidateList)):
            status = afwMath.SpatialCellCandidate.BAD if bad[
                i] else afwMath.SpatialCellCandidate.UNKNOWN
            psfCandidateList[i].setStatus(status)

        return pcaPsf
Example #6
0
class PolypixPsfDeterminer(object):
    ConfigClass = PolypixPsfDeterminerConfig

    def __init__(self, config):
        """
        @param[in] config: instance of PolypixPsfDeterminerConfig
        """
        self.config = config
        # N.b. name of component is meas.algorithms.psfDeterminer so you can turn on psf debugging
        # independent of which determiner is active
        self.debugLog = pexLog.Debug("meas.algorithms.psfDeterminer")
        self.warnLog = pexLog.Log(pexLog.getDefaultLog(), "meas.algorithms.psfDeterminer")

    def determinePsf(self, exposure, psfCandidateList, metadata=None, flagKey=None):
        """
        @param[in] exposure: exposure containing the psf candidates (lsst.afw.image.Exposure)
        @param[in] psfCandidateList: a sequence of PSF candidates (each an lsst.meas.algorithms.PsfCandidate);
            typically obtained by detecting sources and then running them through a star selector
        @param[in,out] metadata  a home for interesting tidbits of information
        @param[in] flagKey: schema key used to mark sources actually used in PSF determination
    
        @return psf
        """

        import lsstDebug
        display = lsstDebug.Info(__name__).display 
        displayExposure = display and \
            lsstDebug.Info(__name__).displayExposure     # display the Exposure + spatialCells 
        displayPsfCandidates = display and \
            lsstDebug.Info(__name__).displayPsfCandidates # show the viable candidates 
        displayPsfComponents = display and \
            lsstDebug.Info(__name__).displayPsfComponents # show the basis functions
        showBadCandidates = display and \
            lsstDebug.Info(__name__).showBadCandidates # Include bad candidates (meaningless, methinks)
        displayResiduals = display and \
            lsstDebug.Info(__name__).displayResiduals         # show residuals
        displayPsfMosaic = display and \
            lsstDebug.Info(__name__).displayPsfMosaic   # show mosaic of reconstructed PSF(x,y)
        matchKernelAmplitudes = lsstDebug.Info(__name__).matchKernelAmplitudes # match Kernel amplitudes for spatial plots
        normalizeResiduals = lsstDebug.Info(__name__).normalizeResiduals # Normalise residuals by object amplitude 

        mi = exposure.getMaskedImage()
        
        nCand = len(psfCandidateList)
        if nCand == 0:
            raise RuntimeError("No PSF candidates supplied.")

        #
        # How big should our PSF models be?
        #
        if display:                     # only needed for debug plots
            # construct and populate a spatial cell set
            bbox = mi.getBBox(afwImage.PARENT)
            psfCellSet = afwMath.SpatialCellSet(bbox, self.config.sizeCellX, self.config.sizeCellY)
        else:
            psfCellSet = None
        
        sizes = np.empty(nCand)
        for i, psfCandidate in enumerate(psfCandidateList):
            try:
                if psfCellSet:
                    psfCellSet.insertCandidate(psfCandidate)
            except Exception, e:
                self.debugLog.debug(2, "Skipping PSF candidate %d of %d: %s" % (i, len(psfCandidateList), e))
                continue

            source = psfCandidate.getSource()
            quad = afwEll.Quadrupole(source.getIxx(), source.getIyy(), source.getIxy())
            rmsSize = quad.getTraceRadius()
            sizes[i] = rmsSize

        if self.config.kernelSize >= 15:
            self.debugLog.debug(1, \
                "WARNING: NOT scaling kernelSize by stellar quadrupole moment, but using absolute value")
            actualKernelSize = int(self.config.kernelSize)
        else:
            actualKernelSize = 2 * int(self.config.kernelSize * np.sqrt(np.median(sizes)) + 0.5) + 1
            if actualKernelSize < self.config.kernelSizeMin:
                actualKernelSize = self.config.kernelSizeMin
            if actualKernelSize > self.config.kernelSizeMax:
                actualKernelSize = self.config.kernelSizeMax
            if display:
                rms = np.median(sizes)
                print "Median PSF RMS size=%.2f pixels (\"FWHM\"=%.2f)" % (rms, 2*np.sqrt(2*np.log(2))*rms)

        # If we manually set the resolution then we need the size in pixel units
        pixKernelSize = actualKernelSize
        if self.config.samplingSize > 0:
            pixKernelSize = int(actualKernelSize*self.config.samplingSize)
            if pixKernelSize % 2 == 0: pixKernelSize += 1 
        self.debugLog.debug(3, "PSF Kernel size=%.2f, Image Kernel Size=%.2f" % 
                            (actualKernelSize,pixKernelSize))

        nside = pixKernelSize // 2
        assert pixKernelSize == (2*nside+1)

        # Set size of image returned around candidate
        psfCandidateList[0].setHeight(pixKernelSize)
        psfCandidateList[0].setWidth(pixKernelSize)

        mask_bits = afwImage.MaskU_getPlaneBitMask(self.config.badMaskBits)            
        fluxName = 'initial.flux.sinc'    # FIXME should be in config? (meas_extensions_psfex has it in a config file)
        fluxFlagName = fluxName + ".flags"

        cs = hscpsfLib.HscCandidateSet(mask_bits, pixKernelSize, pixKernelSize)

        with ds9.Buffering():
            xpos = []; ypos = []
            for i, psfCandidate in enumerate(psfCandidateList):
                source = psfCandidate.getSource()
                xc, yc = source.getX(), source.getY()

                if fluxFlagName in source.schema and source.get(fluxFlagName):
                    continue

                flux = source.get(fluxName)
                if flux < 0 or np.isnan(flux):
                    continue

                cs.add(psfCandidate, i, flux, sizes[i])

                xpos.append(xc); ypos.append(yc) # for QA

                if displayExposure:
                    ds9.dot("o", xc, yc, ctype=ds9.CYAN, size=4, frame=frame)

        if cs.getNcand() == 0:
            raise RuntimeError("No good PSF candidates")

        # Calculate fwhm, backnoise2 and gain
        fwhm = 2*np.sqrt(2*np.log(2))*np.median(sizes)
        backnoise2 = afwMath.makeStatistics(mi.getImage(), afwMath.VARIANCECLIP).getValue()
        ccd = afwCG.cast_Ccd(exposure.getDetector())
        if ccd:
            gain = np.mean(np.array([a.getElectronicParams().getGain() for a in ccd]))
        else:
            gain = 1.0
            self.warnLog.log(pexLog.Log.WARN, "Setting gain to %g" % gain)

        xvec = np.array([ cand.getSource().get('initial.centroid.sdss.x') for cand in psfCandidateList ])
        yvec = np.array([ cand.getSource().get('initial.centroid.sdss.y') for cand in psfCandidateList ])
        spatialModel = hscpsfLib.HscSpatialModelPolynomial(self.config.spatialOrder, min(xvec), max(xvec), min(yvec), max(yvec))

        #
        # This sequence of PSF fits, including "magic numbers" such as psf_make(0.2, 1000.0)
        # matches internal logic in psfex!
        #
        psf = hscpsfLib.PolypixPsf(cs, nside, actualKernelSize, self.config.samplingSize, spatialModel, fwhm, backnoise2, gain)
        psf.psf_make(0.2, 1000.0)
        cs = psf.psf_clean(0.2)

        psf = hscpsfLib.PolypixPsf(cs, psf)
        psf.psf_make(0.1, 1000.0)
        cs = psf.psf_clean(0.1)

        psf = hscpsfLib.PolypixPsf(cs, psf)
        psf.psf_make(0.05, 1000.0)
        cs = psf.psf_clean(0.05)

        psf = hscpsfLib.PolypixPsf(cs, psf)
        psf.psf_make(0.01, 1000.0)
        psf.psf_clip()
        cs = psf.psf_clean(0.01)

        good_indices = [ cs.getId(icand) for icand in xrange(cs.getNcand()) ]
        if flagKey is not None:
            for (icand, cand) in enumerate(psfCandidateList):
                if icand in good_indices:
                    cand.getSource().set(flagKey, True)

        numGoodStars = len(good_indices)
        avgX, avgY = np.mean(xpos), np.mean(ypos)

        #
        # Generate some QA information
        #
        # Count PSF stars
        #
        if metadata != None:
            metadata.set("spatialFitChi2", np.nan)
            metadata.set("numAvailStars", nCand)
            metadata.set("numGoodStars", numGoodStars)
            metadata.set("avgX", avgX)
            metadata.set("avgY", avgY)

        psfCellSet = None
        return psf, psfCellSet
 def countDetected(self, mask):
     idxP = num.where(mask & afwImage.MaskU_getPlaneBitMask("DETECTED"))
     idxN = num.where(mask
                      & afwImage.MaskU_getPlaneBitMask("DETECTED_NEGATIVE"))
     return len(idxP[0]), len(idxN[0])