Пример #1
0
    def addSnaps(self, snap0, snap1):
        """Add two snap exposures together, returning a new exposure

        @param[in] snap0 snap exposure 0
        @param[in] snap1 snap exposure 1
        @return combined exposure
        """
        self.log.info("snapCombine addSnaps")

        combinedExp = snap0.Factory(snap0, True)
        combinedMi = combinedExp.getMaskedImage()
        combinedMi.set(0)

        weightMap = combinedMi.getImage().Factory(combinedMi.getBBox())
        weight = 1.0
        badPixelMask = afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
        addToCoadd(combinedMi, weightMap, snap0.getMaskedImage(), badPixelMask, weight)
        addToCoadd(combinedMi, weightMap, snap1.getMaskedImage(), badPixelMask, weight)

        # pre-scaling the weight map instead of post-scaling the combinedMi saves a bit of time
        # because the weight map is a simple Image instead of a MaskedImage
        weightMap *= 0.5  # so result is sum of both images, instead of average
        combinedMi /= weightMap
        setCoaddEdgeBits(combinedMi.getMask(), weightMap)

        # note: none of the inputs has a valid PhotoCalib object, so that is not touched
        # Filter was already copied

        combinedMetadata = combinedExp.getMetadata()
        metadata0 = snap0.getMetadata()
        metadata1 = snap1.getMetadata()
        self.fixMetadata(combinedMetadata, metadata0, metadata1)

        return combinedExp
Пример #2
0
 def testAssertions(self):
     """Test that addToCoadd requires coadd and weightMap to have the same dimensions and xy0"""
     maskedImage = afwImage.MaskedImageF(geom.Extent2I(10, 10))
     coadd = afwImage.MaskedImageF(geom.Extent2I(11, 11))
     coadd.setXY0(5, 6)
     for dw, dh in (1, 0), (0, 1), (-1, 0), (0, -1):
         weightMapBBox = geom.Box2I(
             coadd.getXY0(),
             coadd.getDimensions() + geom.Extent2I(dw, dh))
         weightMap = afwImage.ImageF(weightMapBBox)
         weightMap.setXY0(coadd.getXY0())
         try:
             coaddUtils.addToCoadd(coadd, weightMap, maskedImage, 0x0, 0.1)
             self.fail("should have raised exception")
         except pexExcept.Exception:
             pass
     for dx0, dy0 in (1, 0), (0, 1), (-1, 0), (0, -1):
         weightMapBBox = geom.Box2I(
             coadd.getXY0() + geom.Extent2I(dx0, dy0),
             coadd.getDimensions())
         weightMap = afwImage.ImageF(weightMapBBox)
         try:
             coaddUtils.addToCoadd(coadd, weightMap, maskedImage, 0x0, 0.1)
             self.fail("should have raised exception")
         except pexExcept.Exception:
             pass
Пример #3
0
    def addSnaps(self, snap0, snap1):
        """Add two snap exposures together, returning a new exposure
        
        @param[in] snap0 snap exposure 0
        @param[in] snap1 snap exposure 1
        @return combined exposure
        """
        self.log.info("snapCombine addSnaps")
        
        combinedExp = snap0.Factory(snap0, True)
        combinedMi = combinedExp.getMaskedImage()
        combinedMi.set(0)
        
        weightMap = combinedMi.getImage().Factory(combinedMi.getBBox(afwImage.PARENT))
        weight = 1.0
        badPixelMask = afwImage.MaskU.getPlaneBitMask(self.config.badMaskPlanes)
        addToCoadd(combinedMi, weightMap, snap0.getMaskedImage(), badPixelMask, weight)
        addToCoadd(combinedMi, weightMap, snap1.getMaskedImage(), badPixelMask, weight)

        # pre-scaling the weight map instead of post-scaling the combinedMi saves a bit of time
        # because the weight map is a simple Image instead of a MaskedImage
        weightMap *= 0.5 # so result is sum of both images, instead of average
        combinedMi /= weightMap
        setCoaddEdgeBits(combinedMi.getMask(), weightMap)
        
        # note: none of the inputs has a valid Calib object, so that is not touched
        # Filter was already copied
        
        combinedMetadata = combinedExp.getMetadata()
        metadata0 = snap0.getMetadata()
        metadata1 = snap1.getMetadata()
        self.fixMetadata(combinedMetadata, metadata0, metadata1)
        
        return combinedExp
Пример #4
0
    def _testAddToCoaddImpl(self, useMask, uniformWeight=True):
        """Test coadd"""

        trueImageValue = 10.0
        imBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(10, 20))
        if useMask:
            coadd = afwImage.MaskedImageF(imBBox)
            weightMap = coadd.getImage().Factory(coadd.getBBox())

            badBits = 0x1
            badPixel = (float("NaN"), badBits, 0)
            truth = (trueImageValue, 0x0, 0)
        else:
            coadd = afwImage.ImageF(imBBox)
            weightMap = coadd.Factory(coadd.getBBox())

            badPixel = float("NaN")
            truth = trueImageValue

        for i in range(0, 20, 3):
            image = coadd.Factory(coadd.getDimensions())
            image.set(badPixel)

            subBBox = afwGeom.Box2I(
                afwGeom.Point2I(0, i),
                image.getDimensions() - afwGeom.Extent2I(0, i))
            subImage = image.Factory(image, subBBox, afwImage.LOCAL)
            subImage.set(truth)
            del subImage

            weight = 1.0 if uniformWeight else 1.0 + 0.1 * i
            if useMask:
                coaddUtils.addToCoadd(coadd, weightMap, image, badBits, weight)
            else:
                coaddUtils.addToCoadd(coadd, weightMap, image, weight)

            self.assertEqual(
                image.get(image.getWidth() - 1,
                          image.getHeight() - 1), truth)

        coadd /= weightMap

        if display:
            ds9.mtv(image, title="image", frame=1)
            ds9.mtv(coadd, title="coadd", frame=2)
            ds9.mtv(weightMap, title="weightMap", frame=3)

        stats = afwMath.makeStatistics(coadd, afwMath.MEAN | afwMath.STDEV)

        return [
            trueImageValue,
            stats.getValue(afwMath.MEAN), 0.0,
            stats.getValue(afwMath.STDEV)
        ]
    def process(self, clipboard):
        """
        Combine two Exposures, omitting any pixels in either positiveDetection or negativeDetection
        """
        self.log.log(Log.INFO, "Combining two Exposures in process")

        #grab exposure from clipboard
        exposures = []
        for k in self.policy.getArray("inputKeys.exposures"):
            exposures.append(clipboard.get(k))
        assert len(exposures) == 2
        badPixelMask = 0x0

        mi0 = exposures[0].getMaskedImage()
        combined = mi0.Factory(mi0.getDimensions())
        combined.setXY0(mi0.getXY0())
        del mi0
        weightMap = combined.getImage().Factory(combined.getDimensions())
        weightMap.setXY0(combined.getXY0())

        for i in range(0, 2):
            e = exposures[i]
            #
            # Get the FootprintSet associated with object that are only in this Exposure
            #
            if i == 0:
                footprintKey = "positiveDetection"
            else:
                footprintKey = "negativeDetection"

            fs = clipboard.get(self.policy.get("inputKeys.%s" % footprintKey))

            mi = e.getMaskedImage()
            fs.setMask(mi.getMask(), "CR")
            fs.setMask(combined.getMask(), "CR")

            coaddUtils.addToCoadd(combined, weightMap, mi,
                                  mi.getMask().getPlaneBitMask("CR"), 1.0)

        combined /= weightMap

        combinedExposure = afwImage.makeExposure(combined,
                                                 exposures[0].getWcs())
        combinedExposure.setMetadata(exposures[0].getMetadata())

        #output products
        clipboard.put(self.policy.get("outputKeys.combinedExposure"),
                      combinedExposure)
    def referenceTest(self, coadd, weightMap, image, badPixelMask, weight):
        """Compare lsst implemenation of addToCoadd to a reference implementation.

        Returns the overlap bounding box
        """
        # this call leaves coadd and weightMap alone:
        overlapBBox, refCoaddArrayList, refweightMapArray = \
            referenceAddToCoadd(coadd, weightMap, image, badPixelMask, weight)
        # this updates coadd and weightMap:
        afwOverlapBox = coaddUtils.addToCoadd(coadd, weightMap, image, badPixelMask, weight)
        self.assertEqual(overlapBBox, afwOverlapBox)

        coaddArrayList = coadd.getArrays()
        weightMapArray = weightMap.getArray()

        for name, ind in (("image", 0), ("mask", 1), ("variance", 2)):
            if not np.allclose(coaddArrayList[ind], refCoaddArrayList[ind]):
                errMsgList = (
                    "Computed %s does not match reference for badPixelMask=%s:" % (name, badPixelMask),
                    "computed=  %s" % (coaddArrayList[ind],),
                    "reference= %s" % (refCoaddArrayList[ind],),
                )
                errMsg = "\n".join(errMsgList)
                self.fail(errMsg)
        if not np.allclose(weightMapArray, refweightMapArray):
            errMsgList = (
                "Computed weight map does not match reference for badPixelMask=%s:" % (badPixelMask,),
                "computed=  %s" % (weightMapArray,),
                "reference= %s" % (refweightMapArray,),
            )
            errMsg = "\n".join(errMsgList)
            self.fail(errMsg)
        return overlapBBox
    def _testAddToCoaddImpl(self, useMask, uniformWeight=True):
        """Test coadd"""

        trueImageValue = 10.0
        imBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(10, 20))
        if useMask:
            coadd = afwImage.MaskedImageF(imBBox)
            weightMap = coadd.getImage().Factory(coadd.getBBox())

            badBits = 0x1
            badPixel = (float("NaN"), badBits, 0)
            truth = (trueImageValue, 0x0, 0)
        else:
            coadd = afwImage.ImageF(imBBox)
            weightMap = coadd.Factory(coadd.getBBox())

            badPixel = float("NaN")
            truth = trueImageValue

        for i in range(0, 20, 3):
            image = coadd.Factory(coadd.getDimensions())
            image.set(badPixel)

            subBBox = afwGeom.Box2I(afwGeom.Point2I(0, i),
                                    image.getDimensions() - afwGeom.Extent2I(0, i))
            subImage = image.Factory(image, subBBox, afwImage.LOCAL)
            subImage.set(truth)
            del subImage

            weight = 1.0 if uniformWeight else 1.0 + 0.1*i
            if useMask:
                coaddUtils.addToCoadd(coadd, weightMap, image, badBits, weight)
            else:
                coaddUtils.addToCoadd(coadd, weightMap, image, weight)

            self.assertEqual(image[-1, -1, afwImage.LOCAL], truth)

        coadd /= weightMap

        if display:
            ds9.mtv(image, title="image", frame=1)
            ds9.mtv(coadd, title="coadd", frame=2)
            ds9.mtv(weightMap, title="weightMap", frame=3)

        stats = afwMath.makeStatistics(coadd, afwMath.MEAN | afwMath.STDEV)

        return [trueImageValue, stats.getValue(afwMath.MEAN), 0.0, stats.getValue(afwMath.STDEV)]
Пример #8
0
    def run(self,
            identMatrix,
            butler,
            ra,
            dec,
            scale,
            xSize,
            ySize,
            ignore=False):
        """Warp and stack images

        @param[in] identMatrix Matrix of warp identifiers
        @param[in] butler Data butler
        @param[in] ra Right Ascension (radians) of skycell centre
        @param[in] dec Declination (radians) of skycell centre
        @param[in] scale Scale (arcsec/pixel) of skycell
        @param[in] xSize Size in x
        @param[in] ySize Size in y
        @param[in] ignore Ignore missing files?
        @output Stacked exposure
        """
        assert identMatrix, "No identMatrix provided"

        skycell = self.skycell(ra, dec, scale, xSize, ySize)

        coaddDim = afwGeom.Extent2I(xSize, ySize)
        coadd = afwImage.ExposureF(coaddDim, skycell.getWcs())
        weight = afwImage.ImageF(coaddDim)

        badpix = afwImage.MaskU.getPlaneBitMask(
            "EDGE")  # Allow everything else through
        for identList in identMatrix:
            warp = self.warp(identList, butler, skycell, ignore=ignore)
            # XXX Save for later?

            coaddUtils.addToCoadd(coadd.getMaskedImage(), weight,
                                  warp.getMaskedImage(), badpix, 1.0)

        coaddUtils.setCoaddEdgeBits(coadd.getMaskedImage().getMask(), weight)

        coaddImage = coadd.getMaskedImage()
        coaddImage /= weight

        # XXX Coadd has NANs where weight=0

        return coadd
    def process(self, clipboard):
        """
        Combine two Exposures, omitting any pixels in either positiveDetection or negativeDetection
        """
        self.log.log(Log.INFO, "Combining two Exposures in process")
        
        #grab exposure from clipboard
        exposures = []
        for k in self.policy.getArray("inputKeys.exposures"):
            exposures.append(clipboard.get(k))
        assert len(exposures) == 2
        badPixelMask = 0x0

        mi0 = exposures[0].getMaskedImage()
        combined = mi0.Factory(mi0.getDimensions())
        combined.setXY0(mi0.getXY0())
        del mi0
        weightMap = combined.getImage().Factory(combined.getDimensions())
        weightMap.setXY0(combined.getXY0())

        for i in range(0, 2):
            e = exposures[i]
            #
            # Get the FootprintSet associated with object that are only in this Exposure
            #
            if i == 0:
                footprintKey = "positiveDetection"
            else:
                footprintKey = "negativeDetection"

            fs = clipboard.get(self.policy.get("inputKeys.%s" % footprintKey))

            mi = e.getMaskedImage()
            fs.setMask(mi.getMask(), "CR")
            fs.setMask(combined.getMask(), "CR")
            
            coaddUtils.addToCoadd(combined, weightMap, mi, mi.getMask().getPlaneBitMask("CR"), 1.0)

        combined /= weightMap

        combinedExposure = afwImage.makeExposure(combined, exposures[0].getWcs())
        combinedExposure.setMetadata(exposures[0].getMetadata())

        #output products
        clipboard.put(self.policy.get("outputKeys.combinedExposure"), combinedExposure)
 def testAssertions(self):
     """Test that addToCoadd requires coadd and weightMap to have the same dimensions and xy0"""
     maskedImage = afwImage.MaskedImageF(afwGeom.Extent2I(10, 10))
     coadd = afwImage.MaskedImageF(afwGeom.Extent2I(11, 11))
     coadd.setXY0(5, 6)
     for dw, dh in (1, 0), (0, 1), (-1, 0), (0, -1):
         weightMapBBox = afwGeom.Box2I(coadd.getXY0(), coadd.getDimensions() + afwGeom.Extent2I(dw, dh))
         weightMap = afwImage.ImageF(weightMapBBox)
         weightMap.setXY0(coadd.getXY0())
         try:
             coaddUtils.addToCoadd(coadd, weightMap, maskedImage, 0x0, 0.1)
             self.fail("should have raised exception")
         except pexExcept.Exception:
             pass
     for dx0, dy0 in (1, 0), (0, 1), (-1, 0), (0, -1):
         weightMapBBox = afwGeom.Box2I(coadd.getXY0() + afwGeom.Extent2I(dx0, dy0), coadd.getDimensions())
         weightMap = afwImage.ImageF(weightMapBBox)
         try:
             coaddUtils.addToCoadd(coadd, weightMap, maskedImage, 0x0, 0.1)
             self.fail("should have raised exception")
         except pexExcept.Exception:
             pass
Пример #11
0
    def addExposure(self, exposure, weightFactor=1.0):
        """Add an Exposure to the coadd

        Parameters
        ----------
        exposure: `afwImage.Exposure`
            Exposure to add to coadd; this should be:
            - background-subtracted or background-matched to the other images
                being coadded
            - psf-matched to the desired PSF model (optional)
            - warped to match the coadd
            - photometrically scaled to the desired flux magnitude
        weightFactor : `float`
            the extra weight factor for this exposure

        Returns
        --------
        overlapBBox, weight : `afwGeom.Box2I`, `float`
            the region of overlap between exposure and coadd in  parent
            coordinates. weight with which exposure was added to coadd;
            weight = weightFactor / clipped mean variance
            Subclasses may override to preprocess the exposure or change
            the way it is added to the coadd.

        """
        maskedImage = exposure.getMaskedImage()

        # compute the weight
        statObj = afwMath.makeStatistics(maskedImage.getVariance(),
                                         maskedImage.getMask(),
                                         afwMath.MEANCLIP, self._statsControl)
        meanVar = statObj.getResult(afwMath.MEANCLIP)[0]
        weight = weightFactor / float(meanVar)
        if math.isnan(weight):
            raise RuntimeError(
                "Weight is NaN (weightFactor=%s; mean variance=%s)" %
                (weightFactor, meanVar))

        # save filter info
        filter = exposure.getFilter()
        self._filterDict.setdefault(filter.getName(), filter)

        self._log.info("Add exposure to coadd with weight=%0.3g", weight)

        overlapBBox = coadd_utils.addToCoadd(self._coadd.getMaskedImage(),
                                             self._weightMap, maskedImage,
                                             self._badPixelMask, weight)

        return overlapBBox, weight
Пример #12
0
    def referenceTest(self, coadd, weightMap, image, badPixelMask, weight):
        """Compare lsst implemenation of addToCoadd to a reference implementation.

        Returns the overlap bounding box
        """
        # this call leaves coadd and weightMap alone:
        overlapBBox, refCoaddArrayList, refweightMapArray = \
            referenceAddToCoadd(coadd, weightMap, image, badPixelMask, weight)
        # this updates coadd and weightMap:
        afwOverlapBox = coaddUtils.addToCoadd(coadd, weightMap, image,
                                              badPixelMask, weight)
        self.assertEqual(overlapBBox, afwOverlapBox)

        coaddArrayList = coadd.getArrays()
        weightMapArray = weightMap.getArray()

        for name, ind in (("image", 0), ("mask", 1), ("variance", 2)):
            if not np.allclose(coaddArrayList[ind], refCoaddArrayList[ind]):
                errMsgList = (
                    "Computed %s does not match reference for badPixelMask=%s:"
                    % (name, badPixelMask),
                    "computed=  %s" % (coaddArrayList[ind], ),
                    "reference= %s" % (refCoaddArrayList[ind], ),
                )
                errMsg = "\n".join(errMsgList)
                self.fail(errMsg)
        if not np.allclose(weightMapArray, refweightMapArray):
            errMsgList = (
                "Computed weight map does not match reference for badPixelMask=%s:"
                % (badPixelMask, ),
                "computed=  %s" % (weightMapArray, ),
                "reference= %s" % (refweightMapArray, ),
            )
            errMsg = "\n".join(errMsgList)
            self.fail(errMsg)
        return overlapBBox
            print "  Compute coadd component"
            coaddComponent = coaddKaiser.CoaddComponent(exposure, psfKernel, normalizePsf)

            print "  Divide exposure by sigma squared = %s" % (coaddComponent.getSigmaSq(),)
            blurredExposure = coaddComponent.getBlurredExposure()
            blurredMaskedImage = blurredExposure.getMaskedImage()
            sigmaSq = coaddComponent.getSigmaSq()
            if saveImages:
                blurredExposure.writeFits("blurred%s" % (fileName,))
            blurredMaskedImage /= sigmaSq
            if saveImages:
                blurredExposure.writeFits("scaledBlurred%s" % (fileName,))
            
            print "  Remap blurred exposure to match coadd WCS"
            remappedBlurredMaskedImage = afwImage.MaskedImageD(
                coaddExposure.getWidth(), coaddExposure.getHeight())
            remappedBlurredExposure = afwImage.ExposureD(remappedBlurredMaskedImage, coaddWcs)
            if saveImages:
                remappedBlurredExposure.writeFits("remappedBlurred%s" % (fileName,))
            nGoodPix = afwMath.warpExposure(remappedBlurredExposure, blurredExposure,
                afwMath.LanczosWarpingKernel(3))
            nPix = coaddExposure.getWidth() * coaddExposure.getHeight()
            print "  Remapped image has %d good pixels (%0.0f %%)" % (nGoodPix, 100 * nGoodPix / float(nPix))

            print "  Add remapped blurred exposure to coadd and save updated coadd exposure"
            coaddUtils.addToCoadd(coaddMaskedImage, depthMap, remappedBlurredExposure.getMaskedImage(),
                coaddMask)
            coaddExposure.writeFits(outName)
            depthMap.writeFits(depthOutName)
    coaddUtils.setCoaddEdgeBits(coaddMaskedImage.getMask(), depthMap)
    coaddExposure.writeFits(outName)    
            blurredMaskedImage = blurredExposure.getMaskedImage()
            sigmaSq = coaddComponent.getSigmaSq()
            if saveImages:
                blurredExposure.writeFits("blurred%s" % (fileName, ))
            blurredMaskedImage /= sigmaSq
            if saveImages:
                blurredExposure.writeFits("scaledBlurred%s" % (fileName, ))

            print "  Remap blurred exposure to match coadd WCS"
            remappedBlurredMaskedImage = afwImage.MaskedImageD(
                coaddExposure.getWidth(), coaddExposure.getHeight())
            remappedBlurredExposure = afwImage.ExposureD(
                remappedBlurredMaskedImage, coaddWcs)
            if saveImages:
                remappedBlurredExposure.writeFits("remappedBlurred%s" %
                                                  (fileName, ))
            nGoodPix = afwMath.warpExposure(remappedBlurredExposure,
                                            blurredExposure,
                                            afwMath.LanczosWarpingKernel(3))
            nPix = coaddExposure.getWidth() * coaddExposure.getHeight()
            print "  Remapped image has %d good pixels (%0.0f %%)" % (
                nGoodPix, 100 * nGoodPix / float(nPix))

            print "  Add remapped blurred exposure to coadd and save updated coadd exposure"
            coaddUtils.addToCoadd(coaddMaskedImage, depthMap,
                                  remappedBlurredExposure.getMaskedImage(),
                                  coaddMask)
            coaddExposure.writeFits(outName)
            depthMap.writeFits(depthOutName)
    coaddUtils.setCoaddEdgeBits(coaddMaskedImage.getMask(), depthMap)
    coaddExposure.writeFits(outName)