def testUndersample(self): """Test how the program handles nx,ny being too small for requested interp style.""" # make an image nx = 64 ny = 64 img = afwImage.ImageD(afwGeom.Extent2I(nx, ny)) # make a background control object bctrl = afwMath.BackgroundControl() bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(2) bctrl.setNySample(2) # see if it adjusts the nx,ny values up to 3x3 bctrl.setUndersampleStyle(afwMath.INCREASE_NXNYSAMPLE) backobj = afwMath.makeBackground(img, bctrl) self.assertEqual(backobj.getBackgroundControl().getNxSample(), 3) self.assertEqual(backobj.getBackgroundControl().getNySample(), 3) # put nx,ny back to 2 and see if it adjusts the interp style down to linear bctrl.setNxSample(2) bctrl.setNySample(2) bctrl.setUndersampleStyle("REDUCE_INTERP_ORDER") backobj = afwMath.makeBackground(img, bctrl) self.assertEqual(backobj.getBackgroundControl().getInterpStyle(), afwMath.Interpolate.LINEAR) # put interp style back up to cspline and see if it throws an exception bctrl.setUndersampleStyle("THROW_EXCEPTION") bctrl.setInterpStyle("CUBIC_SPLINE") def tst(im, bc): backobj = afwMath.makeBackground(im, bc) utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, tst, img, bctrl)
def testTicket1781(self): """Test an unusual-sized image""" nx = 526 ny = 154 parabimg = self.getParabolaImage(nx, ny) bctrl = afwMath.BackgroundControl(16, 4) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) afwMath.makeBackground(parabimg, bctrl)
def testTicket1781(self): """Test an unusual-sized image""" nx = 526 ny = 154 parabimg = self.getParabolaImage(nx, ny) bctrl = afwMath.BackgroundControl(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(16) bctrl.setNySample(4) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) afwMath.makeBackground(parabimg, bctrl)
def complexBackground(image): binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 sctrl = afwMath.StatisticsControl() sctrl.setNumSigmaClip(3) sctrl.setNumIter(4) sctrl.setAndMask(afwImage.MaskU.getPlaneBitMask(["INTRP", "EDGE"])) sctrl.setNoGoodPixelsMask(afwImage.MaskU.getPlaneBitMask("BAD")) sctrl.setNanSafe(True) if False: sctrl.setWeighted(True) sctrl.setCalcErrorFromInputVariance(True) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() ds9.mtv(statsImage.getVariance()) bkdgImages = dict(SPLINE = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE), LINEAR = bkgd.getImageF(afwMath.Interpolate.LINEAR)) return bkgd
def testBackgroundListIO(self): """Test I/O for BackgroundLists""" bgCtrl = afwMath.BackgroundControl(10, 10) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER backgroundList = afwMath.BackgroundList() backImage = afwImage.ImageF(self.image.getDimensions()) for i in range(2): bkgd = afwMath.makeBackground(self.image, bgCtrl) if i == 0: backgroundList.append((bkgd, interpStyle, undersampleStyle,)) # no need to call getImage else: backgroundList.append(bkgd) # Relies on having called getImage; deprecated backImage += bkgd.getImageF(interpStyle, undersampleStyle) with utilsTests.getTempFilePath(".fits") as fileName: backgroundList.writeFits(fileName) backgrounds = afwMath.BackgroundList.readFits(fileName) img = backgrounds.getImage() # # Check that the read-back image is identical to that generated from the backgroundList # round-tripped to disk # backImage -= img self.assertEqual(np.min(backImage.getArray()), 0.0) self.assertEqual(np.max(backImage.getArray()), 0.0)
def testBackgroundList(self): """Test that a BackgroundLists behaves like a list""" bgCtrl = afwMath.BackgroundControl(10, 10) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER backgroundList = afwMath.BackgroundList() for i in range(2): bkgd = afwMath.makeBackground(self.image, bgCtrl) if i == 0: backgroundList.append((bkgd, interpStyle, undersampleStyle,)) # no need to call getImage else: backgroundList.append(bkgd) # Relies on having called getImage; deprecated def assertBackgroundList(bgl): self.assertEqual(len(bgl), 2) # check that len() works for a in bgl: # check that we can iterate pass self.assertEqual(len(bgl[0]), 3) # check that we can index self.assertEqual(len(bgl[1]), 3) # check that we always have a tuple (bkgd, interp, under) assertBackgroundList(backgroundList) # Check pickling new = pickle.loads(pickle.dumps(backgroundList)) assertBackgroundList(new) self.assertEqual(len(new), len(backgroundList)) for i, j in zip(new, backgroundList): self.assertBackgroundEqual(i[0], j[0]) self.assertEqual(i[1:], j[1:])
def testTicket987(self): """This code used to abort; so the test is that it doesn't""" afwdataDir = eups.productDir("afwdata") if not afwdataDir: print >> sys.stderr, "Skipping testTicket987 as afwdata is not setup" return imagePath = os.path.join(afwdataDir, "DC3a-Sim", "sci", "v5-e0", "v5-e0-c011-a00.sci.fits") mimg = afwImage.MaskedImageF(imagePath) binsize = 512 bctrl = afwMath.BackgroundControl("NATURAL_SPLINE") ### Adding this line solves the problem ### # note: by default undersampleStyle is THROW_EXCEPTION bctrl.setUndersampleStyle(afwMath.REDUCE_INTERP_ORDER) ################################################ nx = int(mimg.getWidth() / binsize) + 1 ny = int(mimg.getHeight() / binsize) + 1 #print 'Binning', nx, ny bctrl.setNxSample(nx) bctrl.setNySample(ny) image = mimg.getImage() backobj = afwMath.makeBackground(image, bctrl) image -= backobj.getImageF()
def testRamp(self): # make a ramping image (spline should be exact for linear increasing image nx = 512 ny = 512 rampimg = afwImage.ImageD(afwGeom.Extent2I(nx, ny)) dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 for x in range(nx): for y in range(ny): rampimg.set(x, y, dzdx*x + dzdy*y + z0) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(6) bctrl.setNySample(6) bctrl.getStatisticsControl().setNumSigmaClip(20.0) # something large enough to avoid clipping entirely bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(rampimg, bctrl) xpixels = [0, nx/2, nx - 1] ypixels = [0, ny/2, ny - 1] for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(xpix, ypix) self.assertAlmostEqual(testval/rampimg.get(xpix, ypix), 1, 6)
def complexBackground(image): MaskPixel = afwImage.MaskPixel binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 sctrl = afwMath.StatisticsControl() sctrl.setNumSigmaClip(3) sctrl.setNumIter(4) sctrl.setAndMask(afwImage.Mask[MaskPixel].getPlaneBitMask(["INTRP", "EDGE"])) sctrl.setNoGoodPixelsMask(afwImage.Mask[MaskPixel].getPlaneBitMask("BAD")) sctrl.setNanSafe(True) if False: sctrl.setWeighted(True) sctrl.setCalcErrorFromInputVariance(True) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) statsImage = bkgd.getStatsImage() ds9.mtv(statsImage.getVariance()) return bkgd
def testSubImage(self): """Test getImage on a subregion of the full background image Using real image data is a cheap way to get a variable background """ mi = self.getCfhtImage() bctrl = afwMath.BackgroundControl(mi.getWidth() // 128, mi.getHeight() // 128) backobj = afwMath.makeBackground(mi.getImage(), bctrl) subBBox = lsst.geom.Box2I(lsst.geom.Point2I(1000, 3000), lsst.geom.Extent2I(100, 100)) bgFullImage = backobj.getImageF(afwMath.Interpolate.AKIMA_SPLINE) self.assertEqual(bgFullImage.getBBox(), mi.getBBox()) subFullArr = afwImage.ImageF(bgFullImage, subBBox).getArray() bgSubImage = backobj.getImageF(subBBox, afwMath.Interpolate.AKIMA_SPLINE) subArr = bgSubImage.getArray() # the pixels happen to be identical but it is safer not to rely on # that; close is good enough self.assertFloatsEqual(subArr, subFullArr)
def testOddSize(self): """Test for ticket #1781 -- without it, in oddly-sized images there is a chunk of pixels on the right/bottom that do not go into the fit and are extrapolated. After this ticket, the subimage boundaries are spread more evenly so the last pixels get fit as well. This slightly strange test case checks that the interpolant is close to the function at the end. I could not think of an interpolant that would fit exactly, so this just puts a limit on the errors. """ W, H = 2, 99 image = afwImage.ImageF(lsst.geom.Extent2I(W, H)) bgCtrl = afwMath.BackgroundControl(afwMath.Interpolate.LINEAR) bgCtrl.setNxSample(2) NY = 10 bgCtrl.setNySample(NY) for y in range(H): for x in range(W): B = 89 if y < B: image[x, y, afwImage.LOCAL] = y else: image[x, y, afwImage.LOCAL] = B + (y-B)*-1. bobj = afwMath.makeBackground(image, bgCtrl) back = bobj.getImageF() for iy, by in zip([image[0, y, afwImage.LOCAL] for y in range(H)], [back[0, y, afwImage.LOCAL] for y in range(H)]): self.assertLess(abs(iy - by), 5)
def testCFHT(self): """Test background subtraction on some real CFHT data""" mi = self.getCfhtImage() bctrl = afwMath.BackgroundControl(mi.getWidth() // 128, mi.getHeight() // 128) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if debugMode: afwDisplay.Display(frame=0).mtv(mi, title=self._testMethodName + " image") im = mi.getImage() im -= backobj.getImageF("AKIMA_SPLINE") if debugMode: afwDisplay.Display(frame=1).mtv(mi, title=self._testMethodName + " image-back") statsImage = backobj.getStatsImage() if debugMode: afwDisplay.Display(frame=2).mtv(statsImage, title=self._testMethodName + " bkgd StatsImage") afwDisplay.Display(frame=3).mtv(statsImage.getVariance(), title=self._testMethodName + " bkgd Variance")
def testUndersample(self): """Test how the program handles nx,ny being too small for requested interp style.""" nx = 64 ny = 64 img = afwImage.ImageF(lsst.geom.Extent2I(nx, ny)) # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(3) bctrl.setNySample(3) # put nx,ny back to 2 and see if it adjusts the interp style down to # linear bctrl.setNxSample(2) bctrl.setNySample(2) bctrl.setUndersampleStyle("REDUCE_INTERP_ORDER") backobj = afwMath.makeBackground(img, bctrl) # Need to interpolate background to discover what we actually needed backobj.getImageF() self.assertEqual(backobj.getAsUsedInterpStyle(), afwMath.Interpolate.LINEAR) # put interp style back up to cspline and see if it throws an exception bctrl.setUndersampleStyle("THROW_EXCEPTION") def tst(img, bctrl): backobj = afwMath.makeBackground(img, bctrl) # only now do we see that we have too few points backobj.getImageF("CUBIC_SPLINE") self.assertRaises(lsst.pex.exceptions.InvalidParameterError, tst, img, bctrl)
def testBadRows(self): """Test that a bad set of rows in an image doesn't cause a failure""" initialValue = 20 mi = afwImage.MaskedImageF(500, 200) mi.set((initialValue, 0x0, 1.0)) mi.image[:, 0:100] = np.nan badBits = mi.mask.getPlaneBitMask( ['EDGE', 'DETECTED', 'DETECTED_NEGATIVE']) mi.mask[0:400, :] |= badBits if debugMode: afwDisplay.Display(frame=0).mtv(mi, title=self._testMethodName + " image") sctrl = afwMath.StatisticsControl() sctrl.setAndMask(badBits) nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) statsImage = bkgd.getStatsImage() if debugMode: afwDisplay.Display(frame=1).mtv(statsImage, title=self._testMethodName + " bkgd StatsImage") # the test is that this doesn't fail if the bug (#2297) is fixed for frame, interpStyle in enumerate([afwMath.Interpolate.CONSTANT, afwMath.Interpolate.LINEAR, afwMath.Interpolate.NATURAL_SPLINE, afwMath.Interpolate.AKIMA_SPLINE], 2): bkgdImage = bkgd.getImageF( interpStyle, afwMath.REDUCE_INTERP_ORDER) self.assertEqual( np.mean(bkgdImage[0:100, 0:100].array), initialValue) if debugMode: afwDisplay.Display(frame=frame).mtv(bkgdImage, title=self._testMethodName + " bkgdImage: " + interpStyle.__str__())
def testUndersample(self): """Test how the program handles nx,ny being too small for requested interp style.""" nx = 64 ny = 64 img = afwImage.ImageF(lsst.geom.Extent2I(nx, ny)) # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setNxSample(3) bctrl.setNySample(3) # put nx,ny back to 2 and see if it adjusts the interp style down to # linear bctrl.setNxSample(2) bctrl.setNySample(2) backobj = afwMath.makeBackground(img, bctrl) # Need to interpolate background to discover what we actually needed backobj.getImageF(afwMath.Interpolate.CUBIC_SPLINE, afwMath.UndersampleStyle.REDUCE_INTERP_ORDER) self.assertEqual(backobj.getAsUsedInterpStyle(), afwMath.Interpolate.LINEAR) def tst(img, bctrl): backobj = afwMath.makeBackground(img, bctrl) # only now do we see that we have too few points backobj.getImageF("CUBIC_SPLINE") self.assertRaises(lsst.pex.exceptions.InvalidParameterError, tst, img, bctrl)
def testCFHT(self): """Test background subtraction on some real CFHT data""" mi = self.getCfhtImage() bctrl = afwMath.BackgroundControl( mi.getWidth()//128, mi.getHeight()//128) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if debugMode: afwDisplay.Display(frame=0).mtv(mi, title=self._testMethodName + " image") im = mi.getImage() im -= backobj.getImageF("AKIMA_SPLINE") if debugMode: afwDisplay.Display(frame=1).mtv(mi, title=self._testMethodName + " image-back") statsImage = backobj.getStatsImage() if debugMode: afwDisplay.Display(frame=2).mtv(statsImage, title=self._testMethodName + " bkgd StatsImage") afwDisplay.Display(frame=3).mtv(statsImage.getVariance(), title=self._testMethodName + " bkgd Variance")
def testNaNFromMaskedImage(self): """Check that an extensively masked image doesn't lead to NaNs in the background estimation""" image = afwImage.MaskedImageF(800, 800) msk = image.getMask() bbox = lsst.geom.BoxI(lsst.geom.PointI(560, 0), lsst.geom.PointI(799, 335)) smsk = msk.Factory(msk, bbox) smsk.set(msk.getPlaneBitMask("DETECTED")) binSize = 256 nx = image.getWidth() // binSize + 1 ny = image.getHeight() // binSize + 1 sctrl = afwMath.StatisticsControl() sctrl.setAndMask( reduce(lambda x, y: x | image.getMask().getPlaneBitMask(y), ['EDGE', 'DETECTED', 'DETECTED_NEGATIVE'], 0x0)) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, "MEANCLIP") bkgd = afwMath.makeBackground(image, bctrl) bkgdImage = bkgd.getImageF("NATURAL_SPLINE", "THROW_EXCEPTION") if debugMode: afwDisplay.Display(frame=0).mtv(image, title=self._testMethodName + " image") afwDisplay.Display(frame=1).mtv(bkgdImage, title=self._testMethodName + " bkgdImage") self.assertFalse(np.isnan(bkgdImage[0, 0, afwImage.LOCAL])) # Check that the non-string API works too bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.THROW_EXCEPTION)
def testOnlyOneGridCell(self): """Test how the program handles nxSample,nySample being 1x1.""" # try a ramping image ... has an easy analytic solution nx = 64 ny = 64 img = afwImage.ImageF(lsst.geom.Extent2I(nx, ny), 10) dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 mean = z0 + dzdx * (nx - 1) / 2 + dzdy * ( ny - 1) / 2 # the analytic solution for x in range(nx): for y in range(ny): img[x, y, afwImage.LOCAL] = dzdx * x + dzdy * y + z0 # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setNxSample(1) bctrl.setNySample(1) bctrl.setUndersampleStyle(afwMath.THROW_EXCEPTION) backobj = afwMath.makeBackground(img, bctrl) xpixels = [0, nx // 2, nx - 1] ypixels = [0, ny // 2, ny - 1] for xpix in xpixels: for ypix in ypixels: testval = backobj.getImageF(afwMath.Interpolate.CONSTANT)[xpix, ypix] self.assertAlmostEqual(testval / mean, 1)
def testBadImage(self): """Test that an entirely bad image doesn't cause an absolute failure""" initialValue = 20 mi = afwImage.MaskedImageF(500, 200) # Check that no good values don't crash (they return NaN), and that a single good value # is enough to redeem the entire image for pix00 in [np.nan, initialValue]: mi.image[:] = np.nan mi.image[0, 0] = pix00 sctrl = afwMath.StatisticsControl() nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) for interpStyle in [ afwMath.Interpolate.CONSTANT, afwMath.Interpolate.LINEAR, afwMath.Interpolate.NATURAL_SPLINE, afwMath.Interpolate.AKIMA_SPLINE ]: # the test is that this doesn't fail if the bug (#2297) is # fixed bkgdImage = bkgd.getImageF(interpStyle, afwMath.REDUCE_INTERP_ORDER) val = np.mean(bkgdImage[0:100, 0:100].array) if np.isfinite(pix00): self.assertEqual(val, pix00) else: self.assertTrue(np.isnan(val))
def testOddSize(self): """Test for ticket #1781 -- without it, in oddly-sized images there is a chunk of pixels on the right/bottom that do not go into the fit and are extrapolated. After this ticket, the subimage boundaries are spread more evenly so the last pixels get fit as well. This slightly strange test case checks that the interpolant is close to the function at the end. I could not think of an interpolant that would fit exactly, so this just puts a limit on the errors. """ W, H = 2, 99 image = afwImage.ImageF(lsst.geom.Extent2I(W, H)) NY = 10 bgCtrl = afwMath.BackgroundControl(2, NY) for y in range(H): for x in range(W): B = 89 if y < B: image[x, y, afwImage.LOCAL] = y else: image[x, y, afwImage.LOCAL] = B + (y - B) * -1. bobj = afwMath.makeBackground(image, bgCtrl) back = bobj.getImageF(afwMath.Interpolate.LINEAR) for iy, by in zip([image[0, y, afwImage.LOCAL] for y in range(H)], [back[0, y, afwImage.LOCAL] for y in range(H)]): self.assertLess(abs(iy - by), 5)
def getBackground(image, backgroundConfig, nx=0, ny=0, algorithm=None): """ Make a new Exposure which is exposure - background """ backgroundConfig.validate() if not nx: nx = image.getWidth() // backgroundConfig.binSize + 1 if not ny: ny = image.getHeight() // backgroundConfig.binSize + 1 sctrl = afwMath.StatisticsControl() sctrl.setAndMask( reduce(lambda x, y: x | image.getMask().getPlaneBitMask(y), backgroundConfig.ignoredPixelMask, 0x0)) sctrl.setNanSafe(backgroundConfig.isNanSafe) pl = pexLogging.Debug("meas.utils.sourceDetection.getBackground") pl.debug( 3, "Ignoring mask planes: %s" % ", ".join(backgroundConfig.ignoredPixelMask)) if not algorithm: algorithm = backgroundConfig.algorithm bctrl = afwMath.BackgroundControl(algorithm, nx, ny, backgroundConfig.undersampleStyle, sctrl, backgroundConfig.statisticsProperty) return afwMath.makeBackground(image, bctrl)
def complexBackground(image): binsize = 128 nx = int(image.getWidth() / binsize) + 1 ny = int(image.getHeight() / binsize) + 1 sctrl = afwMath.StatisticsControl() sctrl.setNumSigmaClip(3) sctrl.setNumIter(4) sctrl.setAndMask(afwImage.MaskU.getPlaneBitMask(["INTRP", "EDGE"])) sctrl.setNoGoodPixelsMask(afwImage.MaskU.getPlaneBitMask("BAD")) sctrl.setNanSafe(True) if False: sctrl.setWeighted(True) sctrl.setCalcErrorFromInputVariance(True) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() ds9.mtv(statsImage.getVariance()) bkdgImages = dict(SPLINE=bkgd.getImageF( afwMath.Interpolate.NATURAL_SPLINE), LINEAR=bkgd.getImageF(afwMath.Interpolate.LINEAR)) return bkgd
def testLinearRampAsBackground(self): """Fit a ramp""" ramp, rampCoeffs = self.makeRamp()[0:2] if display: ds9.mtv(ramp, title="Input", frame=0) # Here's the range that the approximation should be valid (and also the # bbox of the image returned by getImage) bkgd = afwMath.makeBackground(ramp, afwMath.BackgroundControl(10, 10)) orderMax = 3 # 1 would be enough to fit the ramp for order in range(orderMax + 1): actrl = afwMath.ApproximateControl( afwMath.ApproximateControl.CHEBYSHEV, order) approx = bkgd.getApproximate(actrl) # Get the Image, the MaskedImage, and the Image with a truncated expansion for i, aim in enumerate([ approx.getImage(), approx.getMaskedImage().getImage(), approx.getImage(order - 1 if order > 1 else -1), ]): if display and (i == 0 and order == 1): ds9.mtv(aim, title="Interpolated", frame=1) for x, y in aim.getBBox().getCorners(): val = np.mean(aim.getArray()) if order == 0 else \ rampCoeffs[0] + rampCoeffs[1]*x + rampCoeffs[1]*y self.assertEqual(aim.get(x, y), val) # Check that we can't "truncate" the expansion to a higher order than we requested self.assertRaises(pexExcept.InvalidParameterError, lambda: approx.getImage(orderMax + 1, orderMax + 1))
def testParabola(self): """Test an image which varies parabolicly (spline should be exact for 2rd order polynomial)""" nx = 512 ny = 512 parabimg = self.getParabolaImage(nx, ny) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(24, 24) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(parabimg, bctrl) segmentCenter = int(0.5 * nx / bctrl.getNxSample()) xpixels = [segmentCenter, nx // 2, nx - segmentCenter] ypixels = [segmentCenter, ny // 2, ny - segmentCenter] for xpix in xpixels: for ypix in ypixels: testval = backobj.getImageF( afwMath.Interpolate.CUBIC_SPLINE)[xpix, ypix] realval = parabimg[xpix, ypix, afwImage.LOCAL] # quadratic terms skew the averages of the subimages and the clipped mean for # a subimage != value of center pixel. 1/20 counts on a 10000 count sky # is a fair (if arbitrary) test. self.assertLess(abs(testval - realval), 0.5)
def complexBackground(image): MaskPixel = afwImage.MaskPixel binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 sctrl = afwMath.StatisticsControl() sctrl.setNumSigmaClip(3) sctrl.setNumIter(4) sctrl.setAndMask(afwImage.Mask[MaskPixel].getPlaneBitMask(["INTRP", "EDGE"])) sctrl.setNoGoodPixelsMask(afwImage.Mask[MaskPixel].getPlaneBitMask("BAD")) sctrl.setNanSafe(True) if False: sctrl.setWeighted(True) sctrl.setCalcErrorFromInputVariance(True) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) statsImage = bkgd.getStatsImage() afwDisplay.Display(frame=3).mtv(statsImage.getVariance(), title="statsImage Variance") return bkgd
def testBackgroundTestImages(self): """Tests Laher's afwdata/Statistics/*.fits images (doubles)""" imginfolist = [] # cooked to known value imginfolist.append(["v1_i1_g_m400_s20_f.fits", 399.9912966583894]) for imginfo in imginfolist: imgfile, centerValue = imginfo imgPath = os.path.join(AfwdataDir, "Statistics", imgfile) # get the image and header dimg = afwImage.DecoratedImageF(imgPath) img = dimg.getImage() fitsHdr = dimg.getMetadata() # the FITS header # get the True values of the mean and stdev reqMean = fitsHdr.getAsDouble("MEANREQ") reqStdev = fitsHdr.getAsDouble("SIGREQ") naxis1 = img.getWidth() naxis2 = img.getHeight() # create a background control object bctrl = afwMath.BackgroundControl(5, 5) # run the background constructor and call the getImage() function. backobj = afwMath.makeBackground(img, bctrl) pixPerSubimage = img.getWidth()*img.getHeight() / \ (bctrl.getNxSample()*bctrl.getNySample()) stdevInterp = reqStdev / math.sqrt(pixPerSubimage) # test getImage() by checking the center pixel bimg = backobj.getImageF(afwMath.Interpolate.AKIMA_SPLINE) testImgval = bimg[naxis1 // 2, naxis2 // 2, afwImage.LOCAL] self.assertLess(abs(testImgval - reqMean), 2 * stdevInterp)
def testBadImage(self): """Test that an entirely bad image doesn't cause an absolute failure """ initialValue = 20 mi = afwImage.MaskedImageF(500, 200) # # Check that no good values don't crash (they return NaN), and that a single good value # is enough to redeem the entire image # for pix00 in [np.nan, initialValue]: mi.getImage()[:] = np.nan mi.getImage()[0, 0] = pix00 sctrl = afwMath.StatisticsControl() nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) afwMath.cast_BackgroundMI(bkgd).getStatsImage() # the test is that this doesn't fail if the bug (#2297) is fixed bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) val = np.mean(bkgdImage[0:100, 0:100].getArray()) if np.isfinite(pix00): self.assertEqual(val, pix00) else: self.assertTrue(np.isnan(val))
def testCFHT_oldAPI(self): """Test background subtraction on some real CFHT data""" mi = afwImage.MaskedImageF( os.path.join(AfwdataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits")) mi = mi.Factory( mi, afwGeom.Box2I(afwGeom.Point2I(32, 2), afwGeom.Point2I(2079, 4609)), afwImage.LOCAL) bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(16) bctrl.setNySample(16) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if display: ds9.mtv(mi, frame=0) im = mi.getImage() im -= backobj.getImageF() if display: ds9.mtv(mi, frame=1)
def testNaNFromMaskedImage(self): """Check that an extensively masked image doesn't lead to NaNs in the background estimation """ image = afwImage.MaskedImageF(800, 800) msk = image.getMask() bbox = afwGeom.BoxI(afwGeom.PointI(560, 0), afwGeom.PointI(799, 335)) smsk = msk.Factory(msk, bbox) smsk.set(msk.getPlaneBitMask("DETECTED")) binSize = 256 nx = image.getWidth()//binSize + 1 ny = image.getHeight()//binSize + 1 sctrl = afwMath.StatisticsControl() sctrl.setAndMask(reduce(lambda x, y: x | image.getMask().getPlaneBitMask(y), ['EDGE', 'DETECTED', 'DETECTED_NEGATIVE'], 0x0)) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, "MEANCLIP") bkgd = afwMath.makeBackground(image, bctrl) bkgdImage = bkgd.getImageF("NATURAL_SPLINE", "THROW_EXCEPTION") if display: ds9.mtv(image) ds9.mtv(bkgdImage, frame=1) self.assertFalse(np.isnan(bkgdImage.get(0,0))) # Check that the non-string API works too bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.THROW_EXCEPTION)
def testBadRows(self): """Test that a bad set of rows in an image doesn't cause a failure """ initialValue = 20 mi = afwImage.MaskedImageF(500, 200) mi.set((initialValue, 0x0, 1.0)) im = mi.getImage() im[:, 0:100] = np.nan del im msk = mi.getMask() badBits = msk.getPlaneBitMask(['EDGE', 'DETECTED', 'DETECTED_NEGATIVE']) msk[0:400, :] |= badBits del msk if display: ds9.mtv(mi, frame=0) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(badBits) nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() if display: ds9.mtv(statsImage, frame=1) # the test is that this doesn't fail if the bug (#2297) is fixed bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) self.assertEqual(np.mean(bkgdImage[0:100, 0:100].getArray()), initialValue) if display: ds9.mtv(bkgdImage, frame=2)
def testOnlyOneGridCell(self): """Test how the program handles nxSample,nySample being 1x1. """ # try a ramping image ... has an easy analytic solution nx = 64 ny = 64 img = afwImage.ImageF(afwGeom.Extent2I(nx, ny), 10) dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 mean = z0 + dzdx*(nx - 1)/2 + dzdy*(ny - 1)/2 # the analytic solution for x in range(nx): for y in range(ny): img.set(x, y, dzdx*x + dzdy*y + z0) # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) bctrl.setNxSample(1) bctrl.setNySample(1) bctrl.setUndersampleStyle(afwMath.THROW_EXCEPTION) backobj = afwMath.makeBackground(img, bctrl) xpixels = [0, nx//2, nx - 1] ypixels = [0, ny//2, ny - 1] for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(bctrl.getInterpStyle(), xpix, ypix) self.assertAlmostEqual(testval/mean, 1)
def testCFHT_oldAPI(self): """Test background subtraction on some real CFHT data""" mi = afwImage.MaskedImageF( os.path.join(AfwdataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits")) mi = mi.Factory( mi, lsst.geom.Box2I(lsst.geom.Point2I(32, 2), lsst.geom.Point2I(2079, 4609)), afwImage.LOCAL) bctrl = afwMath.BackgroundControl(16, 16) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if debugMode: afwDisplay.Display(frame=0).mtv(mi, title=self._testMethodName + " image") im = mi.getImage() im -= backobj.getImageF(afwMath.Interpolate.AKIMA_SPLINE) if debugMode: afwDisplay.Display(frame=1).mtv(mi, title=self._testMethodName + " image-back")
def testParabola(self): # make an image which varies parabolicly (spline should be exact for 2rd order polynomial) nx = 512 ny = 512 parabimg = self.getParabolaImage(nx, ny) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(24) bctrl.setNySample(24) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(parabimg, bctrl) segmentCenter = int(0.5*nx/bctrl.getNxSample()) xpixels = [segmentCenter, nx//2, nx - segmentCenter] ypixels = [segmentCenter, ny//2, ny - segmentCenter] for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(bctrl.getInterpStyle(), xpix, ypix) realval = parabimg.get(xpix, ypix) # quadratic terms skew the averages of the subimages and the clipped mean for # a subimage != value of center pixel. 1/20 counts on a 10000 count sky # is a fair (if arbitrary) test. self.assertTrue( abs(testval - realval) < 0.5 )
def testXY0(self): """Test fitting the background to an image with nonzero xy0 The statsImage and background image should not vary with xy0 """ bgImageList = [] # list of background images, one per xy0 statsImageList = [] # list of stats images, one per xy0 for xy0 in (afwGeom.Point2I(0, 0), afwGeom.Point2I(-100, -999), afwGeom.Point2I(1000, 500)): mi = self.getCfhtImage() mi.setXY0(xy0) bctrl = afwMath.BackgroundControl(mi.getWidth()//128, mi.getHeight()//128) backobj = afwMath.makeBackground(mi.getImage(), bctrl) bgImage = backobj.getImageF() self.assertEqual(bgImage.getBBox(), mi.getBBox()) bgImageList.append(bgImage) statsImage = afwMath.cast_BackgroundMI(backobj).getStatsImage() statsImageList.append(statsImage) # changing the bounding box should make no difference to the pixel values, # so compare pixels using exact equality for bgImage in bgImageList[1:]: self.assertTrue(np.all(bgImage.getArray() == bgImageList[0].getArray())) for statsImage in statsImageList[1:]: for i in range(3): self.assertTrue(np.all(statsImage.getArrays()[i] == statsImageList[0].getArrays()[i]))
def testXY0(self): """Test fitting the background to an image with nonzero xy0 The statsImage and background image should not vary with xy0 """ bgImageList = [] # list of background images, one per xy0 statsImageList = [] # list of stats images, one per xy0 for xy0 in (lsst.geom.Point2I(0, 0), lsst.geom.Point2I(-100, -999), lsst.geom.Point2I(1000, 500)): mi = self.getCfhtImage() mi.setXY0(xy0) bctrl = afwMath.BackgroundControl(mi.getWidth() // 128, mi.getHeight() // 128) backobj = afwMath.makeBackground(mi.getImage(), bctrl) bgImage = backobj.getImageF(afwMath.Interpolate.AKIMA_SPLINE) self.assertEqual(bgImage.getBBox(), mi.getBBox()) bgImageList.append(bgImage) statsImage = backobj.getStatsImage() statsImageList.append(statsImage) # changing the bounding box should make no difference to the pixel values, # so compare pixels using exact equality for bgImage in bgImageList[1:]: self.assertImagesEqual(bgImage, bgImageList[0]) for statsImage in statsImageList[1:]: self.assertMaskedImagesEqual(statsImage, statsImageList[0])
def bg_image(ccd, amp, nx=10, ny=10): """ Generate a background image using lsst.afw.math.makeBackground. """ bg_ctrl = afw_math.BackgroundControl(nx, ny, ccd.stat_ctrl) bg = afw_math.makeBackground(ccd[amp], bg_ctrl) return bg.getImageF()
def testCFHT(self): """Test background subtraction on some real CFHT data""" afwdataDir = eups.productDir("afwdata") if not afwdataDir: print >> sys.stderr, "Skipping testCFHT as afwdata is not setup" return mi = afwImage.MaskedImageF(os.path.join(afwdataDir, "CFHT", "D4", "cal-53535-i-797722_1")) mi = mi.Factory(mi, afwGeom.Box2I(afwGeom.Point2I(32, 2), afwGeom.Point2I(2079, 4609)), afwImage.LOCAL) bctrl = afwMath.BackgroundControl(mi.getWidth()//128, mi.getHeight()//128) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if display: ds9.mtv(mi, frame = 0) im = mi.getImage() im -= backobj.getImageF("AKIMA_SPLINE") if display: ds9.mtv(mi, frame = 1) statsImage = afwMath.cast_BackgroundMI(backobj).getStatsImage() if display: ds9.mtv(backobj.getStatsImage(), frame=2) ds9.mtv(backobj.getStatsImage().getVariance(), frame=3)
def testCFHT_oldAPI(self): """Test background subtraction on some real CFHT data""" afwdataDir = eups.productDir("afwdata") if not afwdataDir: print >> sys.stderr, "Skipping testCFHT as afwdata is not setup" return mi = afwImage.MaskedImageF(os.path.join(afwdataDir, "CFHT", "D4", "cal-53535-i-797722_1")) mi = mi.Factory(mi, afwGeom.Box2I(afwGeom.Point2I(32, 2), afwGeom.Point2I(2079, 4609)), afwImage.LOCAL) bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(16) bctrl.setNySample(16) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if display: ds9.mtv(mi, frame = 0) im = mi.getImage() im -= backobj.getImageF() if display: ds9.mtv(mi, frame = 1)
def testTicket987(self): """This code used to abort; so the test is that it doesn't""" afwdataDir = eups.productDir("afwdata") if not afwdataDir: print >> sys.stderr, "Skipping testTicket987 as afwdata is not setup" return imagePath = os.path.join(afwdataDir, "DC3a-Sim", "sci", "v5-e0", "v5-e0-c011-a00.sci") mimg = afwImage.MaskedImageF(imagePath) binsize = 512 bctrl = afwMath.BackgroundControl("NATURAL_SPLINE") ### Adding this line solves the problem ### # note: by default undersampleStyle is THROW_EXCEPTION bctrl.setUndersampleStyle(afwMath.REDUCE_INTERP_ORDER) ################################################ nx = int(mimg.getWidth()/binsize) + 1 ny = int(mimg.getHeight()/binsize) + 1 #print 'Binning', nx, ny bctrl.setNxSample(nx) bctrl.setNySample(ny) image = mimg.getImage() backobj = afwMath.makeBackground(image, bctrl) image -= backobj.getImageF()
def testBackgroundTestImages(self): imginfolist = [] #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.05551471441612] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00295902395123] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.08468385712251] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00305806663295] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.0035102188698] ) # cooked to known value imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 399.9912966583894] ) # cooked to known value #imgfiles.append("v1_i1_g_m400_s20_u16.fits") #imgfiles.append("v1_i2_g_m400_s20_f.fits" #imgfiles.append("v1_i2_g_m400_s20_u16.fits") #imgfiles.append("v2_i1_p_m9_f.fits") #imgfiles.append("v2_i1_p_m9_u16.fits") #imgfiles.append("v2_i2_p_m9_f.fits") #imgfiles.append("v2_i2_p_m9_u16.fits") afwdataDir = eups.productDir("afwdata") if not afwdataDir: print >> sys.stderr, "Skipping testBackgroundTestImages as afwdata is not setup" return for imginfo in imginfolist: imgfile, centerValue = imginfo imgPath = afwdataDir + "/Statistics/" + imgfile # get the image and header dimg = afwImage.DecoratedImageD(imgPath) img = dimg.getImage() fitsHdr = dimg.getMetadata() # the FITS header # get the True values of the mean and stdev reqMean = fitsHdr.getAsDouble("MEANREQ") reqStdev = fitsHdr.getAsDouble("SIGREQ") naxis1 = img.getWidth() naxis2 = img.getHeight() # create a background control object bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(5) bctrl.setNySample(5) # run the background constructor and call the getPixel() and getImage() functions. backobj = afwMath.makeBackground(img, bctrl) pixPerSubimage = img.getWidth()*img.getHeight()/(bctrl.getNxSample()*bctrl.getNySample()) stdevInterp = reqStdev/math.sqrt(pixPerSubimage) # test getPixel() testval = afwMath.cast_BackgroundMI(backobj).getPixel(naxis1/2, naxis2/2) self.assertAlmostEqual(testval/centerValue, 1, places=7) self.assertTrue( abs(testval - reqMean) < 2*stdevInterp ) # test getImage() by checking the center pixel bimg = backobj.getImageD() testImgval = bimg.get(naxis1/2, naxis2/2) self.assertTrue( abs(testImgval - reqMean) < 2*stdevInterp )
def detectSources(exposure, threshold, psf=None): """Detect sources above positiveThreshold in the provided exposure returning the sourceList """ if not psf: FWHM = 5 psf = algorithms.createPSF("DoubleGaussian", 15, 15, FWHM/(2*math.sqrt(2*math.log(2)))) # # Subtract background # mi = exposure.getMaskedImage() bctrl = afwMath.BackgroundControl(afwMath.NATURAL_SPLINE); bctrl.setNxSample(int(mi.getWidth()/256) + 1); bctrl.setNySample(int(mi.getHeight()/256) + 1); backobj = afwMath.makeBackground(mi.getImage(), bctrl) img = mi.getImage(); img -= backobj.getImageF(); del img if display: ds9.mtv(exposure) ds = detectFootprints(exposure, threshold) objects = ds.getFootprints() # # Time to actually measure # measPipelineDir = lsst.utils.getPackageDir('meas_pipeline') moPolicy = policy.Policy.createPolicy(os.path.join(measPipelineDir, "policy", "MeasureSources.paf")) moPolicy = moPolicy.getPolicy("measureObjects") measureSources = algorithms.makeMeasureSources(exposure, moPolicy, psf) sourceList = afwDetection.SourceSet() for i in range(len(objects)): source = afwDetection.Source() sourceList.append(source) source.setId(i) source.setFlagForDetection(source.getFlagForDetection() | algorithms.Flags.BINNED1); try: measureSources.apply(source, objects[i]) except Exception: pass if source.getFlagForDetection() & algorithms.Flags.EDGE: continue if display: xc, yc = source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0() if False: ds9.dot("%.1f %d" % (source.getPsfFlux(), source.getId()), xc, yc+1) ds9.dot("+", xc, yc, size=1) return sourceList
def testUndersample(self): """Test how the program handles nx,ny being too small for requested interp style.""" # make an image nx = 64 ny = 64 img = afwImage.ImageF(afwGeom.Extent2I(nx, ny)) # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(3) bctrl.setNySample(3) if False: # INCREASE_NXNYSAMPLE is no longer supported post #2074 bctrl.setNxSample(2) bctrl.setNySample(2) # see if it adjusts the nx,ny values up to 3x3 bctrl.setUndersampleStyle(afwMath.INCREASE_NXNYSAMPLE) backobj = afwMath.makeBackground(img, bctrl) self.assertEqual(backobj.getBackgroundControl().getNxSample(), 3) self.assertEqual(backobj.getBackgroundControl().getNySample(), 3) # put nx,ny back to 2 and see if it adjusts the interp style down to linear bctrl.setNxSample(2) bctrl.setNySample(2) bctrl.setUndersampleStyle("REDUCE_INTERP_ORDER") backobj = afwMath.makeBackground(img, bctrl) backobj.getImageF( ) # Need to interpolate background to discover what we actually needed self.assertEqual(backobj.getAsUsedInterpStyle(), afwMath.Interpolate.LINEAR) # put interp style back up to cspline and see if it throws an exception bctrl.setUndersampleStyle("THROW_EXCEPTION") def tst(img, bctrl): backobj = afwMath.makeBackground(img, bctrl) backobj.getImageF( "CUBIC_SPLINE" ) # only now do we see that we have too few points utilsTests.assertRaisesLsstCpp( self, lsst.pex.exceptions.InvalidParameterException, tst, img, bctrl)
def display_segment(ccd, amp, nx=10, ny=10): try: image = ccd.bias_subtracted_image(amp) except MaskedCCDBiasImageException: image = ccd[amp] bg_ctrl = afwMath.BackgroundControl(nx, ny, ccd.stat_ctrl) bg = afwMath.makeBackground(ccd[amp], bg_ctrl) image -= bg.getImageF() ds9.mtv(image)
def testApproximate(self): """Test I/O for BackgroundLists with Approximate""" # approx and interp should be very close, but not the same img = self.getParabolaImage(256, 256) # try regular interpolated image (the default) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER bgCtrl = afwMath.BackgroundControl(6, 6) bgCtrl.setInterpStyle(interpStyle) bgCtrl.setUndersampleStyle(undersampleStyle) bkgd = afwMath.makeBackground(img, bgCtrl) interpImage = bkgd.getImageF() with lsst.utils.tests.getTempFilePath("_bgi.fits") as bgiFile, \ lsst.utils.tests.getTempFilePath("_bga.fits") as bgaFile: bglInterp = afwMath.BackgroundList() bglInterp.append((bkgd, interpStyle, undersampleStyle, afwMath.ApproximateControl.UNKNOWN, 0, 0, True)) bglInterp.writeFits(bgiFile) # try an approx background approxStyle = afwMath.ApproximateControl.CHEBYSHEV approxOrder = 2 actrl = afwMath.ApproximateControl(approxStyle, approxOrder) bkgd.getBackgroundControl().setApproximateControl(actrl) approxImage = bkgd.getImageF() bglApprox = afwMath.BackgroundList() bglApprox.append((bkgd, interpStyle, undersampleStyle, approxStyle, approxOrder, approxOrder, True)) bglApprox.writeFits(bgaFile) # take a difference and make sure the two are very similar interpNp = interpImage.getArray() diff = np.abs(interpNp - approxImage.getArray()) / interpNp # the image and interp/approx parameters are chosen so these limits # will be greater than machine precision for float. The two methods # should be measurably different (so we know we're not just getting the # same thing from the getImage() method. But they should be very close # since they're both doing the same sort of thing. tolSame = 1.0e-3 # should be the same to this order tolDiff = 1.0e-4 # should be different here self.assertLess(diff.max(), tolSame) self.assertGreater(diff.max(), tolDiff) # now see if we can reload them from files and get the same images # we wrote interpImage2 = afwMath.BackgroundList().readFits( bgiFile).getImage() approxImage2 = afwMath.BackgroundList().readFits( bgaFile).getImage() idiff = interpImage.getArray() - interpImage2.getArray() adiff = approxImage.getArray() - approxImage2.getArray() self.assertEqual(idiff.max(), 0.0) self.assertEqual(adiff.max(), 0.0)
def testBackgroundTestImages(self): imginfolist = [] #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.05551471441612] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00295902395123] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.08468385712251] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00305806663295] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.0035102188698] ) # cooked to known value imginfolist.append(["v1_i1_g_m400_s20_f.fits", 399.9912966583894]) # cooked to known value #imgfiles.append("v1_i1_g_m400_s20_u16.fits") #imgfiles.append("v1_i2_g_m400_s20_f.fits" #imgfiles.append("v1_i2_g_m400_s20_u16.fits") #imgfiles.append("v2_i1_p_m9_f.fits") #imgfiles.append("v2_i1_p_m9_u16.fits") #imgfiles.append("v2_i2_p_m9_f.fits") #imgfiles.append("v2_i2_p_m9_u16.fits") for imginfo in imginfolist: imgfile, centerValue = imginfo imgPath = os.path.join(AfwdataDir, "Statistics", imgfile) # get the image and header dimg = afwImage.DecoratedImageD(imgPath) img = dimg.getImage() fitsHdr = dimg.getMetadata() # the FITS header # get the True values of the mean and stdev reqMean = fitsHdr.getAsDouble("MEANREQ") reqStdev = fitsHdr.getAsDouble("SIGREQ") naxis1 = img.getWidth() naxis2 = img.getHeight() # create a background control object bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(5) bctrl.setNySample(5) # run the background constructor and call the getPixel() and getImage() functions. backobj = afwMath.makeBackground(img, bctrl) pixPerSubimage = img.getWidth() * img.getHeight() / ( bctrl.getNxSample() * bctrl.getNySample()) stdevInterp = reqStdev / math.sqrt(pixPerSubimage) # test getPixel() testval = afwMath.cast_BackgroundMI(backobj).getPixel( naxis1 // 2, naxis2 // 2) self.assertAlmostEqual(testval / centerValue, 1, places=7) self.assertTrue(abs(testval - reqMean) < 2 * stdevInterp) # test getImage() by checking the center pixel bimg = backobj.getImageD() testImgval = bimg.get(naxis1 // 2, naxis2 // 2) self.assertTrue(abs(testImgval - reqMean) < 2 * stdevInterp)
def testRamp(self): # make a ramping image (spline should be exact for linear increasing image nx = 512 ny = 512 x0, y0 = 9876, 54321 box = afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(nx, ny)) rampimg = afwImage.ImageF(box) dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 for x in range(nx): for y in range(ny): rampimg.set(x, y, dzdx*x + dzdy*y + z0) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(6) bctrl.setNySample(6) bctrl.getStatisticsControl().setNumSigmaClip(20.0) # something large enough to avoid clipping entirely bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.cast_BackgroundMI(afwMath.makeBackground(rampimg, bctrl)) print(rampimg.getArray()) frame = 1 for interp in ("CONSTANT", "LINEAR", "NATURAL_SPLINE", "AKIMA_SPLINE"): diff = backobj.getImageF(interp) if display: ds9.mtv(diff, frame=frame); frame += 1 diff -= rampimg print(interp, diff.getArray().mean(), diff.getArray().std()) if display: ds9.mtv(diff, frame=frame); frame += 1 if display: ds9.mtv(rampimg, frame=frame); frame += 1 ds9.mtv(backobj.getStatsImage(), frame=frame); frame += 1 xpixels = [0, nx//2, nx - 1] ypixels = [0, ny//2, ny - 1] for xpix in xpixels: for ypix in ypixels: testval = backobj.getPixel(xpix, ypix) self.assertAlmostEqual(testval/rampimg.get(xpix, ypix), 1, 6) # Test pickle new = pickle.loads(pickle.dumps(backobj)) self.assertBackgroundEqual(backobj, new) # Check creation of sub-image box = afwGeom.Box2I(afwGeom.Point2I(123, 45), afwGeom.Extent2I(45, 123)) box.shift(afwGeom.Extent2I(x0, y0)) bgImage = backobj.getImageF("AKIMA_SPLINE") bgSubImage = afwImage.ImageF(bgImage, box) testImage = backobj.getImageF(box, "AKIMA_SPLINE") self.assertEqual(testImage.getXY0(), bgSubImage.getXY0()) self.assertEqual(testImage.getDimensions(), bgSubImage.getDimensions()) self.assertTrue(np.all(testImage.getArray() == bgSubImage.getArray()))
def testDetection(self): """Test CR detection""" # # Subtract background # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE); bctrl.setNxSample(int(self.mi.getWidth()/256) + 1); bctrl.setNySample(int(self.mi.getHeight()/256) + 1); bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) im = self.mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception, e: print >> sys.stderr, e, bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl)
def testDetection(self): """Test CR detection""" # # Subtract background # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(self.mi.getWidth() / 256) + 1) bctrl.setNySample(int(self.mi.getHeight() / 256) + 1) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) im = self.mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception, e: print >> sys.stderr, e, bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl)
def testTicket1681OffByOne(self): im = afwImage.ImageF(40, 40); im.set(5, 6, 100); nx, ny = im.getWidth()//2, im.getHeight()//2 print nx, ny bctrl = afwMath.BackgroundControl("LINEAR", nx, ny) bctrl.setStatisticsProperty(afwMath.MEAN) bkd = afwMath.makeBackground(im, bctrl) bim = bkd.getImageF() im.writeFits("im.fits") bim.writeFits("bim.fits")
def simpleBackground(image): binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 bctrl = afwMath.BackgroundControl(nx, ny) bkgd = afwMath.makeBackground(image, bctrl) image -= bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE) return bkgd
def testTicket1681OffByOne(self): if False: # doesn't seem to actually test anything, and writes b?im.fits im = afwImage.ImageF(40, 40); im.set(5, 6, 100); nx, ny = im.getWidth()//2, im.getHeight()//2 print(nx, ny) bctrl = afwMath.BackgroundControl("LINEAR", nx, ny) bctrl.setStatisticsProperty(afwMath.MEAN) bkd = afwMath.makeBackground(im, bctrl) bim = bkd.getImageF() im.writeFits("im.fits") bim.writeFits("bim.fits")
def testgetPixel(self): """Tests basic functionality of getPixel() method (floats)""" xcen, ycen = 50, 100 bgCtrl = afwMath.BackgroundControl(10, 10) bgCtrl.setNxSample(5) bgCtrl.setNySample(5) bgCtrl.getStatisticsControl().setNumIter(3) bgCtrl.getStatisticsControl().setNumSigmaClip(3) back = afwMath.makeBackground(self.image, bgCtrl) self.assertEqual(back.getPixel(xcen, ycen), self.val)
def testTicket1681OffByOne(self): if False: # doesn't seem to actually test anything, and writes b?im.fits im = afwImage.ImageF(40, 40); im.set(5, 6, 100); nx, ny = im.getWidth()//2, im.getHeight()//2 print nx, ny bctrl = afwMath.BackgroundControl("LINEAR", nx, ny) bctrl.setStatisticsProperty(afwMath.MEAN) bkd = afwMath.makeBackground(im, bctrl) bim = bkd.getImageF() im.writeFits("im.fits") bim.writeFits("bim.fits")