LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
27namespace lsst { namespace afw { namespace image {
28
29namespace {
30
31fits::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
66std::string MaskedImageFitsReader::readImageDType() const { return _imageReader.readDType(); }
67
69
71
73 return _imageReader.readBBox(origin);
74}
75
79
80namespace {
81
82void 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("lsst.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
130template <typename ImagePixelT>
132 bool allowUnsafe) {
133 return _imageReader.read<ImagePixelT>(bbox, origin, allowUnsafe);
134}
135
136template <typename ImagePixelT>
137ndarray::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
143template <typename MaskPixelT>
145 bool conformMasks, bool allowUnsafe) {
146 return _maskReader.read<MaskPixelT>(bbox, origin, conformMasks, allowUnsafe);
147}
148
149template <typename MaskPixelT>
150ndarray::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
156template <typename VariancePixelT>
158 ImageOrigin origin, bool allowUnsafe) {
159 return _varianceReader.read<VariancePixelT>(bbox, origin, allowUnsafe);
160}
161
162template <typename VariancePixelT>
163ndarray::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
169template <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("lsst.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 // Do not even try if we are missing the HDU
206 if (_maskReader._fitsFile) {
207 try {
208 mask = std::make_shared<Mask<MaskPixelT>>(
209 _maskReader.read<MaskPixelT>(bbox, origin, conformMasks, allowUnsafe)
210 );
211 } catch (fits::FitsError& e) {
212 if (needAllHdus) {
213 LSST_EXCEPT_ADD(e, "Reading Mask");
214 throw e;
215 }
216 LOGL_WARN(_log, "Mask unreadable (%s); using default", e.what());
217 // By resetting the status we are able to read the next HDU (the variance).
218 _maskReader._fitsFile->status = 0;
219 }
220 } else if (needAllHdus) {
221 throw LSST_EXCEPT(pex::exceptions::NotFoundError, "No mask extensions found");
222 }
223 if (_varianceReader._fitsFile) {
224 try {
225 variance = std::make_shared<Image<VariancePixelT>>(
226 _varianceReader.read<VariancePixelT>(bbox, origin, allowUnsafe)
227 );
228 } catch (fits::FitsError& e) {
229 if (needAllHdus) {
230 LSST_EXCEPT_ADD(e, "Reading Variance");
231 throw e;
232 }
233 LOGL_WARN(_log, "Variance unreadable (%s); using default", e.what());
234 // By resetting the status we are able to read the next HDU (the variance).
235 _varianceReader._fitsFile->status = 0;
236 }
237 } else if (needAllHdus) {
238 throw LSST_EXCEPT(pex::exceptions::NotFoundError, "No variance extensions found");
239 }
240 }
242}
243
244#define INSTANTIATE(ImagePixelT) \
245 template MaskedImage<ImagePixelT, MaskPixel, VariancePixel> MaskedImageFitsReader::read( \
246 lsst::geom::Box2I const &, \
247 ImageOrigin, \
248 bool, bool, bool \
249 ); \
250 template Image<ImagePixelT> MaskedImageFitsReader::readImage(\
251 lsst::geom::Box2I const &, \
252 ImageOrigin, \
253 bool \
254 ); \
255 template ndarray::Array<ImagePixelT, 2, 2> MaskedImageFitsReader::readImageArray(\
256 lsst::geom::Box2I const &, \
257 ImageOrigin, \
258 bool \
259 )
260
262INSTANTIATE(int);
263INSTANTIATE(float);
264INSTANTIATE(double);
266
268 lsst::geom::Box2I const &,
269 ImageOrigin,
270 bool,
271 bool
272);
273template ndarray::Array<MaskPixel, 2, 2> MaskedImageFitsReader::readMaskArray(
274 lsst::geom::Box2I const &,
275 ImageOrigin,
276 bool
277);
278
280 lsst::geom::Box2I const &,
281 ImageOrigin,
282 bool
283);
284template ndarray::Array<VariancePixel, 2, 2> MaskedImageFitsReader::readVarianceArray(
285 lsst::geom::Box2I const &,
286 ImageOrigin,
287 bool
288);
289
290}}} // lsst::afw::image
AmpInfoBoxKey bbox
Definition Amplifier.cc:117
#define INSTANTIATE(FROMSYS, TOSYS)
Definition Detector.cc:509
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it.
Definition Exception.h:54
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
afw::table::Key< afw::table::Array< MaskPixelT > > mask
afw::table::Key< afw::table::Array< VariancePixelT > > variance
LSST DM logging module built on log4cxx.
#define LOGL_WARN(logger, message...)
Log a warn-level message using a varargs/printf style interface.
Definition Log.h:547
#define LOG_GET(logger)
Returns a Log object associated with logger.
Definition Log.h:75
#define LOG_LOGGER
Definition Log.h:714
T c_str(T... args)
An exception thrown when problems are found when reading or writing FITS files.
Definition fits.h:36
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:308
RAII scoped guard for moving the HDU in a Fits object.
Definition fits.h:782
Lifetime-management for memory that goes into FITS memory files.
Definition fits.h:125
Base class for image FITS readers.
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.
std::shared_ptr< daf::base::PropertyList > readMetadata()
Read the image's FITS header.
ndarray::Array< T, 2, 2 > readArray(lsst::geom::Box2I const &bbox, ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image's data array.
std::string getFileName() const
Return the name of the file this reader targets.
int getHdu() const noexcept
Return the HDU this reader targets.
lsst::geom::Box2I readBBox(ImageOrigin origin=PARENT)
Read the bounding box of the on-disk image.
std::string readDType() const
Read a string describing the pixel type of the on-disk image.
Image< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the Image.
A class to represent a 2-dimensional array of pixels.
Definition Image.h:51
Mask< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool conformMasks=false, bool allowUnsafe=false)
Read the Mask.
Represent a 2-dimensional array of bitmask pixels.
Definition Mask.h:81
A FITS reader class for MaskedImages and their components.
std::string readMaskDType() const
Read a string describing the pixel type of the on-disk image plane.
std::shared_ptr< daf::base::PropertyList > readImageMetadata()
Read the FITS header of one of the HDUs.
std::shared_ptr< daf::base::PropertyList > readPrimaryMetadata()
Read the FITS header of one of the HDUs.
std::string readVarianceDType() const
Read a string describing the pixel type of the on-disk image plane.
ndarray::Array< MaskPixelT, 2, 2 > readMaskArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the mask plane.
MaskedImageFitsReader(std::string const &fileName, int hdu=fits::DEFAULT_HDU)
Construct a FITS reader object.
std::shared_ptr< daf::base::PropertyList > readMaskMetadata()
Read the FITS header of one of the HDUs.
ndarray::Array< ImagePixelT, 2, 2 > readImageArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image plane.
std::shared_ptr< daf::base::PropertyList > readVarianceMetadata()
Read the FITS header of one of the HDUs.
ndarray::Array< VariancePixelT, 2, 2 > readVarianceArray(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the variance plane.
Mask< MaskPixelT > readMask(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool conformMasks=false, bool allowUnsafe=false)
Read the mask plane.
lsst::geom::Box2I readBBox(ImageOrigin origin=PARENT)
Read the bounding box of the on-disk image.
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.
Image< ImagePixelT > readImage(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the image plane.
Image< VariancePixelT > readVariance(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the variance plane.
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.
A class to manipulate images, masks, and variance as a single object.
Definition MaskedImage.h:74
An integer coordinate rectangle.
Definition Box.h:55
virtual char const * what(void) const noexcept
Return a character string summarizing this exception.
Definition Exception.cc:99
Reports invalid arguments.
Definition Runtime.h:66
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
Definition fits.cc:1696
STL namespace.
g2d::python::Image< double > Image
Definition test_image.cc:14
py::scoped_interpreter guard
Definition test_image.cc:19
g2d::python::Image< bool > Mask
Definition test_image.cc:16