LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
MaskedImageFitsReader.cc
Go to the documentation of this file.
1 /*
2  * Developed for the LSST Data Management System.
3  * This product includes software developed by the LSST Project
4  * (https://www.lsst.org).
5  * See the COPYRIGHT file at the top-level directory of this distribution
6  * for details of code ownership.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "lsst/log/Log.h"
23 #include "boost/algorithm/string/trim.hpp"
24 
26 
27 namespace lsst { namespace afw { namespace image {
28 
29 namespace {
30 
31 fits::Fits * nextHdu(fits::Fits * fitsFile) {
32  if (fitsFile == nullptr) {
33  return nullptr;
34  }
35  try {
36  fitsFile->setHdu(1, true);
37  } catch (fits::FitsError &) {
38  fitsFile->status = 0;
39  return nullptr;
40  }
41  return fitsFile;
42 }
43 
44 } // anonymous
45 
47  _imageReader(fileName, hdu),
48  _maskReader(nextHdu(_imageReader._fitsFile)),
49  _varianceReader(nextHdu(_maskReader._fitsFile))
50 {}
51 
53  _imageReader(manager, hdu),
54  _maskReader(nextHdu(_imageReader._fitsFile)),
55  _varianceReader(nextHdu(_maskReader._fitsFile))
56 {}
57 
59  _imageReader(fitsFile),
60  _maskReader(nextHdu(_imageReader._fitsFile)),
61  _varianceReader(nextHdu(_maskReader._fitsFile))
62 {}
63 
65 
67 
69 
70 std::string MaskedImageFitsReader::readVarianceDType() const { return _varianceReader.readDType(); }
71 
73  return _imageReader.readBBox(origin);
74 }
75 
77  return _imageReader.readXY0(bbox, origin);
78 }
79 
80 namespace {
81 
82 void checkExtType(ImageBaseFitsReader const & reader, std::shared_ptr<daf::base::PropertyList> metadata,
83  std::string const& expected) {
84  try {
85  std::string exttype = boost::algorithm::trim_right_copy(metadata->getAsString("EXTTYPE"));
86  if (exttype != "" && exttype != expected) {
88  str(boost::format("Reading %s (hdu %d) Expected EXTTYPE==\"%s\", saw \"%s\"") %
89  reader.getFileName() % reader.getHdu() % expected % exttype));
90  }
91  metadata->remove("EXTTYPE");
92  } catch (pex::exceptions::NotFoundError const&) {
93  LOGL_WARN("afw.image.MaskedImageFitsReader", "Expected extension type not found: %s",
94  expected.c_str());
95  }
96 }
97 
98 } // anonymous
99 
101  auto fitsFile = _imageReader._fitsFile;
102  fits::HduMoveGuard guard(*fitsFile, 0);
103  return fits::readMetadata(*fitsFile, /*strip=*/true);
104 }
105 
107  if (!_imageMetadata) {
108  _imageMetadata = _imageReader.readMetadata();
109  checkExtType(_imageReader, _imageMetadata, "IMAGE");
110  }
111  return _imageMetadata;
112 }
113 
115  if (!_maskMetadata) {
116  _maskReader.readMetadata();
117  checkExtType(_maskReader, _maskMetadata, "MASK");
118  }
119  return _maskMetadata;
120 }
121 
123  if (!_varianceMetadata) {
124  _varianceReader.readMetadata();
125  checkExtType(_varianceReader, _varianceMetadata, "VARIANCE");
126  }
127  return _varianceMetadata;
128 }
129 
130 template <typename ImagePixelT>
132  bool allowUnsafe) {
133  return _imageReader.read<ImagePixelT>(bbox, origin, allowUnsafe);
134 }
135 
136 template <typename ImagePixelT>
137 ndarray::Array<ImagePixelT, 2, 2> MaskedImageFitsReader::readImageArray(lsst::geom::Box2I const & bbox,
138  ImageOrigin origin,
139  bool allowUnsafe) {
140  return _imageReader.readArray<ImagePixelT>(bbox, origin, allowUnsafe);
141 }
142 
143 template <typename MaskPixelT>
145  bool conformMasks, bool allowUnsafe) {
146  return _maskReader.read<MaskPixelT>(bbox, origin, conformMasks, allowUnsafe);
147 }
148 
149 template <typename MaskPixelT>
150 ndarray::Array<MaskPixelT, 2, 2> MaskedImageFitsReader::readMaskArray(lsst::geom::Box2I const & bbox,
151  ImageOrigin origin,
152  bool allowUnsafe) {
153  return _maskReader.readArray<MaskPixelT>(bbox, origin, allowUnsafe);
154 }
155 
156 template <typename VariancePixelT>
158  ImageOrigin origin, bool allowUnsafe) {
159  return _varianceReader.read<VariancePixelT>(bbox, origin, allowUnsafe);
160 }
161 
162 template <typename VariancePixelT>
163 ndarray::Array<VariancePixelT, 2, 2> MaskedImageFitsReader::readVarianceArray(lsst::geom::Box2I const & bbox,
164  ImageOrigin origin,
165  bool allowUnsafe) {
166  return _varianceReader.readArray<VariancePixelT>(bbox, origin, allowUnsafe);
167 }
168 
169 template <typename ImagePixelT, typename MaskPixelT, typename VariancePixelT>
171  lsst::geom::Box2I const & bbox, ImageOrigin origin,
172  bool conformMasks, bool needAllHdus, bool allowUnsafe
173 ) {
174  // When reading a standard Masked Image, we expect four HDUs:
175  // * The primary (HDU 0) is empty;
176  // * The first extension (HDU 1) contains the image data;
177  // * The second extension (HDU 2) contains mask data;
178  // * The third extension (HDU 3) contains the variance.
179  //
180  // If the image HDU is unreadable, we will throw.
181  //
182  // If the user has specified a non-default HDU, we load image data from
183  // that HDU, but do not attempt to load mask/variance data; rather, log a
184  // warning and return (blank) defaults.
185  //
186  // If the mask and/or variance is unreadable, we log a warning and return
187  // (blank) defaults.
188 
189  LOG_LOGGER _log = LOG_GET("afw.image.MaskedImageFitsReader");
190 
191  enum class Hdu { Primary = 0, Image, Mask, Variance };
192 
193  // If the user has requested a non-default HDU and we require all HDUs, we fail.
194  if (needAllHdus && _imageReader.getHdu() > static_cast<int>(Hdu::Image)) {
195  throw LSST_EXCEPT(fits::FitsError, "Cannot read all HDUs starting from non-default");
196  }
197 
198  auto image = std::make_shared<Image<ImagePixelT>>(_imageReader.read<ImagePixelT>(bbox, origin,
199  allowUnsafe));
202 
203  // only read other planes if they're in their normal HDUs
204  if (_imageReader.getHdu() == static_cast<int>(Hdu::Image)) {
205  try {
206  mask = std::make_shared<Mask<MaskPixelT>>(
207  _maskReader.read<MaskPixelT>(bbox, origin, conformMasks, allowUnsafe)
208  );
209  } catch (fits::FitsError& e) {
210  if (needAllHdus) {
211  LSST_EXCEPT_ADD(e, "Reading Mask");
212  throw e;
213  }
214  LOGL_WARN(_log, "Mask unreadable (%s); using default", e.what());
215  // By resetting the status we are able to read the next HDU (the variance).
216  _maskReader._fitsFile->status = 0;
217  }
218  try {
219  variance = std::make_shared<Image<VariancePixelT>>(
220  _varianceReader.read<VariancePixelT>(bbox, origin, allowUnsafe)
221  );
222  } catch (fits::FitsError& e) {
223  if (needAllHdus) {
224  LSST_EXCEPT_ADD(e, "Reading Variance");
225  throw e;
226  }
227  LOGL_WARN(_log, "Variance unreadable (%s); using default", e.what());
228  // By resetting the status we are able to read the next HDU (the variance).
229  _varianceReader._fitsFile->status = 0;
230  }
231  }
233 }
234 
235 #define INSTANTIATE(ImagePixelT) \
236  template MaskedImage<ImagePixelT, MaskPixel, VariancePixel> MaskedImageFitsReader::read( \
237  lsst::geom::Box2I const &, \
238  ImageOrigin, \
239  bool, bool, bool \
240  ); \
241  template Image<ImagePixelT> MaskedImageFitsReader::readImage(\
242  lsst::geom::Box2I const &, \
243  ImageOrigin, \
244  bool \
245  ); \
246  template ndarray::Array<ImagePixelT, 2, 2> MaskedImageFitsReader::readImageArray(\
247  lsst::geom::Box2I const &, \
248  ImageOrigin, \
249  bool \
250  )
251 
253 INSTANTIATE(int);
254 INSTANTIATE(float);
255 INSTANTIATE(double);
257 
258 template Mask<MaskPixel> MaskedImageFitsReader::readMask(
259  lsst::geom::Box2I const &,
260  ImageOrigin,
261  bool,
262  bool
263 );
264 template ndarray::Array<MaskPixel, 2, 2> MaskedImageFitsReader::readMaskArray(
265  lsst::geom::Box2I const &,
266  ImageOrigin,
267  bool
268 );
269 
270 template Image<VariancePixel> MaskedImageFitsReader::readVariance(
271  lsst::geom::Box2I const &,
272  ImageOrigin,
273  bool
274 );
275 template ndarray::Array<VariancePixel, 2, 2> MaskedImageFitsReader::readVarianceArray(
276  lsst::geom::Box2I const &,
277  ImageOrigin,
278  bool
279 );
280 
281 }}} // lsst::afw::image
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
Mask< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool conformMasks=false, bool allowUnsafe=false)
Read the Mask.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
std::shared_ptr< daf::base::PropertyList > readVarianceMetadata()
Read the FITS header of one of the HDUs.
MaskedImageFitsReader(std::string const &fileName, int hdu=fits::DEFAULT_HDU)
Construct a FITS reader object.
afw::table::Key< afw::table::Array< VariancePixelT > > variance
std::shared_ptr< daf::base::PropertyList > readMetadata()
Read the image&#39;s FITS header.
#define LOG_LOGGER
Definition: Log.h:703
afw::table::Key< afw::table::Array< ImagePixelT > > image
afw::table::Key< afw::table::Array< MaskPixelT > > mask
lsst::geom::Box2I readBBox(ImageOrigin origin=PARENT)
Read the bounding box of the on-disk image.
lsst::geom::Box2I readBBox(ImageOrigin origin=PARENT)
Read the bounding box of the on-disk image.
std::string readVarianceDType() const
Read a string describing the pixel type of the on-disk image plane.
std::string getFileName() const
Return the name of the file this reader targets.
ndarray::Array< MaskPixelT, 2, 2 > readMaskArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the mask plane.
#define INSTANTIATE(ImagePixelT)
Image< VariancePixelT > readVariance(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the variance plane.
std::shared_ptr< daf::base::PropertyList > readMaskMetadata()
Read the FITS header of one of the HDUs.
std::string readDType() const
Read a string describing the pixel type of the on-disk image.
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:297
Image< ImagePixelT > readImage(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image plane.
STL class.
LSST DM logging module built on log4cxx.
An exception thrown when problems are found when reading or writing FITS files.
Definition: fits.h:36
lsst::geom::Point2I readXY0(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT)
Read the image origin from the on-disk image or a subimage thereof.
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
virtual char const * what(void) const noexcept
Return a character string summarizing this exception.
Definition: Exception.cc:99
A base class for image defects.
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
Lifetime-management for memory that goes into FITS memory files.
Definition: fits.h:121
std::string readImageDType() const
Read a string describing the pixel type of the on-disk image plane.
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:73
std::shared_ptr< daf::base::PropertyList > readPrimaryMetadata()
Read the FITS header of one of the HDUs.
int getHdu() const noexcept
Return the HDU this reader targets.
#define LOGL_WARN(logger, message...)
Log a warn-level message using a varargs/printf style interface.
Definition: Log.h:536
Image< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the Image.
Mask< MaskPixelT > readMask(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool conformMasks=false, bool allowUnsafe=false)
Read the mask plane.
ndarray::Array< VariancePixelT, 2, 2 > readVarianceArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the variance plane.
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool conformMasks=false, bool needAllHdus=false, bool allowUnsafe=false)
Read the full MaskedImage.
std::string readMaskDType() const
Read a string describing the pixel type of the on-disk image plane.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T c_str(T... args)
Reports invalid arguments.
Definition: Runtime.h:66
std::shared_ptr< daf::base::PropertyList > readImageMetadata()
Read the FITS header of one of the HDUs.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
#define LOG_GET(logger)
Returns a Log object associated with logger.
Definition: Log.h:75
Base class for image FITS readers.
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it...
Definition: Exception.h:54
An integer coordinate rectangle.
Definition: Box.h:55
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:58
ndarray::Array< ImagePixelT, 2, 2 > readImageArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image plane.
RAII scoped guard for moving the HDU in a Fits object.
Definition: fits.h:724
lsst::geom::Point2I readXY0(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT)
Read the image origin from the on-disk image or a subimage thereof.
ndarray::Array< T, 2, 2 > readArray(lsst::geom::Box2I const &bbox, ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image&#39;s data array.
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
Definition: fits.cc:1640