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
maskedImage.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2017 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
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 LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #include "pybind11/pybind11.h"
24 #include "pybind11/stl.h"
25 #include "lsst/utils/python.h"
26 
27 #include "lsst/afw/fits.h"
29 
30 namespace py = pybind11;
31 using namespace pybind11::literals;
32 
33 namespace lsst {
34 namespace afw {
35 namespace image {
36 
37 namespace {
38 
39 template <typename ImagePixelT> // only the image type varies; mask and variance are fixed
40 using PyMaskedImage = py::class_<MaskedImage<ImagePixelT>, std::shared_ptr<MaskedImage<ImagePixelT>>>;
41 
50 template <typename FromPixelT, typename ToPixelT>
51 void declareCastConstructor(PyMaskedImage<ToPixelT> &cls) {
52  cls.def(py::init<MaskedImage<FromPixelT> const &, bool const>(), "src"_a, "deep"_a);
53 }
54 
55 template <typename ImagePixelT>
56 PyMaskedImage<ImagePixelT> declareMaskedImage(lsst::utils::python::WrapperCollection &wrappers,
57  const std::string &suffix) {
58  using MI = MaskedImage<ImagePixelT>;
59 
60  return wrappers.wrapType(
61  PyMaskedImage<ImagePixelT>(wrappers.module, ("MaskedImage" + suffix).c_str()),
62  [](auto &mod, auto &cls) {
63  mod.def("makeMaskedImage", &makeMaskedImage<ImagePixelT, MaskPixel, VariancePixel>, "image"_a,
64  "mask"_a = nullptr, "variance"_a = nullptr);
65 
66  /* Member types and enums */
67 
68  /* Constructors */
69  cls.def(py::init<unsigned int, unsigned int, typename MI::MaskPlaneDict const &>(), "width"_a,
70  "height"_a, "planeDict"_a = typename MI::MaskPlaneDict());
71  cls.def(py::init<lsst::geom::Extent2I, typename MI::MaskPlaneDict const &>(), "dimensions"_a,
72  "planeDict"_a = typename MI::MaskPlaneDict());
73  cls.def(py::init<typename MI::ImagePtr, typename MI::MaskPtr, typename MI::VariancePtr>(),
74  "image"_a, "mask"_a = nullptr, "variance"_a = nullptr);
75  cls.def(py::init<lsst::geom::Box2I const &, typename MI::MaskPlaneDict const &>(), "bbox"_a,
76  "planeDict"_a = typename MI::MaskPlaneDict());
77  cls.def(py::init<std::string const &, std::shared_ptr<daf::base::PropertySet>,
78  lsst::geom::Box2I const &, ImageOrigin, bool, bool,
79  std::shared_ptr<daf::base::PropertySet>,
80  std::shared_ptr<daf::base::PropertySet>,
81  std::shared_ptr<daf::base::PropertySet>, bool>(),
82  "fileName"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
83  "origin"_a = PARENT, "conformMasks"_a = false, "needAllHdus"_a = false,
84  "imageMetadata"_a = nullptr, "maskMetadata"_a = nullptr,
85  "varianceMetadata"_a = nullptr, "allowUnsafe"_a = false);
86  cls.def(py::init<fits::MemFileManager &, std::shared_ptr<daf::base::PropertySet>,
87  lsst::geom::Box2I const &, ImageOrigin, bool, bool,
88  std::shared_ptr<daf::base::PropertySet>,
89  std::shared_ptr<daf::base::PropertySet>,
90  std::shared_ptr<daf::base::PropertySet>, bool>(),
91  "manager"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
92  "origin"_a = PARENT, "conformMasks"_a = false, "needAllHdus"_a = false,
93  "imageMetadata"_a = nullptr, "maskMetadata"_a = nullptr,
94  "varianceMetadata"_a = nullptr, "allowUnsafe"_a = false);
95  cls.def(py::init<MI const &, bool>(), "rhs"_a, "deep"_a = false);
96  cls.def(py::init<MI const &, lsst::geom::Box2I const &, ImageOrigin, bool>(), "rhs"_a,
97  "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
98 
99  /* Operators */
100  cls.def("swap", &MI::swap);
101  cls.def("assign", &MI::assign, "rhs"_a, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
102  py::is_operator() // py::is_operator is a workaround for code in slicing.py
103  // that expects NotImplemented to be returned on failure.
104  );
105 
106  cls.def("subset", &MI::subset, "bbox"_a, "origin"_a = PARENT);
107 
108  cls.def("__iadd__", (MI & (MI::*)(ImagePixelT const)) & MI::operator+=);
109  cls.def("__iadd__", (MI & (MI::*)(MI const &)) & MI::operator+=);
110  cls.def("__iadd__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator+=);
111  cls.def("__iadd__", (MI & (MI::*)(math::Function2<double> const &)) & MI::operator+=);
112  cls.def("scaledPlus", &MI::scaledPlus);
113  cls.def("__isub__", (MI & (MI::*)(ImagePixelT const)) & MI::operator-=);
114  cls.def("__isub__", (MI & (MI::*)(MI const &)) & MI::operator-=);
115  cls.def("__isub__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator-=);
116  cls.def("__isub__", (MI & (MI::*)(math::Function2<double> const &)) & MI::operator-=);
117  cls.def("scaledMinus", &MI::scaledMinus);
118  cls.def("__imul__", (MI & (MI::*)(ImagePixelT const)) & MI::operator*=);
119  cls.def("__imul__", (MI & (MI::*)(MI const &)) & MI::operator*=);
120  cls.def("__imul__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator*=);
121  cls.def("scaledMultiplies", &MI::scaledMultiplies);
122  cls.def("__itruediv__", (MI & (MI::*)(ImagePixelT const)) & MI::operator/=);
123  cls.def("__itruediv__", (MI & (MI::*)(MI const &)) & MI::operator/=);
124  cls.def("__itruediv__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator/=);
125  cls.def("scaledDivides", &MI::scaledDivides);
126 
127  /* Members */
128  cls.def("writeFits",
129  (void (MI::*)(std::string const &, std::shared_ptr<daf::base::PropertySet const>,
130  std::shared_ptr<daf::base::PropertySet const>,
131  std::shared_ptr<daf::base::PropertySet const>,
132  std::shared_ptr<daf::base::PropertySet const>) const) &
133  MI::writeFits,
134  "fileName"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
135  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
136  "maskMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
137  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
138  cls.def("writeFits",
139  (void (MI::*)(fits::MemFileManager &, std::shared_ptr<daf::base::PropertySet const>,
140  std::shared_ptr<daf::base::PropertySet const>,
141  std::shared_ptr<daf::base::PropertySet const>,
142  std::shared_ptr<daf::base::PropertySet const>) const) &
143  MI::writeFits,
144  "manager"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
145  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
146  "maskMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
147  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
148  cls.def("writeFits",
149  (void (MI::*)(fits::Fits &, std::shared_ptr<daf::base::PropertySet const>,
150  std::shared_ptr<daf::base::PropertySet const>,
151  std::shared_ptr<daf::base::PropertySet const>,
152  std::shared_ptr<daf::base::PropertySet const>) const) &
153  MI::writeFits,
154  "fitsfile"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
155  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
156  "maskMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
157  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
158 
159  cls.def(
160  "writeFits",
161  [](MI &self, std::string const &filename, fits::ImageWriteOptions const &imageOptions,
162  fits::ImageWriteOptions const &maskOptions,
163  fits::ImageWriteOptions const &varianceOptions,
164  std::shared_ptr<daf::base::PropertySet const> header) {
165  self.writeFits(filename, imageOptions, maskOptions, varianceOptions, header);
166  },
167  "filename"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
169  cls.def(
170  "writeFits",
171  [](MI &self, fits::MemFileManager &manager,
172  fits::ImageWriteOptions const &imageOptions,
173  fits::ImageWriteOptions const &maskOptions,
174  fits::ImageWriteOptions const &varianceOptions,
176  self.writeFits(manager, imageOptions, maskOptions, varianceOptions, header);
177  },
178  "manager"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
180  cls.def(
181  "writeFits",
182  [](MI &self, fits::Fits &fits, fits::ImageWriteOptions const &imageOptions,
183  fits::ImageWriteOptions const &maskOptions,
184  fits::ImageWriteOptions const &varianceOptions,
186  self.writeFits(fits, imageOptions, maskOptions, varianceOptions, header);
187  },
188  "fits"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
190 
191  cls.def_static("readFits", (MI(*)(std::string const &))MI::readFits, "filename"_a);
192  cls.def_static("readFits", (MI(*)(fits::MemFileManager &))MI::readFits, "manager"_a);
193  cls.def("getImage", &MI::getImage);
194  cls.def("setImage", &MI::setImage);
195  cls.def_property("image", &MI::getImage, &MI::setImage);
196  cls.def("getMask", &MI::getMask);
197  cls.def("setMask", &MI::setMask);
198  cls.def_property("mask", &MI::getMask, &MI::setMask);
199  cls.def("getVariance", &MI::getVariance);
200  cls.def("setVariance", &MI::setVariance);
201  cls.def_property("variance", &MI::getVariance, &MI::setVariance);
202  cls.def("getWidth", &MI::getWidth);
203  cls.def("getHeight", &MI::getHeight);
204  cls.def("getDimensions", &MI::getDimensions);
205  cls.def("getBBox", &MI::getBBox, "origin"_a = PARENT);
206  cls.def("getX0", &MI::getX0);
207  cls.def("getY0", &MI::getY0);
208  cls.def("getXY0", &MI::getXY0);
209  cls.def("setXY0", (void (MI::*)(int const, int const)) & MI::setXY0, "x0"_a, "y0"_a);
210  cls.def("setXY0", (void (MI::*)(lsst::geom::Point2I const)) & MI::setXY0, "origin"_a);
211  cls.def("indexToPosition", &MI::indexToPosition);
212  cls.def("positionToIndex", &MI::positionToIndex);
213  });
214 }
215 
216 template <typename ImagePixelT> // addtional template types do not seem to be needed
217 void declareMakeMaskedImage(lsst::utils::python::WrapperCollection &wrappers) {
218  wrappers.wrap([](auto &mod) {
219  mod.def("makeMaskedImage", makeMaskedImage<ImagePixelT, MaskPixel, VariancePixel>, "image"_a,
220  "mask"_a = nullptr, "variance"_a = nullptr);
221  });
222 }
223 
224 template <typename ImagePixelT1, typename ImagePixelT2>
225 void declareImagesOverlap(lsst::utils::python::WrapperCollection &wrappers) {
226  // wrap both the Image and MaskedImage versions of imagesOverlap here, as wrapping
227  // the Image version in the Image wrapper results in it being invisible in lsst.afw.image
228  wrappers.wrap([](auto &mod) {
229  mod.def("imagesOverlap",
230  py::overload_cast<ImageBase<ImagePixelT1> const &, ImageBase<ImagePixelT2> const &>(
231  &imagesOverlap<ImagePixelT1, ImagePixelT2>),
232  "image1"_a, "image2"_a);
233 
234  mod.def("imagesOverlap",
235  py::overload_cast<MaskedImage<ImagePixelT1> const &, MaskedImage<ImagePixelT2> const &>(
236  &imagesOverlap<ImagePixelT1, ImagePixelT2>),
237  "image1"_a, "image2"_a);
238  });
239 }
240 
241 } // namespace
242 
243 PYBIND11_MODULE(maskedImage, mod) {
244  lsst::utils::python::WrapperCollection wrappers(mod, "lsst.afw.image.maskedImage");
245  wrappers.addSignatureDependency("lsst.afw.image.image");
246  wrappers.addInheritanceDependency("lsst.daf.base");
247 
248  auto clsMaskedImageF = declareMaskedImage<float>(wrappers, "F");
249  auto clsMaskedImageD = declareMaskedImage<double>(wrappers, "D");
250  auto clsMaskedImageI = declareMaskedImage<int>(wrappers, "I");
251  auto clsMaskedImageU = declareMaskedImage<std::uint16_t>(wrappers, "U");
252  auto clsMaskedImageL = declareMaskedImage<std::uint64_t>(wrappers, "L");
253 
254  // Declare constructors for casting all exposure types to to float and double
255  // (the only two types of casts that Python supports)
256  declareCastConstructor<int, float>(clsMaskedImageF);
257  declareCastConstructor<int, double>(clsMaskedImageD);
258  declareCastConstructor<float, double>(clsMaskedImageD);
259  declareCastConstructor<double, float>(clsMaskedImageF);
260  declareCastConstructor<std::uint16_t, float>(clsMaskedImageF);
261  declareCastConstructor<std::uint16_t, double>(clsMaskedImageD);
262  declareCastConstructor<std::uint64_t, float>(clsMaskedImageF);
263  declareCastConstructor<std::uint64_t, double>(clsMaskedImageD);
264 
265  /* Module level */
266  declareMakeMaskedImage<int>(wrappers);
267  declareMakeMaskedImage<float>(wrappers);
268  declareMakeMaskedImage<double>(wrappers);
269  declareMakeMaskedImage<std::uint16_t>(wrappers);
270  declareMakeMaskedImage<std::uint64_t>(wrappers);
271 
272  declareImagesOverlap<int, int>(wrappers);
273  declareImagesOverlap<int, float>(wrappers);
274  declareImagesOverlap<int, double>(wrappers);
275  declareImagesOverlap<int, std::uint16_t>(wrappers);
276  declareImagesOverlap<int, std::uint64_t>(wrappers);
277 
278  declareImagesOverlap<float, int>(wrappers);
279  declareImagesOverlap<float, float>(wrappers);
280  declareImagesOverlap<float, double>(wrappers);
281  declareImagesOverlap<float, std::uint16_t>(wrappers);
282  declareImagesOverlap<float, std::uint64_t>(wrappers);
283 
284  declareImagesOverlap<double, int>(wrappers);
285  declareImagesOverlap<double, float>(wrappers);
286  declareImagesOverlap<double, double>(wrappers);
287  declareImagesOverlap<double, std::uint16_t>(wrappers);
288  declareImagesOverlap<double, std::uint64_t>(wrappers);
289 
290  declareImagesOverlap<std::uint16_t, int>(wrappers);
291  declareImagesOverlap<std::uint16_t, float>(wrappers);
292  declareImagesOverlap<std::uint16_t, double>(wrappers);
293  declareImagesOverlap<std::uint16_t, std::uint16_t>(wrappers);
294  declareImagesOverlap<std::uint16_t, std::uint64_t>(wrappers);
295 
296  declareImagesOverlap<std::uint64_t, int>(wrappers);
297  declareImagesOverlap<std::uint64_t, float>(wrappers);
298  declareImagesOverlap<std::uint64_t, double>(wrappers);
299  declareImagesOverlap<std::uint64_t, std::uint16_t>(wrappers);
300  declareImagesOverlap<std::uint64_t, std::uint64_t>(wrappers);
301  wrappers.finish();
302 }
303 } // namespace image
304 } // namespace afw
305 } // namespace lsst
Fits * fits
Definition: FitsWriter.cc:90
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 addInheritanceDependency(std::string const &name)
Indicate an external module that provides a base class for a subsequent addType call.
Definition: python.h:343
void wrap(WrapperCallback function)
Add a set of wrappers without defining a class.
Definition: python.h:369
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
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
def init()
Definition: tests.py:59
A base class for image defects.