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# 

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 - if True then wrap is ignored, e.g. 0 and 360 degrees are considered 

68 equal 

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

70 different 

71 msg : `str` 

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

73 

74 Raises 

75 ------ 

76 AssertionError 

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

78 """ 

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

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

81 if isNan0 and isNan1: 

82 return 

83 if isNan0: 

84 testCase.fail("ang0 is NaN") 

85 if isNan1: 

86 testCase.fail("ang1 is NaN") 

87 measDiff = ang1 - ang0 

88 if ignoreWrap: 

89 measDiff = measDiff.wrapCtr() 

90 if abs(measDiff) > maxDiff: 

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

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

93 

94 

95@lsst.utils.tests.inTestCase 

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

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

98 

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

100 Point2D or Extent2D, a list or a tuple. 

101 

102 Parameters 

103 ---------- 

104 testCase : `unittest.TestCase` 

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

106 pair0 : pair of `float` 

107 pair 0 

108 pair1 : pair of `floats` 

109 pair 1 

110 maxDiff : `float` 

111 maximum radial separation between the two points 

112 msg : `str` 

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

114 

115 Raises 

116 ------ 

117 AssertionError 

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

119 

120 Notes 

121 ----- 

122 .. warning:: 

123 

124 Does not compare types, just compares values. 

125 """ 

126 if len(pair0) != 2: 

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

128 if len(pair1) != 2: 

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

130 

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

132 measDiff = math.hypot(*pairDiff) 

133 if measDiff > maxDiff: 

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

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

136 

137 

138@lsst.utils.tests.inTestCase 

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

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

141 

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

143 Point2D or Extent2D, a list or a tuple. 

144 

145 Parameters 

146 ---------- 

147 testCase : `unittest.TestCase` 

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

149 list0 : `list` of pairs of `float` 

150 list of pairs 0 

151 list1 : `list` of pairs of `float` 

152 list of pairs 1 

153 maxDiff : `float` 

154 maximum radial separation between the two points 

155 msg : `str` 

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

157 

158 Raises 

159 ------ 

160 AssertionError 

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

162 

163 Notes 

164 ----- 

165 .. warning:: 

166 

167 Does not compare types, just values. 

168 """ 

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

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

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

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

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

174 

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

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

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

178 badArr = sepArr > maxDiff 

179 if np.any(badArr): 

180 maxInd = np.argmax(sepArr) 

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

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

183 

184 

185@lsst.utils.tests.inTestCase 

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

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

188 

189 Parameters 

190 ---------- 

191 testCase : `unittest.TestCase` 

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

193 fail(self, msgStr) 

194 sp0 : `lsst.geom.SpherePoint` 

195 SpherePoint 0 

196 sp1 : `lsst.geom.SpherePoint` 

197 SpherePoint 1 

198 maxSep : `lsst.geom.Angle` 

199 maximum separation 

200 msg : `str` 

201 extra information to be printed with any error message 

202 

203 Raises 

204 ------ 

205 AssertionError 

206 The SpherePoints are not equal. 

207 """ 

208 if sp0.separation(sp1) > maxSep: 

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

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

211 

212 

213@lsst.utils.tests.inTestCase 

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

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

216 

217 Parameters 

218 ---------- 

219 testCase : `unittest.TestCase` 

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

221 fail(self, msgStr) 

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

223 list of SpherePoints 0 

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

225 list of SpherePoints 1 

226 maxSep : `lsst.geom.Angle` 

227 maximum separation 

228 msg : `str` 

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

230 

231 Raises 

232 ------ 

233 AssertionError 

234 The SpherePoint lists are not equal. 

235 """ 

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

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

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

239 badArr = sepArr > maxSep 

240 if np.any(badArr): 

241 maxInd = np.argmax(sepArr) 

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

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

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

245 

246 

247@lsst.utils.tests.inTestCase 

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

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

250 almost equal 

251 

252 Parameters 

253 ---------- 

254 testCase : `unittest.TestCase` 

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

256 fail(self, msgStr) 

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

258 box 0 

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

260 box 1 

261 maxDiff : `float` 

262 maximum radial separation between the min points and max points 

263 msg : `str` 

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

265 

266 Raises 

267 ------ 

268 AssertionError 

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

270 greater than maxDiff 

271 

272 Notes 

273 ----- 

274 .. warning:: 

275 

276 Does not compare types, just compares values. 

277 """ 

278 assertPairsAlmostEqual(testCase, box0.getMin(), 

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

280 assertPairsAlmostEqual(testCase, box0.getMax(), 

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