22 __all__ = (
"FitsRawFormatterBase",)
24 from abc
import ABCMeta, abstractmethod
26 from astro_metadata_translator
import ObservationInfo
31 from lsst.daf.butler
import FileDescriptor
34 from .formatters.fitsExposure
import FitsExposureFormatter
35 from .makeRawVisitInfoViaObsInfo
import MakeRawVisitInfoViaObsInfo
36 from .utils
import createInitialSkyWcsFromBoresight, InitialSkyWcsError
40 """Abstract base class for reading and writing raw data to and from
46 """Control whether the WCS is flipped in the X-direction (`bool`)"""
54 def fromMetadata(cls, metadata, obsInfo=None, storageClass=None, location=None):
55 """Construct a possibly-limited formatter from known metadata.
59 metadata : `lsst.daf.base.PropertyList`
60 Raw header metadata, with any fixes (see
61 `astro_metadata_translator.fix_header`) applied but nothing
63 obsInfo : `astro_metadata_translator.ObservationInfo`, optional
64 Structured information already extracted from ``metadata``.
65 If not provided, will be read from ``metadata`` on first use.
66 storageClass : `lsst.daf.butler.StorageClass`, optional
67 StorageClass for this file. If not provided, the formatter will
68 only support `makeWcs`, `makeVisitInfo`, `makeFilter`, and other
69 operations that operate purely on metadata and not the actual file.
70 location : `lsst.daf.butler.Location`, optional.
71 Location of the file. If not provided, the formatter will only
72 support `makeWcs`, `makeVisitInfo`, `makeFilter`, and other
73 operations that operate purely on metadata and not the actual file.
77 formatter : `FitsRawFormatterBase`
78 An instance of ``cls``.
80 self = cls(FileDescriptor(location, storageClass))
88 """`~astro_metadata_translator.MetadataTranslator` to translate
89 metadata header to `~astro_metadata_translator.ObservationInfo`.
93 _observationInfo =
None
98 """`~lsst.obs.base.FilterDefinitions`, defining the filters for this
104 """Read just the image component of the Exposure.
108 image : `~lsst.afw.image.Image`
109 In-memory image component.
111 return lsst.afw.image.ImageU(self.fileDescriptor.location.path)
114 """Read just the mask component of the Exposure.
116 May return None (as the default implementation does) to indicate that
117 there is no mask information to be extracted (at least not trivially)
118 from the raw data. This will prohibit direct reading of just the mask,
119 and set the mask of the full Exposure to zeros.
123 mask : `~lsst.afw.image.Mask`
124 In-memory mask component.
129 """Read just the variance component of the Exposure.
131 May return None (as the default implementation does) to indicate that
132 there is no variance information to be extracted (at least not
133 trivially) from the raw data. This will prohibit direct reading of
134 just the variance, and set the variance of the full Exposure to zeros.
138 image : `~lsst.afw.image.Image`
139 In-memory variance component.
144 """Boolean to determine if the exposure is thought to be on the sky.
149 Returns `True` if the observation looks like it was taken on the
150 sky. Returns `False` if this observation looks like a calibration
155 If there is tracking RA/Dec information associated with the
156 observation it is assumed that the observation is on sky.
157 Currently the observation type is not checked.
164 """Remove metadata entries that are parsed into components.
173 """Construct a VisitInfo from metadata.
177 visitInfo : `~lsst.afw.image.VisitInfo`
178 Structured metadata about the observation.
180 return MakeRawVisitInfoViaObsInfo.observationInfo2visitInfo(self.
observationInfo)
184 """Return the detector that acquired this raw exposure.
189 The identifying number of the detector to get.
193 detector : `~lsst.afw.cameraGeom.Detector`
194 The detector associated with that ``id``.
196 raise NotImplementedError(
"Must be implemented by subclasses.")
199 """Create a SkyWcs from information about the exposure.
201 If VisitInfo is not None, use it and the detector to create a SkyWcs,
202 otherwise return the metadata-based SkyWcs (always created, so that
203 the relevant metadata keywords are stripped).
207 visitInfo : `~lsst.afw.image.VisitInfo`
208 The information about the telescope boresight and camera
209 orientation angle for this exposure.
210 detector : `~lsst.afw.cameraGeom.Detector`
211 The detector used to acquire this exposure.
215 skyWcs : `~lsst.afw.geom.SkyWcs`
216 Reversible mapping from pixel coordinates to sky coordinates.
221 Raised if there is an error generating the SkyWcs, chained from the
222 lower-level exception if available.
230 log = lsst.log.Log.getLogger(
"fitsRawFormatter")
231 if visitInfo
is None:
232 msg =
"No VisitInfo; cannot access boresight information. Defaulting to metadata-based SkyWcs."
236 "See warnings in log messages for details.")
240 visitInfo.getBoresightRotAngle(),
245 """Class method to make a raw sky WCS from boresight and detector.
249 boresight : `lsst.geom.SpherePoint`
250 The ICRS boresight RA/Dec
251 orientation : `lsst.geom.Angle`
252 The rotation angle of the focal plane on the sky.
253 detector : `lsst.afw.cameraGeom.Detector`
254 Where to get the camera geomtry from.
258 skyWcs : `~lsst.afw.geom.SkyWcs`
259 Reversible mapping from pixel coordinates to sky coordinates.
263 def _createSkyWcsFromMetadata(self):
264 """Create a SkyWcs from the FITS header metadata in an Exposure.
268 skyWcs: `lsst.afw.geom.SkyWcs`, or None
269 The WCS that was created from ``self.metadata``, or None if that
270 creation fails due to invalid metadata.
277 return lsst.afw.geom.makeSkyWcs(self.
metadata, strip=
True)
278 except TypeError
as e:
279 log = lsst.log.Log.getLogger(
"fitsRawFormatter")
280 log.warn(
"Cannot create a valid WCS from metadata: %s", e.args[0])
284 """Construct a Filter from metadata.
288 filter : `~lsst.afw.image.Filter`
289 Object that identifies the filter for this image.
294 Raised if the physical filter was not registered via
295 `~lsst.afw.image.utils.defineFilter`.
300 """Read a component held by the Exposure.
304 component : `str`, optional
305 Component to read from the file.
306 parameters : `dict`, optional
307 If specified, a dictionary of slicing parameters that
308 overrides those in ``fileDescriptor``.
312 obj : component-dependent
313 In-memory component object.
318 Raised if the requested component cannot be handled.
320 if component ==
"image":
322 elif component ==
"mask":
324 elif component ==
"variance":
326 elif component ==
"filter":
328 elif component ==
"visitInfo":
330 elif component ==
"wcs":
333 return self.
makeWcs(visitInfo, detector)
337 """Read the full Exposure object.
341 parameters : `dict`, optional
342 If specified, a dictionary of slicing parameters that overrides
343 those in the `fileDescriptor` attribute.
347 exposure : `~lsst.afw.image.Exposure`
348 Complete in-memory exposure.
350 from lsst.afw.image
import makeExposure, makeMaskedImage
351 full = makeExposure(makeMaskedImage(self.
readImage()))
356 if variance
is not None:
357 full.setVariance(variance)
359 info = full.getInfo()
362 info.setWcs(self.
makeWcs(info.getVisitInfo(), info.getDetector()))
369 """Read the SkyWcs stored in the un-modified raw FITS WCS header keys.
371 return lsst.afw.geom.makeSkyWcs(lsst.afw.fits.readMetadata(self.fileDescriptor))
374 """Write a Python object to a file.
378 inMemoryDataset : `object`
379 The Python object to store.
384 The `URI` where the primary file is stored.
386 raise NotImplementedError(
"Raw data cannot be `put`.")
390 """The `~astro_metadata_translator.ObservationInfo` extracted from
391 this file's metadata (`~astro_metadata_translator.ObservationInfo`,