Coverage for tests/test_brightStarStamps.py: 14%

100 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-03 03:06 -0700

1# This file is part of meas_algorithms. 

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 

23import numpy as np 

24import tempfile 

25 

26from lsst.meas.algorithms import brightStarStamps 

27from lsst.afw import image as afwImage 

28from lsst.geom import Point2I 

29from lsst.daf.base import PropertyList 

30import lsst.utils.tests 

31 

32 

33class BrightStarStampsTestCase(lsst.utils.tests.TestCase): 

34 """Test BrightStarStamps. 

35 """ 

36 def setUp(self): 

37 np.random.seed(12) 

38 stampSize = (25, 25) 

39 # create dummy star stamps 

40 starImages = [afwImage.MaskedImageF(*stampSize) 

41 for _ in range(3)] 

42 for starIm in starImages: 

43 starImArray = starIm.image.array 

44 starImArray += np.random.rand(*stampSize) 

45 ids = ["111", "aaa", "bbb"] 

46 positions = [Point2I(x0, y0) 

47 for x0, y0 in zip(np.random.randint(11, size=3), np.random.randint(11, size=3))] 

48 mags = np.random.rand(3) 

49 # faint object to test magnitude cuts 

50 self.faintObjIdx = 1 

51 mags[self.faintObjIdx] = 18. 

52 ids[self.faintObjIdx] = "faint" 

53 fluxes = np.random.rand(3) 

54 self.starStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm, 

55 gaiaGMag=mag, 

56 position=pos, 

57 gaiaId=gaiaId, 

58 annularFlux=flux) 

59 for starIm, mag, gaiaId, pos, flux in 

60 zip(starImages, mags, ids, positions, fluxes)] 

61 self.unnormalizedStarStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm, 

62 gaiaGMag=mag, 

63 position=pos, 

64 gaiaId=gaiaId) 

65 for starIm, mag, gaiaId, pos, flux in 

66 zip(starImages, mags, ids, positions, fluxes)] 

67 self.toBeNormalizedStarStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm, 

68 gaiaGMag=mag, 

69 position=pos, 

70 gaiaId=gaiaId) 

71 for starIm, mag, gaiaId, pos, flux in 

72 zip(starImages, mags, ids, positions, fluxes)] 

73 self.innerRadius = 5 

74 self.outerRadius = 10 

75 self.nb90Rots = 2 

76 self.bss = brightStarStamps.BrightStarStamps(self.starStamps, 

77 innerRadius=self.innerRadius, 

78 outerRadius=self.outerRadius, 

79 nb90Rots=self.nb90Rots) 

80 

81 def tearDown(self): 

82 del self.bss 

83 del self.starStamps 

84 del self.unnormalizedStarStamps 

85 del self.toBeNormalizedStarStamps 

86 del self.innerRadius 

87 del self.outerRadius 

88 del self.faintObjIdx 

89 

90 def testIO(self): 

91 """Test the class' write and readFits methods. 

92 

93 The ``options`` argument to the read method is only used to read 

94 sub-BBoxes, which is handled by the Butler. Tests of this are done in 

95 afw. 

96 """ 

97 with tempfile.NamedTemporaryFile() as f: 

98 self.bss.writeFits(f.name) 

99 options = PropertyList() 

100 bss2 = brightStarStamps.BrightStarStamps.readFitsWithOptions(f.name, options) 

101 self.assertEqual(len(self.bss), len(bss2)) 

102 for mi1, mi2 in zip(self.bss.getMaskedImages(), bss2.getMaskedImages()): 

103 self.assertMaskedImagesAlmostEqual(mi1, mi2) 

104 np.testing.assert_almost_equal(self.bss.getMagnitudes(), bss2.getMagnitudes()) 

105 np.testing.assert_almost_equal(self.bss.getAnnularFluxes(), bss2.getAnnularFluxes()) 

106 for id1, id2 in zip(self.bss.getGaiaIds(), bss2.getGaiaIds()): 

107 self.assertEqual(id1, id2) 

108 for pos1, pos2 in zip(self.bss.getPositions(), bss2.getPositions()): 

109 self.assertEqual(pos1[0], pos2[0]) 

110 self.assertEqual(pos1[1], pos2[1]) 

111 self.assertEqual(bss2.nb90Rots, self.nb90Rots) 

112 

113 def testMagnitudeSelection(self): 

114 brightOnly = self.bss.selectByMag(magMax=7) 

115 self.assertEqual(len(brightOnly), 2) 

116 self.assertFalse("faint" in brightOnly.getGaiaIds()) 

117 

118 faintOnly = self.bss.selectByMag(magMin=7) 

119 self.assertEqual(len(faintOnly), 1) 

120 self.assertEqual(faintOnly.getGaiaIds()[0], "faint") 

121 faintObj = self.bss[self.faintObjIdx] 

122 self.assertMaskedImagesAlmostEqual(faintObj.stamp_im, faintOnly.getMaskedImages()[0]) 

123 

124 def testTypeMismatchHandling(self): 

125 fullStar = self.bss[0] 

126 # try passing on a dictionary and a maskedImage instead of a 

127 # BrightStarStamp 

128 falseStar = {"starStamp": fullStar.stamp_im, "gaiaGMag": fullStar.gaiaGMag, 

129 "gaiaId": fullStar.gaiaId, "annularFlux": fullStar.annularFlux} 

130 starIm = fullStar.stamp_im 

131 for wrongType in [falseStar, starIm]: 

132 # test at initialization 

133 with self.assertRaises(ValueError): 

134 _ = brightStarStamps.BrightStarStamps([fullStar, wrongType], innerRadius=self.innerRadius, 

135 outerRadius=self.outerRadius) 

136 # test at appending time 

137 with self.assertRaises(ValueError): 

138 self.bss.append(wrongType, innerRadius=self.innerRadius, outerRadius=self.outerRadius) 

139 

140 def testAnnulusMismatch(self): 

141 """Test an exception is raised if mismatching annulus radii are 

142 given (as the annularFlux values would then be meaningless).""" 

143 # starStamps are already normalized; an Exception should be raised when 

144 # trying to pass them onto the initAndNormalize classmethod 

145 with self.assertRaises(AttributeError): 

146 _ = brightStarStamps.BrightStarStamps.initAndNormalize(self.starStamps, 

147 innerRadius=self.innerRadius, 

148 outerRadius=self.outerRadius) 

149 # unnormalizedStarStamps can be kept unnormalized provided no radii are 

150 # passed on as arguments 

151 bss2 = brightStarStamps.BrightStarStamps(self.unnormalizedStarStamps) 

152 with self.assertRaises(AttributeError): 

153 _ = brightStarStamps.BrightStarStamps(self.unnormalizedStarStamps, 

154 innerRadius=self.innerRadius, 

155 outerRadius=self.outerRadius) 

156 # or normalized at initialization, in which case radii must be passed 

157 # on 

158 bss3 = brightStarStamps.BrightStarStamps.initAndNormalize(self.toBeNormalizedStarStamps, 

159 innerRadius=self.innerRadius, 

160 outerRadius=self.outerRadius) 

161 # BrightStarStamps instances can be concatenated if the radii used are 

162 # the same 

163 self.bss.extend(bss3) 

164 # but an Exception should be raised when trying to concatenate a mix of 

165 # normalized and unnormalized stamps 

166 with self.assertRaises(AttributeError): 

167 self.bss.extend(bss2) 

168 # or stamps normalized with different annular radii 

169 bss4 = brightStarStamps.BrightStarStamps.initAndNormalize(self.unnormalizedStarStamps, 

170 innerRadius=int(self.innerRadius/2), 

171 outerRadius=self.outerRadius) 

172 with self.assertRaises(AttributeError): 

173 self.bss.extend(bss4) 

174 # or when appending an extra stamp with different annulus radii 

175 fullStar = self.bss[0] 

176 with self.assertRaises(AttributeError): 

177 self.bss.append(fullStar, innerRadius=int(self.innerRadius/2), outerRadius=self.outerRadius + 1) 

178 # or a normalized stamp to unnormalized BrightStarStamps, or vice-versa 

179 with self.assertRaises(AttributeError): 

180 bss2.append(fullStar, innerRadius=self.innerRadius, outerRadius=self.outerRadius) 

181 unNormFullStar = bss2[0] 

182 with self.assertRaises(AttributeError): 

183 self.bss.append(unNormFullStar) 

184 

185 

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

187 pass 

188 

189 

190def setup_module(module): 

191 lsst.utils.tests.init() 

192 

193 

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

195 lsst.utils.tests.init() 

196 unittest.main()