Coverage for tests/test_footprint.py: 17%

163 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-09-11 01:19 -0700

1# 

2# Copyright 2008-2017 AURA/LSST. 

3# 

4# This product includes software developed by the 

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

6# 

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

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

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

10# (at your option) any later version. 

11# 

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

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

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

15# GNU General Public License for more details. 

16# 

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

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

19# see <https://www.lsstcorp.org/LegalNotices/>. 

20# 

21 

22import os 

23import unittest 

24 

25import lsst.utils.tests 

26import lsst.geom 

27import lsst.afw.geom as afwGeom 

28import lsst.afw.detection as afwDet 

29import lsst.afw.table as afwTable 

30 

31 

32class FootprintTestCase(unittest.TestCase): 

33 def setUp(self): 

34 self.spanRad = 4 

35 self.regionRad = 10 

36 self.spans = afwGeom.SpanSet.fromShape(self.spanRad, afwGeom.Stencil.BOX) 

37 minPoint = lsst.geom.Point2I(-self.regionRad, -self.regionRad) 

38 maxPoint = lsst.geom.Point2I(self.regionRad, self.regionRad) 

39 self.region = lsst.geom.Box2I(minPoint, maxPoint) 

40 self.schema = afwDet.PeakTable.makeMinimalSchema() 

41 # Run the the constructors test to ensure the Footprints are setUp 

42 self.testConstructors() 

43 

44 def tearDown(self): 

45 del self.spans 

46 del self.region 

47 del self.schema 

48 del self.footprint 

49 del self.footprintWithRegion 

50 del self.footprintWithSchema 

51 del self.footprintWithSchemaRegion 

52 del self.emptyFootprint 

53 

54 def testConstructors(self): 

55 ''' 

56 Test that each of the constructors constructs a valid Footprint, 

57 if any of these fails, an exception will be raised and the test 

58 will fail. 

59 ''' 

60 self.footprint = afwDet.Footprint(self.spans) 

61 self.footprintWithRegion = afwDet.Footprint(self.spans, self.region) 

62 self.footprintWithSchema = afwDet.Footprint(self.spans, self.schema) 

63 self.footprintWithSchemaRegion = afwDet.Footprint(self.spans, 

64 self.schema, 

65 self.region) 

66 self.emptyFootprint = afwDet.Footprint() 

67 self.assertEqual(len(self.emptyFootprint.spans), 0) 

68 self.assertEqual(len(self.emptyFootprint.peaks), 0) 

69 

70 def test_str(self): 

71 self.assertEqual(str(self.footprint), "0 peaks, area=81, centroid=(0, 0)") 

72 

73 def testIsHeavy(self): 

74 self.assertFalse(self.footprint.isHeavy()) 

75 

76 def testGetSetSpans(self): 

77 ''' 

78 Test getting and setting the SpanSet member of the Footprint with both 

79 the getters and setters and the python property accessor 

80 ''' 

81 self.assertEqual(self.footprint.getSpans(), self.spans) 

82 self.assertEqual(self.footprint.spans, self.spans) 

83 tempSpanSet = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX) 

84 self.footprint.setSpans(tempSpanSet) 

85 self.assertEqual(self.footprint.spans, tempSpanSet) 

86 # reset back to original with property 

87 self.footprint.spans = self.spans 

88 self.assertEqual(self.footprint.spans, self.spans) 

89 

90 def testPeakFunctionality(self): 

91 newSchema = afwDet.PeakTable.makeMinimalSchema() 

92 newField = afwTable.FieldI("extra", "doc", "na") 

93 newSchema.addField(newField) 

94 self.footprint.setPeakSchema(newSchema) 

95 names = self.footprint.getPeaks().getSchema().getNames() 

96 self.assertIn("extra", names) 

97 # reset the schema back 

98 self.footprint.setPeakSchema(self.schema) 

99 peakData = [[2, 2, 10], [0, 3, 21], [1, 9, 17]] 

100 for peak in peakData: 

101 self.footprint.addPeak(*peak) 

102 # Sort the peaks by value (use the property peaks to test that method 

103 # of access) 

104 sortKey = self.footprint.peaks.getSchema()['peakValue'].asKey() 

105 self.footprint.sortPeaks(sortKey) 

106 for i, peak in enumerate(self.footprint.peaks): 

107 self.assertEqual(peak['i_x'], i) 

108 

109 # Test that peaks outside the Footprint are removed 

110 self.footprint.removeOrphanPeaks() 

111 self.assertEqual(len(self.footprint.peaks), 2) 

112 for peak in self.footprint.peaks: 

113 self.assertNotEqual(peak['i_x'], 1) 

114 

115 def testGeometry(self): 

116 # Move the base footprint by 2 in x and 2 in y 

117 offsetX = 2 

118 offsetY = -3 

119 self.footprint.shift(offsetX, offsetY) 

120 # verify that this shifts the center from 0,0 as the default 

121 # constructed footprint has 

122 center = self.footprint.getCentroid() 

123 self.assertEqual(center.getX(), offsetX) 

124 self.assertEqual(center.getY(), offsetY) 

125 

126 shape = 6.66666 

127 covShape = 0 

128 places = 4 

129 self.assertAlmostEqual(self.footprint.getShape().getIxx(), 

130 shape, places) 

131 self.assertAlmostEqual(self.footprint.getShape().getIyy(), 

132 shape, places) 

133 self.assertEqual(self.footprint.getShape().getIxy(), covShape) 

134 

135 # Shift the footprint back 

136 self.footprint.shift(lsst.geom.ExtentI(-offsetX, -offsetY)) 

137 

138 bBox = self.footprint.getBBox() 

139 self.assertEqual(bBox.getMinX(), -self.spanRad) 

140 self.assertEqual(bBox.getMinY(), -self.spanRad) 

141 self.assertEqual(bBox.getMaxX(), self.spanRad) 

142 self.assertEqual(bBox.getMaxY(), self.spanRad) 

143 

144 # Test the point membership in a Footprint 

145 memberPoint = lsst.geom.Point2I(1, 1) 

146 self.assertTrue(self.footprint.contains(memberPoint)) 

147 self.assertIn(memberPoint, self.footprint) 

148 

149 nonMemberPoint = lsst.geom.Point2I(100, 100) 

150 self.assertFalse(self.footprint.contains(nonMemberPoint)) 

151 self.assertNotIn(nonMemberPoint, self.footprint) 

152 

153 def testRegion(self): 

154 self.assertEqual(self.footprintWithRegion.getRegion(), self.region) 

155 largeRad = 20 

156 testRegion = lsst.geom.Box2I(lsst.geom.Point2I(-largeRad, -largeRad), 

157 lsst.geom.Point2I(largeRad, largeRad)) 

158 self.footprintWithRegion.setRegion(testRegion) 

159 self.assertEqual(testRegion, self.footprintWithRegion.getRegion()) 

160 

161 def testMutationFunctionality(self): 

162 clipRad = 2 

163 clipBox = lsst.geom.Box2I(lsst.geom.Point2I(-clipRad, -clipRad), 

164 lsst.geom.Point2I(clipRad, clipRad)) 

165 self.footprint.clipTo(clipBox) 

166 # Fetch the bounding box using the property notation 

167 bBox = self.footprint.getBBox() 

168 # Check the bounding box is now at the bounds which were clipped to 

169 self.assertEqual(bBox.getMinX(), -clipRad) 

170 self.assertEqual(bBox.getMinY(), -clipRad) 

171 self.assertEqual(bBox.getMaxX(), clipRad) 

172 self.assertEqual(bBox.getMaxY(), clipRad) 

173 

174 # Set the footprint back to what it was 

175 self.footprint = afwDet.Footprint(self.spans) 

176 

177 # Test erode 

178 kernelRad = 1 

179 kernel = afwGeom.SpanSet.fromShape(kernelRad, afwGeom.Stencil.BOX) 

180 self.footprint.erode(kernel) 

181 

182 # Verify the eroded dimensions 

183 bBox = self.footprint.getBBox() 

184 self.assertEqual(bBox.getMinX(), -3) 

185 self.assertEqual(bBox.getMinY(), -3) 

186 self.assertEqual(bBox.getMaxX(), 3) 

187 self.assertEqual(bBox.getMaxY(), 3) 

188 

189 # Dilate the footprint back to the origional 

190 self.footprint.dilate(kernel) 

191 self.assertEqual(self.footprint.spans, self.spans) 

192 

193 # erode using the alternate call syntax 

194 self.footprint.erode(1, afwGeom.Stencil.BOX) 

195 

196 # verify the eroded dimensions 

197 bBox = self.footprint.getBBox() 

198 self.assertEqual(bBox.getMinX(), -3) 

199 self.assertEqual(bBox.getMinY(), -3) 

200 self.assertEqual(bBox.getMaxX(), 3) 

201 self.assertEqual(bBox.getMaxY(), 3) 

202 

203 # Dilate the footprint back to the origional using alternate signature 

204 self.footprint.dilate(1, afwGeom.Stencil.BOX) 

205 self.assertEqual(self.footprint.spans, self.spans) 

206 

207 def testSplit(self): 

208 spanList = [afwGeom.Span(0, 2, 4), 

209 afwGeom.Span(1, 2, 4), 

210 afwGeom.Span(2, 2, 4), 

211 afwGeom.Span(10, 4, 7), 

212 afwGeom.Span(11, 4, 7), 

213 afwGeom.Span(12, 4, 7)] 

214 

215 spans = afwGeom.SpanSet(spanList) 

216 region = lsst.geom.Box2I(lsst.geom.PointI(-6, -6), lsst.geom.PointI(20, 20)) 

217 multiFoot = afwDet.Footprint(spans, region) 

218 

219 records = [multiFoot.addPeak(3, 1, 100), 

220 multiFoot.addPeak(5, 11, 100)] 

221 

222 # Verify that the footprint is multi-component 

223 self.assertFalse(multiFoot.isContiguous()) 

224 

225 footprintList = multiFoot.split() 

226 

227 self.assertEqual(len(footprintList), 2) 

228 for i, fp in enumerate(footprintList): 

229 # check that the correct Spans are populated for each 

230 tempSpan = afwGeom.SpanSet(spanList[i*3:i*3+3]) 

231 self.assertEqual(fp.spans, tempSpan) 

232 

233 # check that the peaks are split properly 

234 self.assertEqual(len(fp.peaks), 1) 

235 self.assertEqual(fp.peaks[0], records[i]) 

236 

237 def testPersistence(self): 

238 # populate the peaks for the peak tests 

239 self.testPeakFunctionality() 

240 

241 with lsst.utils.tests.getTempFilePath(".fits") as filepath: 

242 # Persist the Footprint to file and read it back 

243 self.footprint.writeFits(filepath) 

244 footprintFromFile = afwDet.Footprint.readFits(filepath) 

245 

246 # Check that the Footprint before and after saving are the same 

247 self.assertEqual(self.footprint, footprintFromFile) 

248 

249 # Clean up after ourselves 

250 del footprintFromFile 

251 

252 def testLegacyFootprints(self): 

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

254 fileName = os.path.join(testPath, 'data', 'preSpanSetsFootprint.fits') 

255 legacyFootprint = afwDet.Footprint.readFits(fileName) 

256 

257 # Calculate some quantifying numbers from the legacy Footprint to ensure 

258 # it loaded properly 

259 self.assertEqual(len(legacyFootprint.spans), 303) 

260 self.assertEqual(len(legacyFootprint.peaks), 48) 

261 self.assertEqual(legacyFootprint.spans.getBBox(), 

262 lsst.geom.Box2I(lsst.geom.Point2I(32676, 27387), 

263 lsst.geom.Extent2I(175, 153))) 

264 legacyCenter = legacyFootprint.spans.computeCentroid() 

265 self.assertAlmostEqual(legacyCenter.getY(), 27456.70733, 5) 

266 self.assertAlmostEqual(legacyCenter.getX(), 32775.47611, 5) 

267 

268 del legacyFootprint 

269 

270 

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

272 pass 

273 

274 

275def setup_module(module): 

276 lsst.utils.tests.init() 

277 

278 

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

280 lsst.utils.tests.init() 

281 unittest.main()