Exemple #1
0
    def testTransform(self):
        """Test constructor for Polygon involving transforms"""
        box = afwGeom.Box2D(afwGeom.Point2D(0.0, 0.0),
                            afwGeom.Point2D(123.4, 567.8))
        poly1 = Polygon(box)
        scale = (0.2 * afwGeom.arcseconds).asDegrees()
        wcs = afwImage.makeWcs(
            afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees),
            afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale)
        transform = afwImage.XYTransformFromWcsPair(wcs, wcs)
        poly2 = Polygon(box, transform)

        # We lose some very small precision in the XYTransformFromWcsPair
        # so we can't compare the polygons directly.
        self.assertEqual(poly1.getNumEdges(), poly2.getNumEdges())
        for p1, p2 in zip(poly1.getVertices(), poly2.getVertices()):
            self.assertAlmostEqual(p1.getX(), p2.getX())
            self.assertAlmostEqual(p1.getY(), p2.getY())

        transform = afwGeom.AffineTransform.makeScaling(1.0)
        poly3 = Polygon(box, transform)
        self.assertEqual(poly1, poly3)
    def compareToSwarp(self,
                       kernelName,
                       useWarpExposure=True,
                       useSubregion=False,
                       useDeepCopy=False,
                       interpLength=10,
                       cacheSize=100000,
                       rtol=4e-05,
                       atol=1e-2):
        """Compare warpExposure to swarp for given warping kernel.

        Note that swarp only warps the image plane, so only test that plane.

        Inputs:
        - kernelName: name of kernel in the form used by afwImage.makeKernel
        - useWarpExposure: if True, call warpExposure to warp an ExposureF,
            else call warpImage to warp an ImageF and also call the XYTransform version
        - useSubregion: if True then the original source exposure (from which the usual
            test exposure was extracted) is read and the correct subregion extracted
        - useDeepCopy: if True then the copy of the subimage is a deep copy,
            else it is a shallow copy; ignored if useSubregion is False
        - interpLength: interpLength argument for lsst.afw.math.WarpingControl
        - cacheSize: cacheSize argument for lsst.afw.math.WarpingControl;
            0 disables the cache
            10000 gives some speed improvement but less accurate results (atol must be increased)
            100000 gives better accuracy but no speed improvement in this test
        - rtol: relative tolerance as used by np.allclose
        - atol: absolute tolerance as used by np.allclose
        """
        warpingControl = afwMath.WarpingControl(
            kernelName,
            "",  # there is no point to a separate mask kernel since we aren't testing the mask plane
            cacheSize,
            interpLength,
        )
        if useSubregion:
            originalFullExposure = afwImage.ExposureF(originalExposurePath)
            # "medsub" is a subregion of med starting at 0-indexed pixel (40, 150) of size 145 x 200
            bbox = afwGeom.Box2I(afwGeom.Point2I(40, 150),
                                 afwGeom.Extent2I(145, 200))
            originalExposure = afwImage.ExposureF(originalFullExposure, bbox,
                                                  afwImage.LOCAL, useDeepCopy)
            swarpedImageName = "medsubswarp1%s.fits" % (kernelName, )
        else:
            originalExposure = afwImage.ExposureF(originalExposurePath)
            swarpedImageName = "medswarp1%s.fits" % (kernelName, )

        swarpedImagePath = os.path.join(dataDir, swarpedImageName)
        swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath)
        swarpedImage = swarpedDecoratedImage.getImage()
        swarpedMetadata = swarpedDecoratedImage.getMetadata()
        warpedWcs = afwImage.makeWcs(swarpedMetadata)

        if useWarpExposure:
            # path for saved afw-warped image
            afwWarpedImagePath = "afwWarpedExposure1%s.fits" % (kernelName, )

            afwWarpedMaskedImage = afwImage.MaskedImageF(
                swarpedImage.getDimensions())
            afwWarpedExposure = afwImage.ExposureF(afwWarpedMaskedImage,
                                                   warpedWcs)
            afwMath.warpExposure(afwWarpedExposure, originalExposure,
                                 warpingControl)
            afwWarpedMask = afwWarpedMaskedImage.getMask()
            if SAVE_FITS_FILES:
                afwWarpedExposure.writeFits(afwWarpedImagePath)
            if display:
                ds9.mtv(afwWarpedExposure, frame=1, title="Warped")

            swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage)

            if display:
                ds9.mtv(swarpedMaskedImage, frame=2, title="SWarped")

            msg = "afw and swarp %s-warped differ (ignoring bad pixels)" % (
                kernelName, )
            try:
                self.assertMaskedImagesAlmostEqual(afwWarpedMaskedImage,
                                                   swarpedMaskedImage,
                                                   doImage=True,
                                                   doMask=False,
                                                   doVariance=False,
                                                   skipMask=afwWarpedMask,
                                                   rtol=rtol,
                                                   atol=atol,
                                                   msg=msg)
            except Exception:
                if SAVE_FAILED_FITS_FILES:
                    afwWarpedExposure.writeFits(afwWarpedImagePath)
                    print("Saved failed afw-warped exposure as: %s" %
                          (afwWarpedImagePath, ))
                raise
        else:
            # path for saved afw-warped image
            afwWarpedImagePath = "afwWarpedImage1%s.fits" % (kernelName, )
            afwWarpedImage2Path = "afwWarpedImage1%s_xyTransform.fits" % (
                kernelName, )

            afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions())
            originalImage = originalExposure.getMaskedImage().getImage()
            originalWcs = originalExposure.getWcs()
            afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage,
                              originalWcs, warpingControl)
            if display:
                ds9.mtv(afwWarpedImage, frame=1, title="Warped")
                ds9.mtv(swarpedImage, frame=2, title="SWarped")
                diff = swarpedImage.Factory(swarpedImage, True)
                diff -= afwWarpedImage
                ds9.mtv(diff, frame=3, title="swarp - afw")
            if SAVE_FITS_FILES:
                afwWarpedImage.writeFits(afwWarpedImagePath)

            afwWarpedImageArr = afwWarpedImage.getArray()
            noDataMaskArr = np.isnan(afwWarpedImageArr)
            msg = "afw and swarp %s-warped images do not match (ignoring NaN pixels)" % \
                (kernelName,)
            try:
                self.assertImagesAlmostEqual(afwWarpedImage,
                                             swarpedImage,
                                             skipMask=noDataMaskArr,
                                             rtol=rtol,
                                             atol=atol,
                                             msg=msg)
            except Exception:
                if SAVE_FAILED_FITS_FILES:
                    # save the image anyway
                    afwWarpedImage.writeFits(afwWarpedImagePath)
                    print("Saved failed afw-warped image as: %s" %
                          (afwWarpedImagePath, ))
                raise

            afwWarpedImage2 = afwImage.ImageF(swarpedImage.getDimensions())
            xyTransform = afwImage.XYTransformFromWcsPair(
                warpedWcs, originalWcs)
            afwMath.warpImage(afwWarpedImage2, originalImage, xyTransform,
                              warpingControl)
            msg = "afw xyTransform-based and WCS-based %s-warped images do not match" % (
                kernelName, )
            try:
                self.assertImagesAlmostEqual(afwWarpedImage2,
                                             afwWarpedImage,
                                             rtol=rtol,
                                             atol=atol,
                                             msg=msg)
            except Exception:
                if SAVE_FAILED_FITS_FILES:
                    # save the image anyway
                    afwWarpedImage.writeFits(afwWarpedImagePath)
                    print("Saved failed afw-warped image as: %s" %
                          (afwWarpedImage2Path, ))
                raise
Exemple #3
0
    def run(self,
            exposure,
            wcs,
            modelPsf=None,
            maxBBox=None,
            destBBox=None,
            makeDirect=True,
            makePsfMatched=False):
        """Warp and optionally PSF-match exposure

        Parameters
        ----------
        exposure : :cpp:class: `lsst::afw::image::Exposure`
            Exposure to preprocess.
        wcs : :cpp:class:`lsst::afw::image::Wcs`
            Desired WCS of temporary images.
        modelPsf : :cpp:class: `lsst::meas::algorithms::KernelPsf` or None
            Target PSF to which to match.
        maxBBox : :cpp:class:`lsst::afw::geom::Box2I` or None
            Maximum allowed parent bbox of warped exposure.
            If None then the warped exposure will be just big enough to contain all warped pixels;
            if provided then the warped exposure may be smaller, and so missing some warped pixels;
            ignored if destBBox is not None.
        destBBox: :cpp:class: `lsst::afw::geom::Box2I` or None
            Exact parent bbox of warped exposure.
            If None then maxBBox is used to determine the bbox, otherwise maxBBox is ignored.
        makeDirect : bool
            Return an exposure that has been only warped?
        makePsfMatched : bool
            Return an exposure that has been warped and PSF-matched?

        Returns
        -------
        An lsst.pipe.base.Struct with the following fields:

        direct : :cpp:class:`lsst::afw::image::Exposure`
            warped exposure
        psfMatched : :cpp:class: `lsst::afw::image::Exposure`
            warped and psf-Matched temporary exposure
        """
        if makePsfMatched and modelPsf is None:
            raise RuntimeError(
                "makePsfMatched=True, but no model PSF was provided")

        if not makePsfMatched and not makeDirect:
            self.log.warn("Neither makeDirect nor makePsfMatched requested")

        # Warp PSF before overwriting exposure
        xyTransform = afwImage.XYTransformFromWcsPair(wcs, exposure.getWcs())
        psfWarped = WarpedPsf(exposure.getPsf(), xyTransform)

        if makePsfMatched and maxBBox is not None:
            # grow warped region to provide sufficient area for PSF-matching
            pixToGrow = 2 * max(self.psfMatch.kConfig.sizeCellX,
                                self.psfMatch.kConfig.sizeCellY)
            # replace with copy
            maxBBox = afwGeom.Box2I(maxBBox)
            maxBBox.grow(pixToGrow)

        with self.timer("warp"):
            exposure = self.warper.warpExposure(wcs,
                                                exposure,
                                                maxBBox=maxBBox,
                                                destBBox=destBBox)
            exposure.setPsf(psfWarped)

        if makePsfMatched:
            try:
                exposurePsfMatched = self.psfMatch.run(
                    exposure, modelPsf).psfMatchedExposure
            except Exception as e:
                exposurePsfMatched = None
                self.log.info("Cannot PSF-Match: %s" % (e))

        return pipeBase.Struct(
            direct=exposure if makeDirect else None,
            psfMatched=exposurePsfMatched if makePsfMatched else None)