Coverage for tests/test_kernelIo1.py: 10%

201 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-11 02:47 -0700

1 

2# 

3# LSST Data Management System 

4# Copyright 2008, 2009, 2010 LSST Corporation. 

5# 

6# This product includes software developed by the 

7# LSST Project (http://www.lsst.org/). 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the LSST License Statement and 

20# the GNU General Public License along with this program. If not, 

21# see <http://www.lsstcorp.org/LegalNotices/>. 

22# 

23 

24import unittest 

25import os 

26 

27import numpy as np 

28 

29import lsst.utils.tests 

30import lsst.geom 

31import lsst.afw.image as afwImage 

32import lsst.afw.math as afwMath 

33from lsst.log import Log 

34 

35# Change the level to Log.DEBUG to see debug messages 

36Log.getLogger("lsst.afw.math.KernelFormatter").setLevel(Log.INFO) 

37 

38 

39testPath = os.path.abspath(os.path.dirname(__file__)) 

40 

41 

42class KernelIOTestCase(unittest.TestCase): 

43 """A test case for Kernel I/O""" 

44 

45 def kernelCheck(self, k1, k2): 

46 self.assertEqual(k1.getWidth(), k2.getWidth()) 

47 self.assertEqual(k1.getHeight(), k2.getHeight()) 

48 self.assertEqual(k1.getCtr(), k2.getCtr()) 

49 self.assertEqual(k1.getNKernelParameters(), k2.getNKernelParameters()) 

50 self.assertEqual(k1.getNSpatialParameters(), 

51 k2.getNSpatialParameters()) 

52 self.assertEqual(k1.getKernelParameters(), k2.getKernelParameters()) 

53 self.assertEqual(k1.getSpatialParameters(), k2.getSpatialParameters()) 

54 self.assertEqual(k1.isSpatiallyVarying(), k2.isSpatiallyVarying()) 

55 self.assertEqual(k1.toString(), k2.toString()) 

56 

57 def testFixedKernel(self): 

58 """Test FixedKernel using a ramp function 

59 """ 

60 kWidth = 5 

61 kHeight = 6 

62 

63 inArr = np.arange(kWidth * kHeight, dtype=float) 

64 inArr.shape = [kWidth, kHeight] 

65 

66 inImage = afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight)) 

67 for row in range(inImage.getHeight()): 

68 for col in range(inImage.getWidth()): 

69 inImage[col, row, afwImage.LOCAL] = inArr[col, row] 

70 

71 k = afwMath.FixedKernel(inImage) 

72 

73 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

74 k.writeFits(filename) 

75 k2 = afwMath.FixedKernel.readFits(filename) 

76 

77 self.kernelCheck(k, k2) 

78 

79 outImage = afwImage.ImageD(k2.getDimensions()) 

80 k2.computeImage(outImage, False) 

81 

82 outArr = outImage.getArray().transpose() 

83 if not np.allclose(inArr, outArr): 

84 self.fail(f"{k2.__class__.__name__} = {inArr} != {outArr} (not normalized)") 

85 normInArr = inArr / inArr.sum() 

86 normOutImage = afwImage.ImageD(k2.getDimensions()) 

87 k2.computeImage(normOutImage, True) 

88 normOutArr = normOutImage.getArray().transpose() 

89 if not np.allclose(normOutArr, normInArr): 

90 self.fail(f"{k2.__class__.__name__} = {normInArr} != {normOutArr} (normalized)") 

91 

92 def testAnalyticKernel(self): 

93 """Test AnalyticKernel using a Gaussian function 

94 """ 

95 kWidth = 5 

96 kHeight = 8 

97 

98 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) 

99 k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) 

100 center = k.getCtr() 

101 fArr = np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) 

102 for xsigma in (0.1, 1.0, 3.0): 

103 for ysigma in (0.1, 1.0, 3.0): 

104 for angle in (0.0, 0.4, 1.1): 

105 gaussFunc.setParameters((xsigma, ysigma, angle)) 

106 # compute array of function values and normalize 

107 for row in range(k.getHeight()): 

108 y = row - center.getY() 

109 for col in range(k.getWidth()): 

110 x = col - center.getX() 

111 fArr[col, row] = gaussFunc(x, y) 

112 fArr /= fArr.sum() 

113 

114 k.setKernelParameters((xsigma, ysigma, angle)) 

115 

116 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

117 k.writeFits(filename) 

118 k2 = afwMath.AnalyticKernel.readFits(filename) 

119 

120 self.kernelCheck(k, k2) 

121 

122 kImage = afwImage.ImageD(k2.getDimensions()) 

123 k2.computeImage(kImage, True) 

124 kArr = kImage.getArray().transpose() 

125 if not np.allclose(fArr, kArr): 

126 self.fail(f"{k2.__class__.__name__} = {kArr} != {fArr} " 

127 f"for xsigma={xsigma}, ysigma={ysigma}") 

128 

129 def testDeltaFunctionKernel(self): 

130 """Test DeltaFunctionKernel 

131 """ 

132 for kWidth in range(1, 4): 

133 for kHeight in range(1, 4): 

134 for activeCol in range(kWidth): 

135 for activeRow in range(kHeight): 

136 kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, 

137 lsst.geom.Point2I(activeCol, activeRow)) 

138 

139 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

140 kernel.writeFits(filename) 

141 k2 = afwMath.DeltaFunctionKernel.readFits(filename) 

142 

143 self.kernelCheck(kernel, k2) 

144 self.assertEqual(kernel.getPixel(), k2.getPixel()) 

145 

146 kImage = afwImage.ImageD(k2.getDimensions()) 

147 kSum = k2.computeImage(kImage, False) 

148 self.assertEqual(kSum, 1.0) 

149 kArr = kImage.getArray().transpose() 

150 self.assertEqual(kArr[activeCol, activeRow], 1.0) 

151 kArr[activeCol, activeRow] = 0.0 

152 self.assertEqual(kArr.sum(), 0.0) 

153 

154 @unittest.skip("SeparableKernel does not yet support table persistence") 

155 def testSeparableKernel(self): 

156 """Test SeparableKernel using a Gaussian function 

157 """ 

158 kWidth = 5 

159 kHeight = 8 

160 

161 gaussFunc1 = afwMath.GaussianFunction1D(1.0) 

162 k = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1) 

163 center = k.getCtr() 

164 fArr = np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) 

165 np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) 

166 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) 

167 for xsigma in (0.1, 1.0, 3.0): 

168 gaussFunc1.setParameters((xsigma,)) 

169 for ysigma in (0.1, 1.0, 3.0): 

170 gaussFunc.setParameters((xsigma, ysigma, 0.0)) 

171 # compute array of function values and normalize 

172 for row in range(k.getHeight()): 

173 y = row - center.getY() 

174 for col in range(k.getWidth()): 

175 x = col - center.getX() 

176 fArr[col, row] = gaussFunc(x, y) 

177 fArr /= fArr.sum() 

178 

179 k.setKernelParameters((xsigma, ysigma)) 

180 

181 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

182 k.writeFits(filename) 

183 k2 = afwMath.SeparableKernel.readFits(filename) 

184 

185 self.kernelCheck(k, k2) 

186 

187 kImage = afwImage.ImageD(k2.getDimensions()) 

188 k2.computeImage(kImage, True) 

189 kArr = kImage.getArray().transpose() 

190 if not np.allclose(fArr, kArr): 

191 self.fail(f"{k2.__class__.__name__} = {kArr} != {fArr} " 

192 f"for xsigma={xsigma}, ysigma={ysigma}") 

193 

194 def testLinearCombinationKernel(self): 

195 """Test LinearCombinationKernel using a set of delta basis functions 

196 """ 

197 kWidth = 3 

198 kHeight = 2 

199 

200 # create list of kernels 

201 basisImArrList = [] 

202 kVec = [] 

203 for row in range(kHeight): 

204 for col in range(kWidth): 

205 kernel = afwMath.DeltaFunctionKernel( 

206 kWidth, kHeight, lsst.geom.Point2I(col, row)) 

207 basisImage = afwImage.ImageD(kernel.getDimensions()) 

208 kernel.computeImage(basisImage, True) 

209 basisImArrList.append(basisImage.getArray().transpose().copy()) 

210 kVec.append(kernel) 

211 

212 kParams = [0.0]*len(kVec) 

213 k = afwMath.LinearCombinationKernel(kVec, kParams) 

214 for ii in range(len(kVec)): 

215 kParams = [0.0]*len(kVec) 

216 kParams[ii] = 1.0 

217 k.setKernelParameters(kParams) 

218 

219 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

220 k.writeFits(filename) 

221 k2 = afwMath.LinearCombinationKernel.readFits(filename) 

222 

223 self.kernelCheck(k, k2) 

224 

225 kIm = afwImage.ImageD(k2.getDimensions()) 

226 k2.computeImage(kIm, True) 

227 kImArr = kIm.getArray().transpose() 

228 if not np.allclose(kImArr, basisImArrList[ii]): 

229 self.fail(f"{k2.__class__.__name__} = {kImArr} != {basisImArrList[ii]} " 

230 f"for the {ii}'th basis kernel") 

231 

232 def testSVLinearCombinationKernel(self): 

233 """Test a spatially varying LinearCombinationKernel 

234 """ 

235 kWidth = 3 

236 kHeight = 2 

237 

238 # create image arrays for the basis kernels 

239 basisImArrList = [] 

240 imArr = np.zeros((kWidth, kHeight), dtype=float) 

241 imArr += 0.1 

242 imArr[kWidth//2, :] = 0.9 

243 basisImArrList.append(imArr) 

244 imArr = np.zeros((kWidth, kHeight), dtype=float) 

245 imArr += 0.2 

246 imArr[:, kHeight//2] = 0.8 

247 basisImArrList.append(imArr) 

248 

249 # create a list of basis kernels from the images 

250 kVec = [] 

251 for basisImArr in basisImArrList: 

252 basisImage = afwImage.makeImageFromArray( 

253 basisImArr.transpose().copy()) 

254 kernel = afwMath.FixedKernel(basisImage) 

255 kVec.append(kernel) 

256 

257 # create spatially varying linear combination kernel 

258 spFunc = afwMath.PolynomialFunction2D(1) 

259 

260 # spatial parameters are a list of entries, one per kernel parameter; 

261 # each entry is a list of spatial parameters 

262 sParams = ( 

263 (0.0, 1.0, 0.0), 

264 (0.0, 0.0, 1.0), 

265 ) 

266 

267 k = afwMath.LinearCombinationKernel(kVec, spFunc) 

268 k.setSpatialParameters(sParams) 

269 

270 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

271 k.writeFits(filename) 

272 k2 = afwMath.LinearCombinationKernel.readFits(filename) 

273 

274 self.kernelCheck(k, k2) 

275 

276 kImage = afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight)) 

277 for colPos, rowPos, coeff0, coeff1 in [ 

278 (0.0, 0.0, 0.0, 0.0), 

279 (1.0, 0.0, 1.0, 0.0), 

280 (0.0, 1.0, 0.0, 1.0), 

281 (1.0, 1.0, 1.0, 1.0), 

282 (0.5, 0.5, 0.5, 0.5), 

283 ]: 

284 k2.computeImage(kImage, False, colPos, rowPos) 

285 kImArr = kImage.getArray().transpose() 

286 refKImArr = (basisImArrList[0] * coeff0) + \ 

287 (basisImArrList[1] * coeff1) 

288 if not np.allclose(kImArr, refKImArr): 

289 self.fail(f"{k2.__class__.__name__} = {kImArr} != {refKImArr} " 

290 f"at colPos={colPos}, rowPos={rowPos}") 

291 

292 def testSetCtr(self): 

293 """Test setCtrCol/Row""" 

294 kWidth = 3 

295 kHeight = 4 

296 

297 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) 

298 k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) 

299 for xCtr in range(kWidth): 

300 for yCtr in range(kHeight): 

301 ctr = lsst.geom.Point2I(xCtr, yCtr) 

302 k.setCtr(ctr) 

303 

304 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

305 k.writeFits(filename) 

306 k2 = afwMath.AnalyticKernel.readFits(filename) 

307 

308 self.kernelCheck(k, k2) 

309 

310 self.assertEqual(k2.getCtr(), ctr) 

311 

312 

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

314 pass 

315 

316 

317def setup_module(module): 

318 lsst.utils.tests.init() 

319 

320 

321if __name__ == "__main__": 321 ↛ 322line 321 didn't jump to line 322, because the condition on line 321 was never true

322 lsst.utils.tests.init() 

323 unittest.main()