Coverage for python/lsst/geom/testUtils.py: 19%

64 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-08-19 12:00 -0700

1# 

2# Developed for the LSST Data Management System. 

3# This product includes software developed by the LSST Project 

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

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

6# for details of code ownership. 

7# 

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

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

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

11# (at your option) any later version. 

12# 

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

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

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

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the GNU General Public License 

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

20# 

21 

22"""Utilities that should be imported into the lsst.geom namespace when 

23lsst.geom is used 

24 

25In the case of the assert functions, importing them makes them available in lsst.utils.tests.TestCase 

26""" 

27__all__ = [] 

28 

29import math 

30 

31import numpy as np 

32 

33import lsst.utils.tests 

34from ._geom import arcseconds 

35 

36 

37def extraMsg(msg): 

38 """Format extra error message, if any 

39 """ 

40 if msg: 

41 return ": " + msg 

42 return "" 

43 

44 

45@lsst.utils.tests.inTestCase 

46def assertAnglesAlmostEqual(testCase, ang0, ang1, maxDiff=0.001*arcseconds, 

47 ignoreWrap=True, msg="Angles differ"): 

48 r"""Assert that two `~lsst.geom.Angle`\ s are almost equal, ignoring 

49 wrap differences by default. 

50 

51 If both arguments are NaN the assert will pass. If one of the arguments 

52 is NaN but the other is not the assert will fail. 

53 

54 Parameters 

55 ---------- 

56 testCase : `unittest.TestCase` 

57 test case the test is part of; an object supporting one method: 

58 fail(self, msgStr) 

59 ang0 : `lsst.geom.Angle` 

60 angle 0 

61 ang1 : `lsst.geom.Angle` 

62 angle 1 

63 maxDiff : `lsst.geom.Angle` 

64 maximum difference between the two angles 

65 ignoreWrap : `bool` 

66 ignore wrap when comparing the angles? 

67 

68 - if True then wrap is ignored, e.g. 0 and 360 degrees are considered 

69 equal 

70 - if False then wrap matters, e.g. 0 and 360 degrees are considered 

71 different 

72 

73 msg : `str` 

74 exception message prefix; details of the error are appended after ": " 

75 

76 Raises 

77 ------ 

78 AssertionError 

79 Raised if the difference is greater than ``maxDiff`` 

80 """ 

81 isNan0 = math.isnan(ang0.asRadians()) 

82 isNan1 = math.isnan(ang1.asRadians()) 

83 if isNan0 and isNan1: 

84 return 

85 if isNan0: 

86 testCase.fail("ang0 is NaN") 

87 if isNan1: 

88 testCase.fail("ang1 is NaN") 

89 measDiff = ang1 - ang0 

90 if ignoreWrap: 

91 measDiff = measDiff.wrapCtr() 

92 if abs(measDiff) > maxDiff: 

93 testCase.fail("%s: measured difference %s arcsec > max allowed %s arcsec" % 

94 (msg, measDiff.asArcseconds(), maxDiff.asArcseconds())) 

95 

96 

97@lsst.utils.tests.inTestCase 

98def assertPairsAlmostEqual(testCase, pair0, pair1, maxDiff=1e-7, msg="Pairs differ"): 

99 """Assert that two Cartesian points are almost equal. 

100 

101 Each point can be any indexable pair of two floats, including 

102 Point2D or Extent2D, a list or a tuple. 

103 

104 Parameters 

105 ---------- 

106 testCase : `unittest.TestCase` 

107 test case the test is part of; an object supporting one method: fail(self, msgStr) 

108 pair0 : pair of `float` 

109 pair 0 

110 pair1 : pair of `floats` 

111 pair 1 

112 maxDiff : `float` 

113 maximum radial separation between the two points 

114 msg : `str` 

115 exception message prefix; details of the error are appended after ": " 

116 

117 Raises 

118 ------ 

119 AssertionError 

120 Raised if the radial difference is greater than ``maxDiff`` 

121 

122 Notes 

123 ----- 

124 .. warning:: 

125 

126 Does not compare types, just compares values. 

127 """ 

128 if len(pair0) != 2: 

129 raise RuntimeError("len(pair0)=%s != 2" % (len(pair0),)) 

130 if len(pair1) != 2: 

131 raise RuntimeError("len(pair1)=%s != 2" % (len(pair1),)) 

132 

133 pairDiff = [float(pair1[i] - pair0[i]) for i in range(2)] 

134 measDiff = math.hypot(*pairDiff) 

135 if measDiff > maxDiff: 

136 testCase.fail("%s: measured radial distance = %s > maxDiff = %s, pair0=(%r, %r), pair1=(%r, %r)" % 

137 (msg, measDiff, maxDiff, pair0[0], pair0[1], pair1[0], pair1[1])) 

138 

139 

140@lsst.utils.tests.inTestCase 

141def assertPairListsAlmostEqual(testCase, list0, list1, maxDiff=1e-7, msg=None): 

142 """Assert that two lists of Cartesian points are almost equal 

143 

144 Each point can be any indexable pair of two floats, including 

145 Point2D or Extent2D, a list or a tuple. 

146 

147 Parameters 

148 ---------- 

149 testCase : `unittest.TestCase` 

150 test case the test is part of; an object supporting one method: fail(self, msgStr) 

151 list0 : `list` of pairs of `float` 

152 list of pairs 0 

153 list1 : `list` of pairs of `float` 

154 list of pairs 1 

155 maxDiff : `float` 

156 maximum radial separation between the two points 

157 msg : `str` 

158 additional information for the error message; appended after ": " 

159 

160 Raises 

161 ------ 

162 AssertionError 

163 Raised if the radial difference is greater than ``maxDiff`` 

164 

165 Notes 

166 ----- 

167 .. warning:: 

168 

169 Does not compare types, just values. 

170 """ 

171 testCase.assertEqual(len(list0), len(list1)) 

172 lenList1 = np.array([len(val) for val in list0]) 

173 lenList2 = np.array([len(val) for val in list1]) 

174 testCase.assertTrue(np.all(lenList1 == 2)) 

175 testCase.assertTrue(np.all(lenList2 == 2)) 

176 

177 diffArr = np.array([(val0[0] - val1[0], val0[1] - val1[1]) 

178 for val0, val1 in zip(list0, list1)], dtype=float) 

179 sepArr = np.hypot(diffArr[:, 0], diffArr[:, 1]) 

180 badArr = sepArr > maxDiff 

181 if np.any(badArr): 

182 maxInd = np.argmax(sepArr) 

183 testCase.fail("PairLists differ in %s places; max separation is at %s: %s > %s%s" % 

184 (np.sum(badArr), maxInd, sepArr[maxInd], maxDiff, extraMsg(msg))) 

185 

186 

187@lsst.utils.tests.inTestCase 

188def assertSpherePointsAlmostEqual(testCase, sp0, sp1, maxSep=0.001*arcseconds, msg=""): 

189 r"""Assert that two `~lsst.geom.SpherePoint`\ s are almost equal 

190 

191 Parameters 

192 ---------- 

193 testCase : `unittest.TestCase` 

194 test case the test is part of; an object supporting one method: 

195 fail(self, msgStr) 

196 sp0 : `lsst.geom.SpherePoint` 

197 SpherePoint 0 

198 sp1 : `lsst.geom.SpherePoint` 

199 SpherePoint 1 

200 maxSep : `lsst.geom.Angle` 

201 maximum separation 

202 msg : `str` 

203 extra information to be printed with any error message 

204 

205 Raises 

206 ------ 

207 AssertionError 

208 The SpherePoints are not equal. 

209 """ 

210 if sp0.separation(sp1) > maxSep: 

211 testCase.fail("Angular separation between %s and %s = %s\" > maxSep = %s\"%s" % 

212 (sp0, sp1, sp0.separation(sp1).asArcseconds(), maxSep.asArcseconds(), extraMsg(msg))) 

213 

214 

215@lsst.utils.tests.inTestCase 

216def assertSpherePointListsAlmostEqual(testCase, splist0, splist1, maxSep=0.001*arcseconds, msg=None): 

217 r"""Assert that two lists of `~lsst.geom.SpherePoint`\ s are almost equal 

218 

219 Parameters 

220 ---------- 

221 testCase : `unittest.TestCase` 

222 test case the test is part of; an object supporting one method: 

223 fail(self, msgStr) 

224 splist0 : `list` of `lsst.geom.SpherePoint` 

225 list of SpherePoints 0 

226 splist1 : `list` of `lsst.geom.SpherePoint` 

227 list of SpherePoints 1 

228 maxSep : `lsst.geom.Angle` 

229 maximum separation 

230 msg : `str` 

231 exception message prefix; details of the error are appended after ": " 

232 

233 Raises 

234 ------ 

235 AssertionError 

236 The SpherePoint lists are not equal. 

237 """ 

238 testCase.assertEqual(len(splist0), len(splist1), msg=msg) 

239 sepArr = np.array([sp0.separation(sp1) 

240 for sp0, sp1 in zip(splist0, splist1)]) 

241 badArr = sepArr > maxSep 

242 if np.any(badArr): 

243 maxInd = np.argmax(sepArr) 

244 testCase.fail("SpherePointLists differ in %s places; max separation is at %s: %s\" > %s\"%s" % 

245 (np.sum(badArr), maxInd, sepArr[maxInd].asArcseconds(), 

246 maxSep.asArcseconds(), extraMsg(msg))) 

247 

248 

249@lsst.utils.tests.inTestCase 

250def assertBoxesAlmostEqual(testCase, box0, box1, maxDiff=1e-7, msg="Boxes differ"): 

251 """Assert that two boxes (`~lsst.geom.Box2D` or `~lsst.geom.Box2I`) are 

252 almost equal 

253 

254 Parameters 

255 ---------- 

256 testCase : `unittest.TestCase` 

257 test case the test is part of; an object supporting one method: 

258 fail(self, msgStr) 

259 box0 : `lsst.geom.Box2D` or `lsst.geom.Box2I` 

260 box 0 

261 box1 : `lsst.geom.Box2D` or `lsst.geom.Box2I` 

262 box 1 

263 maxDiff : `float` 

264 maximum radial separation between the min points and max points 

265 msg : `str` 

266 exception message prefix; details of the error are appended after ": " 

267 

268 Raises 

269 ------ 

270 AssertionError 

271 Raised if the radial difference of the min points or max points is 

272 greater than maxDiff 

273 

274 Notes 

275 ----- 

276 .. warning:: 

277 

278 Does not compare types, just compares values. 

279 """ 

280 assertPairsAlmostEqual(testCase, box0.getMin(), 

281 box1.getMin(), maxDiff=maxDiff, msg=msg + ": min") 

282 assertPairsAlmostEqual(testCase, box0.getMax(), 

283 box1.getMax(), maxDiff=maxDiff, msg=msg + ": max")