LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
ExposureInfo.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*- // fixed format comment for emacs
2 /*
3  * LSST Data Management System
4  * Copyright 2008, 2009, 2010 LSST Corporation.
5  *
6  * This product includes software developed by the
7  * LSST Project (http://www.lsst.org/).
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the LSST License Statement and
20  * the GNU General Public License along with this program. If not,
21  * see <http://www.lsstcorp.org/LegalNotices/>.
22  */
23 
24 #include "lsst/pex/exceptions.h"
25 #include "lsst/pex/logging/Log.h"
27 #include "lsst/afw/image/Calib.h"
28 #include "lsst/afw/image/Wcs.h"
31 #include "lsst/afw/detection/Psf.h"
33 #include "lsst/afw/fits.h"
34 
35 namespace lsst { namespace afw { namespace image {
36 
37 namespace {
38 
39 // Return an int value from a PropertySet if it exists and remove it, or return 0.
40 int popInt(daf::base::PropertySet & metadata, std::string const & name) {
41  int r = 0;
42  if (metadata.exists(name)) {
43  r = metadata.get<int>(name);
44  metadata.remove(name);
45  }
46  return r;
47 }
48 
49 } // anonymous
50 
51 
52 // Clone various components; defined here so that we don't have to expose their insides in Exposure.h
53 
54 PTR(Calib) ExposureInfo::_cloneCalib(CONST_PTR(Calib) calib) {
55  if (calib)
56  return PTR(Calib)(new Calib(*calib));
57  return PTR(Calib)();
58 }
59 
61  if (wcs)
62  return wcs->clone();
63  return PTR(Wcs)();
64 }
65 
66 PTR(ApCorrMap) ExposureInfo::_cloneApCorrMap(PTR(ApCorrMap const) apCorrMap) {
67  if (apCorrMap) {
68  return boost::make_shared<ApCorrMap>(*apCorrMap);
69  }
70  return PTR(ApCorrMap)();
71 }
72 
74  CONST_PTR(Wcs) const & wcs,
75  CONST_PTR(detection::Psf) const & psf,
76  CONST_PTR(Calib) const & calib,
77  CONST_PTR(cameraGeom::Detector) const & detector,
78  CONST_PTR(geom::polygon::Polygon) const & polygon,
79  Filter const & filter,
80  PTR(daf::base::PropertySet) const & metadata,
81  PTR(CoaddInputs) const & coaddInputs,
82  PTR(ApCorrMap) const & apCorrMap
83 ) : _wcs(_cloneWcs(wcs)),
84  _psf(boost::const_pointer_cast<detection::Psf>(psf)),
85  _calib(calib ? _cloneCalib(calib) : PTR(Calib)(new Calib())),
86  _detector(detector),
87  _validPolygon(polygon),
88  _filter(filter),
89  _metadata(metadata ? metadata : PTR(daf::base::PropertySet)(new daf::base::PropertyList())),
90  _coaddInputs(coaddInputs),
91  _apCorrMap(_cloneApCorrMap(apCorrMap))
92 {}
93 
95  _wcs(_cloneWcs(other._wcs)),
96  _psf(other._psf),
97  _calib(_cloneCalib(other._calib)),
98  _detector(other._detector),
99  _validPolygon(other._validPolygon),
100  _filter(other._filter),
101  _metadata(other._metadata),
102  _coaddInputs(other._coaddInputs),
103  _apCorrMap(_cloneApCorrMap(other._apCorrMap))
104 {}
105 
106 ExposureInfo::ExposureInfo(ExposureInfo const & other, bool copyMetadata) :
107  _wcs(_cloneWcs(other._wcs)),
108  _psf(other._psf),
109  _calib(_cloneCalib(other._calib)),
110  _detector(other._detector),
111  _validPolygon(other._validPolygon),
112  _filter(other._filter),
113  _metadata(other._metadata),
114  _coaddInputs(other._coaddInputs),
115  _apCorrMap(_cloneApCorrMap(other._apCorrMap))
116 {
117  if (copyMetadata) _metadata = _metadata->deepCopy();
118 }
119 
121  if (&other != this) {
122  _wcs = _cloneWcs(other._wcs);
123  _psf = other._psf;
124  _calib = _cloneCalib(other._calib);
125  _detector = other._detector;
127  _filter = other._filter;
128  _metadata = other._metadata;
129  _coaddInputs = other._coaddInputs;
131  }
132  return *this;
133 }
134 
136  _apCorrMap = boost::make_shared<ApCorrMap>();
137 }
138 
140 
143 
144  FitsWriteData data;
145 
146  data.metadata.reset(new daf::base::PropertyList());
147  data.imageMetadata.reset(new daf::base::PropertyList());
148  data.maskMetadata = data.imageMetadata;
149  data.varianceMetadata = data.imageMetadata;
150 
151  data.metadata->combine(getMetadata());
152 
153  // In the future, we might not have exactly three image HDUs, but we always do right now,
154  // so 1=primary, 2=image, 3=mask, 4=variance, 5+=archive
155  data.metadata->set("AR_HDU", 5, "HDU containing the archive used to store ancillary objects");
156  if (hasCoaddInputs()) {
157  int coaddInputsId = data.archive.put(getCoaddInputs());
158  data.metadata->set("COADD_INPUTS_ID", coaddInputsId, "archive ID for coadd inputs catalogs");
159  }
160  if (hasApCorrMap()) {
161  int apCorrMapId = data.archive.put(getApCorrMap());
162  data.metadata->set("AP_CORR_MAP_ID", apCorrMapId, "archive ID for aperture correction map");
163  }
164  if (hasPsf() && getPsf()->isPersistable()) {
165  int psfId = data.archive.put(getPsf());
166  data.metadata->set("PSF_ID", psfId, "archive ID for the Exposure's main Psf");
167  }
168  if (hasWcs() && getWcs()->isPersistable()) {
169  int wcsId = data.archive.put(getWcs());
170  data.metadata->set("WCS_ID", wcsId, "archive ID for the Exposure's main Wcs");
171  }
172  if (hasValidPolygon() && getValidPolygon()->isPersistable()) {
173  int polygonId = data.archive.put(getValidPolygon());
174  data.metadata->set("VALID_POLYGON_ID", polygonId, "archive ID for the Exposure's valid polygon");
175  }
176 
177  //LSST convention is that Wcs is in pixel coordinates (i.e relative to bottom left
178  //corner of parent image, if any). The Wcs/Fits convention is that the Wcs is in
179  //image coordinates. When saving an image we convert from pixel to index coordinates.
180  //In the case where this image is a parent image, the reference pixels are unchanged
181  //by this transformation
182  if (hasWcs()) {
183  PTR(Wcs) newWcs = getWcs()->clone(); //Create a copy
184  newWcs->shiftReferencePixel(-xy0.getX(), -xy0.getY() );
185 
186  // We want the WCS to appear in all HDUs
187  data.imageMetadata->combine(newWcs->getFitsMetadata());
188  }
189 
190  //Store _x0 and _y0. If this exposure is a portion of a larger image, _x0 and _y0
191  //indicate the origin (the position of the bottom left corner) of the sub-image with
192  //respect to the origin of the parent image.
193  //This is stored in the fits header using the LTV convention used by STScI
194  //(see \S2.6.2 of HST Data Handbook for STIS, version 5.0
195  // http://www.stsci.edu/hst/stis/documents/handbooks/currentDHB/ch2_stis_data7.html#429287).
196  //This is not a fits standard keyword, but is recognised by ds9
197  //LTV keywords use the opposite convention to the LSST, in that they represent
198  //the position of the origin of the parent image relative to the origin of the sub-image.
199  // _x0, _y0 >= 0, while LTV1 and LTV2 <= 0
200 
201  data.imageMetadata->set("LTV1", -xy0.getX());
202  data.imageMetadata->set("LTV2", -xy0.getY());
203 
204  data.metadata->set("FILTER", getFilter().getName());
205  if (hasDetector()) {
206  data.metadata->set("DETNAME", getDetector()->getName());
207  data.metadata->set("DETSER", getDetector()->getSerial());
208  }
212  data.metadata->set("TIME-MID", getCalib()->getMidTime().toString());
213  data.metadata->set("EXPTIME", getCalib()->getExptime());
214  data.metadata->set("FLUXMAG0", getCalib()->getFluxMag0().first);
215  data.metadata->set("FLUXMAG0ERR", getCalib()->getFluxMag0().second);
216 
217  return data;
218 }
219 
220 void ExposureInfo::_finishWriteFits(fits::Fits & fitsfile, FitsWriteData const & data) const {
221  data.archive.writeFits(fitsfile);
222 }
223 
225  fits::Fits & fitsfile,
226  PTR(daf::base::PropertySet) metadata,
227  PTR(daf::base::PropertySet) imageMetadata
228 ) {
229  // true: strip keywords that are related to the created WCS from the input metadata
230  _wcs = makeWcs(imageMetadata, true);
231 
232  if (!imageMetadata->exists("INHERIT")) {
233  // New-style exposures put everything but the Wcs in the primary HDU, use
234  // INHERIT keyword in the others. For backwards compatibility, if we don't
235  // find the INHERIT keyword, we ignore the primary HDU metadata and expect
236  // everything to be in the image HDU metadata. Note that we can't merge them,
237  // because they're probably duplicates.
238  metadata = imageMetadata;
239  }
240 
241  _filter = Filter(metadata, true);
242  detail::stripFilterKeywords(metadata);
243 
244  PTR(Calib) newCalib(new Calib(metadata));
245  setCalib(newCalib);
246  detail::stripCalibKeywords(metadata);
247 
248  int archiveHdu = popInt(*metadata, "AR_HDU");
249 
250  if (archiveHdu) {
251  fitsfile.setHdu(archiveHdu);
253  // Load the Psf and Wcs from the archive; id=0 results in a null pointer.
254  // Note that the binary table Wcs, if present, clobbers the FITS header one,
255  // because the former might be an approximation to something we can't represent
256  // using the FITS WCS standard but can represent with binary tables.
257  int psfId = popInt(*metadata, "PSF_ID");
258  try {
259  _psf = archive.get<detection::Psf>(psfId);
260  } catch (pex::exceptions::NotFoundError & err) {
262  boost::format("Could not read PSF; setting to null: %s") % err.what()
263  );
264  }
265  int wcsId = popInt(*metadata, "WCS_ID");
266  try {
267  auto archiveWcs = archive.get<Wcs>(wcsId);
268  if (archiveWcs) {
269  _wcs = archiveWcs;
270  } else {
271  pex::logging::Log::getDefaultLog().info("Empty WCS extension, using FITS header");
272  }
273  } catch (pex::exceptions::NotFoundError & err) {
274  auto msg = str(boost::format("Could not read WCS extension; setting to null: %s") % err.what());
275  if (_wcs) {
276  msg += " ; using WCS from FITS header";
277  }
278 
280  }
281  int coaddInputsId = popInt(*metadata, "COADD_INPUTS_ID");
282  try {
283  _coaddInputs = archive.get<CoaddInputs>(coaddInputsId);
284  } catch (pex::exceptions::NotFoundError & err) {
286  boost::format("Could not read CoaddInputs; setting to null: %s") % err.what()
287  );
288  }
289  int apCorrMapId = popInt(*metadata, "AP_CORR_MAP_ID");
290  try {
291  _apCorrMap = archive.get<ApCorrMap>(apCorrMapId);
292  } catch (pex::exceptions::NotFoundError & err) {
294  boost::format("Could not read ApCorrMap; setting to null: %s") % err.what()
295  );
296  }
297  int validPolygonId = popInt(*metadata, "VALID_POLYGON_ID");
298  try {
299  _validPolygon = archive.get<geom::polygon::Polygon>(validPolygonId);
300  } catch (pex::exceptions::NotFoundError & err) {
302  boost::format("Could not read ValidPolygon; setting to null: %s") % err.what()
303  );
304  }
305  }
306 
307  _metadata = metadata;
308 }
309 
310 }}} // namespace lsst::afw::image
boost::shared_ptr< ApCorrMap > _apCorrMap
Definition: ExposureInfo.h:284
boost::shared_ptr< detection::Psf > getPsf() const
Return the exposure&#39;s point-spread function.
Definition: ExposureInfo.h:132
table::Key< std::string > name
Definition: ApCorrMap.cc:71
void _finishWriteFits(fits::Fits &fitsfile, FitsWriteData const &data) const
Write any additional non-image HDUs to a FITS file.
boost::shared_ptr< daf::base::PropertyList > imageMetadata
Definition: ExposureInfo.h:229
Class for storing ordered metadata with comments.
Definition: PropertyList.h:81
Include files required for standard LSST Exception handling.
A thin wrapper around std::map to allow aperture corrections to be attached to Exposures.
Definition: ApCorrMap.h:42
static InputArchive readFits(fits::Fits &fitsfile)
Read an object from an already open FITS object.
static boost::shared_ptr< Wcs > _cloneWcs(boost::shared_ptr< Wcs const > wcs)
Definition: ExposureInfo.cc:60
#define PTR(...)
Definition: base.h:41
tbl::Key< int > wcs
bool hasValidPolygon() const
Does this exposure have a valid Polygon.
Definition: ExposureInfo.h:142
Implementation of the WCS standard for a any projection.
Definition: Wcs.h:107
bool hasCoaddInputs() const
Does this exposure have coadd provenance catalogs?
Definition: ExposureInfo.h:171
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:194
static Log & getDefaultLog()
boost::shared_ptr< cameraGeom::Detector const > getDetector() const
Return the exposure&#39;s Detector information.
Definition: ExposureInfo.h:99
static boost::shared_ptr< Calib > _cloneCalib(boost::shared_ptr< Calib const > calib)
Definition: ExposureInfo.cc:54
A simple Persistable struct containing ExposureCatalogs that record the inputs to a coadd...
Definition: CoaddInputs.h:46
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:58
boost::shared_ptr< daf::base::PropertySet > _metadata
Definition: ExposureInfo.h:282
ExposureInfo & operator=(ExposureInfo const &other)
Assignment; deep-copies all components except the metadata.
Wcs::Ptr makeWcs(boost::shared_ptr< lsst::daf::base::PropertySet > const &fitsMetadata, bool stripMetadata=false)
Definition: makeWcs.cc:40
boost::shared_ptr< geom::polygon::Polygon const > getValidPolygon() const
Return the valid Polygon.
Definition: ExposureInfo.h:145
A struct passed back and forth between Exposure and ExposureInfo when writing FITS files...
Definition: ExposureInfo.h:227
ExposureInfo(boost::shared_ptr< Wcs const > const &wcs=boost::shared_ptr< Wcs const >(), boost::shared_ptr< detection::Psf const > const &psf=boost::shared_ptr< detection::Psf const >(), boost::shared_ptr< Calib const > const &calib=boost::shared_ptr< Calib const >(), boost::shared_ptr< cameraGeom::Detector const > const &detector=boost::shared_ptr< cameraGeom::Detector const >(), boost::shared_ptr< geom::polygon::Polygon const > const &polygon=boost::shared_ptr< geom::polygon::Polygon const >(), Filter const &filter=Filter(), boost::shared_ptr< daf::base::PropertySet > const &metadata=boost::shared_ptr< daf::base::PropertySet >(), boost::shared_ptr< CoaddInputs > const &coaddInputs=boost::shared_ptr< CoaddInputs >(), boost::shared_ptr< ApCorrMap > const &apCorrMap=boost::shared_ptr< ApCorrMap >())
Construct an ExposureInfo from its various components.
Definition: ExposureInfo.cc:73
boost::shared_ptr< detection::Psf > _psf
Definition: ExposureInfo.h:277
boost::shared_ptr< Wcs > getWcs()
Return the coordinate system of the exposure.
Definition: ExposureInfo.h:87
void writeFits(fits::Fits &fitsfile) const
Write the archive to an already-open FITS object.
boost::shared_ptr< daf::base::PropertyList > maskMetadata
Definition: ExposureInfo.h:230
boost::shared_ptr< Wcs > _wcs
Definition: ExposureInfo.h:276
boost::shared_ptr< ApCorrMap > getApCorrMap()
Return the exposure&#39;s aperture correction map (null pointer if !hasApCorrMap())
Definition: ExposureInfo.h:154
Holds an integer identifier for an LSST filter.
Definition: Filter.h:107
void setHdu(int hdu, bool relative=false)
Set the current HDU.
int stripCalibKeywords(boost::shared_ptr< lsst::daf::base::PropertySet > metadata)
Definition: Calib.cc:159
boost::shared_ptr< cameraGeom::Detector const > _detector
Definition: ExposureInfo.h:279
static boost::shared_ptr< ApCorrMap > _cloneApCorrMap(boost::shared_ptr< ApCorrMap const > apCorrMap)
Definition: ExposureInfo.cc:66
Filter getFilter() const
Return the exposure&#39;s filter.
Definition: ExposureInfo.h:105
bool hasPsf() const
Does this exposure have a Psf?
Definition: ExposureInfo.h:129
void setCalib(boost::shared_ptr< Calib const > calib)
Set the Exposure&#39;s Calib object.
Definition: ExposureInfo.h:120
bool hasWcs() const
Does this exposure have a Wcs?
Definition: ExposureInfo.h:84
void _readFits(fits::Fits &fitsfile, boost::shared_ptr< daf::base::PropertySet > metadata, boost::shared_ptr< daf::base::PropertySet > imageMetadata)
Read from a FITS file and metadata.
Class for storing generic metadata.
Definition: PropertySet.h:82
void warn(const std::string &message, const lsst::daf::base::PropertySet &properties)
Definition: Log.h:494
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
boost::shared_ptr< daf::base::PropertySet > getMetadata() const
Return flexible metadata.
Definition: ExposureInfo.h:123
#define CONST_PTR(...)
Definition: base.h:47
boost::shared_ptr< Persistable > get(int id) const
Load the Persistable with the given ID and return it.
int stripFilterKeywords(boost::shared_ptr< lsst::daf::base::PropertySet > metadata)
Definition: Filter.cc:167
bool hasApCorrMap() const
Return true if the exposure has an aperture correction map.
Definition: ExposureInfo.h:151
boost::shared_ptr< Calib > _calib
Definition: ExposureInfo.h:278
boost::shared_ptr< CoaddInputs > getCoaddInputs() const
Return a pair of catalogs that record the inputs, if this Exposure is a coadd (otherwise null)...
Definition: ExposureInfo.h:177
A multi-catalog archive object used to load table::io::Persistable objects.
Definition: InputArchive.h:28
boost::shared_ptr< daf::base::PropertyList > metadata
Definition: ExposureInfo.h:228
A collection of all the things that make an Exposure different from a MaskedImage.
Definition: ExposureInfo.h:80
A polymorphic base class for representing an image&#39;s Point Spread Function.
Definition: Psf.h:68
boost::shared_ptr< daf::base::PropertyList > varianceMetadata
Definition: ExposureInfo.h:231
boost::shared_ptr< Calib > getCalib()
Return the exposure&#39;s photometric calibration.
Definition: ExposureInfo.h:114
daf::base::PropertySet & _metadata
Definition: fits_io_mpl.h:79
bool exists(std::string const &name) const
Definition: PropertySet.cc:190
bool hasDetector() const
Does this exposure have Detector information?
Definition: ExposureInfo.h:96
void info(const std::string &message, const lsst::daf::base::PropertySet &properties)
Definition: Log.h:493
FitsWriteData _startWriteFits(geom::Point2I const &xy0=geom::Point2I()) const
Start the process of writing an exposure to FITS.
boost::shared_ptr< geom::polygon::Polygon const > _validPolygon
Definition: ExposureInfo.h:280
boost::shared_ptr< CoaddInputs > _coaddInputs
Definition: ExposureInfo.h:283