Coverage for tests/test_subtractExposures.py: 17%

172 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-14 03:10 -0800

1import logging 

2import os 

3import unittest 

4 

5 

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 

15 

16verbosity = 4 

17logUtils.trace_set_at("lsst.ip.diffim", verbosity) 

18logUtils.getLogger('lsst.psfMatch').setLevel(logging.INFO) 

19 

20display = False 

21 

22# known input images 

23try: 

24 defDataDir = lsst.utils.getPackageDir('afwdata') 

25except Exception: 

26 defDataDir = None 

27 

28 

29class DiffimTestCases(lsst.utils.tests.TestCase): 

30 

31 # D = I - (K.x.T + bg) 

32 

33 def setUp(self): 

34 self.config = ipDiffim.ImagePsfMatchTask.ConfigClass() 

35 self.config.kernel.name = "AL" 

36 self.subconfig = self.config.kernel.active 

37 

38 # Some of the tests are sensitive to the centroids returned by 

39 # "stdev" vs "pixel_stdev" 

40 self.subconfig.detectionConfig.detThresholdType = "stdev" 

41 

42 # Impacts some of the test values 

43 self.subconfig.constantVarianceWeighting = True 

44 

45 if defDataDir: 

46 

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") 

51 

52 self.scienceImage = afwImage.ExposureF(defSciencePath) 

53 self.templateImage = afwImage.ExposureF(defTemplatePath) 

54 

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()]) 

61 

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 

67 

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) 

74 

75 def tearDown(self): 

76 del self.config 

77 if defDataDir: 

78 del self.scienceImage 

79 del self.templateImage 

80 del self.psf 

81 

82 def testModelType(self): 

83 self.runModelType(fitForBackground=True) 

84 self.runModelType(fitForBackground=False) 

85 

86 @unittest.skipIf(not defDataDir, "Warning: afwdata is not set up") 

87 def runModelType(self, fitForBackground): 

88 self.subconfig.fitForBackground = fitForBackground 

89 

90 templateSubImage = afwImage.ExposureF(self.templateImage, self.bbox) 

91 scienceSubImage = afwImage.ExposureF(self.scienceImage, self.bbox) 

92 

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 

98 

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 

104 

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 ) 

112 

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) 

120 

121 if fitForBackground: 

122 # Nterms (zeroth order model) 

123 self.assertEqual(backgroundModel1.getNParameters(), 1) 

124 self.assertEqual(backgroundModel2.getNParameters(), 1) 

125 

126 # Same value of function coefficients (different to 0.001 level) 

127 self.assertAlmostEqual(backgroundModel1.getParameters()[0], 

128 backgroundModel2.getParameters()[0], delta=1e-3) 

129 

130 # Functions evaluate to same value at origin (0.001 difference) 

131 self.assertAlmostEqual(backgroundModel1(0, 0), backgroundModel2(0, 0), delta=1e-3) 

132 

133 # At at different location within image 

134 self.assertAlmostEqual(backgroundModel1(10, 10), backgroundModel2(10, 10), delta=1e-3) 

135 

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) 

147 

148 # Nterms (zeroth order) 

149 self.assertEqual(backgroundModel1.getNParameters(), 1) 

150 self.assertEqual(backgroundModel2.getNParameters(), 1) 

151 

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) 

155 

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) 

159 

160 # Spatially... 

161 self.assertAlmostEqual(backgroundModel1(10, 10), 0.0, delta=1e-7) 

162 self.assertAlmostEqual(backgroundModel2(10, 10), 0.0, delta=1e-7) 

163 

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() 

175 

176 def testXY0(self): 

177 self.runXY0('polynomial') 

178 self.runXY0('chebyshev1') 

179 

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 

184 

185 templateSubImage = afwImage.ExposureF(self.templateImage.clone(), self.bbox) 

186 scienceSubImage = afwImage.ExposureF(self.scienceImage.clone(), self.bbox) 

187 

188 # Have an XY0 

189 psfmatch = ipDiffim.ImagePsfMatchTask(config=self.config) 

190 fwhm = ipDiffim.utils.getPsfFwhm(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 

196 

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)) 

202 

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 

208 

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 

214 

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 

221 

222 cand2 = kernelCellSet2.getCandidateById(cand1.getId()+count) 

223 

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) 

227 

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) 

235 

236 # Spatial fits are the same 

237 skp1 = spatialKernel1.getSpatialParameters() 

238 skp2 = spatialKernel2.getSpatialParameters() 

239 bgp1 = backgroundModel1.getParameters() 

240 bgp2 = backgroundModel2.getParameters() 

241 

242 # first term = kernel sum, 0, 0 

243 self.assertAlmostEqual(skp1[0][0], skp2[0][0], delta=1e-6) 

244 

245 # On other terms, the spatial terms are the same, the zpt terms are different 

246 for nk in range(1, len(skp1)): 

247 

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() 

256 

257 # Spatial terms 

258 for np in range(1, len(skp1[nk])): 

259 self.assertAlmostEqual(skp1[nk][np], skp2[nk][np], delta=1e-4) 

260 

261 for np in range(len(bgp1)): 

262 self.assertAlmostEqual(bgp1[np], bgp2[np], delta=1e-4) 

263 

264##### 

265 

266 

267class TestMemory(lsst.utils.tests.MemoryTestCase): 

268 pass 

269 

270 

271def setup_module(module): 

272 lsst.utils.tests.init() 

273 

274 

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()