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