LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
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"
29 #include "lsst/afw/detection/Psf.h"
31 #include "lsst/afw/fits.h"
32 
33 namespace lsst { namespace afw { namespace image {
34 
35 namespace {
36 
37 // Return an int value from a PropertySet if it exists and remove it, or return 0.
38 int popInt(daf::base::PropertySet & metadata, std::string const & name) {
39  int r = 0;
40  if (metadata.exists(name)) {
41  r = metadata.get<int>(name);
42  metadata.remove(name);
43  }
44  return r;
45 }
46 
47 } // anonymous
48 
49 
50 // Clone various components; defined here so that we don't have to expose their insides in Exposure.h
51 
52 PTR(Calib) ExposureInfo::_cloneCalib(CONST_PTR(Calib) calib) {
53  if (calib)
54  return PTR(Calib)(new Calib(*calib));
55  return PTR(Calib)();
56 }
57 
58 PTR(Wcs) ExposureInfo::_cloneWcs(CONST_PTR(Wcs) wcs) {
59  if (wcs)
60  return wcs->clone();
61  return PTR(Wcs)();
62 }
63 
65  CONST_PTR(Wcs) const & wcs,
66  CONST_PTR(detection::Psf) const & psf,
67  CONST_PTR(Calib) const & calib,
68  CONST_PTR(cameraGeom::Detector) const & detector,
69  Filter const & filter,
70  PTR(daf::base::PropertySet) const & metadata,
71  PTR(CoaddInputs) const & coaddInputs
72 ) : _wcs(_cloneWcs(wcs)),
73  _psf(boost::const_pointer_cast<detection::Psf>(psf)),
74  _calib(calib ? _cloneCalib(calib) : PTR(Calib)(new Calib())),
75  _detector(detector),
76  _filter(filter),
77  _metadata(metadata ? metadata : PTR(daf::base::PropertySet)(new daf::base::PropertyList())),
78  _coaddInputs(coaddInputs)
79 {}
80 
82  _wcs(_cloneWcs(other._wcs)),
83  _psf(other._psf),
84  _calib(_cloneCalib(other._calib)),
85  _detector(other._detector),
86  _filter(other._filter),
87  _metadata(other._metadata),
88  _coaddInputs(other._coaddInputs)
89 {}
90 
91 ExposureInfo::ExposureInfo(ExposureInfo const & other, bool copyMetadata) :
92  _wcs(_cloneWcs(other._wcs)),
93  _psf(other._psf),
94  _calib(_cloneCalib(other._calib)),
95  _detector(other._detector),
96  _filter(other._filter),
97  _metadata(other._metadata),
98  _coaddInputs(other._coaddInputs)
99 {
100  if (copyMetadata) _metadata = _metadata->deepCopy();
101 }
102 
104  if (&other != this) {
105  _wcs = _cloneWcs(other._wcs);
106  _psf = other._psf;
107  _calib = _cloneCalib(other._calib);
108  _detector = other._detector;
109  _filter = other._filter;
110  _metadata = other._metadata;
111  _coaddInputs = other._coaddInputs;
112  }
113  return *this;
114 }
115 
117 
120 
121  FitsWriteData data;
122 
123  data.metadata.reset(new daf::base::PropertyList());
124  data.imageMetadata.reset(new daf::base::PropertyList());
125  data.maskMetadata = data.imageMetadata;
126  data.varianceMetadata = data.imageMetadata;
127 
128  data.metadata->combine(getMetadata());
129 
130  // In the future, we might not have exactly three image HDUs, but we always do right now,
131  // so 1=primary, 2=image, 3=mask, 4=variance, 5+=archive
132  data.metadata->set("AR_HDU", 5, "HDU containing the archive used to store ancillary objects");
133  if (hasCoaddInputs()) {
134  int coaddInputsId = data.archive.put(getCoaddInputs());
135  data.metadata->set("COADD_INPUTS_ID", coaddInputsId, "archive ID for coadd inputs catalogs");
136  }
137  if (hasPsf() && getPsf()->isPersistable()) {
138  int psfId = data.archive.put(getPsf());
139  data.metadata->set("PSF_ID", psfId, "archive ID for the Exposure's main Psf");
140  }
141  if (hasWcs() && getWcs()->isPersistable()) {
142  int wcsId = data.archive.put(getWcs());
143  data.metadata->set("WCS_ID", wcsId, "archive ID for the Exposure's main Wcs");
144  }
145 
146  //LSST convention is that Wcs is in pixel coordinates (i.e relative to bottom left
147  //corner of parent image, if any). The Wcs/Fits convention is that the Wcs is in
148  //image coordinates. When saving an image we convert from pixel to index coordinates.
149  //In the case where this image is a parent image, the reference pixels are unchanged
150  //by this transformation
151  if (hasWcs()) {
152  PTR(Wcs) newWcs = getWcs()->clone(); //Create a copy
153  newWcs->shiftReferencePixel(-xy0.getX(), -xy0.getY() );
154 
155  // We want the WCS to appear in all HDUs
156  data.imageMetadata->combine(newWcs->getFitsMetadata());
157  }
158 
159  //Store _x0 and _y0. If this exposure is a portion of a larger image, _x0 and _y0
160  //indicate the origin (the position of the bottom left corner) of the sub-image with
161  //respect to the origin of the parent image.
162  //This is stored in the fits header using the LTV convention used by STScI
163  //(see \S2.6.2 of HST Data Handbook for STIS, version 5.0
164  // http://www.stsci.edu/hst/stis/documents/handbooks/currentDHB/ch2_stis_data7.html#429287).
165  //This is not a fits standard keyword, but is recognised by ds9
166  //LTV keywords use the opposite convention to the LSST, in that they represent
167  //the position of the origin of the parent image relative to the origin of the sub-image.
168  // _x0, _y0 >= 0, while LTV1 and LTV2 <= 0
169 
170  data.imageMetadata->set("LTV1", -xy0.getX());
171  data.imageMetadata->set("LTV2", -xy0.getY());
172 
173  data.metadata->set("FILTER", getFilter().getName());
174  if (hasDetector()) {
175  data.metadata->set("DETNAME", getDetector()->getName());
176  data.metadata->set("DETSER", getDetector()->getSerial());
177  }
181  data.metadata->set("TIME-MID", getCalib()->getMidTime().toString());
182  data.metadata->set("EXPTIME", getCalib()->getExptime());
183  data.metadata->set("FLUXMAG0", getCalib()->getFluxMag0().first);
184  data.metadata->set("FLUXMAG0ERR", getCalib()->getFluxMag0().second);
185 
186  return data;
187 }
188 
189 void ExposureInfo::_finishWriteFits(fits::Fits & fitsfile, FitsWriteData const & data) const {
190  data.archive.writeFits(fitsfile);
191 }
192 
194  fits::Fits & fitsfile,
195  PTR(daf::base::PropertySet) metadata,
196  PTR(daf::base::PropertySet) imageMetadata
197 ) {
198  // true: strip keywords that are related to the created WCS from the input metadata
199  _wcs = makeWcs(imageMetadata, true);
200 
201  if (!imageMetadata->exists("INHERIT")) {
202  // New-style exposures put everything but the Wcs in the primary HDU, use
203  // INHERIT keyword in the others. For backwards compatibility, if we don't
204  // find the INHERIT keyword, we ignore the primary HDU metadata and expect
205  // everything to be in the image HDU metadata. Note that we can't merge them,
206  // because they're probably duplicates.
207  metadata = imageMetadata;
208  }
209 
210  _filter = Filter(metadata, true);
211  detail::stripFilterKeywords(metadata);
212 
213  PTR(Calib) newCalib(new Calib(metadata));
214  setCalib(newCalib);
215  detail::stripCalibKeywords(metadata);
216 
217  int archiveHdu = popInt(*metadata, "AR_HDU");
218 
219  if (archiveHdu) {
220  fitsfile.setHdu(archiveHdu);
222  // Load the Psf and Wcs from the archive; id=0 results in a null pointer.
223  // Note that the binary table Wcs, if present, clobbers the FITS header one,
224  // because the former might be an approximation to something we can't represent
225  // using the FITS WCS standard but can represent with binary tables.
226  int psfId = popInt(*metadata, "PSF_ID");
227  try {
228  _psf = archive.get<detection::Psf>(psfId);
229  } catch (pex::exceptions::NotFoundError & err) {
231  boost::format("Could not read PSF; setting to null: %s") % err.what()
232  );
233  }
234  int wcsId = popInt(*metadata, "WCS_ID");
235  try {
236  _wcs = archive.get<Wcs>(wcsId);
237  } catch (pex::exceptions::NotFoundError & err) {
239  boost::format("Could not read WCS; setting to null: %s") % err.what()
240  );
241  }
242  int coaddInputsId = popInt(*metadata, "COADD_INPUTS_ID");
243  try {
244  _coaddInputs = archive.get<CoaddInputs>(coaddInputsId);
245  } catch (pex::exceptions::NotFoundError & err) {
247  boost::format("Could not read CoaddInputs; setting to null: %s") % err.what()
248  );
249  }
250  }
251 
252  _metadata = metadata;
253 }
254 
255 }}} // namespace lsst::afw::image
boost::shared_ptr< detection::Psf > getPsf() const
Return the exposure&#39;s point-spread function.
Definition: ExposureInfo.h:127
#define PTR(...)
Definition: base.h:41
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:193
Class for storing ordered metadata with comments.
Definition: PropertyList.h:81
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:58
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:137
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:94
static boost::shared_ptr< Calib > _cloneCalib(boost::shared_ptr< Calib const > calib)
Definition: ExposureInfo.cc:52
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
definition of the DualLog class
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:57
boost::shared_ptr< daf::base::PropertySet > _metadata
Definition: ExposureInfo.h:244
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:39
Include files required for standard LSST Exception handling.
A struct passed back and forth between Exposure and ExposureInfo when writing FITS files...
Definition: ExposureInfo.h:191
boost::shared_ptr< detection::Psf > _psf
Definition: ExposureInfo.h:240
boost::shared_ptr< Wcs > getWcs()
Return the coordinate system of the exposure.
Definition: ExposureInfo.h:82
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:194
boost::shared_ptr< Wcs > _wcs
Definition: ExposureInfo.h:239
#define CONST_PTR(...)
Definition: base.h:47
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:242
Filter getFilter() const
Return the exposure&#39;s filter.
Definition: ExposureInfo.h:100
bool hasPsf() const
Does this exposure have a Psf?
Definition: ExposureInfo.h:124
void setCalib(boost::shared_ptr< Calib const > calib)
Set the Exposure&#39;s Calib object.
Definition: ExposureInfo.h:115
bool hasWcs() const
Does this exposure have a Wcs?
Definition: ExposureInfo.h:79
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.
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 >(), 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 >())
Construct an ExposureInfo from its various components.
Definition: ExposureInfo.cc:64
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:118
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
boost::shared_ptr< Calib > _calib
Definition: ExposureInfo.h:241
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:143
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:192
A collection of all the things that make an Exposure different from a MaskedImage.
Definition: ExposureInfo.h:75
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:195
boost::shared_ptr< Calib > getCalib()
Return the exposure&#39;s photometric calibration.
Definition: ExposureInfo.h:109
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:91
FitsWriteData _startWriteFits(geom::Point2I const &xy0=geom::Point2I()) const
Start the process of writing an exposure to FITS.
boost::shared_ptr< CoaddInputs > _coaddInputs
Definition: ExposureInfo.h:245