LSSTApplications  21.0.0+75b29a8a7f,21.0.0+e70536a077,21.0.0-1-ga51b5d4+62c747d40b,21.0.0-11-ga6ea59e8e+47cba9fc36,21.0.0-2-g103fe59+914993bf7c,21.0.0-2-g1367e85+e2614ded12,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g4bc9b9f+7b2b5f8678,21.0.0-2-g5242d73+e2614ded12,21.0.0-2-g54e2caa+6403186824,21.0.0-2-g7f82c8f+3ac4acbffc,21.0.0-2-g8dde007+04a6aea1af,21.0.0-2-g8f08a60+9402881886,21.0.0-2-ga326454+3ac4acbffc,21.0.0-2-ga63a54e+81dd751046,21.0.0-2-gc738bc1+5f65c6e7a9,21.0.0-2-gde069b7+26c92b3210,21.0.0-2-gecfae73+0993ddc9bd,21.0.0-2-gfc62afb+e2614ded12,21.0.0-21-gba890a8+5a4f502a26,21.0.0-23-g9966ff26+03098d1af8,21.0.0-3-g357aad2+8ad216c477,21.0.0-3-g4be5c26+e2614ded12,21.0.0-3-g6d51c4a+4d2fe0280d,21.0.0-3-g7d9da8d+75b29a8a7f,21.0.0-3-gaa929c8+522e0f12c2,21.0.0-3-ge02ed75+4d2fe0280d,21.0.0-4-g3300ddd+e70536a077,21.0.0-4-gc004bbf+eac6615e82,21.0.0-4-gccdca77+f94adcd104,21.0.0-4-gd1c1571+18b81799f9,21.0.0-5-g7b47fff+4d2fe0280d,21.0.0-5-gb155db7+d2632f662b,21.0.0-5-gdf36809+637e4641ee,21.0.0-6-g722ad07+28c848f42a,21.0.0-7-g959bb79+522e0f12c2,21.0.0-7-gfd72ab2+cf01990774,21.0.0-9-g87fb7b8d+e2ab11cdd6,w.2021.04
LSSTDataManagementBasePackage
image.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2016 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 "ndarray/pybind11.h"
26 
27 #include "lsst/afw/image/Image.h"
29 #include "lsst/afw/image/Mask.h"
30 #include "lsst/afw/fits.h"
32 
33 namespace py = pybind11;
34 using namespace pybind11::literals;
35 
36 namespace lsst {
37 namespace afw {
38 namespace image {
39 
40 namespace {
41 
42 template <typename PixelT>
43 using PyImageBase = py::class_<ImageBase<PixelT>, std::shared_ptr<ImageBase<PixelT>>>;
44 
45 template <typename PixelT>
46 using PyImage = py::class_<Image<PixelT>, std::shared_ptr<Image<PixelT>>, ImageBase<PixelT>>;
47 
48 template <typename PixelT>
49 using PyDecoratedImage = py::class_<DecoratedImage<PixelT>, std::shared_ptr<DecoratedImage<PixelT>>>;
50 
51 template <typename MaskPixelT>
52 using PyMask = py::class_<Mask<MaskPixelT>, std::shared_ptr<Mask<MaskPixelT>>, ImageBase<MaskPixelT>>;
53 
62 template <typename FromPixelT, typename ToPixelT>
63 static void declareCastConstructor(PyImage<ToPixelT> &cls) {
64  cls.def(py::init<Image<FromPixelT> const &, bool const>(), "src"_a, "deep"_a);
65 }
66 
67 template <typename PixelT>
68 static void declareImageBase(py::module &mod, std::string const &suffix) {
69  PyImageBase<PixelT> cls(mod, ("ImageBase" + suffix).c_str());
70 
71  using Array = typename ImageBase<PixelT>::Array;
72 
73  cls.def(py::init<lsst::geom::Extent2I const &>(), "dimensions"_a = lsst::geom::Extent2I());
74  cls.def(py::init<ImageBase<PixelT> const &, bool>(), "src"_a, "deep"_a = false);
75  cls.def(py::init<ImageBase<PixelT> const &, lsst::geom::Box2I const &, ImageOrigin, bool>(), "src"_a,
76  "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
77  cls.def(py::init<Array const &, bool, lsst::geom::Point2I const &>(), "array"_a, "deep"_a = false,
78  "xy0"_a = lsst::geom::Point2I());
79 
80  cls.def("assign", &ImageBase<PixelT>::assign, "rhs"_a, "bbox"_a = lsst::geom::Box2I(),
81  "origin"_a = PARENT,
82  py::is_operator()); // py::is_operator is a workaround for code in slicing.py
83  // that expects NotImplemented to be returned on failure.
84  cls.def("getWidth", &ImageBase<PixelT>::getWidth);
85  cls.def("getHeight", &ImageBase<PixelT>::getHeight);
86  cls.def("getX0", &ImageBase<PixelT>::getX0);
87  cls.def("getY0", &ImageBase<PixelT>::getY0);
88  cls.def("getXY0", &ImageBase<PixelT>::getXY0);
89  cls.def("positionToIndex", &ImageBase<PixelT>::positionToIndex, "position"_a, "xOrY"_a);
90  cls.def("indexToPosition", &ImageBase<PixelT>::indexToPosition, "index"_a, "xOrY"_a);
91  cls.def("getDimensions", &ImageBase<PixelT>::getDimensions);
92  cls.def("getArray", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray);
93  cls.def_property("array", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray,
94  [](ImageBase<PixelT> &self, ndarray::Array<PixelT const, 2, 0> const &array) {
95  // Avoid self-assignment, which is invoked when a Python in-place operator is used.
96  if (array.shallow() != self.getArray().shallow()) {
97  self.getArray().deep() = array;
98  }
99  });
100  cls.def("setXY0", (void (ImageBase<PixelT>::*)(lsst::geom::Point2I const)) & ImageBase<PixelT>::setXY0,
101  "xy0"_a);
102  cls.def("setXY0", (void (ImageBase<PixelT>::*)(int const, int const)) & ImageBase<PixelT>::setXY0, "x0"_a,
103  "y0"_a);
104  cls.def("getBBox", &ImageBase<PixelT>::getBBox, "origin"_a = PARENT);
105 
106  cls.def("set", [](ImageBase<PixelT> &img, PixelT val) { img = val; });
107  cls.def("_set",
108  [](ImageBase<PixelT> &img, geom::Point2I const &index, PixelT val, ImageOrigin origin) {
109  python::checkBounds(index, img.getBBox(origin));
110  img.get(index, origin) = val;
111  },
112  "index"_a, "value"_a, "origin"_a);
113  cls.def("_get",
114  [](ImageBase<PixelT> &img, geom::Point2I const &index, ImageOrigin origin) {
115  python::checkBounds(index, img.getBBox(origin));
116  return img.get(index, origin);
117  },
118  "index"_a, "origin"_a);
119 }
120 
121 template <typename MaskPixelT>
122 static void declareMask(py::module &mod, std::string const &suffix) {
123  PyMask<MaskPixelT> cls(mod, ("Mask" + suffix).c_str());
124 
125  /* Constructors */
126  cls.def(py::init<unsigned int, unsigned int, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
127  "width"_a, "height"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
128  cls.def(py::init<unsigned int, unsigned int, MaskPixelT,
129  typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
130  "width"_a, "height"_a, "initialValue"_a,
131  "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
132  cls.def(py::init<lsst::geom::Extent2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
133  "dimensions"_a = lsst::geom::Extent2I(),
134  "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
135  cls.def(py::init<lsst::geom::Extent2I const &, MaskPixelT,
136  typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
137  "dimensions"_a = lsst::geom::Extent2I(), "initialValue"_a,
138  "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
139  cls.def(py::init<lsst::geom::Box2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(), "bbox"_a,
140  "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
141  cls.def(py::init<lsst::geom::Box2I const &, MaskPixelT,
142  typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
143  "bbox"_a, "initialValue"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
144  cls.def(py::init<const Mask<MaskPixelT> &, const bool>(), "src"_a, "deep"_a = false);
145  cls.def(py::init<const Mask<MaskPixelT> &, const lsst::geom::Box2I &, ImageOrigin const, const bool>(),
146  "src"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
147  cls.def(py::init<ndarray::Array<MaskPixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(),
148  "array"_a, "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
150  lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
151  "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
152  "origin"_a = PARENT, "conformMasks"_a = false, "allowUnsafe"_a = false);
153  cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<lsst::daf::base::PropertySet>,
154  lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
155  "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
156  "origin"_a = PARENT, "conformMasks"_a = false, "allowUnsafe"_a = false);
158  ImageOrigin, bool, bool>(),
159  "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
160  "conformMasks"_a = false, "allowUnsafe"_a = false);
161 
162  /* Operators */
163  cls.def("__ior__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self |= other; });
164  cls.def("__ior__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self |= other; });
165  cls.def("__ior__", [](Mask<MaskPixelT> &self, int other) { return self |= other; });
166  cls.def("__iand__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self &= other; });
167  cls.def("__iand__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self &= other; });
168  cls.def("__iand__", [](Mask<MaskPixelT> &self, int other) { return self &= other; });
169  cls.def("__ixor__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self ^= other; });
170  cls.def("__ixor__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self ^= other; });
171  cls.def("__ixor__", [](Mask<MaskPixelT> &self, int other) { return self ^= other; });
172 
173  /* Members */
174  cls.def("swap", (void (Mask<MaskPixelT>::*)(Mask<MaskPixelT> &)) & Mask<MaskPixelT>::swap);
175  cls.def("writeFits",
176  (void (Mask<MaskPixelT>::*)(std::string const &,
178  std::string const &) const) &
180  "fileName"_a, "metadata"_a = std::shared_ptr<lsst::daf::base::PropertySet>(), "mode"_a = "w");
181  cls.def("writeFits",
182  (void (Mask<MaskPixelT>::*)(fits::MemFileManager &,
184  std::string const &) const) &
186  "manager"_a, "metadata"_a = std::shared_ptr<lsst::daf::base::PropertySet>(), "mode"_a = "w");
187  cls.def("writeFits",
188  (void (Mask<MaskPixelT>::*)(fits::Fits &, std::shared_ptr<lsst::daf::base::PropertySet const>)
189  const) &
191  "fitsfile"_a, "metadata"_a = std::shared_ptr<lsst::daf::base::PropertySet const>());
192  cls.def("writeFits",
193  (void (Mask<MaskPixelT>::*)(std::string const &, fits::ImageWriteOptions const &,
195  const) &
197  "filename"_a, "options"_a, "mode"_a = "w",
199  cls.def("writeFits",
200  (void (Mask<MaskPixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
202  const) &
204  "manager"_a, "options"_a, "mode"_a = "w",
206  cls.def("writeFits",
207  (void (Mask<MaskPixelT>::*)(fits::Fits &, fits::ImageWriteOptions const &,
210  "fits"_a, "options"_a, "header"_a = std::shared_ptr<daf::base::PropertyList>());
211  cls.def_static("readFits", (Mask<MaskPixelT>(*)(std::string const &, int))Mask<MaskPixelT>::readFits,
212  "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
213  cls.def_static("readFits", (Mask<MaskPixelT>(*)(fits::MemFileManager &, int))Mask<MaskPixelT>::readFits,
214  "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
215  cls.def_static("interpret", Mask<MaskPixelT>::interpret);
216  cls.def("subset", &Mask<MaskPixelT>::subset, "bbox"_a, "origin"_a = PARENT);
217  cls.def("getAsString", &Mask<MaskPixelT>::getAsString);
218  cls.def("clearAllMaskPlanes", &Mask<MaskPixelT>::clearAllMaskPlanes);
219  cls.def("clearMaskPlane", &Mask<MaskPixelT>::clearMaskPlane);
220  cls.def("setMaskPlaneValues", &Mask<MaskPixelT>::setMaskPlaneValues);
221  cls.def_static("parseMaskPlaneMetadata", Mask<MaskPixelT>::parseMaskPlaneMetadata);
222  cls.def_static("clearMaskPlaneDict", Mask<MaskPixelT>::clearMaskPlaneDict);
223  cls.def_static("removeMaskPlane", Mask<MaskPixelT>::removeMaskPlane);
224  cls.def("removeAndClearMaskPlane", &Mask<MaskPixelT>::removeAndClearMaskPlane, "name"_a,
225  "removeFromDefault"_a = false);
226  cls.def_static("getMaskPlane", Mask<MaskPixelT>::getMaskPlane);
227  cls.def_static("getPlaneBitMask", (MaskPixelT(*)(const std::string &))Mask<MaskPixelT>::getPlaneBitMask);
228  cls.def_static("getPlaneBitMask",
229  (MaskPixelT(*)(const std::vector<std::string> &))Mask<MaskPixelT>::getPlaneBitMask);
230  cls.def_static("getNumPlanesMax", Mask<MaskPixelT>::getNumPlanesMax);
231  cls.def_static("getNumPlanesUsed", Mask<MaskPixelT>::getNumPlanesUsed);
232  cls.def("getMaskPlaneDict", &Mask<MaskPixelT>::getMaskPlaneDict);
233  cls.def("printMaskPlanes", &Mask<MaskPixelT>::printMaskPlanes);
234  cls.def_static("addMaskPlanesToMetadata", Mask<MaskPixelT>::addMaskPlanesToMetadata);
235  cls.def("conformMaskPlanes", &Mask<MaskPixelT>::conformMaskPlanes);
236  cls.def_static("addMaskPlane", (int (*)(const std::string &))Mask<MaskPixelT>::addMaskPlane);
237 }
238 
239 template <typename PixelT>
240 static PyImage<PixelT> declareImage(py::module &mod, const std::string &suffix) {
241  PyImage<PixelT> cls(mod, ("Image" + suffix).c_str());
242 
243  /* Constructors */
244  cls.def(py::init<unsigned int, unsigned int, PixelT>(), "width"_a, "height"_a, "intialValue"_a = 0);
245  cls.def(py::init<lsst::geom::Extent2I const &, PixelT>(), "dimensions"_a = lsst::geom::Extent2I(),
246  "initialValue"_a = 0);
247  cls.def(py::init<lsst::geom::Box2I const &, PixelT>(), "bbox"_a, "initialValue"_a = 0);
248  cls.def(py::init<Image<PixelT> const &, lsst::geom::Box2I const &, ImageOrigin const, const bool>(),
249  "rhs"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
250  cls.def(py::init<ndarray::Array<PixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(), "array"_a,
251  "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
253  lsst::geom::Box2I const &, ImageOrigin, bool>(),
254  "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
255  "origin"_a = PARENT, "allowUnsafe"_a = false);
256  cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<daf::base::PropertySet>,
257  lsst::geom::Box2I const &, ImageOrigin, bool>(),
258  "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(),
259  "origin"_a = PARENT, "allowUnsafe"_a = false);
261  ImageOrigin, bool>(),
262  "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
263  "allowUnsafe"_a = false);
264 
265  /* Operators */
266  cls.def("__iadd__", [](Image<PixelT> &self, PixelT const &other) { return self += other; });
267  cls.def("__iadd__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self += other; });
268  cls.def("__iadd__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
269  return self += other;
270  });
271  cls.def("__isub__", [](Image<PixelT> &self, PixelT const &other) { return self -= other; });
272  cls.def("__isub__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self -= other; });
273  cls.def("__isub__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
274  return self -= other;
275  });
276  cls.def("__imul__", [](Image<PixelT> &self, PixelT const &other) { return self *= other; });
277  cls.def("__imul__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self *= other; });
278  cls.def("__itruediv__", [](Image<PixelT> &self, PixelT const &other) { return self /= other; });
279  cls.def("__itruediv__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self /= other; });
280 
281  /* Members */
282  cls.def("scaledPlus", &Image<PixelT>::scaledPlus);
283  cls.def("scaledMinus", &Image<PixelT>::scaledMinus);
284  cls.def("scaledMultiplies", &Image<PixelT>::scaledMultiplies);
285  cls.def("scaledDivides", &Image<PixelT>::scaledDivides);
286 
287  cls.def("subset", &Image<PixelT>::subset, "bbox"_a, "origin"_a = PARENT);
288 
289  cls.def("writeFits",
290  (void (Image<PixelT>::*)(std::string const &, std::shared_ptr<daf::base::PropertySet const>,
291  std::string const &) const) &
293  "fileName"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(), "mode"_a = "w");
294  cls.def("writeFits",
295  (void (Image<PixelT>::*)(fits::MemFileManager &, std::shared_ptr<daf::base::PropertySet const>,
296  std::string const &) const) &
298  "manager"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>(), "mode"_a = "w");
299  cls.def("writeFits",
300  (void (Image<PixelT>::*)(fits::Fits &, std::shared_ptr<daf::base::PropertySet const>) const) &
302  "fitsfile"_a, "metadata"_a = std::shared_ptr<daf::base::PropertySet const>());
303  cls.def("writeFits",
304  (void (Image<PixelT>::*)(std::string const &, fits::ImageWriteOptions const &,
308  "filename"_a, "options"_a, "mode"_a = "w",
311  cls.def("writeFits",
312  (void (Image<PixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
316  "manager"_a, "options"_a, "mode"_a = "w", "header"_a = std::shared_ptr<daf::base::PropertyList>(),
318  cls.def("writeFits",
319  (void (Image<PixelT>::*)(fits::Fits &, fits::ImageWriteOptions const &,
323  "fits"_a, "options"_a, "header"_a = std::shared_ptr<daf::base::PropertyList>(),
325 
326  cls.def_static("readFits", (Image<PixelT>(*)(std::string const &, int))Image<PixelT>::readFits,
327  "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
328  cls.def_static("readFits", (Image<PixelT>(*)(fits::MemFileManager &, int))Image<PixelT>::readFits,
329  "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
330  cls.def("sqrt", &Image<PixelT>::sqrt);
331 
332  return cls;
333 }
334 
335 template <typename PixelT>
336 static void declareDecoratedImage(py::module &mod, std::string const &suffix) {
337  PyDecoratedImage<PixelT> cls(mod, ("DecoratedImage" + suffix).c_str());
338 
339  cls.def(py::init<const lsst::geom::Extent2I &>(), "dimensions"_a = lsst::geom::Extent2I());
340  cls.def(py::init<const lsst::geom::Box2I &>(), "bbox"_a);
341  cls.def(py::init<std::shared_ptr<Image<PixelT>>>(), "rhs"_a);
342  cls.def(py::init<DecoratedImage<PixelT> const &, const bool>(), "rhs"_a, "deep"_a = false);
343  cls.def(py::init<std::string const &, const int, lsst::geom::Box2I const &, ImageOrigin const, bool>(),
344  "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
345  "allowUnsafe"_a = false);
346 
347  cls.def("getMetadata", &DecoratedImage<PixelT>::getMetadata);
348  cls.def("setMetadata", &DecoratedImage<PixelT>::setMetadata);
349  cls.def("getWidth", &DecoratedImage<PixelT>::getWidth);
350  cls.def("getHeight", &DecoratedImage<PixelT>::getHeight);
351  cls.def("getX0", &DecoratedImage<PixelT>::getX0);
352  cls.def("getY0", &DecoratedImage<PixelT>::getY0);
353  cls.def("getDimensions", &DecoratedImage<PixelT>::getDimensions);
354  cls.def("swap", &DecoratedImage<PixelT>::swap);
355  cls.def("writeFits",
357  std::string const &>(&DecoratedImage<PixelT>::writeFits, py::const_),
358  "filename"_a, "metadata"_a = std::shared_ptr<daf::base::PropertyList>(), "mode"_a = "w");
359  cls.def("writeFits",
360  py::overload_cast<std::string const &, fits::ImageWriteOptions const &,
362  &DecoratedImage<PixelT>::writeFits, py::const_),
363  "filename"_a, "options"_a, "metadata"_a = std::shared_ptr<daf::base::PropertyList>(),
364  "mode"_a = "w");
365  cls.def("getImage", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
366  cls.def_property_readonly("image", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
367  cls.def("getGain", &DecoratedImage<PixelT>::getGain);
368  cls.def("setGain", &DecoratedImage<PixelT>::setGain);
369 }
370 
371 /* Declare ImageSlice operators separately since they are only instantiated for float double */
372 template <typename PixelT>
373 static void addImageSliceOperators(
374  py::class_<Image<PixelT>, std::shared_ptr<Image<PixelT>>, ImageBase<PixelT>> &cls) {
375  cls.def("__add__",
376  [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self + other; },
377  py::is_operator());
378  cls.def("__sub__",
379  [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self - other; },
380  py::is_operator());
381  cls.def("__mul__",
382  [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self * other; },
383  py::is_operator());
384  cls.def("__truediv__",
385  [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self / other; },
386  py::is_operator());
387  cls.def("__iadd__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
388  self += other;
389  return self;
390  });
391  cls.def("__isub__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
392  self -= other;
393  return self;
394  });
395  cls.def("__imul__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
396  self *= other;
397  return self;
398  });
399  cls.def("__itruediv__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
400  self /= other;
401  return self;
402  });
403 }
404 
405 template <typename PixelT, typename PyClass>
406 static void addGeneralizedCopyConstructors(PyClass &cls) {
407  cls.def(py::init<Image<int> const &, const bool>(), "rhs"_a, "deep"_a = false);
408  cls.def(py::init<Image<float> const &, const bool>(), "rhs"_a, "deep"_a = false);
409  cls.def(py::init<Image<double> const &, const bool>(), "rhs"_a, "deep"_a = false);
410  cls.def(py::init<Image<std::uint16_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
411  cls.def(py::init<Image<std::uint64_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
412 
413  cls.def("convertI", [](Image<PixelT> const &self) { return Image<int>(self, true); });
414  cls.def("convertF", [](Image<PixelT> const &self) { return Image<float>(self, true); });
415  cls.def("convertD", [](Image<PixelT> const &self) { return Image<double>(self, true); });
416  cls.def("convertU", [](Image<PixelT> const &self) { return Image<std::uint16_t>(self, true); });
417  cls.def("convertL", [](Image<PixelT> const &self) { return Image<std::uint64_t>(self, true); });
418 
419  cls.def("convertFloat", [](Image<PixelT> const &self) { return Image<float>(self, true); });
420  cls.def("convertDouble", [](Image<PixelT> const &self) { return Image<double>(self, true); });
421 }
422 
423 PYBIND11_MODULE(image, mod) {
424  py::module::import("lsst.daf.base");
425 
426  py::enum_<ImageOrigin>(mod, "ImageOrigin")
427  .value("PARENT", ImageOrigin::PARENT)
428  .value("LOCAL", ImageOrigin::LOCAL)
429  .export_values();
430 
431  declareImageBase<int>(mod, "I");
432  declareImageBase<float>(mod, "F");
433  declareImageBase<double>(mod, "D");
434  declareImageBase<std::uint16_t>(mod, "U");
435  declareImageBase<std::uint64_t>(mod, "L");
436 
437  // Mask must be declared before Image because a mask is used as a default value in at least one method
438  declareMask<MaskPixel>(mod, "X");
439 
440  auto clsImageI = declareImage<int>(mod, "I");
441  auto clsImageF = declareImage<float>(mod, "F");
442  auto clsImageD = declareImage<double>(mod, "D");
443  auto clsImageU = declareImage<std::uint16_t>(mod, "U");
444  auto clsImageL = declareImage<std::uint64_t>(mod, "L");
445 
446  // Add generalized copy constructors
447  addGeneralizedCopyConstructors<int>(clsImageI);
448  addGeneralizedCopyConstructors<float>(clsImageF);
449  addGeneralizedCopyConstructors<double>(clsImageD);
450  addGeneralizedCopyConstructors<std::uint16_t>(clsImageU);
451  addGeneralizedCopyConstructors<std::uint64_t>(clsImageL);
452 
453  // Add slice operators only for float and double
454  addImageSliceOperators<float>(clsImageF);
455  addImageSliceOperators<double>(clsImageD);
456 
457  declareDecoratedImage<int>(mod, "I");
458  declareDecoratedImage<float>(mod, "F");
459  declareDecoratedImage<double>(mod, "D");
460  declareDecoratedImage<std::uint16_t>(mod, "U");
461  declareDecoratedImage<std::uint64_t>(mod, "L");
462 
463  // Declare constructors for casting all exposure types to to float and double
464  // (the only two types of casts that Python supports)
465  declareCastConstructor<int, float>(clsImageF);
466  declareCastConstructor<int, double>(clsImageD);
467 
468  declareCastConstructor<float, double>(clsImageD);
469 
470  declareCastConstructor<double, float>(clsImageF);
471 
472  declareCastConstructor<std::uint16_t, float>(clsImageF);
473  declareCastConstructor<std::uint16_t, double>(clsImageD);
474 
475  declareCastConstructor<std::uint64_t, float>(clsImageF);
476  declareCastConstructor<std::uint64_t, double>(clsImageD);
477 
478  // Note: wrap both the Image and MaskedImage versions of imagesOverlap in the MaskedImage wrapper,
479  // as wrapping the Image version here results in it being invisible in lsst.afw.image
480 
481  mod.def("bboxFromMetadata", &bboxFromMetadata);
482 }
483 } // namespace
484 } // namespace image
485 } // namespace afw
486 } // namespace lsst
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
lsst::meas::algorithms.stamps.writeFits
def writeFits(filename, stamp_ims, metadata, write_mask, write_variance)
Definition: stamps.py:38
lsst::afw::image::LOCAL
@ LOCAL
Definition: ImageBase.h:94
std::string
STL class.
std::shared_ptr
STL class.
lsst::afw::image::Mask
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:77
lsst::afw::image::detail::MaskPlaneDict
std::map< std::string, int > MaskPlaneDict
Definition: Mask.h:58
lsst::afw::image::positionToIndex
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
lsst::afw::math::scaledPlus
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
Definition: ConvolveImage.cc:162
lsst::afw::fits::DEFAULT_HDU
const int DEFAULT_HDU
Specify that the default HDU should be read.
Definition: fitsDefaults.h:18
std::vector< std::string >
fits.h
lsst::ip::diffim::detail::PixelT
float PixelT
Definition: AssessSpatialKernelVisitor.cc:208
lsst::afw
Definition: imageAlgorithm.dox:1
ImageSlice.h
lsst::afw::image::indexToPosition
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
val
ImageT val
Definition: CR.cc:146
Image.h
lsst::afw::geom.transform.transformContinued.cls
cls
Definition: transformContinued.py:33
other
ItemVariant const * other
Definition: Schema.cc:56
PyClass
py::class_< ProductBoundedField, std::shared_ptr< ProductBoundedField >, BoundedField > PyClass
Definition: productBoundedField.cc:32
indexing.h
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
lsst::afw::image::bboxFromMetadata
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
Definition: Image.cc:688
lsst::afw::math::Function2< double >
Mask.h
lsst::afw::image::python::checkBounds
void checkBounds(geom::Point2I const &index, geom::Box2I const &bbox)
Definition: indexing.h:30
lsst::geom::Point< int, 2 >
lsst::afw::cameraGeom::swap
void swap(CameraSys &a, CameraSys &b)
Definition: CameraSys.h:157
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::afw::image::PARENT
@ PARENT
Definition: ImageBase.h:94
pybind11
Definition: _GenericMap.cc:40
lsst::afw::image::ImageOrigin
ImageOrigin
Definition: ImageBase.h:94
lsst::utils.tests.init
def init()
Definition: tests.py:59
lsst::geom::Extent< int, 2 >
lsst::meas::modelfit.psf.psfContinued.module
module
Definition: psfContinued.py:42
lsst::afw::cameraGeom::PYBIND11_MODULE
PYBIND11_MODULE(camera, mod)
Definition: camera.cc:133