24 import astropy.utils.exceptions
25 from astropy.utils
import iers
30 ErfaWarning = erfa.ErfaWarning
32 import astropy._erfa
as erfa
35 from astro_metadata_translator
import ObservationInfo
37 from lsst.log
import Log
38 from lsst.daf.base
import DateTime
39 from lsst.geom
import degrees, radians
40 from lsst.afw.image
import VisitInfo, RotType
41 from lsst.afw.coord
import Observatory, Weather
42 from lsst.geom
import SpherePoint
44 __all__ = [
"MakeRawVisitInfoViaObsInfo"]
48 """Base class functor to make a VisitInfo from the FITS header of a
49 raw image using `~astro_metadata_translator.ObservationInfo` translators.
51 Subclasses can be used if a specific
52 `~astro_metadata_translator.MetadataTranslator` translator should be used.
54 The design philosophy is to make a best effort and log warnings of
55 problems, rather than raising exceptions, in order to extract as much
56 VisitInfo information as possible from a messy FITS header without the
57 user needing to add a lot of error handling.
61 log : `lsst.log.Log` or None
62 Logger to use for messages.
63 (None to use ``Log.getLogger("MakeRawVisitInfoViaObsInfo")``).
64 doStripHeader : `bool`, optional
65 Strip header keywords from the metadata as they are used?
68 metadataTranslator =
None
69 """Header translator to use to construct VisitInfo, defaulting to
70 automatic determination."""
72 def __init__(self, log=None, doStripHeader=False):
74 log = Log.getLogger(
"MakeRawVisitInfoViaObsInfo")
79 """Construct a VisitInfo and strip associated data from the metadata.
83 md : `lsst.daf.base.PropertyList` or `lsst.daf.base.PropertySet`
84 Metadata to pull from.
85 May be modified if ``stripHeader`` is ``True``.
86 exposureId : `int`, optional
87 Ignored. Here for compatibility with `MakeRawVisitInfo`.
91 visitInfo : `lsst.afw.image.VisitInfo`
92 `~lsst.afw.image.VisitInfo` derived from the header using
93 a `~astro_metadata_translator.MetadataTranslator`.
96 obsInfo = ObservationInfo(md, translator_class=self.
metadataTranslatormetadataTranslator)
100 for c
in obsInfo.cards_used:
107 """Construct a `~lsst.afw.image.VisitInfo` from an
108 `~astro_metadata_translator.ObservationInfo`
112 obsInfo : `astro_metadata_translator.ObservationInfo`
113 Information gathered from the observation metadata.
114 log : `logging.Logger` or `lsst.log.Log`, optional
115 Logger to use for logging informational messages.
116 If `None` logging will be disabled.
120 visitInfo : `lsst.afw.image.VisitInfo`
121 `~lsst.afw.image.VisitInfo` derived from the supplied
122 `~astro_metadata_translator.ObservationInfo`.
127 if obsInfo.exposure_time
is not None:
128 argDict[
"exposureTime"] = obsInfo.exposure_time.to_value(
"s")
129 if obsInfo.dark_time
is not None:
130 argDict[
"darkTime"] = obsInfo.dark_time.to_value(
"s")
131 argDict[
"exposureId"] = obsInfo.detector_exposure_id
132 argDict[
"instrumentLabel"] = obsInfo.instrument
135 if obsInfo.datetime_begin
is not None and obsInfo.datetime_end
is not None:
136 tdelta = obsInfo.datetime_end - obsInfo.datetime_begin
137 middle = obsInfo.datetime_begin + 0.5*tdelta
144 argDict[
"date"] = DateTime(middle.tai.isot, DateTime.TAI)
155 with warnings.catch_warnings():
158 warnings.simplefilter(
"ignore", category=astropy.utils.exceptions.AstropyWarning)
159 if ErfaWarning
is not None:
160 warnings.simplefilter(
"ignore", category=ErfaWarning)
162 except iers.IERSRangeError:
165 era = erfa.era00(ut1time.jd1, ut1time.jd2)
166 argDict[
"era"] = era * radians
168 argDict[
"date"] = DateTime()
171 if obsInfo.tracking_radec
is not None:
172 icrs = obsInfo.tracking_radec.transform_to(
"icrs")
173 argDict[
"boresightRaDec"] = SpherePoint(icrs.ra.degree,
174 icrs.dec.degree, units=degrees)
176 altaz = obsInfo.altaz_begin
177 if altaz
is not None:
178 argDict[
"boresightAzAlt"] = SpherePoint(altaz.az.degree,
179 altaz.alt.degree, units=degrees)
181 argDict[
"boresightAirmass"] = obsInfo.boresight_airmass
183 if obsInfo.boresight_rotation_angle
is not None:
184 argDict[
"boresightRotAngle"] = obsInfo.boresight_rotation_angle.degree*degrees
186 if obsInfo.boresight_rotation_coord
is not None:
187 rotType = RotType.UNKNOWN
188 if obsInfo.boresight_rotation_coord ==
"sky":
189 rotType = RotType.SKY
190 argDict[
"rotType"] = rotType
193 temperature = float(
"nan")
194 if obsInfo.temperature
is not None:
195 temperature = obsInfo.temperature.to_value(
"deg_C", astropy.units.temperature())
196 pressure = float(
"nan")
197 if obsInfo.pressure
is not None:
198 pressure = obsInfo.pressure.to_value(
"Pa")
199 relative_humidity = float(
"nan")
200 if obsInfo.relative_humidity
is not None:
201 relative_humidity = obsInfo.relative_humidity
202 argDict[
"weather"] = Weather(temperature, pressure, relative_humidity)
204 if obsInfo.location
is not None:
205 geolocation = obsInfo.location.to_geodetic()
206 argDict[
"observatory"] = Observatory(geolocation.lon.degree*degrees,
207 geolocation.lat.degree*degrees,
208 geolocation.height.to_value(
"m"))
210 for key
in list(argDict.keys()):
211 if argDict[key]
is None:
213 log.warn(
"argDict[%s] is None; stripping", key)
216 return VisitInfo(**argDict)
def observationInfo2visitInfo(obsInfo, log=None)
def __call__(self, md, exposureId=None)
def __init__(self, log=None, doStripHeader=False)