LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
ExposureInfo.cc
Go to the documentation of this file.
1// -*- LSST-C++ -*- // fixed format comment for emacs
2/*
3 * This file is part of afw.
4 *
5 * Developed for the LSST Data Management System.
6 * This product includes software developed by the LSST Project
7 * (https://www.lsst.org).
8 * See the COPYRIGHT file at the top-level directory of this distribution
9 * for details of code ownership.
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25#include "lsst/pex/exceptions.h"
26#include "lsst/log/Log.h"
35#include "lsst/afw/fits.h"
36
37using namespace std::string_literals;
38
39namespace {
40LOG_LOGGER _log = LOG_GET("lsst.afw.image.ExposureInfo");
41
43} // namespace
44
45namespace lsst {
46namespace afw {
47namespace image {
48
49// Important: do *not* change the keys' strings; doing so will break compatibility with old FITS files
50
51typehandling::Key<std::string, std::shared_ptr<geom::SkyWcs const>> const ExposureInfo::KEY_WCS =
52 typehandling::makeKey<std::shared_ptr<geom::SkyWcs const>>("SKYWCS"s);
53
54bool ExposureInfo::hasWcs() const { return hasComponent(KEY_WCS); }
57
59 typehandling::makeKey<std::shared_ptr<detection::Psf const>>("PSF"s);
60
61bool ExposureInfo::hasPsf() const { return hasComponent(KEY_PSF); }
64
66 typehandling::makeKey<std::shared_ptr<PhotoCalib const>>("PHOTOCALIB"s);
67
71}
74}
75
77 typehandling::makeKey<std::shared_ptr<cameraGeom::Detector const>>("DETECTOR"s);
78
82}
85}
86
89 typehandling::makeKey<std::shared_ptr<geom::polygon::Polygon const>>("VALID_POLYGON"s);
90
94}
97}
98
100 typehandling::makeKey<std::shared_ptr<CoaddInputs const>>("COADD_INPUTS"s);
101
104 setComponent(KEY_COADD_INPUTS, coaddInputs);
105}
108}
109
111 typehandling::makeKey<std::shared_ptr<ApCorrMap const>>("AP_CORR_MAP"s);
112
117}
118
121 typehandling::makeKey<std::shared_ptr<TransmissionCurve const>>("TRANSMISSION_CURVE"s);
122
126}
129}
130
131bool ExposureInfo::hasId() const noexcept { return _exposureId.has_value(); }
132
134 if (_exposureId) {
135 return *_exposureId;
136 } else {
137 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Exposure does not have an ID.");
138 }
139}
140
142 _exposureId = id;
143 // Ensure consistency with VisitInfo::getExposureId() until the latter is removed in DM-32138.
145 if (oldVisitInfo) {
146 auto newVisitInfo = std::make_shared<VisitInfo>(
147 *_exposureId, oldVisitInfo->getExposureTime(), oldVisitInfo->getDarkTime(),
148 oldVisitInfo->getDate(), oldVisitInfo->getUt1(), oldVisitInfo->getEra(),
149 oldVisitInfo->getBoresightRaDec(), oldVisitInfo->getBoresightAzAlt(),
150 oldVisitInfo->getBoresightAirmass(), oldVisitInfo->getBoresightRotAngle(),
151 oldVisitInfo->getRotType(), oldVisitInfo->getObservatory(), oldVisitInfo->getWeather(),
152 oldVisitInfo->getInstrumentLabel(), oldVisitInfo->getId(), oldVisitInfo->getFocusZ(),
153 oldVisitInfo->getObservationType(), oldVisitInfo->getScienceProgram(),
154 oldVisitInfo->getObservationReason(), oldVisitInfo->getObject(),
155 oldVisitInfo->getHasSimulatedContent());
156 // Do not call setVisitInfo, to avoid recursion
157 _visitInfo = newVisitInfo;
158 }
159}
160
161void ExposureInfo::clearId() noexcept { _exposureId.reset(); }
162
164 typehandling::makeKey<std::shared_ptr<FilterLabel const>>("FILTER"s);
168
170 // Version history:
171 // unversioned and 0: photometric calibration via Calib, WCS via SkyWcs using AST.
172 // 1: photometric calibration via PhotoCalib, generic components
173 // 2: remove Filter, replaced with (generic) FilterLabel
174 static int const version = 2;
175 return version;
176}
177
179 static std::string const versionName("EXPINFO_V");
180 return versionName;
181}
182
183// Clone various components; defined here so that we don't have to expose their insides in Exposure.h
184
185std::shared_ptr<ApCorrMap> ExposureInfo::_cloneApCorrMap(std::shared_ptr<ApCorrMap const> apCorrMap) {
186 if (apCorrMap) {
187 return std::make_shared<ApCorrMap>(*apCorrMap);
188 }
190}
191
194 std::shared_ptr<PhotoCalib const> const& photoCalib,
198 std::shared_ptr<CoaddInputs> const& coaddInputs,
199 std::shared_ptr<ApCorrMap> const& apCorrMap,
202 : _exposureId(),
203 _metadata(metadata ? metadata
204 : std::shared_ptr<daf::base::PropertySet>(new daf::base::PropertyList())),
205 _visitInfo(visitInfo),
206 _components(std::make_unique<MapClass>()) {
207 setWcs(wcs);
208 setPsf(psf);
211 setValidPolygon(polygon);
212 setCoaddInputs(coaddInputs);
213 setApCorrMap(_cloneApCorrMap(apCorrMap));
215}
216
218
219// Delegate to copy-constructor for backwards compatibility
221
222ExposureInfo::ExposureInfo(ExposureInfo const& other, bool copyMetadata)
223 : _exposureId(other._exposureId),
224 _metadata(other._metadata),
225 _visitInfo(other._visitInfo),
226 // ExposureInfos can (historically) share objects, but should each have their own pointers to them
227 _components(std::make_unique<MapClass>(*(other._components))) {
228 if (copyMetadata) _metadata = _metadata->deepCopy();
229}
230
232 if (&other != this) {
233 _exposureId = other._exposureId;
234 _metadata = other._metadata;
235 _visitInfo = other._visitInfo;
236 // ExposureInfos can (historically) share objects, but should each have their own pointers to them
237 _components = std::make_unique<MapClass>(*(other._components));
238 }
239 return *this;
240}
241// Delegate to copy-assignment for backwards compatibility
242ExposureInfo& ExposureInfo::operator=(ExposureInfo&& other) { return *this = other; }
243
244void ExposureInfo::initApCorrMap() { setApCorrMap(std::make_shared<ApCorrMap>()); }
245
247
248int ExposureInfo::_addToArchive(FitsWriteData& data, table::io::Persistable const& object, std::string key,
249 std::string comment) {
250 int componentId = data.archive.put(object);
251 data.metadata->set(key, componentId, comment);
252 return componentId;
253}
254
255int ExposureInfo::_addToArchive(FitsWriteData& data,
257 std::string comment) {
258 // Don't delegate to Persistable const& version because OutputArchive::put
259 // has special handling of shared_ptr
260 int componentId = data.archive.put(object);
261 data.metadata->set(key, componentId, comment);
262 return componentId;
263}
264
265// Standardized strings for _startWriteFits
266namespace {
267std::string _getOldHeaderKey(std::string mapKey) { return mapKey + "_ID"; }
268std::string _getNewHeaderKey(std::string mapKey) { return "ARCHIVE_ID_" + mapKey; }
269
270std::string _getHeaderComment(std::string mapKey) {
271 return "archive ID for generic component '" + mapKey + "'";
272}
273} // namespace
274
275ExposureInfo::FitsWriteData ExposureInfo::_startWriteFits(lsst::geom::Point2I const& xy0) const {
276 FitsWriteData data;
277
278 data.metadata.reset(new daf::base::PropertyList());
279 data.imageMetadata.reset(new daf::base::PropertyList());
280 data.maskMetadata = data.imageMetadata;
281 data.varianceMetadata = data.imageMetadata;
282
283 data.metadata->combine(*getMetadata());
284
286
287 // In the future, we might not have exactly three image HDUs, but we always do right now,
288 // so 0=primary, 1=image, 2=mask, 3=variance, 4+=archive
289 //
290 // Historically the AR_HDU keyword was 1-indexed (see RFC-304), and to maintain file compatibility
291 // this is still the case so we're setting AR_HDU to 5 == 4 + 1
292 //
293 data.metadata->set("AR_HDU", 5, "HDU (1-indexed) containing the archive used to store ancillary objects");
294 for (auto const& keyValue : *_components) {
295 std::string const& key = keyValue.first.getId();
296 std::shared_ptr<typehandling::Storable const> const& object = keyValue.second;
297
298 if (object && object->isPersistable()) {
299 std::string comment = _getHeaderComment(key);
300 // Store archive ID in two header keys:
301 // - old-style key for backwards compatibility,
302 // - and new-style key because it's much safer to parse
303 int id = _addToArchive(data, object, _getOldHeaderKey(key), comment);
304 data.metadata->set(_getNewHeaderKey(key), id, comment);
305 }
306 }
307
308 // LSST convention is that Wcs is in pixel coordinates (i.e relative to bottom left
309 // corner of parent image, if any). The Wcs/Fits convention is that the Wcs is in
310 // image coordinates. When saving an image we convert from pixel to index coordinates.
311 // In the case where this image is a parent image, the reference pixels are unchanged
312 // by this transformation
313 if (hasWcs() && getWcs()->isFits()) {
314 // Try to save the WCS as FITS-WCS metadata; if an exact representation
315 // is not possible then skip it
316 auto shift = lsst::geom::Extent2D(lsst::geom::Point2I(0, 0) - xy0);
317 auto newWcs = getWcs()->copyAtShiftedPixelOrigin(shift);
319 try {
320 wcsMetadata = newWcs->getFitsMetadata(true);
321 } catch (pex::exceptions::RuntimeError const&) {
322 // cannot represent this WCS as FITS-WCS; don't write its metadata
323 }
324 if (wcsMetadata) {
325 data.imageMetadata->combine(*newWcs->getFitsMetadata(true));
326 }
327 }
328
329 // For the sake of ds9, store _x0 and _y0 as -LTV1, -LTV2.
330 // This is in addition to saving _x0 and _y0 as WCS A, which is done elsewhere
331 // and is what LSST uses to read _x0 and _y0.
332 // LTV is a convention used by STScI (see \S2.6.2 of HST Data Handbook for STIS, version 5.0
333 // http://www.stsci.edu/hst/stis/documents/handbooks/currentDHB/ch2_stis_data7.html#429287)
334 // and recognized by ds9.
335 data.imageMetadata->set("LTV1", static_cast<double>(-xy0.getX()));
336 data.imageMetadata->set("LTV2", static_cast<double>(-xy0.getY()));
337
338 if (hasDetector()) {
339 data.metadata->set("DETNAME", getDetector()->getName());
340 data.metadata->set("DETSER", getDetector()->getSerial());
341 }
342
343 auto visitInfoPtr = getVisitInfo();
344 if (visitInfoPtr) {
345 detail::setVisitInfoMetadata(*(data.metadata), *visitInfoPtr);
346 }
347
348 // So long as VisitInfo also writes exposureId (until DM-32138), let ours take precedence.
349 if (hasId()) {
350 data.metadata->set("EXPID", getId());
351 }
352
353 return data;
354}
355
356void ExposureInfo::_finishWriteFits(fits::Fits& fitsfile, FitsWriteData const& data) const {
357 data.archive.writeFits(fitsfile);
358}
359
360} // namespace image
361} // namespace afw
362} // namespace lsst
char * data
Definition: BaseRecord.cc:61
table::Key< int > id
Definition: Detector.cc:162
table::Key< int > detector
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
LSST DM logging module built on log4cxx.
#define LOG_GET(logger)
Returns a Log object associated with logger.
Definition: Log.h:75
#define LOG_LOGGER
Definition: Log.h:714
Implementation of the Photometric Calibration class.
table::Key< table::Array< std::uint8_t > > wcs
Definition: SkyWcs.cc:66
table::Key< std::string > object
Definition: VisitInfo.cc:232
A collection of all the things that make an Exposure different from a MaskedImage.
Definition: ExposureInfo.h:88
bool hasWcs() const
Does this exposure have a Wcs?
Definition: ExposureInfo.cc:54
static int getFitsSerializationVersion()
Get the version of FITS serialization that this ExposureInfo understands.
bool hasCoaddInputs() const
Does this exposure have coadd provenance catalogs?
static typehandling::Key< std::string, std::shared_ptr< geom::SkyWcs const > > const KEY_WCS
Standard key for looking up the Wcs.
Definition: ExposureInfo.h:91
ExposureInfo & operator=(ExposureInfo const &other)
Assignment; shares all components.
static typehandling::Key< std::string, std::shared_ptr< cameraGeom::Detector const > > const KEY_DETECTOR
Standard key for looking up the detector information.
Definition: ExposureInfo.h:97
bool hasTransmissionCurve() const
Does this exposure have a transmission curve?
bool hasPsf() const
Does this exposure have a Psf?
Definition: ExposureInfo.cc:61
void setValidPolygon(std::shared_ptr< geom::polygon::Polygon const > polygon)
Set the exposure's valid Polygon.
Definition: ExposureInfo.cc:95
bool hasPhotoCalib() const
Does this exposure have a photometric calibration?
Definition: ExposureInfo.cc:68
bool hasApCorrMap() const
Return true if the exposure has an aperture correction map.
void setWcs(std::shared_ptr< geom::SkyWcs const > wcs)
Set the WCS of the exposure.
Definition: ExposureInfo.cc:56
std::shared_ptr< PhotoCalib const > getPhotoCalib() const
Return the exposure's photometric calibration.
Definition: ExposureInfo.cc:69
bool hasComponent(typehandling::Key< std::string, T > const &key) const
Test whether a generic component is defined.
Definition: ExposureInfo.h:304
std::shared_ptr< ApCorrMap const > getApCorrMap() const
Return the exposure's aperture correction map (null pointer if !hasApCorrMap())
void setApCorrMap(std::shared_ptr< ApCorrMap const > apCorrMap)
Set the exposure's aperture correction map (null pointer if !hasApCorrMap())
void setPhotoCalib(std::shared_ptr< PhotoCalib const > photoCalib)
Set the Exposure's PhotoCalib object.
Definition: ExposureInfo.cc:72
static typehandling::Key< std::string, std::shared_ptr< geom::polygon::Polygon const > > const KEY_VALID_POLYGON
Standard key for looking up the valid polygon.
Definition: ExposureInfo.h:100
void setComponent(typehandling::Key< std::string, std::shared_ptr< T > > const &key, std::shared_ptr< T > const &object)
Add a generic component to the ExposureInfo.
Definition: ExposureInfo.h:284
bool hasValidPolygon() const
Does this exposure have a valid Polygon.
Definition: ExposureInfo.cc:91
std::shared_ptr< geom::SkyWcs const > getWcs() const
Return the WCS of the exposure.
Definition: ExposureInfo.cc:55
std::shared_ptr< T > getComponent(typehandling::Key< std::string, std::shared_ptr< T > > const &key) const
Retrieve a generic component from the ExposureInfo.
Definition: ExposureInfo.h:318
std::shared_ptr< FilterLabel const > getFilter() const
Return the exposure's filter information.
static typehandling::Key< std::string, std::shared_ptr< PhotoCalib const > > const KEY_PHOTO_CALIB
Standard key for looking up the photometric calibration.
Definition: ExposureInfo.h:95
void setCoaddInputs(std::shared_ptr< CoaddInputs const > coaddInputs)
Set the exposure's coadd provenance catalogs.
std::shared_ptr< cameraGeom::Detector const > getDetector() const
Return the exposure's Detector information.
Definition: ExposureInfo.cc:80
void clearId() noexcept
Unset the exposure ID, if any.
void setDetector(std::shared_ptr< cameraGeom::Detector const > detector)
Set the exposure's Detector information.
Definition: ExposureInfo.cc:83
void setFilter(std::shared_ptr< FilterLabel const > filter)
Set the exposure's filter information.
void setPsf(std::shared_ptr< detection::Psf const > psf)
Set the exposure's point-spread function.
Definition: ExposureInfo.cc:63
static typehandling::Key< std::string, std::shared_ptr< TransmissionCurve const > > const KEY_TRANSMISSION_CURVE
Standard key for looking up the transmission curve.
Definition: ExposureInfo.h:107
void initApCorrMap()
Set the exposure's aperture correction map to a new, empty map.
static typehandling::Key< std::string, std::shared_ptr< CoaddInputs const > > const KEY_COADD_INPUTS
Standard key for looking up coadd provenance catalogs.
Definition: ExposureInfo.h:102
static typehandling::Key< std::string, std::shared_ptr< detection::Psf const > > const KEY_PSF
Standard key for looking up the point-spread function.
Definition: ExposureInfo.h:93
std::shared_ptr< CoaddInputs const > getCoaddInputs() const
Return a pair of catalogs that record the inputs, if this Exposure is a coadd (otherwise null).
bool hasFilter() const
Does this exposure have filter information?
table::RecordId getId() const
Return the exposure ID.
std::shared_ptr< geom::polygon::Polygon const > getValidPolygon() const
Return the valid Polygon.
Definition: ExposureInfo.cc:92
std::shared_ptr< daf::base::PropertySet > getMetadata() const
Return flexible metadata.
Definition: ExposureInfo.h:183
ExposureInfo(std::shared_ptr< geom::SkyWcs const > const &wcs=std::shared_ptr< geom::SkyWcs const >(), std::shared_ptr< detection::Psf const > const &psf=std::shared_ptr< detection::Psf const >(), std::shared_ptr< PhotoCalib const > const &photoCalib=std::shared_ptr< PhotoCalib const >(), std::shared_ptr< cameraGeom::Detector const > const &detector=std::shared_ptr< cameraGeom::Detector const >(), std::shared_ptr< geom::polygon::Polygon const > const &polygon=std::shared_ptr< geom::polygon::Polygon const >(), std::shared_ptr< daf::base::PropertySet > const &metadata=std::shared_ptr< daf::base::PropertySet >(), std::shared_ptr< CoaddInputs > const &coaddInputs=std::shared_ptr< CoaddInputs >(), std::shared_ptr< ApCorrMap > const &apCorrMap=std::shared_ptr< ApCorrMap >(), std::shared_ptr< image::VisitInfo const > const &visitInfo=std::shared_ptr< image::VisitInfo const >(), std::shared_ptr< TransmissionCurve const > const &transmissionCurve=std::shared_ptr< TransmissionCurve >())
Construct an ExposureInfo from its various components.
bool hasDetector() const
Does this exposure have Detector information?
Definition: ExposureInfo.cc:79
static typehandling::Key< std::string, std::shared_ptr< ApCorrMap const > > const KEY_AP_CORR_MAP
Standard key for looking up the aperture correction map.
Definition: ExposureInfo.h:104
static std::string const & getFitsSerializationVersionName()
Get the version of FITS serialization version info name.
std::shared_ptr< image::VisitInfo const > getVisitInfo() const
Return the exposure's visit info.
Definition: ExposureInfo.h:233
static typehandling::Key< std::string, std::shared_ptr< FilterLabel const > > const KEY_FILTER
Standard key for looking up filter information.
Definition: ExposureInfo.h:109
void setId(table::RecordId id)
Set the exposure ID.
bool hasId() const noexcept
Does this Exposure have an exposure id?
void setTransmissionCurve(std::shared_ptr< TransmissionCurve const > tc)
Set the exposure's transmission curve.
std::shared_ptr< detection::Psf const > getPsf() const
Return the exposure's point-spread function.
Definition: ExposureInfo.cc:62
std::shared_ptr< TransmissionCurve const > getTransmissionCurve() const
Return the exposure's transmission curve.
A map of Storable supporting strongly-typed access.
Definition: StorableMap.h:59
A base class for objects that can be persisted via afw::table::io Archive classes.
Definition: Persistable.h:74
Key for type-safe lookup in a GenericMap.
Definition: Key.h:52
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
void setVisitInfoMetadata(daf::base::PropertyList &metadata, VisitInfo const &visitInfo)
Set FITS metadata from a VisitInfo.
Definition: VisitInfo.cc:419
Extent< double, 2 > Extent2D
Definition: Extent.h:400
STL namespace.
Key< int > psf
Definition: Exposure.cc:65
Key< int > visitInfo
Definition: Exposure.cc:70
Key< int > photoCalib
Definition: Exposure.cc:67
Key< int > transmissionCurve
Definition: Exposure.cc:71
Key< int > apCorrMap
Definition: Exposure.cc:68