Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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("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 with self.assertWarns(FutureWarning): 

50 self.assertEqual(k1.getCtrX(), k2.getCtrX()) 

51 self.assertEqual(k1.getCtrY(), k2.getCtrY()) 

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

53 self.assertEqual(k1.getNSpatialParameters(), 

54 k2.getNSpatialParameters()) 

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

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

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

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

59 

60 def testFixedKernel(self): 

61 """Test FixedKernel using a ramp function 

62 """ 

63 kWidth = 5 

64 kHeight = 6 

65 

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

67 inArr.shape = [kWidth, kHeight] 

68 

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

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

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

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

73 

74 k = afwMath.FixedKernel(inImage) 

75 

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

77 k.writeFits(filename) 

78 k2 = afwMath.FixedKernel.readFits(filename) 

79 

80 self.kernelCheck(k, k2) 

81 

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

83 k2.computeImage(outImage, False) 

84 

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

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

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

88 normInArr = inArr / inArr.sum() 

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

90 k2.computeImage(normOutImage, True) 

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

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

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

94 

95 def testAnalyticKernel(self): 

96 """Test AnalyticKernel using a Gaussian function 

97 """ 

98 kWidth = 5 

99 kHeight = 8 

100 

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

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

103 center = k.getCtr() 

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

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

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

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

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

109 # compute array of function values and normalize 

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

111 y = row - center.getY() 

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

113 x = col - center.getX() 

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

115 fArr /= fArr.sum() 

116 

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

118 

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

120 k.writeFits(filename) 

121 k2 = afwMath.AnalyticKernel.readFits(filename) 

122 

123 self.kernelCheck(k, k2) 

124 

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

126 k2.computeImage(kImage, True) 

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

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

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

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

131 

132 def testDeltaFunctionKernel(self): 

133 """Test DeltaFunctionKernel 

134 """ 

135 for kWidth in range(1, 4): 

136 for kHeight in range(1, 4): 

137 for activeCol in range(kWidth): 

138 for activeRow in range(kHeight): 

139 kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, 

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

141 

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

143 kernel.writeFits(filename) 

144 k2 = afwMath.DeltaFunctionKernel.readFits(filename) 

145 

146 self.kernelCheck(kernel, k2) 

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

148 

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

150 kSum = k2.computeImage(kImage, False) 

151 self.assertEqual(kSum, 1.0) 

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

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

154 kArr[activeCol, activeRow] = 0.0 

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

156 

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

158 def testSeparableKernel(self): 

159 """Test SeparableKernel using a Gaussian function 

160 """ 

161 kWidth = 5 

162 kHeight = 8 

163 

164 gaussFunc1 = afwMath.GaussianFunction1D(1.0) 

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

166 center = k.getCtr() 

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

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

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

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

171 gaussFunc1.setParameters((xsigma,)) 

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

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

174 # compute array of function values and normalize 

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

176 y = row - center.getY() 

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

178 x = col - center.getX() 

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

180 fArr /= fArr.sum() 

181 

182 k.setKernelParameters((xsigma, ysigma)) 

183 

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

185 k.writeFits(filename) 

186 k2 = afwMath.SeparableKernel.readFits(filename) 

187 

188 self.kernelCheck(k, k2) 

189 

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

191 k2.computeImage(kImage, True) 

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

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

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

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

196 

197 def testLinearCombinationKernel(self): 

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

199 """ 

200 kWidth = 3 

201 kHeight = 2 

202 

203 # create list of kernels 

204 basisImArrList = [] 

205 kVec = [] 

206 for row in range(kHeight): 

207 for col in range(kWidth): 

208 kernel = afwMath.DeltaFunctionKernel( 

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

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

211 kernel.computeImage(basisImage, True) 

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

213 kVec.append(kernel) 

214 

215 kParams = [0.0]*len(kVec) 

216 k = afwMath.LinearCombinationKernel(kVec, kParams) 

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

218 kParams = [0.0]*len(kVec) 

219 kParams[ii] = 1.0 

220 k.setKernelParameters(kParams) 

221 

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

223 k.writeFits(filename) 

224 k2 = afwMath.LinearCombinationKernel.readFits(filename) 

225 

226 self.kernelCheck(k, k2) 

227 

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

229 k2.computeImage(kIm, True) 

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

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

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

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

234 

235 def testSVLinearCombinationKernel(self): 

236 """Test a spatially varying LinearCombinationKernel 

237 """ 

238 kWidth = 3 

239 kHeight = 2 

240 

241 # create image arrays for the basis kernels 

242 basisImArrList = [] 

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

244 imArr += 0.1 

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

246 basisImArrList.append(imArr) 

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

248 imArr += 0.2 

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

250 basisImArrList.append(imArr) 

251 

252 # create a list of basis kernels from the images 

253 kVec = [] 

254 for basisImArr in basisImArrList: 

255 basisImage = afwImage.makeImageFromArray( 

256 basisImArr.transpose().copy()) 

257 kernel = afwMath.FixedKernel(basisImage) 

258 kVec.append(kernel) 

259 

260 # create spatially varying linear combination kernel 

261 spFunc = afwMath.PolynomialFunction2D(1) 

262 

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

264 # each entry is a list of spatial parameters 

265 sParams = ( 

266 (0.0, 1.0, 0.0), 

267 (0.0, 0.0, 1.0), 

268 ) 

269 

270 k = afwMath.LinearCombinationKernel(kVec, spFunc) 

271 k.setSpatialParameters(sParams) 

272 

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

274 k.writeFits(filename) 

275 k2 = afwMath.LinearCombinationKernel.readFits(filename) 

276 

277 self.kernelCheck(k, k2) 

278 

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

280 for colPos, rowPos, coeff0, coeff1 in [ 

281 (0.0, 0.0, 0.0, 0.0), 

282 (1.0, 0.0, 1.0, 0.0), 

283 (0.0, 1.0, 0.0, 1.0), 

284 (1.0, 1.0, 1.0, 1.0), 

285 (0.5, 0.5, 0.5, 0.5), 

286 ]: 

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

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

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

290 (basisImArrList[1] * coeff1) 

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

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

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

294 

295 def testSetCtr(self): 

296 """Test setCtrCol/Row""" 

297 kWidth = 3 

298 kHeight = 4 

299 

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

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

302 for xCtr in range(kWidth): 

303 for yCtr in range(kHeight): 

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

305 k.setCtr(ctr) 

306 

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

308 k.writeFits(filename) 

309 k2 = afwMath.AnalyticKernel.readFits(filename) 

310 

311 self.kernelCheck(k, k2) 

312 

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

314 

315 

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

317 pass 

318 

319 

320def setup_module(module): 

321 lsst.utils.tests.init() 

322 

323 

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

325 lsst.utils.tests.init() 

326 unittest.main()