From 56bcefcadb06c806fc8e2eda189862f635547eaf Mon Sep 17 00:00:00 2001 From: Aaron Watkins Date: Tue, 25 Nov 2025 06:06:50 -0800 Subject: [PATCH] Remove matchBackgrounds unit test --- tests/test_matchBackgrounds.py | 317 --------------------------------- 1 file changed, 317 deletions(-) delete mode 100755 tests/test_matchBackgrounds.py diff --git a/tests/test_matchBackgrounds.py b/tests/test_matchBackgrounds.py deleted file mode 100755 index ac0e46b2f..000000000 --- a/tests/test_matchBackgrounds.py +++ /dev/null @@ -1,317 +0,0 @@ -# -# LSST Data Management System -# Copyright 2008, 2009, 2010 LSST Corporation. -# -# This product includes software developed by the -# LSST Project (http://www.lsst.org/). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the LSST License Statement and -# the GNU General Public License along with this program. If not, -# see . -# - -import unittest - -import numpy as np - -import lsst.utils.tests -import lsst.afw.image as afwImage -import lsst.afw.math as afwMath -from lsst.pipe.tasks.matchBackgrounds import MatchBackgroundsTask - - -class MatchBackgroundsTestCase(unittest.TestCase): - - """Background Matching""" - - def setUp(self): - np.random.seed(1) - - # Make a few test images here - # 1) full coverage (plain vanilla image) has mean = 50counts - self.vanilla = afwImage.ExposureF(600, 600) - im = self.vanilla.getMaskedImage().getImage() - afwMath.randomGaussianImage(im, afwMath.Random('MT19937', 1)) - im += 50 - self.vanilla.getMaskedImage().getVariance().set(1.0) - - # 2) has chip gap and mean = 10 counts - self.chipGap = afwImage.ExposureF(600, 600) - im = self.chipGap.getMaskedImage().getImage() - afwMath.randomGaussianImage(im, afwMath.Random('MT19937', 2)) - im += 10 - im.getArray()[:, 200:300] = np.nan # simulate 100pix chip gap - self.chipGap.getMaskedImage().getVariance().set(1.0) - - # 3) has low coverage and mean = 20 counts - self.lowCover = afwImage.ExposureF(600, 600) - im = self.lowCover.getMaskedImage().getImage() - afwMath.randomGaussianImage(im, afwMath.Random('MT19937', 3)) - im += 20 - self.lowCover.getMaskedImage().getImage().getArray()[:, 200:] = np.nan - self.lowCover.getMaskedImage().getVariance().set(1.0) - - # make a matchBackgrounds object - self.matcher = MatchBackgroundsTask() - self.matcher.config.usePolynomial = True - self.matcher.binSize = 64 - self.matcher.debugDataIdString = 'Test Visit' - - self.sctrl = afwMath.StatisticsControl() - self.sctrl.setNanSafe(True) - self.sctrl.setAndMask(afwImage.Mask.getPlaneBitMask(["NO_DATA", "DETECTED", "DETECTED_NEGATIVE", - "SAT", "BAD", "INTRP", "CR"])) - - def tearDown(self): - self.vanilla = None - self.lowCover = None - self.chipGap = None - self.matcher = None - self.sctrl = None - - def checkAccuracy(self, refExp, sciExp): - """Check for accurate background matching in the matchBackgrounds Method. - - To be called by tests expecting successful matching. - """ - struct = self.matcher.matchBackgrounds(refExp, sciExp) - resultExp = sciExp - MSE = struct.matchedMSE - diffImVar = struct.diffImVar - - resultStats = afwMath.makeStatistics(resultExp.getMaskedImage(), - afwMath.MEAN | afwMath.VARIANCE, - self.sctrl) - resultMean, _ = resultStats.getResult(afwMath.MEAN) - resultVar, _ = resultStats.getResult(afwMath.VARIANCE) - refStats = afwMath.makeStatistics( - refExp.getMaskedImage(), afwMath.MEAN | afwMath.VARIANCE, self.sctrl) - refMean, _ = refStats.getResult(afwMath.MEAN) - self.assertAlmostEqual(refMean, resultMean, delta=resultVar) # very loose test. - # If MSE is within 1% of the variance of the difference image: SUCCESS - self.assertLess(MSE, diffImVar * 1.01) - - # -=-=-=-=-=-=Test Polynomial Fit (Approximate class)-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - - def testConfig(self): - """Test checks on the configuration. - - 1) Should throw ValueError if binsize is > size of image - 2) Need Order + 1 points to fit. Should throw ValueError if Order > # of grid points - """ - for size in range(601, 1000, 100): - self.matcher.config.binSize = size - self.assertRaises(ValueError, self.matcher.matchBackgrounds, self.chipGap, self.vanilla) - - # for image 600x600 and binsize 256 = 3x3 grid for fitting. order 3,4,5...should fail - self.matcher.config.binSize = 256 - for order in range(3, 8): - self.matcher.config.order = order - self.assertRaises(ValueError, self.matcher.matchBackgrounds, self.chipGap, self.vanilla) - - for size, order in [(600, 0), (300, 1), (200, 2), (100, 5)]: - self.matcher.config.binSize = size - self.matcher.config.order = order - self.checkAccuracy(self.chipGap, self.vanilla) - - def testInputParams(self): - """Test throws RuntimeError when dimensions don't match.""" - self.matcher.config.binSize = 128 - self.matcher.config.order = 2 - # make image with wronge size - wrongSize = afwImage.ExposureF(500, 500) - wrongSize.getMaskedImage().getImage().set(1.0) - wrongSize.getMaskedImage().getVariance().set(1.0) - self.assertRaises(RuntimeError, self.matcher.matchBackgrounds, self.chipGap, wrongSize) - - def testVanillaApproximate(self): - """Test basic matching scenario with .Approximate.""" - self.matcher.config.binSize = 128 - self.matcher.config.order = 4 - self.checkAccuracy(self.chipGap, self.vanilla) - - def testRampApproximate(self): - """Test basic matching of a linear gradient with Approximate.""" - self.matcher.config.binSize = 64 - testExp = afwImage.ExposureF(self.vanilla, True) - testIm = testExp.getMaskedImage().getImage() - afwMath.randomGaussianImage(testIm, afwMath.Random()) - nx, ny = testExp.getDimensions() - dzdx, dzdy, z0 = 1, 2, 0.0 - for x in range(nx): - for y in range(ny): - z = testIm[x, y, afwImage.LOCAL] - testIm[x, y, afwImage.LOCAL] = z + dzdx * x + dzdy * y + z0 - self.checkAccuracy(testExp, self.vanilla) - - def testLowCoverThrowExpectionApproximate(self): - """Test low coverage with .config.undersampleStyle = THROW_EXCEPTION. - Confirm throws ValueError with Approximate. - """ - self.matcher.config.binSize = 64 - self.matcher.config.order = 8 - self.matcher.config.undersampleStyle = "THROW_EXCEPTION" - self.assertRaises(ValueError, self.matcher.matchBackgrounds, self.chipGap, self.lowCover) - - def testLowCoverIncreaseSampleApproximate(self): - """Test low coverage with .config.undersampleStyle = INCREASE_NXNYSAMPLE. - Confirm successful matching with .Approximate. - """ - self.matcher.config.binSize = 128 - self.matcher.config.order = 4 - self.matcher.config.undersampleStyle = "INCREASE_NXNYSAMPLE" - self.checkAccuracy(self.chipGap, self.lowCover) - - def testLowCoverReduceInterpOrderApproximate(self): - """Test low coverage with .config.undersampleStyle = REDUCE_INTERP_ORDER. - Confirm successful matching with .Approximate. - """ - self.matcher.config.binSize = 64 - self.matcher.config.order = 8 - self.matcher.config.undersampleStyle = "REDUCE_INTERP_ORDER" - self.checkAccuracy(self.chipGap, self.lowCover) - - def testMasksApproximate(self): - """Test that masks are ignored in matching backgrounds: .Approximate.""" - testExp = afwImage.ExposureF(self.chipGap, True) - im = testExp.getMaskedImage().getImage() - im += 10 - mask = testExp.getMaskedImage().getMask() - satbit = mask.getPlaneBitMask('SAT') - for i in range(0, 200, 20): - mask[5, i, afwImage.LOCAL] = satbit - im[5, i, afwImage.LOCAL] = 65000 - self.matcher.config.binSize = 128 - self.matcher.config.order = 4 - self.checkAccuracy(self.chipGap, testExp) - - def testWeightsByInvError(self): - """Test that bins with high std.dev. and low count are weighted less in fit.""" - testExp = afwImage.ExposureF(self.chipGap, True) - testIm = testExp.getMaskedImage().getImage() - self.matcher.config.binSize = 60 - self.matcher.config.order = 4 - for x in range(0, 50): - for y in range(0, 50): - if np.random.rand(1)[0] < 0.6: - testIm[x, y, afwImage.LOCAL] = np.nan - else: - testIm[x, y, afwImage.LOCAL] = np.random.rand()*1000 - - self.matcher.matchBackgrounds(self.vanilla, testExp) - resultExp = testExp - resultArr = resultExp.getMaskedImage().getImage().getArray()[60:, 60:] - resultMean = np.mean(resultArr[np.where(~np.isnan(resultArr))]) - resultVar = np.std(resultArr[np.where(~np.isnan(resultArr))])**2 - self.assertAlmostEqual(50, resultMean, delta=resultVar) # very loose test. - - def testSameImageApproximate(self): - """Test able to match identical images: .Approximate.""" - vanillaTwin = afwImage.ExposureF(self.vanilla, True) - self.matcher.config.binSize = 128 - self.matcher.config.order = 4 - self.checkAccuracy(self.vanilla, vanillaTwin) - - # -=-=-=-=-=-=-=-=-=Background Interp (Splines) -=-=-=-=-=-=-=-=- - - def testVanillaBackground(self): - """Test basic matching scenario with .Background.""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 128 - self.checkAccuracy(self.chipGap, self.vanilla) - - def testRampBackground(self): - """Test basic matching of a linear gradient with .Background.""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 64 - testExp = afwImage.ExposureF(self.vanilla, True) - testIm = testExp.getMaskedImage().getImage() - afwMath.randomGaussianImage(testIm, afwMath.Random()) - nx, ny = testExp.getDimensions() - dzdx, dzdy, z0 = 1, 2, 0.0 - for x in range(nx): - for y in range(ny): - z = testIm[x, y, afwImage.LOCAL] - testIm[x, y, afwImage.LOCAL] = z + dzdx * x + dzdy * y + z0 - self.checkAccuracy(testExp, self.vanilla) - - def testUndersampleBackgroundPasses(self): - """Test undersample style (REDUCE_INTERP_ORDER): .Background. - - INCREASE_NXNYSAMPLE no longer supported by .Background because .Backgrounds's are - defined by their nx and ny grid. - """ - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 256 - self.matcher.config.undersampleStyle = "REDUCE_INTERP_ORDER" - self.checkAccuracy(self.chipGap, self.vanilla) - - self.matcher.config.undersampleStyle = "INCREASE_NXNYSAMPLE" - self.assertRaises(RuntimeError, self.matcher.matchBackgrounds, self.chipGap, self.vanilla) - - def testSameImageBackground(self): - """Test able to match identical images with .Background.""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 256 - self.checkAccuracy(self.vanilla, self.vanilla) - - def testMasksBackground(self): - """Test masks ignored in matching backgrounds with .Background.""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 256 - testExp = afwImage.ExposureF(self.chipGap, True) - im = testExp.getMaskedImage().getImage() - im += 10 - mask = testExp.getMaskedImage().getMask() - satbit = mask.getPlaneBitMask('SAT') - for i in range(0, 200, 20): - mask[5, i, afwImage.LOCAL] = satbit - im[5, i, afwImage.LOCAL] = 65000 - self.checkAccuracy(self.chipGap, testExp) - - def testChipGapHorizontalBackground(self): - """ Test able to match image with horizontal chip gap (row of nans) with .Background""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 64 - chipGapHorizontal = afwImage.ExposureF(600, 600) - im = chipGapHorizontal.getMaskedImage().getImage() - afwMath.randomGaussianImage(im, afwMath.Random()) - im += 10 - im.getArray()[200:300, :] = np.nan # simulate 100pix chip gap horizontal - chipGapHorizontal.getMaskedImage().getVariance().set(1.0) - self.checkAccuracy(self.vanilla, chipGapHorizontal) - - def testChipGapVerticalBackground(self): - """ Test able to match images with vertical chip gaps (column of nans) wider than bin size""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 64 - self.checkAccuracy(self.chipGap, self.vanilla) - - def testLowCoverBackground(self): - """ Test able to match images that do not cover the whole patch""" - self.matcher.config.usePolynomial = False - self.matcher.config.binSize = 64 - self.checkAccuracy(self.vanilla, self.lowCover) - - -def setup_module(module): - lsst.utils.tests.init() - - -class MatchMemoryTestCase(lsst.utils.tests.MemoryTestCase): - pass - - -if __name__ == "__main__": - lsst.utils.tests.init() - unittest.main()