Coverage for tests/test_functorKeys.py: 7%

346 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-03-20 00:40 -0700

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 table FunctorKeys 

24 

25Run with: 

26 python test_functorKeys.py 

27or 

28 pytest test_functorKeys.py 

29""" 

30import unittest 

31 

32import numpy 

33 

34import lsst.utils.tests 

35import lsst.pex.exceptions 

36import lsst.geom 

37import lsst.afw.table 

38import lsst.afw.geom 

39 

40 

41def makePositiveSymmetricMatrix(size): 

42 """Return a random symmetric matrix with only positive eigenvalues, suitable 

43 for use as a covariance matrix. 

44 """ 

45 a = numpy.random.randn(size, size + 1).astype(numpy.float32) 

46 m = numpy.dot(a, a.transpose()) 

47 for i in range(size): 

48 for j in range(i): 

49 m[i, j] = m[j, i] 

50 return m 

51 

52 

53class FunctorKeysTestCase(lsst.utils.tests.TestCase): 

54 

55 def setUp(self): 

56 numpy.random.seed(5) 

57 

58 def doTestPointKey(self, fieldType, functorKeyType, valueType): 

59 schema = lsst.afw.table.Schema() 

60 fKey0 = functorKeyType.addFields(schema, "a", "x or y", "pixel") 

61 xKey = schema.find("a_x").key 

62 yKey = schema.find("a_y").key 

63 # we create two equivalent functor keys, using the two different 

64 # constructors 

65 fKey1 = functorKeyType(xKey, yKey) 

66 fKey2 = functorKeyType(schema["a"]) 

67 # test that they're equivalent, and that their constituent keys are 

68 # what we expect 

69 self.assertEqual(fKey0.getX(), xKey) 

70 self.assertEqual(fKey0.getY(), yKey) 

71 self.assertEqual(fKey1.getX(), xKey) 

72 self.assertEqual(fKey2.getX(), xKey) 

73 self.assertEqual(fKey1.getY(), yKey) 

74 self.assertEqual(fKey2.getY(), yKey) 

75 self.assertEqual(fKey0, fKey1) 

76 self.assertEqual(fKey1, fKey2) 

77 self.assertTrue(fKey0.isValid()) 

78 self.assertTrue(fKey1.isValid()) 

79 self.assertTrue(fKey2.isValid()) 

80 # check that a default-constructed functor key is invalid 

81 fKey3 = functorKeyType() 

82 self.assertNotEqual(fKey3, fKey1) 

83 self.assertFalse(fKey3.isValid()) 

84 # create a record from the test schema, and fill it using the 

85 # constituent keys 

86 table = lsst.afw.table.BaseTable.make(schema) 

87 record = table.makeRecord() 

88 record.set(xKey, 4) 

89 record.set(yKey, 2) 

90 # test that the return type and value is correct 

91 self.assertIsInstance(record.get(fKey1), valueType) 

92 self.assertEqual(record.get(fKey1).getX(), record.get(xKey)) 

93 self.assertEqual(record.get(fKey1).getY(), record.get(yKey)) 

94 # test that we can set using the functor key 

95 p = valueType(8, 16) 

96 record.set(fKey1, p) 

97 self.assertEqual(record.get(xKey), p.getX()) 

98 self.assertEqual(record.get(yKey), p.getY()) 

99 

100 def testPointKey(self): 

101 self.doTestPointKey("I", lsst.afw.table.Point2IKey, 

102 lsst.geom.Point2I) 

103 self.doTestPointKey("D", lsst.afw.table.Point2DKey, 

104 lsst.geom.Point2D) 

105 

106 def doTestBoxKey(self, pointFieldType, functorKeyType, valueType): 

107 """Run type-parameterized tests on a Box FunctorKey. 

108 

109 Parameters 

110 ---------- 

111 pointFieldType : `type` 

112 A FunctorKey class for the Point type of this box; one of 

113 Point2IKey or Point2DKey. 

114 functorKeyType : `type` 

115 The Box FunctorKey class to test; one of Box2IKey or Box2DKey. 

116 valueType : `type` 

117 The Box type to test; one of Box2I or Box2D. 

118 """ 

119 schema = lsst.afw.table.Schema() 

120 fKey0 = functorKeyType.addFields(schema, "a", "box", "pixel") 

121 minKey = pointFieldType(schema["a_min"]) 

122 maxKey = pointFieldType(schema["a_max"]) 

123 # we create two equivalent functor keys, using the two different constructors 

124 fKey1 = functorKeyType(minKey, maxKey) 

125 fKey2 = functorKeyType(schema["a"]) 

126 # test that they're equivalent, and that their constituent keys are what we expect 

127 self.assertEqual(fKey0.getMin(), minKey) 

128 self.assertEqual(fKey0.getMax(), maxKey) 

129 self.assertEqual(fKey1.getMin(), minKey) 

130 self.assertEqual(fKey2.getMin(), minKey) 

131 self.assertEqual(fKey1.getMax(), maxKey) 

132 self.assertEqual(fKey2.getMax(), maxKey) 

133 self.assertEqual(fKey0, fKey1) 

134 self.assertEqual(fKey1, fKey2) 

135 self.assertTrue(fKey0.isValid()) 

136 self.assertTrue(fKey1.isValid()) 

137 self.assertTrue(fKey2.isValid()) 

138 # check that a default-constructed functor key is invalid 

139 fKey3 = functorKeyType() 

140 self.assertNotEqual(fKey3, fKey1) 

141 self.assertFalse(fKey3.isValid()) 

142 # create a record from the test schema, and fill it using the constituent keys 

143 table = lsst.afw.table.BaseTable.make(schema) 

144 record = table.makeRecord() 

145 record.set(minKey, valueType.Point(2, 4)) 

146 record.set(maxKey, valueType.Point(5, 8)) 

147 # test that the return type and value is correct 

148 self.assertIsInstance(record.get(fKey1), valueType) 

149 self.assertEqual(record.get(fKey1).getMin(), record.get(minKey)) 

150 self.assertEqual(record.get(fKey1).getMax(), record.get(maxKey)) 

151 # test that we can set using the functor key 

152 b = valueType(valueType.Point(8, 16), valueType.Point(11, 20)) 

153 record.set(fKey1, b) 

154 self.assertEqual(record.get(minKey), b.getMin()) 

155 self.assertEqual(record.get(maxKey), b.getMax()) 

156 

157 def testBoxKey(self): 

158 self.doTestBoxKey(lsst.afw.table.Point2IKey, lsst.afw.table.Box2IKey, lsst.geom.Box2I) 

159 self.doTestBoxKey(lsst.afw.table.Point2DKey, lsst.afw.table.Box2DKey, lsst.geom.Box2D) 

160 

161 def testCoordKey(self): 

162 schema = lsst.afw.table.Schema() 

163 fKey0 = lsst.afw.table.CoordKey.addFields(schema, "a", "position") 

164 longKey = schema.find("a_ra").key 

165 latKey = schema.find("a_dec").key 

166 # create two equivalent functor keys using the two different 

167 # constructors 

168 fKey1 = lsst.afw.table.CoordKey(longKey, latKey) 

169 fKey2 = lsst.afw.table.CoordKey(schema["a"]) 

170 # test that they are equivalent 

171 self.assertEqual(fKey0.getRa(), longKey) 

172 self.assertEqual(fKey0.getRa(), fKey1.getRa()) 

173 self.assertEqual(fKey0.getRa(), fKey2.getRa()) 

174 self.assertEqual(fKey0.getDec(), latKey) 

175 self.assertEqual(fKey0.getDec(), fKey1.getDec()) 

176 self.assertEqual(fKey0.getDec(), fKey2.getDec()) 

177 self.assertEqual(fKey0, fKey1) 

178 self.assertEqual(fKey0, fKey2) 

179 self.assertEqual(fKey1, fKey2) 

180 # a default-constructed key is invalid 

181 fKey3 = lsst.afw.table.CoordKey() 

182 self.assertFalse(fKey3.isValid()) 

183 # create a record from the test schema, and fill it using the 

184 # constituent keys 

185 table = lsst.afw.table.BaseTable.make(schema) 

186 record = table.makeRecord() 

187 record.set(longKey, lsst.geom.Angle(0)) 

188 record.set(latKey, lsst.geom.Angle(1)) 

189 self.assertIsInstance(record.get(fKey1), lsst.geom.SpherePoint) 

190 self.assertEqual(record.get(fKey1).getRa(), record.get(longKey)) 

191 self.assertEqual(record.get(fKey1).getDec(), record.get(latKey)) 

192 # Test that we can set using the functor key 

193 coord = lsst.geom.SpherePoint( 

194 lsst.geom.Angle(0), lsst.geom.Angle(1)) 

195 record.set(fKey1, coord) 

196 self.assertEqual(record.get(longKey), coord.getRa()) 

197 self.assertEqual(record.get(latKey), coord.getDec()) 

198 # Check for inequality with a different key 

199 fKey3 = lsst.afw.table.CoordKey.addFields(schema, "b", "position") 

200 self.assertNotEqual(fKey0, fKey3) 

201 

202 def testQuadrupoleKey(self): 

203 schema = lsst.afw.table.Schema() 

204 fKey0 = lsst.afw.table.QuadrupoleKey.addFields( 

205 schema, "a", "moments", lsst.afw.table.CoordinateType.PIXEL) 

206 xxKey = schema.find("a_xx").key 

207 yyKey = schema.find("a_yy").key 

208 xyKey = schema.find("a_xy").key 

209 # we create two equivalent functor keys, using the two different 

210 # constructors 

211 fKey1 = lsst.afw.table.QuadrupoleKey(xxKey, yyKey, xyKey) 

212 fKey2 = lsst.afw.table.QuadrupoleKey(schema["a"]) 

213 # test that they're equivalent, and tha=t their constituent keys are 

214 # what we expect 

215 self.assertEqual(fKey0.getIxx(), xxKey) 

216 self.assertEqual(fKey1.getIxx(), xxKey) 

217 self.assertEqual(fKey2.getIxx(), xxKey) 

218 self.assertEqual(fKey0.getIyy(), yyKey) 

219 self.assertEqual(fKey1.getIyy(), yyKey) 

220 self.assertEqual(fKey2.getIyy(), yyKey) 

221 self.assertEqual(fKey0.getIxy(), xyKey) 

222 self.assertEqual(fKey1.getIxy(), xyKey) 

223 self.assertEqual(fKey2.getIxy(), xyKey) 

224 self.assertEqual(fKey0, fKey1) 

225 self.assertEqual(fKey1, fKey2) 

226 self.assertTrue(fKey0.isValid()) 

227 self.assertTrue(fKey1.isValid()) 

228 self.assertTrue(fKey2.isValid()) 

229 # check that a default-constructed functor key is invalid 

230 fKey3 = lsst.afw.table.QuadrupoleKey() 

231 self.assertNotEqual(fKey3, fKey1) 

232 self.assertFalse(fKey3.isValid()) 

233 # create a record from the test schema, and fill it using the 

234 # constituent keys 

235 table = lsst.afw.table.BaseTable.make(schema) 

236 record = table.makeRecord() 

237 record.set(xxKey, 4) 

238 record.set(yyKey, 2) 

239 record.set(xyKey, 2) 

240 # test that the return type and value is correct 

241 self.assertIsInstance(record.get(fKey1), 

242 lsst.afw.geom.Quadrupole) 

243 self.assertEqual(record.get(fKey1).getIxx(), record.get(xxKey)) 

244 self.assertEqual(record.get(fKey1).getIyy(), record.get(yyKey)) 

245 self.assertEqual(record.get(fKey1).getIxy(), record.get(xyKey)) 

246 # test that we can set using the functor key 

247 p = lsst.afw.geom.Quadrupole(8, 16, 4) 

248 record.set(fKey1, p) 

249 self.assertEqual(record.get(xxKey), p.getIxx()) 

250 self.assertEqual(record.get(yyKey), p.getIyy()) 

251 self.assertEqual(record.get(xyKey), p.getIxy()) 

252 

253 def testEllipseKey(self): 

254 schema = lsst.afw.table.Schema() 

255 fKey0 = lsst.afw.table.EllipseKey.addFields( 

256 schema, "a", "ellipse", "pixel") 

257 qKey = lsst.afw.table.QuadrupoleKey(schema["a"]) 

258 pKey = lsst.afw.table.Point2DKey(schema["a"]) 

259 # we create two more equivalent functor keys, using the two different 

260 # constructors 

261 fKey1 = lsst.afw.table.EllipseKey(qKey, pKey) 

262 fKey2 = lsst.afw.table.EllipseKey(schema["a"]) 

263 # test that they're equivalent, and tha=t their constituent keys are 

264 # what we expect 

265 self.assertEqual(fKey0.getCore(), qKey) 

266 self.assertEqual(fKey1.getCore(), qKey) 

267 self.assertEqual(fKey2.getCore(), qKey) 

268 self.assertEqual(fKey0.getCenter(), pKey) 

269 self.assertEqual(fKey1.getCenter(), pKey) 

270 self.assertEqual(fKey2.getCenter(), pKey) 

271 self.assertEqual(fKey0, fKey1) 

272 self.assertEqual(fKey1, fKey2) 

273 self.assertTrue(fKey0.isValid()) 

274 self.assertTrue(fKey1.isValid()) 

275 self.assertTrue(fKey2.isValid()) 

276 # check that a default-constructed functor key is invalid 

277 fKey3 = lsst.afw.table.EllipseKey() 

278 self.assertNotEqual(fKey3, fKey1) 

279 self.assertFalse(fKey3.isValid()) 

280 # create a record from the test schema, and fill it using the 

281 # constituent keys 

282 table = lsst.afw.table.BaseTable.make(schema) 

283 record = table.makeRecord() 

284 record.set(qKey, lsst.afw.geom.Quadrupole(4, 3, 1)) 

285 record.set(pKey, lsst.geom.Point2D(5, 6)) 

286 # test that the return type and value is correct 

287 self.assertIsInstance(record.get(fKey1), 

288 lsst.afw.geom.Ellipse) 

289 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIxx(), 

290 record.get(qKey).getIxx(), rtol=1E-14) 

291 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIyy(), 

292 record.get(qKey).getIyy(), rtol=1E-14) 

293 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIxy(), 

294 record.get(qKey).getIxy(), rtol=1E-14) 

295 self.assertEqual(record.get(fKey1).getCenter().getX(), 

296 record.get(pKey).getX()) 

297 self.assertEqual(record.get(fKey1).getCenter().getX(), 

298 record.get(pKey).getX()) 

299 # test that we can set using the functor key 

300 e = lsst.afw.geom.Ellipse(lsst.afw.geom.Quadrupole(8, 16, 4), 

301 lsst.geom.Point2D(5, 6)) 

302 record.set(fKey1, e) 

303 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIxx(), 

304 e.getCore().getIxx(), rtol=1E-14) 

305 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIyy(), 

306 e.getCore().getIyy(), rtol=1E-14) 

307 self.assertFloatsAlmostEqual(record.get(fKey1).getCore().getIxy(), 

308 e.getCore().getIxy(), rtol=1E-14) 

309 self.assertEqual(record.get(fKey1).getCenter().getX(), 

310 e.getCenter().getX()) 

311 self.assertEqual(record.get(fKey1).getCenter().getX(), 

312 e.getCenter().getX()) 

313 

314 def doTestCovarianceMatrixKeyAddFields(self, fieldType, varianceOnly, dynamicSize): 

315 names = ["x", "y"] 

316 schema = lsst.afw.table.Schema() 

317 if dynamicSize: 

318 FunctorKeyType = getattr( 

319 lsst.afw.table, f"CovarianceMatrix2{fieldType.lower()}Key") 

320 else: 

321 FunctorKeyType = getattr( 

322 lsst.afw.table, f"CovarianceMatrixX{fieldType.lower()}Key") 

323 fKey1 = FunctorKeyType.addFields( 

324 schema, "a", names, ["m", "s"], varianceOnly) 

325 fKey2 = FunctorKeyType.addFields( 

326 schema, "b", names, "kg", varianceOnly) 

327 self.assertEqual(schema.find("a_xErr").field.getUnits(), "m") 

328 self.assertEqual(schema.find("a_yErr").field.getUnits(), "s") 

329 self.assertEqual(schema.find("b_xErr").field.getUnits(), "kg") 

330 self.assertEqual(schema.find("b_yErr").field.getUnits(), "kg") 

331 dtype = numpy.float64 if fieldType == "D" else numpy.float32 

332 if varianceOnly: 

333 m = numpy.diagflat(numpy.random.randn(2)**2).astype(dtype) 

334 else: 

335 self.assertEqual(schema.find("a_x_y_Cov").field.getUnits(), 

336 "m s") 

337 self.assertEqual(schema.find("b_x_y_Cov").field.getUnits(), 

338 "kg kg") 

339 v = numpy.random.randn(2, 2).astype(dtype) 

340 m = numpy.dot(v.transpose(), v) 

341 table = lsst.afw.table.BaseTable.make(schema) 

342 record = table.makeRecord() 

343 record.set(fKey1, m) 

344 self.assertFloatsAlmostEqual(record.get(fKey1), m, rtol=1E-6) 

345 record.set(fKey2, m*2) 

346 self.assertFloatsAlmostEqual(record.get(fKey2), m*2, rtol=1E-6) 

347 

348 def doTestCovarianceMatrixKey(self, fieldType, parameterNames, varianceOnly, dynamicSize): 

349 schema = lsst.afw.table.Schema() 

350 sigmaKeys = [] 

351 covKeys = [] 

352 # we generate a schema with a complete set of fields for the diagonal and some (but not all) 

353 # of the covariance elements 

354 for i, pi in enumerate(parameterNames): 

355 sigmaKeys.append(schema.addField(f"a_{pi}Err", type=fieldType, 

356 doc=f"uncertainty on {pi}")) 

357 if varianceOnly: 

358 continue # in this case we have fields for only the diagonal 

359 for pj in parameterNames[:i]: 

360 # intentionally be inconsistent about whether we store the lower or upper triangle, 

361 # and occasionally don't store anything at all; this tests that the 

362 # CovarianceMatrixKey constructor can handle all those 

363 # possibilities. 

364 r = numpy.random.rand() 

365 if r < 0.3: 

366 k = schema.addField(f"a_{pi}_{pj}_Cov", type=fieldType, 

367 doc=f"{pi},{pj} covariance") 

368 elif r < 0.6: 

369 k = schema.addField(f"a_{pj}_{pi}_Cov", type=fieldType, 

370 doc=f"{pj},{pi} covariance") 

371 else: 

372 k = lsst.afw.table.Key[fieldType]() 

373 covKeys.append(k) 

374 if dynamicSize: 

375 FunctorKeyType = getattr(lsst.afw.table, "CovarianceMatrix%d%sKey" 

376 % (len(parameterNames), fieldType.lower())) 

377 else: 

378 FunctorKeyType = getattr(lsst.afw.table, "CovarianceMatrixX%sKey" 

379 % fieldType.lower()) 

380 # construct two equivalent functor keys using the different 

381 # constructors 

382 fKey1 = FunctorKeyType(sigmaKeys, covKeys) 

383 fKey2 = FunctorKeyType(schema["a"], parameterNames) 

384 self.assertTrue(fKey1.isValid()) 

385 self.assertTrue(fKey2.isValid()) 

386 self.assertEqual(fKey1, fKey2) 

387 # verify that a default-constructed functor key is invalid 

388 fKey3 = FunctorKeyType() 

389 self.assertNotEqual(fKey3, fKey1) 

390 self.assertFalse(fKey3.isValid()) 

391 # create a record from the test schema, and fill it using the 

392 # constituent keys 

393 table = lsst.afw.table.BaseTable.make(schema) 

394 record = table.makeRecord() 

395 k = 0 

396 # we set each matrix element a two-digit number where the first digit is the row 

397 # index and the second digit is the column index. 

398 for i in range(len(parameterNames)): 

399 record.set(sigmaKeys[i], ((i + 1)*10 + (i + 1))**0.5) 

400 if varianceOnly: 

401 continue 

402 for j in range(i): 

403 if covKeys[k].isValid(): 

404 record.set(covKeys[k], (i + 1)*10 + (j + 1)) 

405 k += 1 

406 # test that the return type and value is correct 

407 matrix1 = record.get(fKey1) 

408 matrix2 = record.get(fKey2) 

409 # we use assertFloatsAlmostEqual because it can handle matrices, and because square root 

410 # in Python might not be exactly reversible with squaring in C++ (with possibly 

411 # different precision). 

412 self.assertFloatsAlmostEqual(matrix1, matrix2) 

413 k = 0 

414 for i in range(len(parameterNames)): 

415 self.assertFloatsAlmostEqual( 

416 matrix1[i, i], (i + 1)*10 + (i + 1), rtol=1E-7) 

417 if varianceOnly: 

418 continue 

419 for j in range(i): 

420 if covKeys[k].isValid(): 

421 self.assertFloatsAlmostEqual( 

422 matrix1[i, j], (i + 1)*10 + (j + 1), rtol=1E-7) 

423 self.assertFloatsAlmostEqual( 

424 matrix2[i, j], (i + 1)*10 + (j + 1), rtol=1E-7) 

425 self.assertFloatsAlmostEqual( 

426 matrix1[j, i], (i + 1)*10 + (j + 1), rtol=1E-7) 

427 self.assertFloatsAlmostEqual( 

428 matrix2[j, i], (i + 1)*10 + (j + 1), rtol=1E-7) 

429 self.assertFloatsAlmostEqual( 

430 fKey1.getElement(record, i, j), 

431 (i + 1)*10 + (j + 1), rtol=1E-7) 

432 self.assertFloatsAlmostEqual( 

433 fKey2.getElement(record, i, j), 

434 (i + 1)*10 + (j + 1), rtol=1E-7) 

435 v = numpy.random.randn() 

436 fKey1.setElement(record, i, j, v) 

437 self.assertFloatsAlmostEqual( 

438 fKey2.getElement(record, i, j), v, rtol=1E-7) 

439 fKey2.setElement(record, i, j, (i + 1)*10 + (j + 1)) 

440 else: 

441 with self.assertRaises(lsst.pex.exceptions.LogicError): 

442 fKey1.setElement(record, i, j, 0.0) 

443 k += 1 

444 

445 def testCovarianceMatrixKey(self): 

446 for fieldType in ("F", "D"): 

447 for varianceOnly in (True, False): 

448 for dynamicSize in (True, False): 

449 for parameterNames in (["x", "y"], ["xx", "yy", "xy"]): 

450 self.doTestCovarianceMatrixKey( 

451 fieldType, parameterNames, varianceOnly, dynamicSize) 

452 self.doTestCovarianceMatrixKeyAddFields( 

453 fieldType, varianceOnly, dynamicSize) 

454 

455 def doTestArrayKey(self, fieldType, numpyType): 

456 FunctorKeyType = getattr(lsst.afw.table, f"Array{fieldType}Key") 

457 self.assertFalse(FunctorKeyType().isValid()) 

458 schema = lsst.afw.table.Schema() 

459 a0 = schema.addField("a_0", type=fieldType, doc="valid array element") 

460 a1 = schema.addField("a_1", type=fieldType, doc="valid array element") 

461 a2 = schema.addField("a_2", type=fieldType, doc="valid array element") 

462 b0 = schema.addField("b_0", type=fieldType, 

463 doc="invalid out-of-order array element") 

464 b2 = schema.addField("b_2", type=fieldType, 

465 doc="invalid out-of-order array element") 

466 b1 = schema.addField("b_1", type=fieldType, 

467 doc="invalid out-of-order array element") 

468 c = schema.addField("c", type=f"Array{fieldType}", 

469 doc="old-style array", size=4) 

470 k1 = FunctorKeyType([a0, a1, a2]) # construct from a list of keys 

471 k2 = FunctorKeyType(schema["a"]) # construct from SubSchema 

472 # construct from old-style Key<Array<T>> 

473 k3 = FunctorKeyType(c) 

474 k4 = FunctorKeyType.addFields(schema, "d", "doc for d", "barn", 4) 

475 k5 = FunctorKeyType.addFields( 

476 schema, "e", "doc for e %3.1f", "barn", [2.1, 2.2]) 

477 self.assertTrue(k1.isValid()) 

478 self.assertTrue(k2.isValid()) 

479 self.assertTrue(k3.isValid()) 

480 self.assertTrue(k4.isValid()) 

481 self.assertTrue(k5.isValid()) 

482 # k1 and k2 point to the same underlying fields 

483 self.assertEqual(k1, k2) 

484 self.assertEqual(k1[2], a2) # test that we can extract an element 

485 # test that we can slice ArrayKeys 

486 self.assertEqual(k1[1:3], FunctorKeyType([a1, a2])) 

487 self.assertEqual(k1.getSize(), 3) 

488 self.assertEqual(k2.getSize(), 3) 

489 self.assertEqual(k3.getSize(), 4) 

490 self.assertEqual(k4.getSize(), 4) 

491 self.assertEqual(k5.getSize(), 2) 

492 # none of these point to the same underlying fields; 

493 self.assertNotEqual(k1, k3) 

494 self.assertNotEqual(k1, k4) # they should all be unequal 

495 self.assertNotEqual(k1, k5) 

496 # test that the fields we added 

497 self.assertEqual(schema.find(k5[0]).field.getDoc(), "doc for e 2.1") 

498 # got the right docs 

499 self.assertEqual(schema.find(k5[1]).field.getDoc(), "doc for e 2.2") 

500 # test that invalid slices raise exceptions 

501 self.assertRaises(IndexError, lambda k: k[1:3:2], k1) 

502 # test that trying to construct from a SubSchema with badly ordered 

503 # fields doesn't work 

504 self.assertRaises( 

505 lsst.pex.exceptions.InvalidParameterError, FunctorKeyType, schema["b"]) 

506 # test that trying to construct from a list of keys that are not 

507 # ordered doesn't work 

508 self.assertRaises( 

509 lsst.pex.exceptions.InvalidParameterError, FunctorKeyType, [b0, b1, b2]) 

510 self.assertEqual(k4, FunctorKeyType(schema["d"])) 

511 self.assertEqual(k5, FunctorKeyType(schema["e"])) 

512 # finally, we create a record, fill it with random data, and verify 

513 # that get/set/__getitem__ work 

514 table = lsst.afw.table.BaseTable.make(schema) 

515 record = table.makeRecord() 

516 array = numpy.random.randn(3).astype(numpyType) 

517 record.set(k1, array) 

518 self.assertFloatsAlmostEqual(record.get(k1), array) 

519 self.assertFloatsAlmostEqual(record.get(k2), array) 

520 self.assertFloatsAlmostEqual(record[k1], array) 

521 self.assertEqual(record.get(k1).dtype, numpy.dtype(numpyType)) 

522 

523 def testArrayKey(self): 

524 self.doTestArrayKey("F", numpy.float32) 

525 self.doTestArrayKey("D", numpy.float64) 

526 

527 

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

529 pass 

530 

531 

532def setup_module(module): 

533 lsst.utils.tests.init() 

534 

535 

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

537 lsst.utils.tests.init() 

538 unittest.main()