LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+4b710797af,21.0.0-1-gfc31b0f+3b24369756,21.0.0-10-g2408eff+50e97f2f47,21.0.0-10-g560fb7b+0803ad37c5,21.0.0-10-g5daeb2b+f9b8dc6d5a,21.0.0-10-g8d1d15d+77a6b82ebf,21.0.0-10-gcf60f90+c961be884d,21.0.0-11-g25eff31+7692554667,21.0.0-17-g6590b197+a14a01c114,21.0.0-2-g103fe59+b79afc2051,21.0.0-2-g1367e85+1003a3501c,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+1003a3501c,21.0.0-2-g7f82c8f+c2a1919b98,21.0.0-2-g8f08a60+fd0b970de5,21.0.0-2-ga326454+c2a1919b98,21.0.0-2-gde069b7+ca45a81b40,21.0.0-2-gecfae73+afcaaec585,21.0.0-2-gfc62afb+1003a3501c,21.0.0-21-g5d80ea29e+5e3c9a3766,21.0.0-3-g357aad2+c67f36f878,21.0.0-3-g4be5c26+1003a3501c,21.0.0-3-g65f322c+02b1f88459,21.0.0-3-g7d9da8d+3b24369756,21.0.0-3-ge02ed75+a423c2ae7a,21.0.0-4-g591bb35+a423c2ae7a,21.0.0-4-g65b4814+0803ad37c5,21.0.0-4-g88306b8+199c7497e5,21.0.0-4-gccdca77+a631590478,21.0.0-4-ge8a399c+b923ff878e,21.0.0-5-gd00fb1e+d8b1e95daa,21.0.0-53-ge728e5d5+3cb64fea8e,21.0.0-6-g2d4f3f3+04719a4bac,21.0.0-7-g04766d7+8d320c19d5,21.0.0-7-g98eecf7+205433fbda,21.0.0-9-g39e06b5+a423c2ae7a,master-gac4afde19b+a423c2ae7a,w.2021.11
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 "lsst/utils/python.h"
26 
27 #include "ndarray/pybind11.h"
28 
35 #include "lsst/afw/geom/SkyWcs.h"
37 #include "lsst/afw/detection/Psf.h"
39 #include "lsst/afw/image/Filter.h"
45 
46 namespace py = pybind11;
47 using namespace pybind11::literals;
48 
49 namespace lsst {
50 namespace afw {
51 namespace image {
52 namespace {
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).
57 using PyImageFitsReader = py::class_<ImageFitsReader, std::shared_ptr<ImageFitsReader>>;
58 using PyMaskFitsReader = py::class_<MaskFitsReader, std::shared_ptr<MaskFitsReader>>;
59 using PyMaskedImageFitsReader = py::class_<MaskedImageFitsReader, std::shared_ptr<MaskedImageFitsReader>>;
60 using 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.
64 template <typename Class, typename... Args>
65 void 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
73 template <typename Class, typename... Args>
74 void 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.
101 template <typename Class, typename... Args>
102 void 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  },
117  py::dtype(dtype),
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  },
134  py::dtype(dtype),
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 
203 void 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 
225 void 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 
248 void 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 
279 void 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("readMetadata", &ExposureFitsReader::readMetadata);
287  cls.def("readWcs", &ExposureFitsReader::readWcs);
288  cls.def("readFilter", &ExposureFitsReader::readFilter);
289  cls.def("readFilterLabel", &ExposureFitsReader::readFilterLabel);
290  cls.def("readPhotoCalib", &ExposureFitsReader::readPhotoCalib);
291  cls.def("readPsf", &ExposureFitsReader::readPsf);
292  cls.def("readValidPolygon", &ExposureFitsReader::readValidPolygon);
293  cls.def("readApCorrMap", &ExposureFitsReader::readApCorrMap);
294  cls.def("readCoaddInputs", &ExposureFitsReader::readCoaddInputs);
295  cls.def("readVisitInfo", &ExposureFitsReader::readVisitInfo);
296  cls.def("readTransmissionCurve", &ExposureFitsReader::readTransmissionCurve);
297  cls.def("readComponent", &ExposureFitsReader::readComponent);
298  cls.def("readDetector", &ExposureFitsReader::readDetector);
299  cls.def("readExposureInfo", &ExposureFitsReader::readExposureInfo);
300  cls.def(
301  "readMaskedImage",
302  [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
303  bool conformMasks, bool allowUnsafe, py::object dtype) {
304  if (dtype.is(py::none())) {
305  dtype = py::dtype(self.readImageDType());
306  }
307  return utils::python::TemplateInvoker().apply(
308  [&](auto t) {
309  return self.readMaskedImage<decltype(t)>(bbox, origin, conformMasks,
310  allowUnsafe);
311  },
312  py::dtype(dtype),
313  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
314  std::uint64_t>());
315  },
316  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
317  "allowUnsafe"_a = false, "dtype"_a = py::none());
318  cls.def(
319  "read",
320  [](ExposureFitsReader &self, lsst::geom::Box2I const &bbox, ImageOrigin origin,
321  bool conformMasks, bool allowUnsafe, py::object dtype) {
322  if (dtype.is(py::none())) {
323  dtype = py::dtype(self.readImageDType());
324  }
325  return utils::python::TemplateInvoker().apply(
326  [&](auto t) {
327  return self.read<decltype(t)>(bbox, origin, conformMasks, allowUnsafe);
328  },
329  py::dtype(dtype),
330  utils::python::TemplateInvoker::Tag<std::uint16_t, int, float, double,
331  std::uint64_t>());
332  },
333  "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
334  "allowUnsafe"_a = false, "dtype"_a = py::none());
335  });
336 }
337 
338 PYBIND11_MODULE(readers, mod) {
339  lsst::utils::python::WrapperCollection wrappers(mod, "lsst.afw.image.readers");
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  wrappers.finish();
351 }
352 
353 } // namespace
354 } // namespace image
355 } // namespace afw
356 } // namespace lsst
Implementation of the Photometric Calibration class.
An integer coordinate rectangle.
Definition: Box.h:55
A helper class for subdividing pybind11 module across multiple translation units (i....
Definition: python.h:242
pybind11::module module
The module object passed to the PYBIND11_MODULE block that contains this WrapperCollection.
Definition: python.h:448
void finish()
Invoke all deferred wrapper-declaring callables.
Definition: python.h:435
PyType wrapType(PyType cls, ClassWrapperCallback function, bool setModuleName=true)
Add a type (class or enum) wrapper, deferring method and other attribute definitions until finish() i...
Definition: python.h:391
void addSignatureDependency(std::string const &name)
Indicate an external module that provides a type used in function/method signatures.
Definition: python.h:357
PYBIND11_MODULE(imageUtils, mod)
Definition: imageUtils.cc:33
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.
A base class for image defects.
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117