Coverage for tests/test_gaussianPsf.py: 28%

77 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-08 03:13 -0700

1# This file is part of afw. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

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 GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import unittest 

23 

24import numpy as np 

25 

26import lsst.utils.tests 

27import lsst.pex.exceptions 

28import lsst.geom 

29import lsst.afw.table 

30import lsst.afw.fits 

31import lsst.afw.image 

32import lsst.afw.detection 

33 

34 

35def makeGaussianImage(bbox, sigma, xc=0.0, yc=0.0): 

36 image = lsst.afw.image.ImageD(bbox) 

37 array = image.getArray() 

38 for yi, yv in enumerate(range(bbox.getBeginY(), bbox.getEndY())): 

39 for xi, xv in enumerate(range(bbox.getBeginX(), bbox.getEndX())): 

40 array[yi, xi] = np.exp(-0.5*((xv - xc)**2 + (yv - yc)**2)/sigma**2) 

41 array /= array.sum() 

42 return image 

43 

44 

45def computeNaiveApertureFlux(image, radius, xc=0.0, yc=0.0): 

46 bbox = image.getBBox() 

47 array = image.getArray() 

48 s = 0.0 

49 for yi, yv in enumerate(range(bbox.getBeginY(), bbox.getEndY())): 

50 for xi, xv in enumerate(range(bbox.getBeginX(), bbox.getEndX())): 

51 if (xv - xc)**2 + (yv - yc)**2 < radius**2: 

52 s += array[yi, xi] 

53 return s 

54 

55 

56class GaussianPsfTestCase(lsst.utils.tests.TestCase): 

57 

58 def setUp(self): 

59 self.kernelSize = 51 

60 self.psf = lsst.afw.detection.GaussianPsf( 

61 self.kernelSize, self.kernelSize, 4.0) 

62 

63 def tearDown(self): 

64 del self.psf 

65 

66 def testKernelImage(self): 

67 image = self.psf.computeKernelImage(self.psf.getAveragePosition()) 

68 check = makeGaussianImage(image.getBBox(), self.psf.getSigma()) 

69 self.assertFloatsAlmostEqual(image.getArray(), check.getArray()) 

70 self.assertFloatsAlmostEqual(image.getArray().sum(), 1.0, atol=1E-14) 

71 

72 def testOffsetImage(self): 

73 image = self.psf.computeImage(lsst.geom.Point2D(0.25, 0.25)) 

74 check = makeGaussianImage( 

75 image.getBBox(), self.psf.getSigma(), 0.25, 0.25) 

76 self.assertFloatsAlmostEqual(image.getArray(), check.getArray(), atol=1E-4, rtol=1E-4, 

77 plotOnFailure=True) 

78 

79 def testApertureFlux(self): 

80 image = self.psf.computeKernelImage(lsst.geom.Point2D(0.0, 0.0)) 

81 # test aperture implementation is very crude; can only test to about 10% 

82 self.assertFloatsAlmostEqual( 

83 self.psf.computeApertureFlux(5.0, self.psf.getAveragePosition()), 

84 computeNaiveApertureFlux(image, 5.0), 

85 rtol=0.1 

86 ) 

87 self.assertFloatsAlmostEqual( 

88 self.psf.computeApertureFlux(7.0, self.psf.getAveragePosition()), 

89 computeNaiveApertureFlux(image, 7.0), 

90 rtol=0.1 

91 ) 

92 

93 def testShape(self): 

94 self.assertFloatsAlmostEqual( 

95 self.psf.computeShape(self.psf.getAveragePosition()).getDeterminantRadius(), 4.0) 

96 

97 def testPersistence(self): 

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

99 self.psf.writeFits(filename) 

100 psf = lsst.afw.detection.GaussianPsf.readFits(filename) 

101 self.assertEqual(self.psf.getSigma(), psf.getSigma()) 

102 self.assertEqual(self.psf.getDimensions(), psf.getDimensions()) 

103 

104 def testBBox(self): 

105 

106 self.assertEqual(self.psf.computeKernelImage(self.psf.getAveragePosition()).getBBox(), 

107 self.psf.computeBBox(self.psf.getAveragePosition())) 

108 

109 self.assertEqual( 

110 self.psf.computeBBox(self.psf.getAveragePosition()).getWidth(), 

111 self.kernelSize 

112 ) 

113 

114 # Test interface. GaussianPsf does not vary spatially 

115 self.assertEqual(self.psf.computeKernelImage(lsst.geom.Point2D(0.0, 0.0)).getBBox(), 

116 self.psf.computeBBox(lsst.geom.Point2D(0.0, 0.0))) 

117 

118 self.assertEqual(self.psf.computeImage(self.psf.getAveragePosition()).getBBox(), 

119 self.psf.computeImageBBox(self.psf.getAveragePosition())) 

120 

121 def testResized(self): 

122 for pad in [0, -10, 10]: 

123 newLen = self.kernelSize - pad 

124 resizedPsf = self.psf.resized(newLen, newLen) 

125 newBBox = resizedPsf.computeBBox(resizedPsf.getAveragePosition()) 

126 self.assertEqual(newBBox.getWidth(), newLen) 

127 self.assertEqual(newBBox.getHeight(), newLen) 

128 self.assertEqual(resizedPsf.getSigma(), self.psf.getSigma()) 

129 

130 image = resizedPsf.computeKernelImage(resizedPsf.getAveragePosition()) 

131 check = makeGaussianImage(newBBox, self.psf.getSigma()) 

132 self.assertFloatsAlmostEqual(image.getArray(), check.getArray()) 

133 # tolerance same as in self.testKernelImage 

134 self.assertFloatsAlmostEqual(image.getArray().sum(), 1.0, atol=1E-14) 

135 

136 

137class MemoryTester(lsst.utils.tests.MemoryTestCase): 

138 pass 

139 

140 

141def setup_module(module): 

142 lsst.utils.tests.init() 

143 

144 

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

146 lsst.utils.tests.init() 

147 unittest.main()