Coverage for tests/test_kernelImagesForRegion.py: 17%

139 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-15 02:29 -0700

1# 

2# LSST Data Management System 

3# Copyright 2008, 2009, 2010 LSST Corporation. 

4# 

5# This product includes software developed by the 

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

7# 

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

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

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

11# (at your option) any later version. 

12# 

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

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

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

16# GNU General Public License for more details. 

17# 

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

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

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

21# 

22import math 

23import unittest 

24 

25import numpy as np 

26 

27import lsst.utils.tests 

28import lsst.geom 

29import lsst.afw.image as afwImage 

30import lsst.afw.math as afwMath 

31import lsst.afw.math.detail as mathDetail 

32from lsst.log import Log 

33 

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

35Log.getLogger("TRACE5.lsst.afw.math.convolve").setLevel(Log.INFO) 

36 

37LocNameDict = { 

38 mathDetail.KernelImagesForRegion.BOTTOM_LEFT: "BOTTOM_LEFT", 

39 mathDetail.KernelImagesForRegion.BOTTOM_RIGHT: "BOTTOM_RIGHT", 

40 mathDetail.KernelImagesForRegion.TOP_LEFT: "TOP_LEFT", 

41 mathDetail.KernelImagesForRegion.TOP_RIGHT: "TOP_RIGHT", 

42} 

43 

44NameLocDict = dict((name, loc) for (loc, name) in LocNameDict.items()) 

45 

46 

47class KernelImagesForRegion(lsst.utils.tests.TestCase): 

48 

49 def setUp(self): 

50 boxCorner = lsst.geom.Point2I(11, 50) 

51 boxExtent = lsst.geom.Extent2I(100, 99) 

52 self.bbox = lsst.geom.Box2I(boxCorner, boxExtent) 

53 self.xy0 = lsst.geom.Point2I(100, 251) 

54 self.kernel = self.makeKernel() 

55 

56 def tearDown(self): 

57 self.bbox = None 

58 self.kernel = None 

59 

60 def assertRegionCorrect(self, region): 

61 """Assert that a region has correct corner images 

62 

63 This test is only relevant for operations that try to reuse the image array data 

64 """ 

65 regionCopy = mathDetail.KernelImagesForRegion( 

66 region.getKernel(), region.getBBox(), region.getXY0(), region.getDoNormalize()) 

67 

68 for location in ( 

69 region.BOTTOM_LEFT, 

70 region.BOTTOM_RIGHT, 

71 region.TOP_LEFT, 

72 region.TOP_RIGHT, 

73 ): 

74 actImage = region.getImage(location) 

75 actImArr = actImage.getArray().transpose().copy() 

76 desImage = regionCopy.getImage(location) 

77 desImArr = desImage.getArray().transpose().copy() 

78 actImArr -= desImArr 

79 if not np.allclose(actImArr, 0): 

80 actImage.writeFits(f"actImage{location}.fits") 

81 desImage.writeFits(f"desImage{location}.fits") 

82 self.fail(f"failed on location {location}") 

83 

84 def makeKernel(self): 

85 kCols = 7 

86 kRows = 6 

87 

88 # create spatial model 

89 sFunc = afwMath.PolynomialFunction2D(1) 

90 

91 minSigma = 0.1 

92 maxSigma = 3.0 

93 

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

95 # each entry is a list of spatial parameters 

96 xSlope = (maxSigma - minSigma) / self.bbox.getWidth() 

97 ySlope = (maxSigma - minSigma) / self.bbox.getHeight() 

98 xOrigin = minSigma - (self.xy0[0] * xSlope) 

99 yOrigin = minSigma - (self.xy0[1] * ySlope) 

100 sParams = ( 

101 (xOrigin, xSlope, 0.0), 

102 (yOrigin, 0.0, ySlope), 

103 (0.0, 0.0, 0.0), 

104 ) 

105 

106 kFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) 

107 kernel = afwMath.AnalyticKernel(kCols, kRows, kFunc, sFunc) 

108 kernel.setSpatialParameters(sParams) 

109 return kernel 

110 

111 def testDoNormalize(self): 

112 """Test getDoNormalize 

113 """ 

114 kernel = self.makeKernel() 

115 for doNormalize in (False, True): 

116 region = mathDetail.KernelImagesForRegion( 

117 kernel, self.bbox, self.xy0, doNormalize) 

118 self.assertEqual(region.getDoNormalize(), doNormalize) 

119 

120 def testGetPixelIndex(self): 

121 """Test getPixelIndex method 

122 """ 

123 region = mathDetail.KernelImagesForRegion( 

124 self.kernel, self.bbox, self.xy0, False) 

125 leftInd = self.bbox.getMinX() 

126 rightInd = self.bbox.getMaxX() + 1 

127 bottomInd = self.bbox.getMinY() 

128 topInd = self.bbox.getMaxY() + 1 

129 int(round((leftInd + rightInd) / 2.0)) 

130 int(round((bottomInd + topInd) / 2.0)) 

131 

132 for location, desIndex in ( 

133 (region.BOTTOM_LEFT, (leftInd, bottomInd)), 

134 (region.BOTTOM_RIGHT, (rightInd, bottomInd)), 

135 (region.TOP_LEFT, (leftInd, topInd)), 

136 (region.TOP_RIGHT, (rightInd, topInd)), 

137 ): 

138 desPixIndex = lsst.geom.Point2I(desIndex[0], desIndex[1]) 

139 self.assertEqual(region.getPixelIndex(location), desPixIndex, 

140 f"getPixelIndex({LocNameDict[location]}) = {region.getPixelIndex(location)} " 

141 f"!= desPixIndex") 

142 

143 def testComputeNextRow(self): 

144 """Test computeNextRow method and the resulting RowOfKernelImagesForRegion 

145 """ 

146 nx = 6 

147 ny = 5 

148 regionRow = mathDetail.RowOfKernelImagesForRegion(nx, ny) 

149 self.assertFalse(regionRow.hasData()) 

150 self.assertFalse(regionRow.isLastRow()) 

151 self.assertEqual(regionRow.getYInd(), -1) 

152 

153 region = mathDetail.KernelImagesForRegion( 

154 self.kernel, self.bbox, self.xy0, False) 

155 floatWidth = self.bbox.getWidth() / float(nx) 

156 validWidths = (int(math.floor(floatWidth)), int(math.ceil(floatWidth))) 

157 floatHeight = self.bbox.getHeight() / float(ny) 

158 validHeights = (int(math.floor(floatHeight)), 

159 int(math.ceil(floatHeight))) 

160 

161 totalHeight = 0 

162 prevBBox = None 

163 prevFirstBBox = None 

164 for yInd in range(ny): 

165 rowWidth = 0 

166 isOK = region.computeNextRow(regionRow) 

167 self.assertTrue(isOK) 

168 self.assertTrue(regionRow.hasData()) 

169 self.assertEqual(regionRow.isLastRow(), (yInd + 1 >= ny)) 

170 self.assertEqual(regionRow.getYInd(), yInd) 

171 firstBBox = regionRow.getRegion(0).getBBox() 

172 self.assertEqual(firstBBox.getMinX(), self.bbox.getMinX()) 

173 if yInd == 0: 

174 self.assertEqual(firstBBox.getMinY(), self.bbox.getMinY()) 

175 firstBBoxHeight = firstBBox.getHeight() 

176 self.assertTrue(firstBBoxHeight in validHeights) 

177 totalHeight += firstBBoxHeight 

178 if yInd > 0: 

179 self.assertEqual(firstBBox.getMinY(), 

180 prevFirstBBox.getMaxY() + 1) 

181 if yInd == ny - 1: 

182 self.assertEqual(firstBBox.getMaxY(), self.bbox.getMaxY()) 

183 prevFirstBBox = firstBBox 

184 for xInd in range(nx): 

185 subregion = regionRow.getRegion(xInd) 

186 try: 

187 self.assertRegionCorrect(subregion) 

188 except Exception: 

189 print(f"failed on xInd={xInd}, yInd={yInd}") 

190 raise 

191 bbox = subregion.getBBox() 

192 rowWidth += bbox.getWidth() 

193 self.assertTrue(bbox.getWidth() in validWidths) 

194 self.assertEqual(bbox.getHeight(), firstBBoxHeight) 

195 if xInd > 0: 

196 self.assertEqual(bbox.getMinX(), prevBBox.getMaxX() + 1) 

197 self.assertEqual(bbox.getMinY(), prevBBox.getMinY()) 

198 self.assertEqual(bbox.getMaxY(), prevBBox.getMaxY()) 

199 if xInd == nx - 1: 

200 self.assertEqual(bbox.getMaxX(), self.bbox.getMaxX()) 

201 prevBBox = bbox 

202 self.assertEqual(rowWidth, self.bbox.getWidth()) 

203 self.assertEqual(totalHeight, self.bbox.getHeight()) 

204 self.assertTrue(not region.computeNextRow(regionRow)) 

205 

206 def testExactImages(self): 

207 """Confirm that kernel image at each location is correct 

208 """ 

209 desImage = afwImage.ImageD(lsst.geom.Extent2I( 

210 self.kernel.getWidth(), self.kernel.getHeight())) 

211 

212 for doNormalize in (False, True): 

213 region = mathDetail.KernelImagesForRegion( 

214 self.kernel, self.bbox, self.xy0, doNormalize) 

215 for location in ( 

216 region.BOTTOM_LEFT, 

217 region.BOTTOM_RIGHT, 

218 region.TOP_LEFT, 

219 region.TOP_RIGHT, 

220 ): 

221 pixelIndex = region.getPixelIndex(location) 

222 xPos = afwImage.indexToPosition(pixelIndex[0] + self.xy0[0]) 

223 yPos = afwImage.indexToPosition(pixelIndex[1] + self.xy0[1]) 

224 self.kernel.computeImage(desImage, doNormalize, xPos, yPos) 

225 

226 actImage = region.getImage(location) 

227 msg = f"exact image({LocNameDict[location]}) incorrect" 

228 self.assertImagesAlmostEqual(actImage, desImage, msg=msg) 

229 

230 

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

232 pass 

233 

234 

235def setup_module(module): 

236 lsst.utils.tests.init() 

237 

238 

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

240 lsst.utils.tests.init() 

241 unittest.main()