LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
_readers.cc
Go to the documentation of this file.
1/*
2 * This file is part of afw.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (https://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include "pybind11/pybind11.h"
25#include "pybind11/stl.h"
26#include "lsst/utils/python.h"
27
28#include "ndarray/pybind11.h"
29
45
46namespace py = pybind11;
47using namespace pybind11::literals;
48
49namespace lsst {
50namespace afw {
51namespace image {
52namespace {
53
54// ImageBaseFitsReader is an implementation detail and is not exposed directly
55// to Python, as we have better ways to share wrapper code between classes
56// at the pybind11 level (e.g. declareCommon below).
57using PyImageFitsReader = py::class_<ImageFitsReader, std::shared_ptr<ImageFitsReader>>;
58using PyMaskFitsReader = py::class_<MaskFitsReader, std::shared_ptr<MaskFitsReader>>;
59using PyMaskedImageFitsReader = py::class_<MaskedImageFitsReader, std::shared_ptr<MaskedImageFitsReader>>;
60using PyExposureFitsReader = py::class_<ExposureFitsReader, std::shared_ptr<ExposureFitsReader>>;
61
62// Declare attributes common to all FitsReaders. Excludes constructors
63// because ExposureFitsReader's don't take an HDU argument.
64template <typename Class, typename... Args>
65void declareCommonMethods(py::class_<Class, Args...> &cls) {
66 cls.def("readBBox", &Class::readBBox, "origin"_a = PARENT);
67 cls.def("readXY0", &Class::readXY0, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT);
68 cls.def("getFileName", &Class::getFileName);
69 cls.def_property_readonly("fileName", &Class::getFileName);
70}
71
72// Declare attributes common to ImageFitsReader and MaskFitsReader
73template <typename Class, typename... Args>
74void declareSinglePlaneMethods(py::class_<Class, Args...> &cls) {
75 cls.def(py::init<std::string const &, int>(), "fileName"_a, "hdu"_a = fits::DEFAULT_HDU);
76 cls.def(py::init<fits::MemFileManager &, int>(), "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
77 cls.def("readMetadata", &Class::readMetadata);
78 cls.def("readDType", [](Class &self) { return py::dtype(self.readDType()); });
79 cls.def("getHdu", &Class::getHdu);
80 cls.def_property_readonly("hdu", &Class::getHdu);
81 cls.def(
82 "readArray",
83 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
84 py::object dtype) {
85 if (dtype.is(py::none())) {
86 dtype = py::dtype(self.readDType());
87 }
88 return utils::python::TemplateInvoker().apply(
89 [&](auto t) {
90 return self.template readArray<decltype(t)>(bbox, origin, allowUnsafe);
91 },
93 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
94 std::uint64_t>());
95 },
96 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
97 "dtype"_a = py::none());
98}
99
100// Declare attributes shared by MaskedImageFitsReader and MaskedImageFitsReader.
101template <typename Class, typename... Args>
102void declareMultiPlaneMethods(py::class_<Class, Args...> &cls) {
103 cls.def("readImageDType", [](Class &self) { return py::dtype(self.readImageDType()); });
104 cls.def("readMaskDType", [](Class &self) { return py::dtype(self.readMaskDType()); });
105 cls.def("readVarianceDType", [](Class &self) { return py::dtype(self.readVarianceDType()); });
106 cls.def(
107 "readImage",
108 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
109 py::object dtype) {
110 if (dtype.is(py::none())) {
111 dtype = py::dtype(self.readImageDType());
112 }
113 return utils::python::TemplateInvoker().apply(
114 [&](auto t) {
115 return self.template readImage<decltype(t)>(bbox, origin, allowUnsafe);
116 },
118 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
119 std::uint64_t>());
120 },
121 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
122 "dtype"_a = py::none());
123 cls.def(
124 "readImageArray",
125 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
126 py::object dtype) {
127 if (dtype.is(py::none())) {
128 dtype = py::dtype(self.readImageDType());
129 }
130 return utils::python::TemplateInvoker().apply(
131 [&](auto t) {
132 return self.template readImageArray<decltype(t)>(bbox, origin, allowUnsafe);
133 },
135 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
136 std::uint64_t>());
137 },
138 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
139 "dtype"_a = py::none());
140 cls.def(
141 "readMask",
142 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool conformMasks,
143 bool allowUnsafe, py::object dtype) {
144 if (dtype.is(py::none())) {
145 dtype = py::dtype(self.readMaskDType());
146 }
147 return utils::python::TemplateInvoker().apply(
148 [&](auto t) {
149 return self.template readMask<decltype(t)>(bbox, origin, conformMasks,
150 allowUnsafe);
151 },
152 py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
153 },
154 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
155 "allowUnsafe"_a = false, "dtype"_a = py::none());
156 cls.def(
157 "readMaskArray",
158 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
159 py::object dtype) {
160 if (dtype.is(py::none())) {
161 dtype = py::dtype(self.readMaskDType());
162 }
163 return utils::python::TemplateInvoker().apply(
164 [&](auto t) {
165 return self.template readMaskArray<decltype(t)>(bbox, origin, allowUnsafe);
166 },
167 py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
168 },
169 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
170 "dtype"_a = py::none());
171 cls.def(
172 "readVariance",
173 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
174 py::object dtype) {
175 if (dtype.is(py::none())) {
176 dtype = py::dtype(self.readVarianceDType());
177 }
178 return utils::python::TemplateInvoker().apply(
179 [&](auto t) {
180 return self.template readVariance<decltype(t)>(bbox, origin, allowUnsafe);
181 },
182 py::dtype(dtype), utils::python::TemplateInvoker::Tag<VariancePixel>());
183 },
184 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
185 "dtype"_a = py::none());
186 cls.def(
187 "readVarianceArray",
188 [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
189 py::object dtype) {
190 if (dtype.is(py::none())) {
191 dtype = py::dtype(self.readVarianceDType());
192 }
193 return utils::python::TemplateInvoker().apply(
194 [&](auto t) {
195 return self.template readVarianceArray<decltype(t)>(bbox, origin, allowUnsafe);
196 },
197 py::dtype(dtype), utils::python::TemplateInvoker::Tag<VariancePixel>());
198 },
199 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
200 "dtype"_a = py::none());
201}
202
203void declareImageFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
204 wrappers.wrapType(PyImageFitsReader(wrappers.module, "ImageFitsReader"), [](auto &mod, auto &cls) {
205 declareCommonMethods(cls);
206 declareSinglePlaneMethods(cls);
207 cls.def(
208 "read",
209 [](ImageFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
210 py::object dtype) {
211 if (dtype.is(py::none())) {
212 dtype = py::dtype(self.readDType());
213 }
214 return utils::python::TemplateInvoker().apply(
215 [&](auto t) { return self.read<decltype(t)>(bbox, origin, allowUnsafe); },
216 py::dtype(dtype),
217 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
218 std::uint64_t>());
219 },
220 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
221 "dtype"_a = py::none());
222 });
223}
224
225void declareMaskFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
226 wrappers.wrapType(PyMaskFitsReader(wrappers.module, "MaskFitsReader"), [](auto &mod, auto &cls) {
227 declareCommonMethods(cls);
228 declareSinglePlaneMethods(cls);
229 cls.def(
230 "read",
231 [](MaskFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool conformMasks,
232 bool allowUnsafe, py::object dtype) {
233 if (dtype.is(py::none())) {
234 dtype = py::dtype(self.readDType());
235 }
236 return utils::python::TemplateInvoker().apply(
237 [&](auto t) {
238 return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
239 },
240 py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
241 },
242 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
243 "allowUnsafe"_a = false, "dtype"_a = py::none());
244 });
245 // all other methods provided by base class wrappers
246}
247
248void declareMaskedImageFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
249 wrappers.wrapType(PyMaskedImageFitsReader(wrappers.module, "MaskedImageFitsReader"), [](auto &mod,
250 auto &cls) {
251 cls.def(py::init<std::string const &, int>(), "fileName"_a, "hdu"_a = fits::DEFAULT_HDU);
252 cls.def(py::init<fits::MemFileManager &, int>(), "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
253 declareCommonMethods(cls);
254 declareMultiPlaneMethods(cls);
255 cls.def("readPrimaryMetadata", &MaskedImageFitsReader::readPrimaryMetadata);
256 cls.def("readImageMetadata", &MaskedImageFitsReader::readImageMetadata);
257 cls.def("readMaskMetadata", &MaskedImageFitsReader::readMaskMetadata);
258 cls.def("readVarianceMetadata", &MaskedImageFitsReader::readVarianceMetadata);
259 cls.def(
260 "read",
261 [](MaskedImageFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
262 bool conformMasks, bool needAllHdus, bool allowUnsafe, py::object dtype) {
263 if (dtype.is(py::none())) {
264 dtype = py::dtype(self.readImageDType());
265 }
266 return utils::python::TemplateInvoker().apply(
267 [&](auto t) {
268 return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
269 },
270 py::dtype(dtype),
271 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
272 std::uint64_t>());
273 },
274 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
275 "needAllHdus"_a = false, "allowUnsafe"_a = false, "dtype"_a = py::none());
276 });
277}
278
279void declareExposureFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
280 wrappers.wrapType(PyExposureFitsReader(wrappers.module, "ExposureFitsReader"), [](auto &mod, auto &cls) {
281 cls.def(py::init<std::string const &>(), "fileName"_a);
282 cls.def(py::init<fits::MemFileManager &>(), "manager"_a);
283 declareCommonMethods(cls);
284 declareMultiPlaneMethods(cls);
285 cls.def("readSerializationVersion", &ExposureFitsReader::readSerializationVersion);
286 cls.def("readExposureId", &ExposureFitsReader::readExposureId);
287 cls.def("readMetadata", &ExposureFitsReader::readMetadata);
288 cls.def("readWcs", &ExposureFitsReader::readWcs);
289 cls.def("readFilterLabel", &ExposureFitsReader::readFilterLabel);
290 cls.def("readFilter", &ExposureFitsReader::readFilter);
291 cls.def("readPhotoCalib", &ExposureFitsReader::readPhotoCalib);
292 cls.def("readPsf", &ExposureFitsReader::readPsf);
293 cls.def("readValidPolygon", &ExposureFitsReader::readValidPolygon);
294 cls.def("readApCorrMap", &ExposureFitsReader::readApCorrMap);
295 cls.def("readCoaddInputs", &ExposureFitsReader::readCoaddInputs);
296 cls.def("readVisitInfo", &ExposureFitsReader::readVisitInfo);
297 cls.def("readTransmissionCurve", &ExposureFitsReader::readTransmissionCurve);
298 cls.def("readComponent", &ExposureFitsReader::readComponent);
299 cls.def("readDetector", &ExposureFitsReader::readDetector);
300 cls.def("readExposureInfo", &ExposureFitsReader::readExposureInfo);
301 cls.def(
302 "readMaskedImage",
303 [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
304 bool conformMasks, bool allowUnsafe, py::object dtype) {
305 if (dtype.is(py::none())) {
306 dtype = py::dtype(self.readImageDType());
307 }
308 return utils::python::TemplateInvoker().apply(
309 [&](auto t) {
310 return self.readMaskedImage<decltype(t)>(bbox, origin, conformMasks,
311 allowUnsafe);
312 },
313 py::dtype(dtype),
314 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
315 std::uint64_t>());
316 },
317 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
318 "allowUnsafe"_a = false, "dtype"_a = py::none());
319 cls.def(
320 "read",
321 [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
322 bool conformMasks, bool allowUnsafe, py::object dtype) {
323 if (dtype.is(py::none())) {
324 dtype = py::dtype(self.readImageDType());
325 }
326 return utils::python::TemplateInvoker().apply(
327 [&](auto t) {
328 return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
329 },
331 utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
332 std::uint64_t>());
333 },
334 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
335 "allowUnsafe"_a = false, "dtype"_a = py::none());
336 });
337}
338} // namespace
339void wrapReaders(lsst::utils::python::WrapperCollection &wrappers) {
340 // wrappers.addInheritanceDependency("lsst.daf.base");
341 wrappers.addSignatureDependency("lsst.geom");
342 wrappers.addSignatureDependency("lsst.afw.image.image");
343 wrappers.addSignatureDependency("lsst.afw.image.maskedImage");
344 wrappers.addSignatureDependency("lsst.afw.image.exposure");
345 declareImageFitsReader(wrappers);
346 declareMaskFitsReader(wrappers);
347 declareMaskedImageFitsReader(wrappers);
348 declareExposureFitsReader(wrappers);
349}
350} // namespace image
351} // namespace afw
352} // namespace lsst
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
Implementation of the Photometric Calibration class.
An integer coordinate rectangle.
Definition: Box.h:55
const int DEFAULT_HDU
Specify that the default HDU should be read.
Definition: fitsDefaults.h:18
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
Definition: fits.cc:1676
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
void wrapReaders(lsst::utils::python::WrapperCollection &)
Definition: _readers.cc:339
A base class for image defects.