Coverage for tests/test_visitInfo.py: 11%

Shortcuts 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

342 statements  

1# 

2# LSST Data Management System 

3# Copyright 2016 LSST Corporation. 

4# 

5# This product includes software developed by the 

6# LSST Project (http://www.lsst.org/). 

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 LSST License Statement and 

19# the GNU General Public License along with this program. If not, 

20# see <http://www.lsstcorp.org/LegalNotices/>. 

21# 

22import math 

23import os 

24import unittest 

25import collections 

26import numpy as np 

27 

28import lsst.utils.tests 

29import lsst.pex.exceptions 

30from lsst.daf.base import DateTime, PropertySet, PropertyList 

31from lsst.geom import Angle, degrees, SpherePoint 

32from lsst.afw.coord import Observatory, Weather 

33import lsst.afw.image as afwImage 

34 

35RotTypeEnumNameDict = { 

36 afwImage.RotType.UNKNOWN: "UNKNOWN", 

37 afwImage.RotType.SKY: "SKY", 

38 afwImage.RotType.HORIZON: "HORIZON", 

39 afwImage.RotType.MOUNT: "MOUNT", 

40} 

41 

42 

43def propertySetFromDict(keyValDict): 

44 """Make an lsst.daf.base.PropertySet from a dict of key: value""" 

45 metadata = PropertySet() 

46 for key, val in keyValDict.items(): 

47 metadata.set(key, val) 

48 return metadata 

49 

50 

51def makeVisitInfo(data): 

52 """Return a VisitInfo constructed from a VisitInfoData namedtuple.""" 

53 return afwImage.VisitInfo(data.exposureId, 

54 data.exposureTime, 

55 data.darkTime, 

56 data.date, 

57 data.ut1, 

58 data.era, 

59 data.boresightRaDec, 

60 data.boresightAzAlt, 

61 data.boresightAirmass, 

62 data.boresightRotAngle, 

63 data.rotType, 

64 data.observatory, 

65 data.weather, 

66 data.instrumentLabel, 

67 data.id, 

68 ) 

69 

70 

71class VisitInfoTestCase(lsst.utils.tests.TestCase): 

72 """Test lsst.afw.image.VisitInfo, a simple struct-like class""" 

73 

74 def setUp(self): 

75 self.testDir = os.path.dirname(__file__) 

76 

77 def computeLstHA(data): 

78 """Return LST, Hour Angle, computed from VisitInfoData.""" 

79 localEra = data.era + data.observatory.getLongitude() 

80 hourAngle = localEra - data.boresightRaDec[0] 

81 return localEra, hourAngle 

82 

83 fields = ['exposureId', 

84 'exposureTime', 

85 'darkTime', 

86 'date', 

87 'ut1', 

88 'era', 

89 'boresightRaDec', 

90 'boresightAzAlt', 

91 'boresightAirmass', 

92 'boresightRotAngle', 

93 'rotType', 

94 'observatory', 

95 'weather', 

96 'instrumentLabel', 

97 'id', 

98 ] 

99 VisitInfoData = collections.namedtuple("VisitInfoData", fields) 

100 data1 = VisitInfoData(exposureId=10313423, 

101 exposureTime=10.01, 

102 darkTime=11.02, 

103 date=DateTime( 

104 65321.1, DateTime.MJD, DateTime.TAI), 

105 ut1=12345.1, 

106 era=45.1*degrees, 

107 boresightRaDec=SpherePoint( 

108 23.1*degrees, 73.2*degrees), 

109 boresightAzAlt=SpherePoint( 

110 134.5*degrees, 33.3*degrees), 

111 boresightAirmass=1.73, 

112 boresightRotAngle=73.2*degrees, 

113 rotType=afwImage.RotType.SKY, 

114 observatory=Observatory( 

115 11.1*degrees, 22.2*degrees, 0.333), 

116 weather=Weather(1.1, 2.2, 34.5), 

117 instrumentLabel="TestCameraOne", 

118 id=987654, 

119 ) 

120 self.data1 = data1 

121 self.localEra1, self.hourAngle1 = computeLstHA(data1) 

122 data2 = VisitInfoData(exposureId=1, 

123 exposureTime=15.5, 

124 darkTime=17.8, 

125 date=DateTime( 

126 55321.2, DateTime.MJD, DateTime.TAI), 

127 ut1=312345.1, 

128 era=25.1*degrees, 

129 boresightRaDec=SpherePoint( 

130 2.1*degrees, 33.2*degrees), 

131 boresightAzAlt=SpherePoint(13.5*degrees, 83.3*degrees), 

132 boresightAirmass=2.05, 

133 boresightRotAngle=-53.2*degrees, 

134 rotType=afwImage.RotType.HORIZON, 

135 observatory=Observatory( 

136 22.2*degrees, 33.3*degrees, 0.444), 

137 weather=Weather(2.2, 3.3, 44.4), 

138 instrumentLabel="TestCameraTwo", 

139 id=123456 

140 ) 

141 self.data2 = data2 

142 self.localEra2, self.hourAngle2 = computeLstHA(data2) 

143 

144 def _testValueConstructor(self, data, localEra, hourAngle): 

145 visitInfo = makeVisitInfo(data) 

146 with self.assertWarns(FutureWarning): 

147 self.assertEqual(visitInfo.getExposureId(), data.exposureId) 

148 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime) 

149 self.assertEqual(visitInfo.getDarkTime(), data.darkTime) 

150 self.assertEqual(visitInfo.getDate(), data.date) 

151 self.assertEqual(visitInfo.getUt1(), data.ut1) 

152 self.assertEqual(visitInfo.getEra(), data.era) 

153 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec) 

154 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt) 

155 self.assertEqual(visitInfo.getBoresightAirmass(), 

156 data.boresightAirmass) 

157 self.assertEqual(visitInfo.getBoresightRotAngle(), 

158 data.boresightRotAngle) 

159 self.assertEqual(visitInfo.getRotType(), data.rotType) 

160 self.assertEqual(visitInfo.getObservatory(), data.observatory) 

161 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel) 

162 self.assertEqual(visitInfo.getWeather(), data.weather) 

163 self.assertEqual(visitInfo.getLocalEra(), localEra) 

164 self.assertEqual(visitInfo.getBoresightHourAngle(), hourAngle) 

165 self.assertEqual(visitInfo.getId(), data.id) 

166 

167 def _testProperties(self, data, localEra, hourAngle): 

168 """Test property attribute accessors.""" 

169 visitInfo = makeVisitInfo(data) 

170 self.assertEqual(visitInfo.exposureTime, data.exposureTime) 

171 self.assertEqual(visitInfo.darkTime, data.darkTime) 

172 self.assertEqual(visitInfo.date, data.date) 

173 self.assertEqual(visitInfo.ut1, data.ut1) 

174 self.assertEqual(visitInfo.era, data.era) 

175 self.assertEqual(visitInfo.boresightRaDec, data.boresightRaDec) 

176 self.assertEqual(visitInfo.boresightAzAlt, data.boresightAzAlt) 

177 self.assertEqual(visitInfo.boresightAirmass, data.boresightAirmass) 

178 self.assertEqual(visitInfo.boresightRotAngle, data.boresightRotAngle) 

179 self.assertEqual(visitInfo.rotType, data.rotType) 

180 self.assertEqual(visitInfo.observatory, data.observatory) 

181 self.assertEqual(visitInfo.instrumentLabel, data.instrumentLabel) 

182 self.assertEqual(visitInfo.weather, data.weather) 

183 self.assertEqual(visitInfo.localEra, localEra) 

184 self.assertEqual(visitInfo.boresightHourAngle, hourAngle) 

185 self.assertEqual(visitInfo.id, data.id) 

186 

187 def testValueConstructor_data1(self): 

188 self._testValueConstructor(self.data1, self.localEra1, self.hourAngle1) 

189 self._testProperties(self.data1, self.localEra1, self.hourAngle1) 

190 

191 def testValueConstructor_data2(self): 

192 self._testValueConstructor(self.data2, self.localEra2, self.hourAngle2) 

193 self._testProperties(self.data2, self.localEra2, self.hourAngle2) 

194 

195 def testTablePersistence(self): 

196 """Test that VisitInfo can be round-tripped with current code. 

197 """ 

198 for item in (self.data1, self.data2): 

199 tablePath = os.path.join( 

200 self.testDir, "testVisitInfo_testTablePersistence.fits") 

201 v1 = afwImage.VisitInfo(*item) 

202 v1.writeFits(tablePath) 

203 v2 = afwImage.VisitInfo.readFits(tablePath) 

204 self.assertEqual(v1, v2) 

205 os.unlink(tablePath) 

206 

207 def _testFitsRead(self, data, filePath, version): 

208 """Test that old VersionInfo files are read correctly. 

209 

210 Parameters 

211 ---------- 

212 data : `VisitInfoData` 

213 The values expected to be stored in the file, or a 

214 superset thereof. 

215 filePath : `str` 

216 The file to test. 

217 version : `int` 

218 The VersionInfo persistence format used in ``filePath``. 

219 """ 

220 visitInfo = afwImage.VisitInfo.readFits(filePath) 

221 

222 if version >= 0: 

223 with self.assertWarns(FutureWarning): 

224 self.assertEqual(visitInfo.getExposureId(), data.exposureId) 

225 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime) 

226 self.assertEqual(visitInfo.getDarkTime(), data.darkTime) 

227 self.assertEqual(visitInfo.getDate(), data.date) 

228 self.assertEqual(visitInfo.getUt1(), data.ut1) 

229 self.assertEqual(visitInfo.getEra(), data.era) 

230 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec) 

231 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt) 

232 self.assertEqual(visitInfo.getBoresightAirmass(), 

233 data.boresightAirmass) 

234 self.assertEqual(visitInfo.getBoresightRotAngle(), 

235 data.boresightRotAngle) 

236 self.assertEqual(visitInfo.getRotType(), data.rotType) 

237 self.assertEqual(visitInfo.getObservatory(), data.observatory) 

238 self.assertEqual(visitInfo.getWeather(), data.weather) 

239 if version >= 1: 

240 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel) 

241 else: 

242 self.assertEqual(visitInfo.getInstrumentLabel(), "") 

243 if version >= 2: 

244 self.assertEqual(visitInfo.getId(), data.id) 

245 else: 

246 self.assertEqual(visitInfo.getId(), 0) 

247 

248 def testPersistenceVersions(self): 

249 """Test that older versions are handled appropriately. 

250 """ 

251 dataDir = os.path.join(os.path.dirname(__file__), "data") 

252 

253 # All files created by makeVisitInfo(self.data1).writeFits() 

254 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-noversion.fits"), 0) 

255 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-version-1.fits"), 1) 

256 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-version-2.fits"), 2) 

257 

258 def testSetVisitInfoMetadata(self): 

259 for item in (self.data1, self.data2): 

260 visitInfo = makeVisitInfo(item) 

261 metadata = PropertyList() 

262 afwImage.setVisitInfoMetadata(metadata, visitInfo) 

263 self.assertEqual(metadata.nameCount(), 22) 

264 self.assertEqual(metadata.getScalar("EXPID"), item.exposureId) 

265 self.assertEqual(metadata.getScalar("EXPTIME"), item.exposureTime) 

266 self.assertEqual(metadata.getScalar("DARKTIME"), item.darkTime) 

267 self.assertEqual(metadata.getScalar("DATE-AVG"), 

268 item.date.toString(DateTime.TAI)) 

269 self.assertEqual(metadata.getScalar("TIMESYS"), "TAI") 

270 self.assertEqual(metadata.getScalar("MJD-AVG-UT1"), item.ut1) 

271 self.assertEqual(metadata.getScalar("AVG-ERA"), item.era.asDegrees()) 

272 self.assertEqual(metadata.getScalar("BORE-RA"), 

273 item.boresightRaDec[0].asDegrees()) 

274 self.assertEqual(metadata.getScalar("BORE-DEC"), 

275 item.boresightRaDec[1].asDegrees()) 

276 self.assertEqual(metadata.getScalar("BORE-AZ"), 

277 item.boresightAzAlt[0].asDegrees()) 

278 self.assertEqual(metadata.getScalar("BORE-ALT"), 

279 item.boresightAzAlt[1].asDegrees()) 

280 self.assertEqual(metadata.getScalar("BORE-AIRMASS"), 

281 item.boresightAirmass) 

282 self.assertEqual(metadata.getScalar("BORE-ROTANG"), 

283 item.boresightRotAngle.asDegrees()) 

284 self.assertEqual(metadata.getScalar("ROTTYPE"), 

285 RotTypeEnumNameDict[item.rotType]) 

286 self.assertEqual(metadata.getScalar("OBS-LONG"), 

287 item.observatory.getLongitude().asDegrees()) 

288 self.assertEqual(metadata.getScalar("OBS-LAT"), 

289 item.observatory.getLatitude().asDegrees()) 

290 self.assertEqual(metadata.getScalar("OBS-ELEV"), 

291 item.observatory.getElevation()) 

292 self.assertEqual(metadata.getScalar("AIRTEMP"), 

293 item.weather.getAirTemperature()) 

294 self.assertEqual(metadata.getScalar("AIRPRESS"), 

295 item.weather.getAirPressure()) 

296 self.assertEqual(metadata.getScalar("HUMIDITY"), 

297 item.weather.getHumidity()) 

298 self.assertEqual(metadata.getScalar("INSTRUMENT"), 

299 item.instrumentLabel) 

300 self.assertEqual(metadata.getScalar("IDNUM"), 

301 item.id) 

302 

303 def testSetVisitInfoMetadataMissingValues(self): 

304 """If a value is unknown then it should not be written to the metadata""" 

305 visitInfo = afwImage.VisitInfo() # only rot type is known 

306 metadata = PropertyList() 

307 afwImage.setVisitInfoMetadata(metadata, visitInfo) 

308 self.assertEqual(metadata.getScalar("ROTTYPE"), 

309 RotTypeEnumNameDict[afwImage.RotType.UNKNOWN]) 

310 self.assertEqual(metadata.nameCount(), 1) 

311 

312 def testStripVisitInfoKeywords(self): 

313 for argList in (self.data1, self.data2): 

314 visitInfo = afwImage.VisitInfo(*argList) 

315 metadata = PropertyList() 

316 afwImage.setVisitInfoMetadata(metadata, visitInfo) 

317 # add an extra keyword that will not be stripped 

318 metadata.set("EXTRA", 5) 

319 self.assertEqual(metadata.nameCount(), 23) 

320 afwImage.stripVisitInfoKeywords(metadata) 

321 self.assertEqual(metadata.nameCount(), 1) 

322 

323 def _testIsEmpty(self, visitInfo): 

324 """Test that visitInfo is all NaN, 0, or empty string, as appropriate. 

325 """ 

326 with self.assertWarns(FutureWarning): 

327 self.assertEqual(visitInfo.getExposureId(), 0) 

328 self.assertTrue(math.isnan(visitInfo.getExposureTime())) 

329 self.assertTrue(math.isnan(visitInfo.getDarkTime())) 

330 self.assertEqual(visitInfo.getDate(), DateTime()) 

331 self.assertTrue(math.isnan(visitInfo.getUt1())) 

332 self.assertTrue(math.isnan(visitInfo.getEra().asDegrees())) 

333 for i in range(2): 

334 self.assertTrue(math.isnan( 

335 visitInfo.getBoresightRaDec()[i].asDegrees())) 

336 self.assertTrue(math.isnan( 

337 visitInfo.getBoresightAzAlt()[i].asDegrees())) 

338 self.assertTrue(math.isnan(visitInfo.getBoresightAirmass())) 

339 self.assertTrue(math.isnan( 

340 visitInfo.getBoresightRotAngle().asDegrees())) 

341 self.assertEqual(visitInfo.getRotType(), afwImage.RotType.UNKNOWN) 

342 self.assertTrue(math.isnan( 

343 visitInfo.getObservatory().getLongitude().asDegrees())) 

344 self.assertTrue(math.isnan( 

345 visitInfo.getObservatory().getLatitude().asDegrees())) 

346 self.assertTrue(math.isnan(visitInfo.getObservatory().getElevation())) 

347 self.assertTrue(math.isnan(visitInfo.getWeather().getAirTemperature())) 

348 self.assertTrue(math.isnan(visitInfo.getWeather().getAirPressure())) 

349 self.assertTrue(math.isnan(visitInfo.getWeather().getHumidity())) 

350 self.assertTrue(math.isnan(visitInfo.getBoresightHourAngle())) 

351 self.assertEqual(visitInfo.getInstrumentLabel(), "") 

352 self.assertEqual(visitInfo.getId(), 0) 

353 

354 def testEquals(self): 

355 """Test that identical VisitInfo objects compare equal, even if some fields are NaN. 

356 """ 

357 # objects with "equal state" should be equal 

358 self.assertEqual(makeVisitInfo(self.data1), makeVisitInfo(self.data1)) 

359 self.assertEqual(makeVisitInfo(self.data2), makeVisitInfo(self.data2)) 

360 self.assertNotEqual(makeVisitInfo(self.data1), makeVisitInfo(self.data2)) 

361 self.assertEqual(afwImage.VisitInfo(), afwImage.VisitInfo()) 

362 

363 # equality must be reflexive 

364 info = makeVisitInfo(self.data1) 

365 self.assertEqual(info, info) 

366 info = makeVisitInfo(self.data2) 

367 self.assertEqual(info, info) 

368 info = afwImage.VisitInfo() 

369 self.assertEqual(info, info) 

370 

371 # commutativity and transitivity difficult to test with this setup 

372 

373 def testMetadataConstructor(self): 

374 """Test the metadata constructor 

375 

376 This constructor allows missing values 

377 """ 

378 data = self.data1 

379 

380 metadata = propertySetFromDict({}) 

381 visitInfo = afwImage.VisitInfo(metadata) 

382 self._testIsEmpty(visitInfo) 

383 

384 metadata = propertySetFromDict({"EXPID": data.exposureId}) 

385 visitInfo = afwImage.VisitInfo(metadata) 

386 with self.assertWarns(FutureWarning): 

387 self.assertEqual(visitInfo.getExposureId(), data.exposureId) 

388 self.assertTrue(math.isnan(visitInfo.getExposureTime())) 

389 

390 metadata = propertySetFromDict({"EXPTIME": data.exposureTime}) 

391 visitInfo = afwImage.VisitInfo(metadata) 

392 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime) 

393 

394 metadata = propertySetFromDict({"DARKTIME": data.darkTime}) 

395 visitInfo = afwImage.VisitInfo(metadata) 

396 self.assertEqual(visitInfo.getDarkTime(), data.darkTime) 

397 

398 metadata = propertySetFromDict( 

399 {"DATE-AVG": data.date.toString(DateTime.TAI), "TIMESYS": "TAI"}) 

400 visitInfo = afwImage.VisitInfo(metadata) 

401 self.assertEqual(visitInfo.getDate(), data.date) 

402 

403 # TIME-MID in UTC is an acceptable alternative to DATE-AVG 

404 metadata = propertySetFromDict( 

405 {"TIME-MID": data.date.toString(DateTime.UTC)}) 

406 visitInfo = afwImage.VisitInfo(metadata) 

407 self.assertEqual(visitInfo.getDate(), data.date) 

408 

409 # TIME-MID must be in UTC and TIMESYS is ignored 

410 metadata = propertySetFromDict({ 

411 "TIME-MID": data.date.toString(DateTime.TAI) + "Z", 

412 "TIMESYS": "TAI", 

413 }) 

414 visitInfo = afwImage.VisitInfo(metadata) 

415 self.assertNotEqual(visitInfo.getDate(), data.date) 

416 

417 # if both DATE-AVG and TIME-MID provided then use DATE-AVG 

418 # use the wrong time system for TIME-MID so if it is used, an error 

419 # will result 

420 metadata = propertySetFromDict({ 

421 "DATE-AVG": data.date.toString(DateTime.TAI), 

422 "TIMESYS": "TAI", 

423 "TIME-MID": data.date.toString(DateTime.TAI) + "Z", 

424 }) 

425 visitInfo = afwImage.VisitInfo(metadata) 

426 self.assertEqual(visitInfo.getDate(), data.date) 

427 

428 metadata = propertySetFromDict({"MJD-AVG-UT1": data.ut1}) 

429 visitInfo = afwImage.VisitInfo(metadata) 

430 self.assertEqual(visitInfo.getUt1(), data.ut1) 

431 

432 metadata = propertySetFromDict({"AVG-ERA": data.era.asDegrees()}) 

433 visitInfo = afwImage.VisitInfo(metadata) 

434 self.assertEqual(visitInfo.getEra(), data.era) 

435 

436 for i, key in enumerate(("BORE-RA", "BORE-DEC")): 

437 metadata = propertySetFromDict( 

438 {key: data.boresightRaDec[i].asDegrees()}) 

439 visitInfo = afwImage.VisitInfo(metadata) 

440 self.assertEqual(visitInfo.getBoresightRaDec() 

441 [i], data.boresightRaDec[i]) 

442 

443 for i, key in enumerate(("BORE-AZ", "BORE-ALT")): 

444 metadata = propertySetFromDict( 

445 {key: data.boresightAzAlt[i].asDegrees()}) 

446 visitInfo = afwImage.VisitInfo(metadata) 

447 self.assertEqual(visitInfo.getBoresightAzAlt() 

448 [i], data.boresightAzAlt[i]) 

449 

450 metadata = propertySetFromDict({"BORE-AIRMASS": data.boresightAirmass}) 

451 visitInfo = afwImage.VisitInfo(metadata) 

452 self.assertEqual(visitInfo.getBoresightAirmass(), 

453 data.boresightAirmass) 

454 

455 metadata = propertySetFromDict( 

456 {"BORE-ROTANG": data.boresightRotAngle.asDegrees()}) 

457 visitInfo = afwImage.VisitInfo(metadata) 

458 self.assertEqual(visitInfo.getBoresightRotAngle(), 

459 data.boresightRotAngle) 

460 

461 metadata = propertySetFromDict( 

462 {"ROTTYPE": RotTypeEnumNameDict[data.rotType]}) 

463 visitInfo = afwImage.VisitInfo(metadata) 

464 self.assertEqual(visitInfo.getRotType(), data.rotType) 

465 

466 metadata = propertySetFromDict( 

467 {"OBS-LONG": data.observatory.getLongitude().asDegrees()}) 

468 visitInfo = afwImage.VisitInfo(metadata) 

469 self.assertEqual(visitInfo.getObservatory().getLongitude(), 

470 data.observatory.getLongitude()) 

471 

472 metadata = propertySetFromDict( 

473 {"OBS-LAT": data.observatory.getLatitude().asDegrees()}) 

474 visitInfo = afwImage.VisitInfo(metadata) 

475 self.assertEqual(visitInfo.getObservatory().getLatitude(), 

476 data.observatory.getLatitude()) 

477 

478 metadata = propertySetFromDict( 

479 {"OBS-ELEV": data.observatory.getElevation()}) 

480 visitInfo = afwImage.VisitInfo(metadata) 

481 self.assertEqual(visitInfo.getObservatory().getElevation(), 

482 data.observatory.getElevation()) 

483 

484 metadata = propertySetFromDict( 

485 {"AIRTEMP": data.weather.getAirTemperature()}) 

486 visitInfo = afwImage.VisitInfo(metadata) 

487 self.assertEqual(visitInfo.getWeather().getAirTemperature(), 

488 data.weather.getAirTemperature()) 

489 

490 metadata = propertySetFromDict( 

491 {"AIRPRESS": data.weather.getAirPressure()}) 

492 visitInfo = afwImage.VisitInfo(metadata) 

493 self.assertEqual(visitInfo.getWeather().getAirPressure(), 

494 data.weather.getAirPressure()) 

495 

496 metadata = propertySetFromDict( 

497 {"HUMIDITY": data.weather.getHumidity()}) 

498 visitInfo = afwImage.VisitInfo(metadata) 

499 self.assertEqual(visitInfo.getWeather().getHumidity(), 

500 data.weather.getHumidity()) 

501 

502 metadata = propertySetFromDict({"INSTRUMENT": data.instrumentLabel}) 

503 visitInfo = afwImage.VisitInfo(metadata) 

504 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel) 

505 

506 metadata = propertySetFromDict({"IDNUM": data.id}) 

507 visitInfo = afwImage.VisitInfo(metadata) 

508 self.assertEqual(visitInfo.getId(), data.id) 

509 

510 def testConstructorKeywordArguments(self): 

511 """Test VisitInfo with named arguments""" 

512 data = self.data1 

513 

514 visitInfo = afwImage.VisitInfo() 

515 self._testIsEmpty(visitInfo) 

516 

517 visitInfo = afwImage.VisitInfo(exposureId=data.exposureId) 

518 with self.assertWarns(FutureWarning): 

519 self.assertEqual(visitInfo.getExposureId(), data.exposureId) 

520 self.assertTrue(math.isnan(visitInfo.getExposureTime())) 

521 

522 visitInfo = afwImage.VisitInfo(exposureTime=data.exposureTime) 

523 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime) 

524 

525 visitInfo = afwImage.VisitInfo(darkTime=data.darkTime) 

526 self.assertEqual(visitInfo.getDarkTime(), data.darkTime) 

527 

528 visitInfo = afwImage.VisitInfo(date=data.date) 

529 self.assertEqual(visitInfo.getDate(), data.date) 

530 

531 visitInfo = afwImage.VisitInfo(ut1=data.ut1) 

532 self.assertEqual(visitInfo.getUt1(), data.ut1) 

533 

534 visitInfo = afwImage.VisitInfo(era=data.era) 

535 self.assertEqual(visitInfo.getEra(), data.era) 

536 

537 visitInfo = afwImage.VisitInfo(boresightRaDec=data.boresightRaDec) 

538 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec) 

539 

540 visitInfo = afwImage.VisitInfo(boresightAzAlt=data.boresightAzAlt) 

541 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt) 

542 

543 visitInfo = afwImage.VisitInfo(boresightAirmass=data.boresightAirmass) 

544 self.assertEqual(visitInfo.getBoresightAirmass(), 

545 data.boresightAirmass) 

546 

547 visitInfo = afwImage.VisitInfo( 

548 boresightRotAngle=data.boresightRotAngle) 

549 self.assertEqual(visitInfo.getBoresightRotAngle(), 

550 data.boresightRotAngle) 

551 

552 visitInfo = afwImage.VisitInfo(rotType=data.rotType) 

553 self.assertEqual(visitInfo.getRotType(), data.rotType) 

554 

555 visitInfo = afwImage.VisitInfo(observatory=data.observatory) 

556 self.assertEqual(visitInfo.getObservatory(), data.observatory) 

557 

558 visitInfo = afwImage.VisitInfo(weather=data.weather) 

559 self.assertEqual(visitInfo.getWeather(), data.weather) 

560 

561 visitInfo = afwImage.VisitInfo(instrumentLabel=data.instrumentLabel) 

562 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel) 

563 

564 visitInfo = afwImage.VisitInfo(id=data.id) 

565 self.assertEqual(visitInfo.getId(), data.id) 

566 

567 def testGoodRotTypes(self): 

568 """Test round trip of all valid rot types""" 

569 for rotType in RotTypeEnumNameDict: 

570 metadata = propertySetFromDict( 

571 {"ROTTYPE": RotTypeEnumNameDict[rotType]}) 

572 visitInfo = afwImage.VisitInfo(metadata) 

573 self.assertEqual(visitInfo.getRotType(), rotType) 

574 

575 def testBadRotTypes(self): 

576 """Test that invalid rot type names cannot be used to construct a VisitInfo""" 

577 for badRotTypeName in ( 

578 "unknown", # must be all uppercase 

579 "sky", # must be all uppercase 

580 "Sky", # must be all uppercase 

581 "SKY1", # extra chars 

582 "HORIZONTAL", # extra chars 

583 ): 

584 metadata = propertySetFromDict({"ROTTYPE": badRotTypeName}) 

585 with self.assertRaises(lsst.pex.exceptions.RuntimeError): 

586 afwImage.VisitInfo(metadata) 

587 

588 def test_str(self): 

589 """Check that we get something reasonable for str()""" 

590 visitInfo = makeVisitInfo(self.data1) 

591 string = str(visitInfo) 

592 self.assertIn("exposureId=10313423", string) 

593 self.assertIn("exposureTime=10.01", string) 

594 self.assertIn("darkTime=11.02", string) 

595 self.assertIn("rotType=1", string) 

596 

597 # Check that it at least doesn't throw 

598 str(afwImage.VisitInfo()) 

599 

600 def testParallacticAngle(self): 

601 """Check that we get the same precomputed values for parallactic angle.""" 

602 parallacticAngle = [141.39684140703142*degrees, 76.99982166973487*degrees] 

603 for item, parAngle in zip((self.data1, self.data2), parallacticAngle): 

604 visitInfo = afwImage.VisitInfo(era=item.era, 

605 boresightRaDec=item.boresightRaDec, 

606 observatory=item.observatory, 

607 ) 

608 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), parAngle) 

609 

610 def testParallacticAngleNorthMeridian(self): 

611 """An observation on the Meridian that is North of zenith has a parallactic angle of pi radians.""" 

612 meridianBoresightRA = self.data1.era + self.data1.observatory.getLongitude() 

613 northBoresightDec = self.data1.observatory.getLatitude() + 10.*degrees 

614 visitInfo = afwImage.VisitInfo(era=self.data1.era, 

615 boresightRaDec=SpherePoint(meridianBoresightRA, 

616 northBoresightDec), 

617 observatory=self.data1.observatory, 

618 ) 

619 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), Angle(np.pi)) 

620 

621 def testParallacticAngleSouthMeridian(self): 

622 """An observation on the Meridian that is South of zenith has a parallactic angle of zero.""" 

623 meridianBoresightRA = self.data1.era + self.data1.observatory.getLongitude() 

624 southBoresightDec = self.data1.observatory.getLatitude() - 10.*degrees 

625 visitInfo = afwImage.VisitInfo(era=self.data1.era, 

626 boresightRaDec=SpherePoint(meridianBoresightRA, 

627 southBoresightDec), 

628 observatory=self.data1.observatory, 

629 ) 

630 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), Angle(0.)) 

631 

632 

633def setup_module(module): 

634 lsst.utils.tests.init() 

635 

636 

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

638 pass 

639 

640 

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

642 lsst.utils.tests.init() 

643 unittest.main()