Coverage for tests/test_subtractExposures.py: 17%
172 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-01 02:27 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-01 02:27 -0700
1import logging
2import os
3import unittest
6import lsst.utils.tests
7import lsst.utils
8import lsst.afw.image as afwImage
9import lsst.afw.math as afwMath
10import lsst.geom as geom
11import lsst.utils.logging as logUtils
12import lsst.meas.algorithms as measAlg
13import lsst.ip.diffim as ipDiffim
14import lsst.ip.diffim.diffimTools as diffimTools
16verbosity = 4
17logUtils.trace_set_at("lsst.ip.diffim", verbosity)
18logUtils.getLogger('lsst.psfMatch').setLevel(logging.INFO)
20display = False
22# known input images
23try:
24 defDataDir = lsst.utils.getPackageDir('afwdata')
25except Exception:
26 defDataDir = None
29class DiffimTestCases(lsst.utils.tests.TestCase):
31 # D = I - (K.x.T + bg)
33 def setUp(self):
34 self.config = ipDiffim.ImagePsfMatchTask.ConfigClass()
35 self.config.kernel.name = "AL"
36 self.subconfig = self.config.kernel.active
38 # Some of the tests are sensitive to the centroids returned by
39 # "stdev" vs "pixel_stdev"
40 self.subconfig.detectionConfig.detThresholdType = "stdev"
42 # Impacts some of the test values
43 self.subconfig.constantVarianceWeighting = True
45 if defDataDir:
47 defTemplatePath = os.path.join(defDataDir, "DC3a-Sim", "sci", "v5-e0",
48 "v5-e0-c011-a00.sci.fits")
49 defSciencePath = os.path.join(defDataDir, "DC3a-Sim", "sci", "v26-e0",
50 "v26-e0-c011-a00.sci.fits")
52 self.scienceImage = afwImage.ExposureF(defSciencePath)
53 self.templateImage = afwImage.ExposureF(defTemplatePath)
55 bgConfig = self.subconfig.afwBackgroundConfig
56 bgConfig.useApprox = False
57 bgConfig.binSize = 512
58 diffimTools.backgroundSubtract(bgConfig,
59 [self.templateImage.getMaskedImage(),
60 self.scienceImage.getMaskedImage()])
62 self.offset = 1500
63 self.bbox = geom.Box2I(geom.Point2I(0, self.offset),
64 geom.Point2I(511, 2046))
65 self.subconfig.spatialKernelOrder = 1
66 self.subconfig.spatialBgOrder = 0
68 # Take a stab at a PSF. This is needed to get the KernelCandidateList if you don't provide one.
69 ksize = 21
70 sigma = 2.0
71 self.psf = measAlg.DoubleGaussianPsf(ksize, ksize, sigma)
72 self.scienceImage.setPsf(self.psf)
73 self.templateImage.setPsf(self.psf)
75 def tearDown(self):
76 del self.config
77 if defDataDir:
78 del self.scienceImage
79 del self.templateImage
80 del self.psf
82 def testModelType(self):
83 self.runModelType(fitForBackground=True)
84 self.runModelType(fitForBackground=False)
86 @unittest.skipIf(not defDataDir, "Warning: afwdata is not set up")
87 def runModelType(self, fitForBackground):
88 self.subconfig.fitForBackground = fitForBackground
90 templateSubImage = afwImage.ExposureF(self.templateImage, self.bbox)
91 scienceSubImage = afwImage.ExposureF(self.scienceImage, self.bbox)
93 self.subconfig.spatialModelType = 'chebyshev1'
94 psfmatch1 = ipDiffim.ImagePsfMatchTask(config=self.config)
95 results1 = psfmatch1.subtractExposures(templateSubImage, scienceSubImage, doWarping=True)
96 spatialKernel1 = results1.psfMatchingKernel
97 backgroundModel1 = results1.backgroundModel
99 self.subconfig.spatialModelType = 'polynomial'
100 psfmatch2 = ipDiffim.ImagePsfMatchTask(config=self.config)
101 results2 = psfmatch2.subtractExposures(templateSubImage, scienceSubImage, doWarping=True)
102 spatialKernel2 = results2.psfMatchingKernel
103 backgroundModel2 = results2.backgroundModel
105 # Got the types right?
106 self.assertTrue(
107 spatialKernel1.getSpatialFunctionList()[0].toString().startswith('Chebyshev1Function2')
108 )
109 self.assertTrue(
110 spatialKernel2.getSpatialFunctionList()[0].toString().startswith('PolynomialFunction2')
111 )
113 # First order term has zero spatial variation and sum = kernel sum
114 kp1par0 = spatialKernel1.getSpatialFunctionList()[0].getParameters()
115 kp2par0 = spatialKernel2.getSpatialFunctionList()[0].getParameters()
116 self.assertAlmostEqual(kp1par0[0], kp2par0[0], delta=1e-5)
117 for i in range(1, len(kp1par0)):
118 self.assertAlmostEqual(kp1par0[i], 0.0, delta=1e-5)
119 self.assertAlmostEqual(kp1par0[i], kp2par0[i], delta=1e-5)
121 if fitForBackground:
122 # Nterms (zeroth order model)
123 self.assertEqual(backgroundModel1.getNParameters(), 1)
124 self.assertEqual(backgroundModel2.getNParameters(), 1)
126 # Same value of function coefficients (different to 0.001 level)
127 self.assertAlmostEqual(backgroundModel1.getParameters()[0],
128 backgroundModel2.getParameters()[0], delta=1e-3)
130 # Functions evaluate to same value at origin (0.001 difference)
131 self.assertAlmostEqual(backgroundModel1(0, 0), backgroundModel2(0, 0), delta=1e-3)
133 # At at different location within image
134 self.assertAlmostEqual(backgroundModel1(10, 10), backgroundModel2(10, 10), delta=1e-3)
136 else:
137 # More improtant is the kernel needs to be then same when realized at a coordinate
138 kim1 = afwImage.ImageD(spatialKernel1.getDimensions())
139 kim2 = afwImage.ImageD(spatialKernel2.getDimensions())
140 ksum1 = spatialKernel1.computeImage(kim1, False, 0.0, 0.0)
141 ksum2 = spatialKernel2.computeImage(kim2, False, 0.0, 0.0)
142 self.assertAlmostEqual(ksum1, ksum2, delta=1e-5)
143 for y in range(kim1.getHeight()):
144 for x in range(kim1.getHeight()):
145 self.assertAlmostEqual(kim1[x, y, afwImage.LOCAL], kim2[x, y, afwImage.LOCAL],
146 delta=1e-1)
148 # Nterms (zeroth order)
149 self.assertEqual(backgroundModel1.getNParameters(), 1)
150 self.assertEqual(backgroundModel2.getNParameters(), 1)
152 # Zero value in function
153 self.assertAlmostEqual(backgroundModel1.getParameters()[0], 0.0, delta=1e-7)
154 self.assertAlmostEqual(backgroundModel2.getParameters()[0], 0.0, delta=1e-7)
156 # Function evaluates to zero
157 self.assertAlmostEqual(backgroundModel1(0, 0), 0.0, delta=1e-7)
158 self.assertAlmostEqual(backgroundModel2(0, 0), 0.0, delta=1e-7)
160 # Spatially...
161 self.assertAlmostEqual(backgroundModel1(10, 10), 0.0, delta=1e-7)
162 self.assertAlmostEqual(backgroundModel2(10, 10), 0.0, delta=1e-7)
164 @unittest.skipIf(not defDataDir, "Warning: afwdata is not set up")
165 def testWarping(self):
166 templateSubImage = afwImage.ExposureF(self.templateImage, self.bbox)
167 scienceSubImage = afwImage.ExposureF(self.scienceImage, self.bbox)
168 psfmatch = ipDiffim.ImagePsfMatchTask(config=self.config)
169 try:
170 psfmatch.subtractExposures(templateSubImage, scienceSubImage, doWarping=False)
171 except Exception:
172 pass
173 else:
174 self.fail()
176 def testXY0(self):
177 self.runXY0('polynomial')
178 self.runXY0('chebyshev1')
180 @unittest.skipIf(not defDataDir, "Warning: afwdata is not set up")
181 def runXY0(self, poly, fitForBackground=False):
182 self.subconfig.spatialModelType = poly
183 self.subconfig.fitForBackground = fitForBackground
185 templateSubImage = afwImage.ExposureF(self.templateImage.clone(), self.bbox)
186 scienceSubImage = afwImage.ExposureF(self.scienceImage.clone(), self.bbox)
188 # Have an XY0
189 psfmatch = ipDiffim.ImagePsfMatchTask(config=self.config)
190 fwhm = psfmatch.getFwhmPix(self.psf)
191 results1 = psfmatch.subtractExposures(templateSubImage, scienceSubImage, doWarping=True,
192 templateFwhmPix=fwhm, scienceFwhmPix=fwhm)
193 spatialKernel1 = results1.psfMatchingKernel
194 backgroundModel1 = results1.backgroundModel
195 kernelCellSet1 = results1.kernelCellSet
197 # And then take away XY0
198 templateSubImage = afwImage.ExposureF(self.templateImage.clone(), self.bbox)
199 scienceSubImage = afwImage.ExposureF(self.scienceImage.clone(), self.bbox)
200 templateSubImage.setXY0(geom.Point2I(0, 0))
201 scienceSubImage.setXY0(geom.Point2I(0, 0))
203 results2 = psfmatch.subtractExposures(templateSubImage, scienceSubImage, doWarping=True,
204 templateFwhmPix=fwhm, scienceFwhmPix=fwhm)
205 spatialKernel2 = results2.psfMatchingKernel
206 backgroundModel2 = results2.backgroundModel
207 kernelCellSet2 = results2.kernelCellSet
209 # need to count up the candidates first, since its a running tally
210 count = 0
211 for cell in kernelCellSet1.getCellList():
212 for cand1 in cell.begin(False):
213 count += 1
215 for cell in kernelCellSet1.getCellList():
216 for cand1 in cell.begin(False):
217 if cand1.getStatus() == afwMath.SpatialCellCandidate.UNKNOWN:
218 continue
219 if cand1.getStatus() == afwMath.SpatialCellCandidate.BAD:
220 continue
222 cand2 = kernelCellSet2.getCandidateById(cand1.getId()+count)
224 # positions are nearly the same (different at the 0.01 pixel level)
225 self.assertAlmostEqual(cand1.getXCenter(), cand2.getXCenter(), delta=1e-1)
226 self.assertAlmostEqual(cand1.getYCenter(), cand2.getYCenter() + self.offset, delta=1e-1)
228 # kernels are the same
229 im1 = cand1.getKernelImage(ipDiffim.KernelCandidateF.RECENT)
230 im2 = cand2.getKernelImage(ipDiffim.KernelCandidateF.RECENT)
231 for y in range(im1.getHeight()):
232 for x in range(im1.getWidth()):
233 self.assertAlmostEqual(im1[x, y, afwImage.LOCAL], im2[x, y, afwImage.LOCAL],
234 delta=1e-7)
236 # Spatial fits are the same
237 skp1 = spatialKernel1.getSpatialParameters()
238 skp2 = spatialKernel2.getSpatialParameters()
239 bgp1 = backgroundModel1.getParameters()
240 bgp2 = backgroundModel2.getParameters()
242 # first term = kernel sum, 0, 0
243 self.assertAlmostEqual(skp1[0][0], skp2[0][0], delta=1e-6)
245 # On other terms, the spatial terms are the same, the zpt terms are different
246 for nk in range(1, len(skp1)):
248 # Zeropoint
249 if poly == 'polynomial':
250 self.assertNotEqual(skp1[nk][0], skp2[nk][0])
251 elif poly == 'chebyshev1':
252 # Cheby remaps coords, so model should be the same!
253 self.assertAlmostEqual(skp1[nk][0], skp2[nk][0], delta=1e-4)
254 else:
255 self.fail()
257 # Spatial terms
258 for np in range(1, len(skp1[nk])):
259 self.assertAlmostEqual(skp1[nk][np], skp2[nk][np], delta=1e-4)
261 for np in range(len(bgp1)):
262 self.assertAlmostEqual(bgp1[np], bgp2[np], delta=1e-4)
264#####
267class TestMemory(lsst.utils.tests.MemoryTestCase):
268 pass
271def setup_module(module):
272 lsst.utils.tests.init()
275if __name__ == "__main__": 275 ↛ 276line 275 didn't jump to line 276, because the condition on line 275 was never true
276 lsst.utils.tests.init()
277 unittest.main()