LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
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 
26 #include "lsst/afw/fits.h"
28 
29 namespace py = pybind11;
30 using namespace pybind11::literals;
31 
32 namespace lsst {
33 namespace afw {
34 namespace image {
35 
36 namespace {
37 
38 template <typename ImagePixelT> // only the image type varies; mask and variance are fixed
39 using PyMaskedImage = py::class_<MaskedImage<ImagePixelT>, std::shared_ptr<MaskedImage<ImagePixelT>>>;
40 
49 template <typename FromPixelT, typename ToPixelT>
50 void declareCastConstructor(PyMaskedImage<ToPixelT> &cls) {
51  cls.def(py::init<MaskedImage<FromPixelT> const &, bool const>(), "src"_a, "deep"_a);
52 }
53 
54 template <typename ImagePixelT>
55 PyMaskedImage<ImagePixelT> declareMaskedImage(py::module &mod, const std::string &suffix) {
56  using MI = MaskedImage<ImagePixelT>;
57 
58  py::module::import("lsst.daf.base");
59 
60  PyMaskedImage<ImagePixelT> cls(mod, ("MaskedImage" + suffix).c_str());
61 
62  mod.def("makeMaskedImage", &makeMaskedImage<ImagePixelT, MaskPixel, VariancePixel>, "image"_a,
63  "mask"_a = nullptr, "variance"_a = nullptr);
64 
65  /* Member types and enums */
66 
67  /* Constructors */
68  cls.def(py::init<unsigned int, unsigned int, typename MI::MaskPlaneDict const &>(), "width"_a, "height"_a,
69  "planeDict"_a = typename MI::MaskPlaneDict());
70  cls.def(py::init<lsst::geom::Extent2I, typename MI::MaskPlaneDict const &>(), "dimensions"_a,
71  "planeDict"_a = typename MI::MaskPlaneDict());
72  cls.def(py::init<typename MI::ImagePtr, typename MI::MaskPtr, typename MI::VariancePtr>(), "image"_a,
73  "mask"_a = nullptr, "variance"_a = nullptr);
74  cls.def(py::init<lsst::geom::Box2I const &, typename MI::MaskPlaneDict const &>(), "bbox"_a,
75  "planeDict"_a = typename MI::MaskPlaneDict());
79  bool>(),
80  "fileName"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
81  "conformMasks"_a = false, "needAllHdus"_a = false, "imageMetadata"_a = nullptr,
82  "maskMetadata"_a = nullptr, "varianceMetadata"_a = nullptr, "allowUnsafe"_a = false);
83  cls.def(py::init<fits::MemFileManager &, std::shared_ptr<daf::base::PropertySet>,
84  lsst::geom::Box2I const &, ImageOrigin, bool, bool,
87  "manager"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
88  "conformMasks"_a = false, "needAllHdus"_a = false, "imageMetadata"_a = nullptr,
89  "maskMetadata"_a = nullptr, "varianceMetadata"_a = nullptr, "allowUnsafe"_a = false);
90  cls.def(py::init<MI const &, bool>(), "rhs"_a, "deep"_a = false);
91  cls.def(py::init<MI const &, lsst::geom::Box2I const &, ImageOrigin, bool>(), "rhs"_a, "bbox"_a,
92  "origin"_a = PARENT, "deep"_a = false);
93 
94  /* Operators */
95  cls.def("swap", &MI::swap);
96  cls.def("assign", &MI::assign, "rhs"_a, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
97  py::is_operator() // py::is_operator is a workaround for code in slicing.py
98  // that expects NotImplemented to be returned on failure.
99  );
100 
101  cls.def("subset", &MI::subset, "bbox"_a, "origin"_a = PARENT);
102 
103  cls.def("__ilshift__", &MI::operator<<=);
104  cls.def("__iadd__", (MI & (MI::*)(ImagePixelT const)) & MI::operator+=);
105  cls.def("__iadd__", (MI & (MI::*)(MI const &)) & MI::operator+=);
106  cls.def("__iadd__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator+=);
107  cls.def("__iadd__", (MI & (MI::*)(math::Function2<double> const &)) & MI::operator+=);
108  cls.def("scaledPlus", &MI::scaledPlus);
109  cls.def("__isub__", (MI & (MI::*)(ImagePixelT const)) & MI::operator-=);
110  cls.def("__isub__", (MI & (MI::*)(MI const &)) & MI::operator-=);
111  cls.def("__isub__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator-=);
112  cls.def("__isub__", (MI & (MI::*)(math::Function2<double> const &)) & MI::operator-=);
113  cls.def("scaledMinus", &MI::scaledMinus);
114  cls.def("__imul__", (MI & (MI::*)(ImagePixelT const)) & MI::operator*=);
115  cls.def("__imul__", (MI & (MI::*)(MI const &)) & MI::operator*=);
116  cls.def("__imul__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator*=);
117  cls.def("scaledMultiplies", &MI::scaledMultiplies);
118  cls.def("__itruediv__", (MI & (MI::*)(ImagePixelT const)) & MI::operator/=);
119  cls.def("__itruediv__", (MI & (MI::*)(MI const &)) & MI::operator/=);
120  cls.def("__itruediv__", (MI & (MI::*)(Image<ImagePixelT> const &)) & MI::operator/=);
121  cls.def("scaledDivides", &MI::scaledDivides);
122 
123  /* Members */
124  cls.def("writeFits",
129  MI::writeFits,
130  "fileName"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
131  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
133  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
134  cls.def("writeFits",
135  (void (MI::*)(fits::MemFileManager &, std::shared_ptr<daf::base::PropertySet const>,
139  MI::writeFits,
140  "manager"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
141  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
143  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
144  cls.def("writeFits",
145  (void (MI::*)(fits::Fits &, std::shared_ptr<daf::base::PropertySet const>,
149  MI::writeFits,
150  "fitsfile"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
151  "imageMetadata"_a = std::shared_ptr<daf::base::PropertySet const>(),
153  "varianceMetadata"_a = std::shared_ptr<daf::base::PropertySet const>());
154 
155  cls.def("writeFits",
156  [](MI &self, std::string const &filename, fits::ImageWriteOptions const &imageOptions,
157  fits::ImageWriteOptions const &maskOptions, fits::ImageWriteOptions const &varianceOptions,
159  self.writeFits(filename, imageOptions, maskOptions, varianceOptions, header);
160  },
161  "filename"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
163  cls.def("writeFits",
164  [](MI &self, fits::MemFileManager &manager, fits::ImageWriteOptions const &imageOptions,
165  fits::ImageWriteOptions const &maskOptions, fits::ImageWriteOptions const &varianceOptions,
167  self.writeFits(manager, imageOptions, maskOptions, varianceOptions, header);
168  },
169  "manager"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
171  cls.def("writeFits",
172  [](MI &self, fits::Fits &fits, fits::ImageWriteOptions const &imageOptions,
173  fits::ImageWriteOptions const &maskOptions, fits::ImageWriteOptions const &varianceOptions,
175  self.writeFits(fits, imageOptions, maskOptions, varianceOptions, header);
176  },
177  "fits"_a, "imageOptions"_a, "maskOptions"_a, "varianceOptions"_a,
179 
180  cls.def_static("readFits", (MI(*)(std::string const &))MI::readFits, "filename"_a);
181  cls.def_static("readFits", (MI(*)(fits::MemFileManager &))MI::readFits, "manager"_a);
182  cls.def("getImage", &MI::getImage);
183  cls.def("setImage", &MI::setImage);
184  cls.def_property("image", &MI::getImage, &MI::setImage);
185  cls.def("getMask", &MI::getMask);
186  cls.def("setMask", &MI::setMask);
187  cls.def_property("mask", &MI::getMask, &MI::setMask);
188  cls.def("getVariance", &MI::getVariance);
189  cls.def("setVariance", &MI::setVariance);
190  cls.def_property("variance", &MI::getVariance, &MI::setVariance);
191  cls.def("getWidth", &MI::getWidth);
192  cls.def("getHeight", &MI::getHeight);
193  cls.def("getDimensions", &MI::getDimensions);
194  cls.def("getBBox", &MI::getBBox, "origin"_a = PARENT);
195  cls.def("getX0", &MI::getX0);
196  cls.def("getY0", &MI::getY0);
197  cls.def("getXY0", &MI::getXY0);
198  cls.def("setXY0", (void (MI::*)(int const, int const)) & MI::setXY0, "x0"_a, "y0"_a);
199  cls.def("setXY0", (void (MI::*)(lsst::geom::Point2I const)) & MI::setXY0, "origin"_a);
200  cls.def("indexToPosition", &MI::indexToPosition);
201  cls.def("positionToIndex", &MI::positionToIndex);
202 
203  return cls;
204 }
205 
206 template <typename ImagePixelT> // addtional template types do not seem to be needed
207 void declareMakeMaskedImage(py::module &mod) {
208  mod.def("makeMaskedImage", makeMaskedImage<ImagePixelT, MaskPixel, VariancePixel>, "image"_a,
209  "mask"_a = nullptr, "variance"_a = nullptr);
210 }
211 
212 template <typename ImagePixelT1, typename ImagePixelT2>
213 void declareImagesOverlap(py::module &mod) {
214  // wrap both the Image and MaskedImage versions of imagesOverlap here, as wrapping
215  // the Image version in the Image wrapper results in it being invisible in lsst.afw.image
216  mod.def("imagesOverlap",
217  py::overload_cast<ImageBase<ImagePixelT1> const &, ImageBase<ImagePixelT2> const &>(
218  &imagesOverlap<ImagePixelT1, ImagePixelT2>),
219  "image1"_a, "image2"_a);
220 
221  mod.def("imagesOverlap",
222  py::overload_cast<MaskedImage<ImagePixelT1> const &, MaskedImage<ImagePixelT2> const &>(
223  &imagesOverlap<ImagePixelT1, ImagePixelT2>),
224  "image1"_a, "image2"_a);
225 }
226 
227 } // namespace
228 
229 PYBIND11_MODULE(maskedImage, mod) {
230  py::module::import("lsst.afw.image.image");
231 
232  auto clsMaskedImageF = declareMaskedImage<float>(mod, "F");
233  auto clsMaskedImageD = declareMaskedImage<double>(mod, "D");
234  auto clsMaskedImageI = declareMaskedImage<int>(mod, "I");
235  auto clsMaskedImageU = declareMaskedImage<std::uint16_t>(mod, "U");
236  auto clsMaskedImageL = declareMaskedImage<std::uint64_t>(mod, "L");
237 
238  // Declare constructors for casting all exposure types to to float and double
239  // (the only two types of casts that Python supports)
240  declareCastConstructor<int, float>(clsMaskedImageF);
241  declareCastConstructor<int, double>(clsMaskedImageD);
242  declareCastConstructor<float, double>(clsMaskedImageD);
243  declareCastConstructor<double, float>(clsMaskedImageF);
244  declareCastConstructor<std::uint16_t, float>(clsMaskedImageF);
245  declareCastConstructor<std::uint16_t, double>(clsMaskedImageD);
246  declareCastConstructor<std::uint64_t, float>(clsMaskedImageF);
247  declareCastConstructor<std::uint64_t, double>(clsMaskedImageD);
248 
249  /* Module level */
250  declareMakeMaskedImage<int>(mod);
251  declareMakeMaskedImage<float>(mod);
252  declareMakeMaskedImage<double>(mod);
253  declareMakeMaskedImage<std::uint16_t>(mod);
254  declareMakeMaskedImage<std::uint64_t>(mod);
255 
256  declareImagesOverlap<int, int>(mod);
257  declareImagesOverlap<int, float>(mod);
258  declareImagesOverlap<int, double>(mod);
259  declareImagesOverlap<int, std::uint16_t>(mod);
260  declareImagesOverlap<int, std::uint64_t>(mod);
261 
262  declareImagesOverlap<float, int>(mod);
263  declareImagesOverlap<float, float>(mod);
264  declareImagesOverlap<float, double>(mod);
265  declareImagesOverlap<float, std::uint16_t>(mod);
266  declareImagesOverlap<float, std::uint64_t>(mod);
267 
268  declareImagesOverlap<double, int>(mod);
269  declareImagesOverlap<double, float>(mod);
270  declareImagesOverlap<double, double>(mod);
271  declareImagesOverlap<double, std::uint16_t>(mod);
272  declareImagesOverlap<double, std::uint64_t>(mod);
273 
274  declareImagesOverlap<std::uint16_t, int>(mod);
275  declareImagesOverlap<std::uint16_t, float>(mod);
276  declareImagesOverlap<std::uint16_t, double>(mod);
277  declareImagesOverlap<std::uint16_t, std::uint16_t>(mod);
278  declareImagesOverlap<std::uint16_t, std::uint64_t>(mod);
279 
280  declareImagesOverlap<std::uint64_t, int>(mod);
281  declareImagesOverlap<std::uint64_t, float>(mod);
282  declareImagesOverlap<std::uint64_t, double>(mod);
283  declareImagesOverlap<std::uint64_t, std::uint16_t>(mod);
284  declareImagesOverlap<std::uint64_t, std::uint64_t>(mod);
285 }
286 } // namespace image
287 } // namespace afw
288 } // namespace lsst
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
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:65
std::map< std::string, int > MaskPlaneDict
Definition: Mask.h:58
Fits * fits
Definition: FitsWriter.cc:90
STL class.
A base class for image defects.
PYBIND11_MODULE(maskedImage, mod)
Definition: maskedImage.cc:229
void swap(CameraSys &a, CameraSys &b)
Definition: CameraSys.h:157
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
An integer coordinate rectangle.
Definition: Box.h:55