LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
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 
36 #include "lsst/afw/geom/SkyWcs.h"
38 #include "lsst/afw/detection/Psf.h"
40 #include "lsst/afw/image/Filter.h"
46 
47 namespace py = pybind11;
48 using namespace pybind11::literals;
49 
50 namespace lsst {
51 namespace afw {
52 namespace image {
53 namespace {
54 
55 // ImageBaseFitsReader is an implementation detail and is not exposed directly
56 // to Python, as we have better ways to share wrapper code between classes
57 // at the pybind11 level (e.g. declareCommon below).
58 using PyImageFitsReader = py::class_<ImageFitsReader, std::shared_ptr<ImageFitsReader>>;
59 using PyMaskFitsReader = py::class_<MaskFitsReader, std::shared_ptr<MaskFitsReader>>;
60 using PyMaskedImageFitsReader = py::class_<MaskedImageFitsReader, std::shared_ptr<MaskedImageFitsReader>>;
61 using PyExposureFitsReader = py::class_<ExposureFitsReader, std::shared_ptr<ExposureFitsReader>>;
62 
63 // Declare attributes common to all FitsReaders. Excludes constructors
64 // because ExposureFitsReader's don't take an HDU argument.
65 template <typename Class, typename... Args>
66 void declareCommonMethods(py::class_<Class, Args...> &cls) {
67  cls.def("readBBox", &Class::readBBox, "origin"_a = PARENT);
68  cls.def("readXY0", &Class::readXY0, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT);
69  cls.def("getFileName", &Class::getFileName);
70  cls.def_property_readonly("fileName", &Class::getFileName);
71 }
72 
73 // Declare attributes common to ImageFitsReader and MaskFitsReader
74 template <typename Class, typename... Args>
75 void declareSinglePlaneMethods(py::class_<Class, Args...> &cls) {
76  cls.def(py::init<std::string const &, int>(), "fileName"_a, "hdu"_a = fits::DEFAULT_HDU);
77  cls.def(py::init<fits::MemFileManager &, int>(), "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
78  cls.def("readMetadata", &Class::readMetadata);
79  cls.def("readDType", [](Class &self) { return py::dtype(self.readDType()); });
80  cls.def("getHdu", &Class::getHdu);
81  cls.def_property_readonly("hdu", &Class::getHdu);
82  cls.def(
83  "readArray",
84  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
85  py::object dtype) {
86  if (dtype.is(py::none())) {
87  dtype = py::dtype(self.readDType());
88  }
89  return utils::python::TemplateInvoker().apply(
90  [&](auto t) {
91  return self.template readArray<decltype(t)>(bbox, origin, allowUnsafe);
92  },
94  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
95  std::uint64_t>());
96  },
97  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
98  "dtype"_a = py::none());
99 }
100 
101 // Declare attributes shared by MaskedImageFitsReader and MaskedImageFitsReader.
102 template <typename Class, typename... Args>
103 void declareMultiPlaneMethods(py::class_<Class, Args...> &cls) {
104  cls.def("readImageDType", [](Class &self) { return py::dtype(self.readImageDType()); });
105  cls.def("readMaskDType", [](Class &self) { return py::dtype(self.readMaskDType()); });
106  cls.def("readVarianceDType", [](Class &self) { return py::dtype(self.readVarianceDType()); });
107  cls.def(
108  "readImage",
109  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
110  py::object dtype) {
111  if (dtype.is(py::none())) {
112  dtype = py::dtype(self.readImageDType());
113  }
114  return utils::python::TemplateInvoker().apply(
115  [&](auto t) {
116  return self.template readImage<decltype(t)>(bbox, origin, allowUnsafe);
117  },
118  py::dtype(dtype),
119  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
120  std::uint64_t>());
121  },
122  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
123  "dtype"_a = py::none());
124  cls.def(
125  "readImageArray",
126  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
127  py::object dtype) {
128  if (dtype.is(py::none())) {
129  dtype = py::dtype(self.readImageDType());
130  }
131  return utils::python::TemplateInvoker().apply(
132  [&](auto t) {
133  return self.template readImageArray<decltype(t)>(bbox, origin, allowUnsafe);
134  },
135  py::dtype(dtype),
136  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
137  std::uint64_t>());
138  },
139  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
140  "dtype"_a = py::none());
141  cls.def(
142  "readMask",
143  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool conformMasks,
144  bool allowUnsafe, py::object dtype) {
145  if (dtype.is(py::none())) {
146  dtype = py::dtype(self.readMaskDType());
147  }
148  return utils::python::TemplateInvoker().apply(
149  [&](auto t) {
150  return self.template readMask<decltype(t)>(bbox, origin, conformMasks,
151  allowUnsafe);
152  },
153  py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
154  },
155  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
156  "allowUnsafe"_a = false, "dtype"_a = py::none());
157  cls.def(
158  "readMaskArray",
159  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
160  py::object dtype) {
161  if (dtype.is(py::none())) {
162  dtype = py::dtype(self.readMaskDType());
163  }
164  return utils::python::TemplateInvoker().apply(
165  [&](auto t) {
166  return self.template readMaskArray<decltype(t)>(bbox, origin, allowUnsafe);
167  },
168  py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
169  },
170  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
171  "dtype"_a = py::none());
172  cls.def(
173  "readVariance",
174  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
175  py::object dtype) {
176  if (dtype.is(py::none())) {
177  dtype = py::dtype(self.readVarianceDType());
178  }
179  return utils::python::TemplateInvoker().apply(
180  [&](auto t) {
181  return self.template readVariance<decltype(t)>(bbox, origin, allowUnsafe);
182  },
183  py::dtype(dtype), utils::python::TemplateInvoker::Tag<VariancePixel>());
184  },
185  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
186  "dtype"_a = py::none());
187  cls.def(
188  "readVarianceArray",
189  [](Class &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
190  py::object dtype) {
191  if (dtype.is(py::none())) {
192  dtype = py::dtype(self.readVarianceDType());
193  }
194  return utils::python::TemplateInvoker().apply(
195  [&](auto t) {
196  return self.template readVarianceArray<decltype(t)>(bbox, origin, allowUnsafe);
197  },
198  py::dtype(dtype), utils::python::TemplateInvoker::Tag<VariancePixel>());
199  },
200  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
201  "dtype"_a = py::none());
202 }
203 
204 void declareImageFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
205  wrappers.wrapType(PyImageFitsReader(wrappers.module, "ImageFitsReader"), [](auto &mod, auto &cls) {
206  declareCommonMethods(cls);
207  declareSinglePlaneMethods(cls);
208  cls.def(
209  "read",
210  [](ImageFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool allowUnsafe,
211  py::object dtype) {
212  if (dtype.is(py::none())) {
213  dtype = py::dtype(self.readDType());
214  }
215  return utils::python::TemplateInvoker().apply(
216  [&](auto t) { return self.read<decltype(t)>(bbox, origin, allowUnsafe); },
217  py::dtype(dtype),
218  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
219  std::uint64_t>());
220  },
221  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false,
222  "dtype"_a = py::none());
223  });
224 }
225 
226 void declareMaskFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
227  wrappers.wrapType(PyMaskFitsReader(wrappers.module, "MaskFitsReader"), [](auto &mod, auto &cls) {
228  declareCommonMethods(cls);
229  declareSinglePlaneMethods(cls);
230  cls.def(
231  "read",
232  [](MaskFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin, bool conformMasks,
233  bool allowUnsafe, py::object dtype) {
234  if (dtype.is(py::none())) {
235  dtype = py::dtype(self.readDType());
236  }
237  return utils::python::TemplateInvoker().apply(
238  [&](auto t) {
239  return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
240  },
241  py::dtype(dtype), utils::python::TemplateInvoker::Tag<MaskPixel>());
242  },
243  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
244  "allowUnsafe"_a = false, "dtype"_a = py::none());
245  });
246  // all other methods provided by base class wrappers
247 }
248 
249 void declareMaskedImageFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
250  wrappers.wrapType(PyMaskedImageFitsReader(wrappers.module, "MaskedImageFitsReader"), [](auto &mod,
251  auto &cls) {
252  cls.def(py::init<std::string const &, int>(), "fileName"_a, "hdu"_a = fits::DEFAULT_HDU);
253  cls.def(py::init<fits::MemFileManager &, int>(), "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
254  declareCommonMethods(cls);
255  declareMultiPlaneMethods(cls);
256  cls.def("readPrimaryMetadata", &MaskedImageFitsReader::readPrimaryMetadata);
257  cls.def("readImageMetadata", &MaskedImageFitsReader::readImageMetadata);
258  cls.def("readMaskMetadata", &MaskedImageFitsReader::readMaskMetadata);
259  cls.def("readVarianceMetadata", &MaskedImageFitsReader::readVarianceMetadata);
260  cls.def(
261  "read",
262  [](MaskedImageFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
263  bool conformMasks, bool needAllHdus, bool allowUnsafe, py::object dtype) {
264  if (dtype.is(py::none())) {
265  dtype = py::dtype(self.readImageDType());
266  }
267  return utils::python::TemplateInvoker().apply(
268  [&](auto t) {
269  return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
270  },
271  py::dtype(dtype),
272  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
273  std::uint64_t>());
274  },
275  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
276  "needAllHdus"_a = false, "allowUnsafe"_a = false, "dtype"_a = py::none());
277  });
278 }
279 
280 void declareExposureFitsReader(lsst::utils::python::WrapperCollection &wrappers) {
281  wrappers.wrapType(PyExposureFitsReader(wrappers.module, "ExposureFitsReader"), [](auto &mod, auto &cls) {
282  cls.def(py::init<std::string const &>(), "fileName"_a);
283  cls.def(py::init<fits::MemFileManager &>(), "manager"_a);
284  declareCommonMethods(cls);
285  declareMultiPlaneMethods(cls);
286  cls.def("readSerializationVersion", &ExposureFitsReader::readSerializationVersion);
287  cls.def("readExposureId", &ExposureFitsReader::readExposureId);
288  cls.def("readMetadata", &ExposureFitsReader::readMetadata);
289  cls.def("readWcs", &ExposureFitsReader::readWcs);
290  cls.def("readFilter", &ExposureFitsReader::readFilter);
291  cls.def("readFilterLabel", &ExposureFitsReader::readFilterLabel);
292  cls.def("readPhotoCalib", &ExposureFitsReader::readPhotoCalib);
293  cls.def("readPsf", &ExposureFitsReader::readPsf);
294  cls.def("readValidPolygon", &ExposureFitsReader::readValidPolygon);
295  cls.def("readApCorrMap", &ExposureFitsReader::readApCorrMap);
296  cls.def("readCoaddInputs", &ExposureFitsReader::readCoaddInputs);
297  cls.def("readVisitInfo", &ExposureFitsReader::readVisitInfo);
298  cls.def("readTransmissionCurve", &ExposureFitsReader::readTransmissionCurve);
299  cls.def("readComponent", &ExposureFitsReader::readComponent);
300  cls.def("readDetector", &ExposureFitsReader::readDetector);
301  cls.def("readExposureInfo", &ExposureFitsReader::readExposureInfo);
302  cls.def(
303  "readMaskedImage",
304  [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
305  bool conformMasks, bool allowUnsafe, py::object dtype) {
306  if (dtype.is(py::none())) {
307  dtype = py::dtype(self.readImageDType());
308  }
309  return utils::python::TemplateInvoker().apply(
310  [&](auto t) {
311  return self.readMaskedImage<decltype(t)>(bbox, origin, conformMasks,
312  allowUnsafe);
313  },
314  py::dtype(dtype),
315  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
316  std::uint64_t>());
317  },
318  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
319  "allowUnsafe"_a = false, "dtype"_a = py::none());
320  cls.def(
321  "read",
322  [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
323  bool conformMasks, bool allowUnsafe, py::object dtype) {
324  if (dtype.is(py::none())) {
325  dtype = py::dtype(self.readImageDType());
326  }
327  return utils::python::TemplateInvoker().apply(
328  [&](auto t) {
329  return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
330  },
331  py::dtype(dtype),
332  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
333  std::uint64_t>());
334  },
335  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
336  "allowUnsafe"_a = false, "dtype"_a = py::none());
337  });
338 }
339 } // namespace
340 void wrapReaders(lsst::utils::python::WrapperCollection &wrappers) {
341  // wrappers.addInheritanceDependency("lsst.daf.base");
342  wrappers.addSignatureDependency("lsst.geom");
343  wrappers.addSignatureDependency("lsst.afw.image.image");
344  wrappers.addSignatureDependency("lsst.afw.image.maskedImage");
345  wrappers.addSignatureDependency("lsst.afw.image.exposure");
346  declareImageFitsReader(wrappers);
347  declareMaskFitsReader(wrappers);
348  declareMaskedImageFitsReader(wrappers);
349  declareExposureFitsReader(wrappers);
350 }
351 } // namespace image
352 } // namespace afw
353 } // 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:1657
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
void wrapReaders(lsst::utils::python::WrapperCollection &)
Definition: _readers.cc:340
A base class for image defects.