Coverage for tests/test_visitInfo.py: 11%
355 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-30 02:37 -0700
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-30 02:37 -0700
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
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
35RotTypeEnumNameDict = {
36 afwImage.RotType.UNKNOWN: "UNKNOWN",
37 afwImage.RotType.SKY: "SKY",
38 afwImage.RotType.HORIZON: "HORIZON",
39 afwImage.RotType.MOUNT: "MOUNT",
40}
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
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 data.focusZ,
69 )
72class VisitInfoTestCase(lsst.utils.tests.TestCase):
73 """Test lsst.afw.image.VisitInfo, a simple struct-like class"""
75 def setUp(self):
76 self.testDir = os.path.dirname(__file__)
78 def computeLstHA(data):
79 """Return LST, Hour Angle, computed from VisitInfoData."""
80 localEra = data.era + data.observatory.getLongitude()
81 hourAngle = localEra - data.boresightRaDec[0]
82 return localEra, hourAngle
84 fields = ['exposureId',
85 'exposureTime',
86 'darkTime',
87 'date',
88 'ut1',
89 'era',
90 'boresightRaDec',
91 'boresightAzAlt',
92 'boresightAirmass',
93 'boresightRotAngle',
94 'rotType',
95 'observatory',
96 'weather',
97 'instrumentLabel',
98 'id',
99 'focusZ',
100 ]
101 VisitInfoData = collections.namedtuple("VisitInfoData", fields)
102 data1 = VisitInfoData(exposureId=10313423,
103 exposureTime=10.01,
104 darkTime=11.02,
105 date=DateTime(
106 65321.1, DateTime.MJD, DateTime.TAI),
107 ut1=12345.1,
108 era=45.1*degrees,
109 boresightRaDec=SpherePoint(
110 23.1*degrees, 73.2*degrees),
111 boresightAzAlt=SpherePoint(
112 134.5*degrees, 33.3*degrees),
113 boresightAirmass=1.73,
114 boresightRotAngle=73.2*degrees,
115 rotType=afwImage.RotType.SKY,
116 observatory=Observatory(
117 11.1*degrees, 22.2*degrees, 0.333),
118 weather=Weather(1.1, 2.2, 34.5),
119 instrumentLabel="TestCameraOne",
120 id=987654,
121 focusZ=1.5,
122 )
123 self.data1 = data1
124 self.localEra1, self.hourAngle1 = computeLstHA(data1)
125 data2 = VisitInfoData(exposureId=1,
126 exposureTime=15.5,
127 darkTime=17.8,
128 date=DateTime(
129 55321.2, DateTime.MJD, DateTime.TAI),
130 ut1=312345.1,
131 era=25.1*degrees,
132 boresightRaDec=SpherePoint(
133 2.1*degrees, 33.2*degrees),
134 boresightAzAlt=SpherePoint(13.5*degrees, 83.3*degrees),
135 boresightAirmass=2.05,
136 boresightRotAngle=-53.2*degrees,
137 rotType=afwImage.RotType.HORIZON,
138 observatory=Observatory(
139 22.2*degrees, 33.3*degrees, 0.444),
140 weather=Weather(2.2, 3.3, 44.4),
141 instrumentLabel="TestCameraTwo",
142 id=123456,
143 focusZ=-0.7,
144 )
145 self.data2 = data2
146 self.localEra2, self.hourAngle2 = computeLstHA(data2)
148 def _testValueConstructor(self, data, localEra, hourAngle):
149 visitInfo = makeVisitInfo(data)
150 with self.assertWarns(FutureWarning):
151 self.assertEqual(visitInfo.getExposureId(), data.exposureId)
152 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime)
153 self.assertEqual(visitInfo.getDarkTime(), data.darkTime)
154 self.assertEqual(visitInfo.getDate(), data.date)
155 self.assertEqual(visitInfo.getUt1(), data.ut1)
156 self.assertEqual(visitInfo.getEra(), data.era)
157 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec)
158 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt)
159 self.assertEqual(visitInfo.getBoresightAirmass(),
160 data.boresightAirmass)
161 self.assertEqual(visitInfo.getBoresightRotAngle(),
162 data.boresightRotAngle)
163 self.assertEqual(visitInfo.getRotType(), data.rotType)
164 self.assertEqual(visitInfo.getObservatory(), data.observatory)
165 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel)
166 self.assertEqual(visitInfo.getWeather(), data.weather)
167 self.assertEqual(visitInfo.getLocalEra(), localEra)
168 self.assertEqual(visitInfo.getBoresightHourAngle(), hourAngle)
169 self.assertEqual(visitInfo.getId(), data.id)
170 self.assertEqual(visitInfo.getFocusZ(), data.focusZ)
172 def _testProperties(self, data, localEra, hourAngle):
173 """Test property attribute accessors."""
174 visitInfo = makeVisitInfo(data)
175 self.assertEqual(visitInfo.exposureTime, data.exposureTime)
176 self.assertEqual(visitInfo.darkTime, data.darkTime)
177 self.assertEqual(visitInfo.date, data.date)
178 self.assertEqual(visitInfo.ut1, data.ut1)
179 self.assertEqual(visitInfo.era, data.era)
180 self.assertEqual(visitInfo.boresightRaDec, data.boresightRaDec)
181 self.assertEqual(visitInfo.boresightAzAlt, data.boresightAzAlt)
182 self.assertEqual(visitInfo.boresightAirmass, data.boresightAirmass)
183 self.assertEqual(visitInfo.boresightRotAngle, data.boresightRotAngle)
184 self.assertEqual(visitInfo.rotType, data.rotType)
185 self.assertEqual(visitInfo.observatory, data.observatory)
186 self.assertEqual(visitInfo.instrumentLabel, data.instrumentLabel)
187 self.assertEqual(visitInfo.weather, data.weather)
188 self.assertEqual(visitInfo.localEra, localEra)
189 self.assertEqual(visitInfo.boresightHourAngle, hourAngle)
190 self.assertEqual(visitInfo.id, data.id)
191 self.assertEqual(visitInfo.focusZ, data.focusZ)
193 def testValueConstructor_data1(self):
194 self._testValueConstructor(self.data1, self.localEra1, self.hourAngle1)
195 self._testProperties(self.data1, self.localEra1, self.hourAngle1)
197 def testValueConstructor_data2(self):
198 self._testValueConstructor(self.data2, self.localEra2, self.hourAngle2)
199 self._testProperties(self.data2, self.localEra2, self.hourAngle2)
201 def testTablePersistence(self):
202 """Test that VisitInfo can be round-tripped with current code.
203 """
204 for item in (self.data1, self.data2):
205 tablePath = os.path.join(
206 self.testDir, "testVisitInfo_testTablePersistence.fits")
207 v1 = afwImage.VisitInfo(*item)
208 v1.writeFits(tablePath)
209 v2 = afwImage.VisitInfo.readFits(tablePath)
210 self.assertEqual(v1, v2)
211 os.unlink(tablePath)
213 def _testFitsRead(self, data, filePath, version):
214 """Test that old VersionInfo files are read correctly.
216 Parameters
217 ----------
218 data : `VisitInfoData`
219 The values expected to be stored in the file, or a
220 superset thereof.
221 filePath : `str`
222 The file to test.
223 version : `int`
224 The VersionInfo persistence format used in ``filePath``.
225 """
226 visitInfo = afwImage.VisitInfo.readFits(filePath)
228 if version >= 0:
229 with self.assertWarns(FutureWarning):
230 self.assertEqual(visitInfo.getExposureId(), data.exposureId)
231 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime)
232 self.assertEqual(visitInfo.getDarkTime(), data.darkTime)
233 self.assertEqual(visitInfo.getDate(), data.date)
234 self.assertEqual(visitInfo.getUt1(), data.ut1)
235 self.assertEqual(visitInfo.getEra(), data.era)
236 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec)
237 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt)
238 self.assertEqual(visitInfo.getBoresightAirmass(),
239 data.boresightAirmass)
240 self.assertEqual(visitInfo.getBoresightRotAngle(),
241 data.boresightRotAngle)
242 self.assertEqual(visitInfo.getRotType(), data.rotType)
243 self.assertEqual(visitInfo.getObservatory(), data.observatory)
244 self.assertEqual(visitInfo.getWeather(), data.weather)
245 if version >= 1:
246 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel)
247 else:
248 self.assertEqual(visitInfo.getInstrumentLabel(), "")
249 if version >= 2:
250 self.assertEqual(visitInfo.getId(), data.id)
251 else:
252 self.assertEqual(visitInfo.getId(), 0)
253 if version >= 3:
254 self.assertEqual(visitInfo.getFocusZ(), data.focusZ)
255 else:
256 self.assertTrue(math.isnan(visitInfo.getFocusZ()))
258 def testPersistenceVersions(self):
259 """Test that older versions are handled appropriately.
260 """
261 dataDir = os.path.join(os.path.dirname(__file__), "data")
263 # All files created by makeVisitInfo(self.data1).writeFits()
264 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-noversion.fits"), 0)
265 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-version-1.fits"), 1)
266 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-version-2.fits"), 2)
267 self._testFitsRead(self.data1, os.path.join(dataDir, "visitInfo-version-3.fits"), 3)
269 def testSetVisitInfoMetadata(self):
270 for item in (self.data1, self.data2):
271 visitInfo = makeVisitInfo(item)
272 metadata = PropertyList()
273 afwImage.setVisitInfoMetadata(metadata, visitInfo)
274 self.assertEqual(metadata.nameCount(), 23)
275 self.assertEqual(metadata.getScalar("EXPID"), item.exposureId)
276 self.assertEqual(metadata.getScalar("EXPTIME"), item.exposureTime)
277 self.assertEqual(metadata.getScalar("DARKTIME"), item.darkTime)
278 self.assertEqual(metadata.getScalar("DATE-AVG"),
279 item.date.toString(DateTime.TAI))
280 self.assertEqual(metadata.getScalar("TIMESYS"), "TAI")
281 self.assertEqual(metadata.getScalar("MJD-AVG-UT1"), item.ut1)
282 self.assertEqual(metadata.getScalar("AVG-ERA"), item.era.asDegrees())
283 self.assertEqual(metadata.getScalar("BORE-RA"),
284 item.boresightRaDec[0].asDegrees())
285 self.assertEqual(metadata.getScalar("BORE-DEC"),
286 item.boresightRaDec[1].asDegrees())
287 self.assertEqual(metadata.getScalar("BORE-AZ"),
288 item.boresightAzAlt[0].asDegrees())
289 self.assertEqual(metadata.getScalar("BORE-ALT"),
290 item.boresightAzAlt[1].asDegrees())
291 self.assertEqual(metadata.getScalar("BORE-AIRMASS"),
292 item.boresightAirmass)
293 self.assertEqual(metadata.getScalar("BORE-ROTANG"),
294 item.boresightRotAngle.asDegrees())
295 self.assertEqual(metadata.getScalar("ROTTYPE"),
296 RotTypeEnumNameDict[item.rotType])
297 self.assertEqual(metadata.getScalar("OBS-LONG"),
298 item.observatory.getLongitude().asDegrees())
299 self.assertEqual(metadata.getScalar("OBS-LAT"),
300 item.observatory.getLatitude().asDegrees())
301 self.assertEqual(metadata.getScalar("OBS-ELEV"),
302 item.observatory.getElevation())
303 self.assertEqual(metadata.getScalar("AIRTEMP"),
304 item.weather.getAirTemperature())
305 self.assertEqual(metadata.getScalar("AIRPRESS"),
306 item.weather.getAirPressure())
307 self.assertEqual(metadata.getScalar("HUMIDITY"),
308 item.weather.getHumidity())
309 self.assertEqual(metadata.getScalar("INSTRUMENT"),
310 item.instrumentLabel)
311 self.assertEqual(metadata.getScalar("IDNUM"),
312 item.id)
313 self.assertEqual(metadata.getScalar("FOCUSZ"),
314 item.focusZ)
316 def testSetVisitInfoMetadataMissingValues(self):
317 """If a value is unknown then it should not be written to the metadata"""
318 visitInfo = afwImage.VisitInfo() # only rot type is known
319 metadata = PropertyList()
320 afwImage.setVisitInfoMetadata(metadata, visitInfo)
321 self.assertEqual(metadata.getScalar("ROTTYPE"),
322 RotTypeEnumNameDict[afwImage.RotType.UNKNOWN])
323 self.assertEqual(metadata.nameCount(), 1)
325 def testStripVisitInfoKeywords(self):
326 for argList in (self.data1, self.data2):
327 visitInfo = afwImage.VisitInfo(*argList)
328 metadata = PropertyList()
329 afwImage.setVisitInfoMetadata(metadata, visitInfo)
330 # add an extra keyword that will not be stripped
331 metadata.set("EXTRA", 5)
332 self.assertEqual(metadata.nameCount(), 24)
333 afwImage.stripVisitInfoKeywords(metadata)
334 self.assertEqual(metadata.nameCount(), 1)
336 def _testIsEmpty(self, visitInfo):
337 """Test that visitInfo is all NaN, 0, or empty string, as appropriate.
338 """
339 with self.assertWarns(FutureWarning):
340 self.assertEqual(visitInfo.getExposureId(), 0)
341 self.assertTrue(math.isnan(visitInfo.getExposureTime()))
342 self.assertTrue(math.isnan(visitInfo.getDarkTime()))
343 self.assertEqual(visitInfo.getDate(), DateTime())
344 self.assertTrue(math.isnan(visitInfo.getUt1()))
345 self.assertTrue(math.isnan(visitInfo.getEra().asDegrees()))
346 for i in range(2):
347 self.assertTrue(math.isnan(
348 visitInfo.getBoresightRaDec()[i].asDegrees()))
349 self.assertTrue(math.isnan(
350 visitInfo.getBoresightAzAlt()[i].asDegrees()))
351 self.assertTrue(math.isnan(visitInfo.getBoresightAirmass()))
352 self.assertTrue(math.isnan(
353 visitInfo.getBoresightRotAngle().asDegrees()))
354 self.assertEqual(visitInfo.getRotType(), afwImage.RotType.UNKNOWN)
355 self.assertTrue(math.isnan(
356 visitInfo.getObservatory().getLongitude().asDegrees()))
357 self.assertTrue(math.isnan(
358 visitInfo.getObservatory().getLatitude().asDegrees()))
359 self.assertTrue(math.isnan(visitInfo.getObservatory().getElevation()))
360 self.assertTrue(math.isnan(visitInfo.getWeather().getAirTemperature()))
361 self.assertTrue(math.isnan(visitInfo.getWeather().getAirPressure()))
362 self.assertTrue(math.isnan(visitInfo.getWeather().getHumidity()))
363 self.assertTrue(math.isnan(visitInfo.getBoresightHourAngle()))
364 self.assertEqual(visitInfo.getInstrumentLabel(), "")
365 self.assertEqual(visitInfo.getId(), 0)
366 self.assertTrue(math.isnan(visitInfo.getFocusZ()))
368 def testEquals(self):
369 """Test that identical VisitInfo objects compare equal, even if some fields are NaN.
370 """
371 # objects with "equal state" should be equal
372 self.assertEqual(makeVisitInfo(self.data1), makeVisitInfo(self.data1))
373 self.assertEqual(makeVisitInfo(self.data2), makeVisitInfo(self.data2))
374 self.assertNotEqual(makeVisitInfo(self.data1), makeVisitInfo(self.data2))
375 self.assertEqual(afwImage.VisitInfo(), afwImage.VisitInfo())
377 # equality must be reflexive
378 info = makeVisitInfo(self.data1)
379 self.assertEqual(info, info)
380 info = makeVisitInfo(self.data2)
381 self.assertEqual(info, info)
382 info = afwImage.VisitInfo()
383 self.assertEqual(info, info)
385 # commutativity and transitivity difficult to test with this setup
387 def testMetadataConstructor(self):
388 """Test the metadata constructor
390 This constructor allows missing values
391 """
392 data = self.data1
394 metadata = propertySetFromDict({})
395 visitInfo = afwImage.VisitInfo(metadata)
396 self._testIsEmpty(visitInfo)
398 metadata = propertySetFromDict({"EXPID": data.exposureId})
399 visitInfo = afwImage.VisitInfo(metadata)
400 with self.assertWarns(FutureWarning):
401 self.assertEqual(visitInfo.getExposureId(), data.exposureId)
402 self.assertTrue(math.isnan(visitInfo.getExposureTime()))
404 metadata = propertySetFromDict({"EXPTIME": data.exposureTime})
405 visitInfo = afwImage.VisitInfo(metadata)
406 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime)
408 metadata = propertySetFromDict({"DARKTIME": data.darkTime})
409 visitInfo = afwImage.VisitInfo(metadata)
410 self.assertEqual(visitInfo.getDarkTime(), data.darkTime)
412 metadata = propertySetFromDict(
413 {"DATE-AVG": data.date.toString(DateTime.TAI), "TIMESYS": "TAI"})
414 visitInfo = afwImage.VisitInfo(metadata)
415 self.assertEqual(visitInfo.getDate(), data.date)
417 # TIME-MID in UTC is an acceptable alternative to DATE-AVG
418 metadata = propertySetFromDict(
419 {"TIME-MID": data.date.toString(DateTime.UTC)})
420 visitInfo = afwImage.VisitInfo(metadata)
421 self.assertEqual(visitInfo.getDate(), data.date)
423 # TIME-MID must be in UTC and TIMESYS is ignored
424 metadata = propertySetFromDict({
425 "TIME-MID": data.date.toString(DateTime.TAI) + "Z",
426 "TIMESYS": "TAI",
427 })
428 visitInfo = afwImage.VisitInfo(metadata)
429 self.assertNotEqual(visitInfo.getDate(), data.date)
431 # if both DATE-AVG and TIME-MID provided then use DATE-AVG
432 # use the wrong time system for TIME-MID so if it is used, an error
433 # will result
434 metadata = propertySetFromDict({
435 "DATE-AVG": data.date.toString(DateTime.TAI),
436 "TIMESYS": "TAI",
437 "TIME-MID": data.date.toString(DateTime.TAI) + "Z",
438 })
439 visitInfo = afwImage.VisitInfo(metadata)
440 self.assertEqual(visitInfo.getDate(), data.date)
442 metadata = propertySetFromDict({"MJD-AVG-UT1": data.ut1})
443 visitInfo = afwImage.VisitInfo(metadata)
444 self.assertEqual(visitInfo.getUt1(), data.ut1)
446 metadata = propertySetFromDict({"AVG-ERA": data.era.asDegrees()})
447 visitInfo = afwImage.VisitInfo(metadata)
448 self.assertEqual(visitInfo.getEra(), data.era)
450 for i, key in enumerate(("BORE-RA", "BORE-DEC")):
451 metadata = propertySetFromDict(
452 {key: data.boresightRaDec[i].asDegrees()})
453 visitInfo = afwImage.VisitInfo(metadata)
454 self.assertEqual(visitInfo.getBoresightRaDec()
455 [i], data.boresightRaDec[i])
457 for i, key in enumerate(("BORE-AZ", "BORE-ALT")):
458 metadata = propertySetFromDict(
459 {key: data.boresightAzAlt[i].asDegrees()})
460 visitInfo = afwImage.VisitInfo(metadata)
461 self.assertEqual(visitInfo.getBoresightAzAlt()
462 [i], data.boresightAzAlt[i])
464 metadata = propertySetFromDict({"BORE-AIRMASS": data.boresightAirmass})
465 visitInfo = afwImage.VisitInfo(metadata)
466 self.assertEqual(visitInfo.getBoresightAirmass(),
467 data.boresightAirmass)
469 metadata = propertySetFromDict(
470 {"BORE-ROTANG": data.boresightRotAngle.asDegrees()})
471 visitInfo = afwImage.VisitInfo(metadata)
472 self.assertEqual(visitInfo.getBoresightRotAngle(),
473 data.boresightRotAngle)
475 metadata = propertySetFromDict(
476 {"ROTTYPE": RotTypeEnumNameDict[data.rotType]})
477 visitInfo = afwImage.VisitInfo(metadata)
478 self.assertEqual(visitInfo.getRotType(), data.rotType)
480 metadata = propertySetFromDict(
481 {"OBS-LONG": data.observatory.getLongitude().asDegrees()})
482 visitInfo = afwImage.VisitInfo(metadata)
483 self.assertEqual(visitInfo.getObservatory().getLongitude(),
484 data.observatory.getLongitude())
486 metadata = propertySetFromDict(
487 {"OBS-LAT": data.observatory.getLatitude().asDegrees()})
488 visitInfo = afwImage.VisitInfo(metadata)
489 self.assertEqual(visitInfo.getObservatory().getLatitude(),
490 data.observatory.getLatitude())
492 metadata = propertySetFromDict(
493 {"OBS-ELEV": data.observatory.getElevation()})
494 visitInfo = afwImage.VisitInfo(metadata)
495 self.assertEqual(visitInfo.getObservatory().getElevation(),
496 data.observatory.getElevation())
498 metadata = propertySetFromDict(
499 {"AIRTEMP": data.weather.getAirTemperature()})
500 visitInfo = afwImage.VisitInfo(metadata)
501 self.assertEqual(visitInfo.getWeather().getAirTemperature(),
502 data.weather.getAirTemperature())
504 metadata = propertySetFromDict(
505 {"AIRPRESS": data.weather.getAirPressure()})
506 visitInfo = afwImage.VisitInfo(metadata)
507 self.assertEqual(visitInfo.getWeather().getAirPressure(),
508 data.weather.getAirPressure())
510 metadata = propertySetFromDict(
511 {"HUMIDITY": data.weather.getHumidity()})
512 visitInfo = afwImage.VisitInfo(metadata)
513 self.assertEqual(visitInfo.getWeather().getHumidity(),
514 data.weather.getHumidity())
516 metadata = propertySetFromDict({"INSTRUMENT": data.instrumentLabel})
517 visitInfo = afwImage.VisitInfo(metadata)
518 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel)
520 metadata = propertySetFromDict({"IDNUM": data.id})
521 visitInfo = afwImage.VisitInfo(metadata)
522 self.assertEqual(visitInfo.getId(), data.id)
524 metadata = propertySetFromDict({"FOCUSZ": data.focusZ})
525 visitInfo = afwImage.VisitInfo(metadata)
526 self.assertEqual(visitInfo.getFocusZ(), data.focusZ)
528 def testConstructorKeywordArguments(self):
529 """Test VisitInfo with named arguments"""
530 data = self.data1
532 visitInfo = afwImage.VisitInfo()
533 self._testIsEmpty(visitInfo)
535 visitInfo = afwImage.VisitInfo(exposureId=data.exposureId)
536 with self.assertWarns(FutureWarning):
537 self.assertEqual(visitInfo.getExposureId(), data.exposureId)
538 self.assertTrue(math.isnan(visitInfo.getExposureTime()))
540 visitInfo = afwImage.VisitInfo(exposureTime=data.exposureTime)
541 self.assertEqual(visitInfo.getExposureTime(), data.exposureTime)
543 visitInfo = afwImage.VisitInfo(darkTime=data.darkTime)
544 self.assertEqual(visitInfo.getDarkTime(), data.darkTime)
546 visitInfo = afwImage.VisitInfo(date=data.date)
547 self.assertEqual(visitInfo.getDate(), data.date)
549 visitInfo = afwImage.VisitInfo(ut1=data.ut1)
550 self.assertEqual(visitInfo.getUt1(), data.ut1)
552 visitInfo = afwImage.VisitInfo(era=data.era)
553 self.assertEqual(visitInfo.getEra(), data.era)
555 visitInfo = afwImage.VisitInfo(boresightRaDec=data.boresightRaDec)
556 self.assertEqual(visitInfo.getBoresightRaDec(), data.boresightRaDec)
558 visitInfo = afwImage.VisitInfo(boresightAzAlt=data.boresightAzAlt)
559 self.assertEqual(visitInfo.getBoresightAzAlt(), data.boresightAzAlt)
561 visitInfo = afwImage.VisitInfo(boresightAirmass=data.boresightAirmass)
562 self.assertEqual(visitInfo.getBoresightAirmass(),
563 data.boresightAirmass)
565 visitInfo = afwImage.VisitInfo(
566 boresightRotAngle=data.boresightRotAngle)
567 self.assertEqual(visitInfo.getBoresightRotAngle(),
568 data.boresightRotAngle)
570 visitInfo = afwImage.VisitInfo(rotType=data.rotType)
571 self.assertEqual(visitInfo.getRotType(), data.rotType)
573 visitInfo = afwImage.VisitInfo(observatory=data.observatory)
574 self.assertEqual(visitInfo.getObservatory(), data.observatory)
576 visitInfo = afwImage.VisitInfo(weather=data.weather)
577 self.assertEqual(visitInfo.getWeather(), data.weather)
579 visitInfo = afwImage.VisitInfo(instrumentLabel=data.instrumentLabel)
580 self.assertEqual(visitInfo.getInstrumentLabel(), data.instrumentLabel)
582 visitInfo = afwImage.VisitInfo(id=data.id)
583 self.assertEqual(visitInfo.getId(), data.id)
585 visitInfo = afwImage.VisitInfo(focusZ=data.focusZ)
586 self.assertEqual(visitInfo.getFocusZ(), data.focusZ)
588 def testGoodRotTypes(self):
589 """Test round trip of all valid rot types"""
590 for rotType in RotTypeEnumNameDict:
591 metadata = propertySetFromDict(
592 {"ROTTYPE": RotTypeEnumNameDict[rotType]})
593 visitInfo = afwImage.VisitInfo(metadata)
594 self.assertEqual(visitInfo.getRotType(), rotType)
596 def testBadRotTypes(self):
597 """Test that invalid rot type names cannot be used to construct a VisitInfo"""
598 for badRotTypeName in (
599 "unknown", # must be all uppercase
600 "sky", # must be all uppercase
601 "Sky", # must be all uppercase
602 "SKY1", # extra chars
603 "HORIZONTAL", # extra chars
604 ):
605 metadata = propertySetFromDict({"ROTTYPE": badRotTypeName})
606 with self.assertRaises(lsst.pex.exceptions.RuntimeError):
607 afwImage.VisitInfo(metadata)
609 def test_str(self):
610 """Check that we get something reasonable for str()"""
611 visitInfo = makeVisitInfo(self.data1)
612 string = str(visitInfo)
613 self.assertIn("exposureId=10313423", string)
614 self.assertIn("exposureTime=10.01", string)
615 self.assertIn("darkTime=11.02", string)
616 self.assertIn("rotType=1", string)
618 # Check that it at least doesn't throw
619 str(afwImage.VisitInfo())
621 def testParallacticAngle(self):
622 """Check that we get the same precomputed values for parallactic angle."""
623 parallacticAngle = [141.39684140703142*degrees, 76.99982166973487*degrees]
624 for item, parAngle in zip((self.data1, self.data2), parallacticAngle):
625 visitInfo = afwImage.VisitInfo(era=item.era,
626 boresightRaDec=item.boresightRaDec,
627 observatory=item.observatory,
628 )
629 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), parAngle)
631 def testParallacticAngleNorthMeridian(self):
632 """An observation on the Meridian that is North of zenith has a parallactic angle of pi radians."""
633 meridianBoresightRA = self.data1.era + self.data1.observatory.getLongitude()
634 northBoresightDec = self.data1.observatory.getLatitude() + 10.*degrees
635 visitInfo = afwImage.VisitInfo(era=self.data1.era,
636 boresightRaDec=SpherePoint(meridianBoresightRA,
637 northBoresightDec),
638 observatory=self.data1.observatory,
639 )
640 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), Angle(np.pi))
642 def testParallacticAngleSouthMeridian(self):
643 """An observation on the Meridian that is South of zenith has a parallactic angle of zero."""
644 meridianBoresightRA = self.data1.era + self.data1.observatory.getLongitude()
645 southBoresightDec = self.data1.observatory.getLatitude() - 10.*degrees
646 visitInfo = afwImage.VisitInfo(era=self.data1.era,
647 boresightRaDec=SpherePoint(meridianBoresightRA,
648 southBoresightDec),
649 observatory=self.data1.observatory,
650 )
651 self.assertAnglesAlmostEqual(visitInfo.getBoresightParAngle(), Angle(0.))
654def setup_module(module):
655 lsst.utils.tests.init()
658class MemoryTester(lsst.utils.tests.MemoryTestCase):
659 pass
662if __name__ == "__main__": 662 ↛ 663line 662 didn't jump to line 663, because the condition on line 662 was never true
663 lsst.utils.tests.init()
664 unittest.main()