LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
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 } // namespace
338 void wrapReaders(lsst::utils::python::WrapperCollection &wrappers) {
339  // wrappers.addInheritanceDependency("lsst.daf.base");
340  wrappers.addSignatureDependency("lsst.geom");
341  wrappers.addSignatureDependency("lsst.afw.image.image");
342  wrappers.addSignatureDependency("lsst.afw.image.maskedImage");
343  wrappers.addSignatureDependency("lsst.afw.image.exposure");
344  declareImageFitsReader(wrappers);
345  declareMaskFitsReader(wrappers);
346  declareMaskedImageFitsReader(wrappers);
347  declareExposureFitsReader(wrappers);
348 }
349 } // namespace image
350 } // namespace afw
351 } // 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:338
A base class for image defects.