def testWarpIntoSelf(self, interpLength=10): """Cannot warp in-place """ originalExposure = afwImage.ExposureF(afwGeom.Extent2I(100, 100)) warpingControl = afwMath.WarpingControl("bilinear", "", 0, interpLength) try: afwMath.warpExposure(originalExposure, originalExposure, warpingControl) self.fail("warpExposure in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getMaskedImage(), originalExposure.getWcs(), originalExposure.getMaskedImage(), originalExposure.getWcs(), warpingControl) self.fail( "warpImage<MaskedImage> in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getImage(), originalExposure.getWcs(), originalExposure.getImage(), originalExposure.getWcs(), warpingControl) self.fail("warpImage<Image> in place (dest is src) should fail") except Exception: pass
def toCcdBackground(self, detector, bbox): """Produce a background model for a CCD The superpixel background model is warped back to the CCD frame, for application to the individual CCD. Parameters ---------- detector : `lsst.afw.cameraGeom.Detector` CCD for which to produce background model. bbox : `lsst.geom.Box2I` Bounding box of CCD exposure. Returns ------- bg : `lsst.afw.math.BackgroundList` Background model for CCD. """ transform = detector.getTransformMap().getTransform( detector.makeCameraSys(afwCameraGeom.PIXELS), detector.makeCameraSys(afwCameraGeom.FOCAL_PLANE)) binTransform = ( geom.AffineTransform.makeScaling(self.config.binning) * geom.AffineTransform.makeTranslation(geom.Extent2D(0.5, 0.5))) # Binned image on CCD --> unbinned image on CCD --> focal plane --> binned focal plane toSample = afwGeom.makeTransform(binTransform).then(transform).then( self.transform) focalPlane = self.getStatsImage() fpNorm = afwImage.ImageF(focalPlane.getBBox()) fpNorm.set(1.0) image = afwImage.ImageF(bbox.getDimensions() // self.config.binning) norm = afwImage.ImageF(image.getBBox()) ctrl = afwMath.WarpingControl("bilinear") afwMath.warpImage(image, focalPlane, toSample.inverted(), ctrl) afwMath.warpImage(norm, fpNorm, toSample.inverted(), ctrl) image /= norm mask = afwImage.Mask(image.getBBox()) isBad = numpy.isnan(image.getArray()) mask.getArray()[isBad] = mask.getPlaneBitMask("BAD") image.getArray()[isBad] = image.getArray()[~isBad].mean() return afwMath.BackgroundList( (afwMath.BackgroundMI(bbox, afwImage.makeMaskedImage(image, mask)), afwMath.stringToInterpStyle(self.config.interpolation), afwMath.stringToUndersampleStyle("REDUCE_INTERP_ORDER"), afwMath.ApproximateControl.UNKNOWN, 0, 0, False))
def timeWarp(destMaskedImage, srcMaskedImage, destToSrc, warpingControl): """Time warpImage Parameters ---------- destMaskedImage : `lsst.afw.image.MaskedImage` Destination (output) masked image srcMaskedImage : `lsst.afw.image.MaskedImage` Source (input) masked image destToSrc : `lsst.afw.geom.TransformPoint2ToPoint2` Transform from source pixels to destination pixels warpingControl : `lsst.afw.geom.WarpingControl` Warning control parameters Returns ------- `tuple(float, int, int)` - Elapsed time in seconds - Number of iterations - Number of good pixels """ startTime = time.time() for nIter in range(1, MaxIter + 1): goodPix = afwMath.warpImage(destMaskedImage, srcMaskedImage, destToSrc, warpingControl) endTime = time.time() if endTime - startTime > MaxTime: break return (endTime - startTime, nIter, goodPix)
def testNullWarpImage(self, interpLength=10): """Test that warpImage maps an image onto itself. """ originalExposure = afwImage.ExposureF(originalExposurePath) afwWarpedExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() afwWarpedImage = afwWarpedExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwWarpedWcs = afwWarpedExposure.getWcs() warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpImage(afwWarpedImage, afwWarpedWcs, originalImage, originalWcs, warpingControl) if SAVE_FITS_FILES: afwWarpedImage.writeFits("afwWarpedImageNull.fits") afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = numpy.isnan(afwWarpedImageArr) # relax specs a bit because of minor noise introduced by bad pixels msg = "afw null-warped Image" self.assertImagesNearlyEqual(originalImage, afwWarpedImage, skipMask=noDataMaskArr, atol=1e-5, msg=msg)
def testNullWarpImage(self, interpLength=10): """Test that warpImage maps an image onto itself. """ originalExposure = afwImage.ExposureF(originalExposurePath) afwWarpedExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() afwWarpedImage = afwWarpedExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwWarpedWcs = afwWarpedExposure.getWcs() warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpImage(afwWarpedImage, afwWarpedWcs, originalImage, originalWcs, warpingControl) if SAVE_FITS_FILES: afwWarpedImage.writeFits("afwWarpedImageNull.fits") afwWarpedImageArr = afwWarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) originalImageArr = originalImage.getArray() # relax specs a bit because of minor noise introduced by bad pixels errStr = imageTestUtils.imagesDiffer(originalImageArr, originalImageArr, skipMaskArr=edgeMaskArr) if errStr: self.fail("afw null-warped Image: %s" % (errStr,))
def testNullWarpImage(self, interpLength=10): """Test that warpImage maps an image onto itself. """ originalExposure = afwImage.ExposureF(originalExposurePath) afwWarpedExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() afwWarpedImage = afwWarpedExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwWarpedWcs = afwWarpedExposure.getWcs() warpingControl = afwMath.WarpingControl( "lanczos4", "", 0, interpLength) afwMath.warpImage(afwWarpedImage, afwWarpedWcs, originalImage, originalWcs, warpingControl) if SAVE_FITS_FILES: afwWarpedImage.writeFits("afwWarpedImageNull.fits") afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) # relax specs a bit because of minor noise introduced by bad pixels msg = "afw null-warped Image" self.assertImagesAlmostEqual(originalImage, afwWarpedImage, skipMask=noDataMaskArr, atol=1e-5, msg=msg)
def testWarpIntoSelf(self, interpLength=10): """Cannot warp in-place """ wcs = afwGeom.makeSkyWcs( crpix=lsst.geom.Point2D(0, 0), crval=lsst.geom.SpherePoint(359, 0, lsst.geom.degrees), cdMatrix=afwGeom.makeCdMatrix(1.0e-8*lsst.geom.degrees), ) exposure = afwImage.ExposureF(lsst.geom.Extent2I(100, 100), wcs) maskedImage = exposure.getMaskedImage() warpingControl = afwMath.WarpingControl( "bilinear", "", 0, interpLength) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpExposure(exposure, exposure, warpingControl) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpImage(maskedImage, wcs, maskedImage, wcs, warpingControl) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpImage(maskedImage.getImage(), wcs, maskedImage.getImage(), wcs, warpingControl)
def testWarpIntoSelf(self, interpLength=10): """Cannot warp in-place """ wcs = afwGeom.makeSkyWcs( crpix=afwGeom.Point2D(0, 0), crval=afwGeom.SpherePoint(359, 0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(1.0e-8*afwGeom.degrees), ) exposure = afwImage.ExposureF(afwGeom.Extent2I(100, 100), wcs) maskedImage = exposure.getMaskedImage() warpingControl = afwMath.WarpingControl( "bilinear", "", 0, interpLength) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpExposure(exposure, exposure, warpingControl) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpImage(maskedImage, wcs, maskedImage, wcs, warpingControl) with self.assertRaises(pexExcept.InvalidParameterError): afwMath.warpImage(maskedImage.getImage(), wcs, maskedImage.getImage(), wcs, warpingControl)
def testNonIcrs(self): """Test that warping to a non-ICRS-like coordinate system produces different results It would be better to also test that the results are as expected, but I have not been able to get swarp to perform this operation, so have not found an independent means of generating the expected results. """ kernelName = "lanczos3" rtol = 4e-5 atol = 1e-2 warpingControl = afwMath.WarpingControl(kernelName, ) originalExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() swarpedImageName = "medswarp1%s.fits" % (kernelName, ) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() for changeEquinox in (False, True): swarpedMetadata = swarpedDecoratedImage.getMetadata() if changeEquinox: swarpedMetadata.set("RADECSYS", "FK5") swarpedMetadata.set("EQUINOX", swarpedMetadata.get("EQUINOX") + 1) warpedWcs = afwImage.makeWcs(swarpedMetadata) afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions()) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() numGoodPix = afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage, originalWcs, warpingControl) self.assertGreater(numGoodPix, 50) afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) if changeEquinox: with self.assertRaises(AssertionError): self.assertImagesAlmostEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol) else: self.assertImagesAlmostEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol)
def testWarpIntoSelf(self, interpLength=10): """Cannot warp in-place """ originalExposure = afwImage.ExposureF(afwGeom.Extent2I(100, 100)) warpingKernel = afwMath.BilinearWarpingKernel() try: afwMath.warpExposure(originalExposure, originalExposure, warpingKernel, interpLength) self.fail("warpExposure in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getMaskedImage(), originalExposure.getWcs(), originalExposure.getMaskedImage(), originalExposure.getWcs(), warpingKernel, interpLength) self.fail("warpImage<MaskedImage> in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getImage(), originalExposure.getWcs(), originalExposure.getImage(), originalExposure.getWcs(), warpingKernel, interpLength) self.fail("warpImage<Image> in place (dest is src) should fail") except Exception: pass
def testNullWarpImage(self, interpLength=10): """Test that warpImage maps an image onto itself. """ originalExposure = afwImage.ExposureF(originalExposurePath) afwWarpedExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() afwWarpedImage = afwWarpedExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwWarpedWcs = afwWarpedExposure.getWcs() warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpImage(afwWarpedImage, afwWarpedWcs, originalImage, originalWcs, warpingControl) if SAVE_FITS_FILES: afwWarpedImage.writeFits("afwWarpedImageNull.fits") afwWarpedImageArr = afwWarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) originalImageArr = originalImage.getArray() # relax specs a bit because of minor noise introduced by bad pixels errStr = imageTestUtils.imagesDiffer(originalImageArr, originalImageArr, skipMaskArr=edgeMaskArr) if errStr: self.fail("afw null-warped Image: %s" % (errStr, ))
def testTransformBasedWarp(self): """Test warping using Transform<Point2Endpoint, Point2Endpoint> """ for interpLength in (0, 1, 2, 4): kernelName = "lanczos3" rtol = 4e-5 atol = 1e-2 warpingControl = afwMath.WarpingControl( warpingKernelName=kernelName, interpLength=interpLength, ) originalExposure = afwImage.ExposureF(originalExposurePath) originalMetadata = afwImage.DecoratedImageF( originalExposurePath).getMetadata() originalSkyWcs = afwGeom.SkyWcs(originalMetadata) swarpedImageName = "medswarp1%s.fits" % (kernelName, ) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() warpedSkyWcs = afwGeom.SkyWcs(swarpedMetadata) # warped image is destination, original image is source # and WCS computes pixels to sky in the forward direction, so... destToSrc = warpedSkyWcs.then(originalSkyWcs.getInverse()) afwWarpedMaskedImage = afwImage.MaskedImageF( swarpedImage.getDimensions()) originalMaskedImage = originalExposure.getMaskedImage() numGoodPix = afwMath.warpImage(afwWarpedMaskedImage, originalMaskedImage, destToSrc, warpingControl) self.assertGreater(numGoodPix, 50) afwWarpedImage = afwWarpedMaskedImage.getImage() afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) self.assertImagesAlmostEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol)
def testNonIcrs(self): """Test that warping to a non-ICRS-like coordinate system produces different results It would be better to also test that the results are as expected, but I have not been able to get swarp to perform this operation, so have not found an independent means of generating the expected results. """ kernelName = "lanczos3" rtol=4e-5 atol=1e-2 warpingControl = afwMath.WarpingControl( kernelName, ) originalExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() swarpedImageName = "medswarp1%s.fits" % (kernelName,) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() for changeEquinox in (False, True): swarpedMetadata = swarpedDecoratedImage.getMetadata() if changeEquinox: swarpedMetadata.set("RADECSYS", "FK5") swarpedMetadata.set("EQUINOX", swarpedMetadata.get("EQUINOX") + 1) warpedWcs = afwImage.makeWcs(swarpedMetadata) afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions()) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() numGoodPix = afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage, originalWcs, warpingControl) self.assertGreater(numGoodPix, 50) afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = numpy.isnan(afwWarpedImageArr) if changeEquinox: with self.assertRaises(AssertionError): self.assertImagesNearlyEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol) else: self.assertImagesNearlyEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol)
def testTransformBasedWarp(self): """Test warping using TransformPoint2ToPoint2 """ for interpLength in (0, 1, 2, 4): kernelName = "lanczos3" rtol = 4e-5 atol = 1e-2 warpingControl = afwMath.WarpingControl( warpingKernelName=kernelName, interpLength=interpLength, ) originalExposure = afwImage.ExposureF(originalExposurePath) originalMetadata = afwImage.DecoratedImageF( originalExposurePath).getMetadata() originalSkyWcs = afwGeom.makeSkyWcs(originalMetadata) swarpedImageName = f"medswarp1{kernelName}.fits" swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() warpedSkyWcs = afwGeom.makeSkyWcs(swarpedMetadata) # original image is source, warped image is destination srcToDest = afwGeom.makeWcsPairTransform(originalSkyWcs, warpedSkyWcs) afwWarpedMaskedImage = afwImage.MaskedImageF( swarpedImage.getDimensions()) originalMaskedImage = originalExposure.getMaskedImage() numGoodPix = afwMath.warpImage(afwWarpedMaskedImage, originalMaskedImage, srcToDest, warpingControl) self.assertGreater(numGoodPix, 50) afwWarpedImage = afwWarpedMaskedImage.getImage() afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) self.assertImagesAlmostEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol)
def testTransformBasedWarp(self): """Test warping using TransformPoint2ToPoint2 """ for interpLength in (0, 1, 2, 4): kernelName = "lanczos3" rtol = 4e-5 atol = 1e-2 warpingControl = afwMath.WarpingControl( warpingKernelName=kernelName, interpLength=interpLength, ) originalExposure = afwImage.ExposureF(originalExposurePath) originalMetadata = afwImage.DecoratedImageF(originalExposurePath).getMetadata() originalSkyWcs = afwGeom.makeSkyWcs(originalMetadata) swarpedImageName = "medswarp1%s.fits" % (kernelName,) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() warpedSkyWcs = afwGeom.makeSkyWcs(swarpedMetadata) # original image is source, warped image is destination srcToDest = afwGeom.makeWcsPairTransform(originalSkyWcs, warpedSkyWcs) afwWarpedMaskedImage = afwImage.MaskedImageF(swarpedImage.getDimensions()) originalMaskedImage = originalExposure.getMaskedImage() numGoodPix = afwMath.warpImage(afwWarpedMaskedImage, originalMaskedImage, srcToDest, warpingControl) self.assertGreater(numGoodPix, 50) afwWarpedImage = afwWarpedMaskedImage.getImage() afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) self.assertImagesAlmostEqual(afwWarpedImage, swarpedImage, skipMask=noDataMaskArr, rtol=rtol, atol=atol)
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 Transform 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 = lsst.geom.Box2I(lsst.geom.Point2I(40, 150), lsst.geom.Extent2I(145, 200)) originalExposure = afwImage.ExposureF(originalFullExposure, bbox, afwImage.LOCAL, useDeepCopy) swarpedImageName = f"medsubswarp1{kernelName}.fits" else: originalExposure = afwImage.ExposureF(originalExposurePath) swarpedImageName = f"medswarp1{kernelName}.fits" swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() warpedWcs = afwGeom.makeSkyWcs(swarpedMetadata) if useWarpExposure: # path for saved afw-warped image afwWarpedImagePath = f"afwWarpedExposure1{kernelName}.fits" 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: afwDisplay.Display(frame=1).mtv(afwWarpedExposure, title="Warped") swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage) if display: afwDisplay.Display(frame=2).mtv(swarpedMaskedImage, title="SWarped") msg = f"afw and swarp {kernelName}-warped differ (ignoring bad pixels)" 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( f"Saved failed afw-warped exposure as: {afwWarpedImagePath}" ) raise else: # path for saved afw-warped image afwWarpedImagePath = f"afwWarpedImage1{kernelName}.fits" afwWarpedImage2Path = f"afwWarpedImage1{kernelName}_xyTransform.fits" afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions()) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage, originalWcs, warpingControl) if display: afwDisplay.Display(frame=1).mtv(afwWarpedImage, title="Warped") afwDisplay.Display(frame=2).mtv(swarpedImage, title="SWarped") diff = swarpedImage.Factory(swarpedImage, True) diff -= afwWarpedImage afwDisplay.Display(frame=3).mtv(diff, title="swarp - afw") if SAVE_FITS_FILES: afwWarpedImage.writeFits(afwWarpedImagePath) afwWarpedImageArr = afwWarpedImage.getArray() noDataMaskArr = np.isnan(afwWarpedImageArr) msg = f"afw and swarp {kernelName}-warped images do not match (ignoring NaN pixels)" 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( f"Saved failed afw-warped image as: {afwWarpedImagePath}" ) raise afwWarpedImage2 = afwImage.ImageF(swarpedImage.getDimensions()) srcToDest = afwGeom.makeWcsPairTransform(originalWcs, warpedWcs) afwMath.warpImage(afwWarpedImage2, originalImage, srcToDest, warpingControl) msg = f"afw transform-based and WCS-based {kernelName}-warped images do not match" try: self.assertImagesAlmostEqual(afwWarpedImage2, afwWarpedImage, rtol=rtol, atol=atol, msg=msg) except Exception: if SAVE_FAILED_FITS_FILES: # save the image anyway afwWarpedImage.writeFits(afwWarpedImage2) print( f"Saved failed afw-warped image as: {afwWarpedImage2Path}" ) raise
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 - 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 numpy.allclose - atol: absolute tolerance as used by numpy.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" % (kernelName, ) afwWarpedMaskedImage = afwImage.MaskedImageF( swarpedImage.getDimensions()) afwWarpedExposure = afwImage.ExposureF(afwWarpedMaskedImage, warpedWcs) afwMath.warpExposure(afwWarpedExposure, originalExposure, warpingControl) if SAVE_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) if display: ds9.mtv(afwWarpedExposure, frame=1, title="Warped") afwWarpedMask = afwWarpedMaskedImage.getMask() edgeBitMask = afwWarpedMask.getPlaneBitMask("EDGE") if edgeBitMask == 0: self.fail("warped mask has no EDGE bit") afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays() afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1] swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage) swarpedMaskedImageArrSet = swarpedMaskedImage.getArrays() if display: ds9.mtv(swarpedMaskedImage, frame=2, title="SWarped") errStr = imageTestUtils.maskedImagesDiffer( afwWarpedMaskedImageArrSet, swarpedMaskedImageArrSet, doImage=True, doMask=False, doVariance=False, skipMaskArr=afwWarpedMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) print "Saved failed afw-warped exposure as: %s" % ( afwWarpedImagePath, ) self.fail("afw and swarp %s-warped %s (ignoring bad pixels)" % (kernelName, errStr)) else: # path for saved afw-warped image afwWarpedImagePath = "afwWarpedImage1%s.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() swarpedImageArr = swarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) errStr = imageTestUtils.imagesDiffer(afwWarpedImageArr, swarpedImageArr, skipMaskArr=edgeMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: # save the image anyway afwWarpedImage.writeFits(afwWarpedImagePath) print "Saved failed afw-warped image as: %s" % ( afwWarpedImagePath, ) self.fail("afw and swarp %s-warped images do not match (ignoring NaN pixels): %s" % \ (kernelName, errStr))
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 Transform 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 = lsst.geom.Box2I(lsst.geom.Point2I(40, 150), lsst.geom.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 = afwGeom.makeSkyWcs(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: afwDisplay.Display(frame=1).mtv(afwWarpedExposure, title="Warped") swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage) if display: afwDisplay.Display(frame=2).mtv(swarpedMaskedImage, 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: afwDisplay.Display(frame=1).mtv(afwWarpedImage, title="Warped") afwDisplay.Display(frame=2).mtv(swarpedImage, title="SWarped") diff = swarpedImage.Factory(swarpedImage, True) diff -= afwWarpedImage afwDisplay.Display(frame=3).mtv(diff, 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()) srcToDest = afwGeom.makeWcsPairTransform(originalWcs, warpedWcs) afwMath.warpImage(afwWarpedImage2, originalImage, srcToDest, warpingControl) msg = "afw transform-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
def warpStamps(self, stamps, pixCenters): """Warps and shifts all given stamps so they are sampled on the same pixel grid and centered on the central pixel. This includes rotating the stamp depending on detector orientation. Parameters ---------- stamps : `collections.abc.Sequence` [`afwImage.exposure.exposure.ExposureF`] Image cutouts centered on a single object. pixCenters : `collections.abc.Sequence` [`geom.Point2D`] Positions of each object's center (as obtained from the refCat), in pixels. Returns ------- warpedStars : `list` [`afwImage.maskedImage.maskedImage.MaskedImage`] """ # warping control; only contains shiftingALg provided in config warpCont = afwMath.WarpingControl(self.config.warpingKernelName) # Compare model to star stamp sizes bufferPix = (self.modelStampSize[0] - self.config.stampSize[0], self.modelStampSize[1] - self.config.stampSize[1]) # Initialize detector instance (note all stars were extracted from an # exposure from the same detector) det = stamps[0].getDetector() # Define correction for optical distortions if self.config.doApplyTransform: pixToTan = det.getTransform(cg.PIXELS, cg.TAN_PIXELS) else: pixToTan = tFactory.makeIdentityTransform() # Array of all possible rotations for detector orientation: possibleRots = np.array([k*np.pi/2 for k in range(4)]) # determine how many, if any, rotations are required yaw = det.getOrientation().getYaw() nb90Rots = np.argmin(np.abs(possibleRots - float(yaw))) # apply transformation to each star warpedStars = [] for star, cent in zip(stamps, pixCenters): # (re)create empty destination image destImage = afwImage.MaskedImageF(*self.modelStampSize) bottomLeft = geom.Point2D(star.image.getXY0()) newBottomLeft = pixToTan.applyForward(bottomLeft) newBottomLeft.setX(newBottomLeft.getX() - bufferPix[0]/2) newBottomLeft.setY(newBottomLeft.getY() - bufferPix[1]/2) # Convert to int newBottomLeft = geom.Point2I(newBottomLeft) # Set origin destImage.setXY0(newBottomLeft) # Define linear shifting to recenter stamps newCenter = pixToTan.applyForward(cent) # center of warped star shift = self.modelCenter[0] + newBottomLeft[0] - newCenter[0],\ self.modelCenter[1] + newBottomLeft[1] - newCenter[1] affineShift = geom.AffineTransform(shift) shiftTransform = tFactory.makeTransform(affineShift) # Define full transform (warp and shift) starWarper = pixToTan.then(shiftTransform) # Apply it goodPix = afwMath.warpImage(destImage, star.getMaskedImage(), starWarper, warpCont) if not goodPix: self.log.debug("Warping of a star failed: no good pixel in output") # Arbitrarily set origin of shifted star to 0 destImage.setXY0(0, 0) # Apply rotation if apropriate if nb90Rots: destImage = afwMath.rotateImageBy90(destImage, nb90Rots) warpedStars.append(destImage.clone()) return warpedStars
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 - 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.warpExposure - cacheSize: cacheSize argument for lsst.afw.math.SeparableKernel.computeCache; 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 numpy.allclose - atol: absolute tolerance as used by numpy.allclose """ warpingKernel = afwMath.makeWarpingKernel(kernelName) warpingKernel.computeCache(cacheSize) 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" % (kernelName,) afwWarpedMaskedImage = afwImage.MaskedImageF(swarpedImage.getDimensions()) afwWarpedExposure = afwImage.ExposureF(afwWarpedMaskedImage, warpedWcs) afwMath.warpExposure(afwWarpedExposure, originalExposure, warpingKernel, interpLength) if SAVE_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) if display: ds9.mtv(afwWarpedExposure, frame=1, title="Warped") afwWarpedMask = afwWarpedMaskedImage.getMask() edgeBitMask = afwWarpedMask.getPlaneBitMask("EDGE") if edgeBitMask == 0: self.fail("warped mask has no EDGE bit") afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays() afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1] swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage) swarpedMaskedImageArrSet = swarpedMaskedImage.getArrays() if display: ds9.mtv(swarpedMaskedImage, frame=2, title="SWarped") errStr = imageTestUtils.maskedImagesDiffer(afwWarpedMaskedImageArrSet, swarpedMaskedImageArrSet, doImage=True, doMask=False, doVariance=False, skipMaskArr=afwWarpedMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) print "Saved failed afw-warped exposure as: %s" % (afwWarpedImagePath,) self.fail("afw and swarp %s-warped %s (ignoring bad pixels)" % (kernelName, errStr)) else: # path for saved afw-warped image afwWarpedImagePath = "afwWarpedImage1%s.fits" % (kernelName,) afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions()) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage, originalWcs, warpingKernel, interpLength) 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() swarpedImageArr = swarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) errStr = imageTestUtils.imagesDiffer(afwWarpedImageArr, swarpedImageArr, skipMaskArr=edgeMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: # save the image anyway afwWarpedImage.writeFits(afwWarpedImagePath) print "Saved failed afw-warped image as: %s" % (afwWarpedImagePath,) self.fail("afw and swarp %s-warped images do not match (ignoring NaN pixels): %s" % \ (kernelName, errStr))