Coverage for tests/test_imagePca.py: 18%

129 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-12 02:30 -0800

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 PCA on Images 

24 

25Run with: 

26 python test_imagePca.py 

27or 

28 pytest test_imagePca.py 

29""" 

30 

31import unittest 

32import random 

33import math 

34import itertools 

35 

36import numpy as np 

37 

38import lsst.utils.tests 

39import lsst.pex.exceptions as pexExcept 

40import lsst.geom 

41import lsst.afw.image as afwImage 

42import lsst.afw.display as afwDisplay 

43 

44try: 

45 type(display) 

46except NameError: 

47 display = False 

48 

49 

50class ImagePcaTestCase(lsst.utils.tests.TestCase): 

51 """A test case for ImagePca""" 

52 

53 def setUp(self): 

54 random.seed(0) 

55 self.ImageSet = afwImage.ImagePcaF() 

56 

57 def tearDown(self): 

58 del self.ImageSet 

59 

60 def testInnerProducts(self): 

61 """Test inner products""" 

62 

63 width, height = 10, 20 

64 im1 = afwImage.ImageF(lsst.geom.Extent2I(width, height)) 

65 val1 = 10 

66 im1.set(val1) 

67 

68 im2 = im1.Factory(im1.getDimensions()) 

69 val2 = 20 

70 im2.set(val2) 

71 

72 self.assertEqual(afwImage.innerProduct(im1, im1), 

73 width*height*val1*val1) 

74 self.assertEqual(afwImage.innerProduct(im1, im2), 

75 width*height*val1*val2) 

76 

77 im2[0, 0, afwImage.LOCAL] = 0 

78 self.assertEqual(afwImage.innerProduct(im1, im2), 

79 (width*height - 1)*val1*val2) 

80 

81 im2[0, 0, afwImage.LOCAL] = val2 # reinstate value 

82 im2[width - 1, height - 1, afwImage.LOCAL] = 1 

83 self.assertEqual(afwImage.innerProduct(im1, im2), 

84 (width*height - 1)*val1*val2 + val1) 

85 

86 def testAddImages(self): 

87 """Test adding images to a PCA set""" 

88 

89 nImage = 3 

90 for i in range(nImage): 

91 im = afwImage.ImageF(lsst.geom.Extent2I(21, 21)) 

92 val = 1 

93 im.set(val) 

94 

95 self.ImageSet.addImage(im, 1.0) 

96 

97 vec = self.ImageSet.getImageList() 

98 self.assertEqual(len(vec), nImage) 

99 self.assertEqual(vec[nImage - 1][0, 0, afwImage.LOCAL], val) 

100 

101 def tst(): 

102 """Try adding an image with no flux""" 

103 self.ImageSet.addImage(im, 0.0) 

104 

105 self.assertRaises(pexExcept.OutOfRangeError, tst) 

106 

107 def testMean(self): 

108 """Test calculating mean image""" 

109 

110 width, height = 10, 20 

111 

112 values = (100, 200, 300) 

113 meanVal = 0 

114 for val in values: 

115 im = afwImage.ImageF(lsst.geom.Extent2I(width, height)) 

116 im.set(val) 

117 

118 self.ImageSet.addImage(im, 1.0) 

119 meanVal += val 

120 

121 meanVal = meanVal/len(values) 

122 

123 mean = self.ImageSet.getMean() 

124 

125 self.assertEqual(mean.getWidth(), width) 

126 self.assertEqual(mean.getHeight(), height) 

127 self.assertEqual(mean[0, 0, afwImage.LOCAL], meanVal) 

128 self.assertEqual(mean[width - 1, height - 1, afwImage.LOCAL], meanVal) 

129 

130 def testPca(self): 

131 """Test calculating PCA""" 

132 width, height = 200, 100 

133 numBases = 3 

134 numInputs = 3 

135 

136 bases = [] 

137 for i in range(numBases): 

138 im = afwImage.ImageF(width, height) 

139 array = im.getArray() 

140 x, y = np.indices(array.shape) 

141 period = 5*(i+1) 

142 fx = np.sin(2*math.pi/period*x + 2*math.pi/numBases*i) 

143 fy = np.sin(2*math.pi/period*y + 2*math.pi/numBases*i) 

144 array[x, y] = fx + fy 

145 bases.append(im) 

146 

147 if display: 

148 mos = afwDisplay.utils.Mosaic(background=-10) 

149 afwDisplay.Display(frame=1).mtv(mos.makeMosaic(bases), title="Basis functions") 

150 

151 inputs = [] 

152 for i in range(numInputs): 

153 im = afwImage.ImageF(lsst.geom.Extent2I(width, height)) 

154 im.set(0) 

155 for b in bases: 

156 im.scaledPlus(random.random(), b) 

157 

158 inputs.append(im) 

159 self.ImageSet.addImage(im, 1.0) 

160 

161 if display: 

162 mos = afwDisplay.utils.Mosaic(background=-10) 

163 afwDisplay.Display(frame=2).mtv(mos.makeMosaic(inputs), title="Inputs") 

164 

165 self.ImageSet.analyze() 

166 

167 eImages = [] 

168 for img in self.ImageSet.getEigenImages(): 

169 eImages.append(img) 

170 

171 if display: 

172 mos = afwDisplay.utils.Mosaic(background=-10) 

173 afwDisplay.Display(frame=3).mtv(mos.makeMosaic(eImages), title="EigenImages") 

174 

175 self.assertEqual(len(eImages), numInputs) 

176 

177 # Test for orthogonality 

178 for i1, i2 in itertools.combinations(list(range(len(eImages))), 2): 

179 inner = afwImage.innerProduct(eImages[i1], eImages[i2]) 

180 norm1 = eImages[i1].getArray().sum() 

181 norm2 = eImages[i2].getArray().sum() 

182 inner /= norm1*norm2 

183 self.assertAlmostEqual(inner, 0, 6) 

184 

185 def testPcaNaN(self): 

186 """Test calculating PCA when the images can contain NaNs""" 

187 

188 width, height = 20, 10 

189 

190 values = (100, 200, 300) 

191 for i, val in enumerate(values): 

192 im = afwImage.ImageF(lsst.geom.Extent2I(width, height)) 

193 im.set(val) 

194 

195 if i == 1: 

196 im[width//2, height//2, afwImage.LOCAL] = np.nan 

197 

198 self.ImageSet.addImage(im, 1.0) 

199 

200 self.ImageSet.analyze() 

201 

202 eImages = [] 

203 for img in self.ImageSet.getEigenImages(): 

204 eImages.append(img) 

205 

206 if display: 

207 mos = afwDisplay.utils.Mosaic(background=-10) 

208 afwDisplay.Display(frame=0).mtv(mos.makeMosaic(eImages), title="testPcaNaN") 

209 

210 

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

212 pass 

213 

214 

215def setup_module(module): 

216 lsst.utils.tests.init() 

217 

218 

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

220 lsst.utils.tests.init() 

221 unittest.main()