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# 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 

22""" 

23Tests for detection.GaussianPsf 

24 

25Run with: 

26 python test_gaussianPsf.py 

27or 

28 pytest test_gaussianPsf.py 

29""" 

30 

31import unittest 

32 

33import numpy as np 

34 

35import lsst.utils.tests 

36import lsst.pex.exceptions 

37import lsst.geom 

38import lsst.afw.table 

39import lsst.afw.fits 

40import lsst.afw.detection 

41 

42 

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

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

45 array = image.getArray() 

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

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

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

49 array /= array.sum() 

50 return image 

51 

52 

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

54 bbox = image.getBBox() 

55 array = image.getArray() 

56 s = 0.0 

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

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

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

60 s += array[yi, xi] 

61 return s 

62 

63 

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

65 

66 def setUp(self): 

67 self.kernelSize = 51 

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

69 self.kernelSize, self.kernelSize, 4.0) 

70 

71 def tearDown(self): 

72 del self.psf 

73 

74 def testKernelImage(self): 

75 image = self.psf.computeKernelImage() 

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

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

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

79 

80 def testOffsetImage(self): 

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

82 check = makeGaussianImage( 

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

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

85 plotOnFailure=True) 

86 

87 def testApertureFlux(self): 

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

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

90 self.assertFloatsAlmostEqual(self.psf.computeApertureFlux(5.0), computeNaiveApertureFlux(image, 5.0), 

91 rtol=0.1) 

92 self.assertFloatsAlmostEqual(self.psf.computeApertureFlux(7.0), computeNaiveApertureFlux(image, 7.0), 

93 rtol=0.1) 

94 

95 def testShape(self): 

96 self.assertFloatsAlmostEqual( 

97 self.psf.computeShape().getDeterminantRadius(), 4.0) 

98 

99 def testPersistence(self): 

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

101 self.psf.writeFits(filename) 

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

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

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

105 

106 def testBBox(self): 

107 

108 self.assertEqual(self.psf.computeKernelImage().getBBox(), 

109 self.psf.computeBBox()) 

110 

111 self.assertEqual(self.psf.computeBBox().getWidth(), self.kernelSize) 

112 

113 # Test interface. GaussianPsf does not vary spatially 

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

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

116 

117 def testResized(self): 

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

119 newLen = self.kernelSize - pad 

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

121 newBBox = resizedPsf.computeBBox() 

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

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

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

125 

126 image = resizedPsf.computeKernelImage() 

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

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

129 # tolerance same as in self.testKernelImage 

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

131 

132 

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

134 pass 

135 

136 

137def setup_module(module): 

138 lsst.utils.tests.init() 

139 

140 

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

142 lsst.utils.tests.init() 

143 unittest.main()