LSST Applications g00d0e8bbd7+edbf708997,g03191d30f7+9ce8016dbd,g1955dfad08+0bd186d245,g199a45376c+5137f08352,g1fd858c14a+a888a50aa2,g262e1987ae+45f9aba685,g29ae962dfc+1c7d47a24f,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3fd5ace14f+eed17d2c67,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+c4107e45b5,g67b6fd64d1+6dc8069a4c,g74acd417e5+f452e9c21a,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+2025e9ce17,g7cc15d900a+2d158402f9,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d4809ba88+c4107e45b5,g8d7436a09f+e96c132b44,g8ea07a8fe4+db21c37724,g98df359435+aae6d409c1,ga2180abaac+edbf708997,gac66b60396+966efe6077,gb632fb1845+88945a90f8,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gca7fc764a6+6dc8069a4c,gd7ef33dd92+6dc8069a4c,gda68eeecaf+7d1e613a8d,gdab6d2f7ff+f452e9c21a,gdbb4c4dda9+c4107e45b5,ge410e46f29+6dc8069a4c,ge41e95a9f2+c4107e45b5,geaed405ab2+e194be0d2b,w.2025.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
_image.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"
27#include "ndarray/pybind11.h"
28
31#include "lsst/afw/image/Mask.h"
32#include "lsst/afw/fits.h"
34
35namespace py = pybind11;
36using namespace pybind11::literals;
37
38namespace lsst {
39namespace afw {
40namespace image {
41
42namespace {
43
44template <typename PixelT>
45using PyImageBase = py::classh<ImageBase<PixelT>>;
46
47template <typename PixelT>
48using PyImage = py::classh<Image<PixelT>, ImageBase<PixelT>>;
49
50template <typename PixelT>
51using PyDecoratedImage = py::classh<DecoratedImage<PixelT>>;
52
53template <typename MaskPixelT>
54using PyMask = py::classh<Mask<MaskPixelT>, ImageBase<MaskPixelT>>;
55
64template <typename FromPixelT, typename ToPixelT>
65static void declareCastConstructor(PyImage<ToPixelT> &cls) {
66 cls.def(py::init<Image<FromPixelT> const &, bool const>(), "src"_a, "deep"_a);
67}
68
69template <typename PixelT>
70static void declareImageBase(lsst::cpputils::python::WrapperCollection &wrappers, std::string const &suffix) {
71 using Array = typename ImageBase<PixelT>::Array;
72 wrappers.wrapType(PyImageBase<PixelT>(wrappers.module, ("ImageBase" + suffix).c_str()), [](auto &mod,
73 auto &cls) {
74 cls.def(py::init<lsst::geom::Extent2I const &>(), "dimensions"_a = lsst::geom::Extent2I());
75 cls.def(py::init<ImageBase<PixelT> const &, bool>(), "src"_a, "deep"_a = false);
76 cls.def(py::init<ImageBase<PixelT> const &, lsst::geom::Box2I const &, ImageOrigin, bool>(), "src"_a,
77 "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
78 cls.def(py::init<Array const &, bool, lsst::geom::Point2I const &>(), "array"_a, "deep"_a = false,
79 "xy0"_a = lsst::geom::Point2I());
80
81 cls.def("assign", &ImageBase<PixelT>::assign, "rhs"_a, "bbox"_a = lsst::geom::Box2I(),
82 "origin"_a = PARENT,
83 py::is_operator()); // py::is_operator is a workaround for code in slicing.py
84 // that expects NotImplemented to be returned on failure.
85 cls.def("getWidth", &ImageBase<PixelT>::getWidth);
86 cls.def("getHeight", &ImageBase<PixelT>::getHeight);
87 cls.def_property_readonly("width", &ImageBase<PixelT>::getWidth);
88 cls.def_property_readonly("height", &ImageBase<PixelT>::getHeight);
89 cls.def("getX0", &ImageBase<PixelT>::getX0);
90 cls.def("getY0", &ImageBase<PixelT>::getY0);
91 cls.def_property_readonly("x0", &ImageBase<PixelT>::getX0);
92 cls.def_property_readonly("y0", &ImageBase<PixelT>::getY0);
93 cls.def("getXY0", &ImageBase<PixelT>::getXY0);
94 cls.def("positionToIndex", &ImageBase<PixelT>::positionToIndex, "position"_a, "xOrY"_a);
95 cls.def("indexToPosition", &ImageBase<PixelT>::indexToPosition, "index"_a, "xOrY"_a);
96 cls.def("getDimensions", &ImageBase<PixelT>::getDimensions);
97 cls.def("getArray", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray);
98 cls.def_property("array", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray,
99 [](py::object &self, py::object value) {
100 if (value == py::none()) {
101 throw py::type_error("Cannot assign None to an array.");
102 }
103 py::array array = self.attr("array");
104 array[py::ellipsis()] = value;
105 });
106 cls.def("setXY0",
108 "xy0"_a);
109 cls.def("setXY0", (void (ImageBase<PixelT>::*)(int const, int const)) & ImageBase<PixelT>::setXY0,
110 "x0"_a, "y0"_a);
111 cls.def("getBBox", &ImageBase<PixelT>::getBBox, "origin"_a = PARENT);
112
113 cls.def("set", [](ImageBase<PixelT> &img, PixelT val) { img = val; });
114 cls.def(
115 "_set",
116 [](ImageBase<PixelT> &img, geom::Point2I const &index, PixelT val, ImageOrigin origin) {
117 python::checkBounds(index, img.getBBox(origin));
118 img.get(index, origin) = val;
119 },
120 "index"_a, "value"_a, "origin"_a);
121 cls.def(
122 "_get",
123 [](ImageBase<PixelT> &img, geom::Point2I const &index, ImageOrigin origin) {
124 python::checkBounds(index, img.getBBox(origin));
125 return img.get(index, origin);
126 },
127 "index"_a, "origin"_a);
128 });
129}
130
131template <typename MaskPixelT>
132static void declareMask(lsst::cpputils::python::WrapperCollection &wrappers, std::string const &suffix) {
133 wrappers.wrapType(PyMask<MaskPixelT>(wrappers.module, ("Mask" + suffix).c_str()), [](auto &mod,
134 auto &cls) {
135 /* Constructors */
136 cls.def(py::init<unsigned int, unsigned int, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
137 "width"_a, "height"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
138 cls.def(py::init<unsigned int, unsigned int, MaskPixelT,
139 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
140 "width"_a, "height"_a, "initialValue"_a,
141 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
142 cls.def(py::init<lsst::geom::Extent2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
143 "dimensions"_a = lsst::geom::Extent2I(),
144 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
145 cls.def(py::init<lsst::geom::Extent2I const &, MaskPixelT,
146 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
147 "dimensions"_a = lsst::geom::Extent2I(), "initialValue"_a,
148 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
149 cls.def(py::init<lsst::geom::Box2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
150 "bbox"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
151 cls.def(py::init<lsst::geom::Box2I const &, MaskPixelT,
152 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
153 "bbox"_a, "initialValue"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
154 cls.def(py::init<const Mask<MaskPixelT> &, const bool>(), "src"_a, "deep"_a = false);
155 cls.def(py::init<const Mask<MaskPixelT> &, const lsst::geom::Box2I &, ImageOrigin const,
156 const bool>(),
157 "src"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
158 cls.def(py::init<ndarray::Array<MaskPixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(),
159 "array"_a, "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
160 cls.def(py::init<std::string const &, int, std::shared_ptr<lsst::daf::base::PropertySet>,
161 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
162 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
163 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
164 "allowUnsafe"_a = false);
165 cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<lsst::daf::base::PropertySet>,
166 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
167 "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
168 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
169 "allowUnsafe"_a = false);
170 cls.def(py::init<fits::Fits &, std::shared_ptr<lsst::daf::base::PropertySet>,
171 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
172 "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
173 "conformMasks"_a = false, "allowUnsafe"_a = false);
174
175 /* Operators */
176 cls.def("__ior__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self |= other; });
177 cls.def("__ior__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self |= other; });
178 cls.def("__ior__", [](Mask<MaskPixelT> &self, int other) { return self |= other; });
179 cls.def("__iand__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self &= other; });
180 cls.def("__iand__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self &= other; });
181 cls.def("__iand__", [](Mask<MaskPixelT> &self, int other) { return self &= other; });
182 cls.def("__ixor__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self ^= other; });
183 cls.def("__ixor__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self ^= other; });
184 cls.def("__ixor__", [](Mask<MaskPixelT> &self, int other) { return self ^= other; });
185
186 /* Members */
187 cls.def("swap", (void (Mask<MaskPixelT>::*)(Mask<MaskPixelT> &)) & Mask<MaskPixelT>::swap);
188 cls.def("writeFits",
189 (void (Mask<MaskPixelT>::*)(std::string const &,
190 daf::base::PropertySet const *,
191 std::string const &) const) &
193 "fileName"_a, "metadata"_a = nullptr, "mode"_a = "w");
194 cls.def("writeFits",
195 (void (Mask<MaskPixelT>::*)(fits::MemFileManager &,
196 daf::base::PropertySet const *,
197 std::string const &) const) &
199 "manager"_a, "metadata"_a = nullptr, "mode"_a = "w");
200 cls.def("writeFits",
201 (void (Mask<MaskPixelT>::*)(fits::Fits &, daf::base::PropertySet const *)
202 const) &
204 "fitsfile"_a, "metadata"_a = nullptr);
205 cls.def("writeFits",
206 (void (Mask<MaskPixelT>::*)(std::string const &, fits::CompressionOptions const *,
207 std::string const &,
208 daf::base::PropertySet const *) const) &
210 "filename"_a, "options"_a, "mode"_a = "w",
211 "header"_a = nullptr);
212 cls.def("writeFits",
213 (void (Mask<MaskPixelT>::*)(fits::MemFileManager &, fits::CompressionOptions const *,
214 std::string const &,
215 daf::base::PropertySet const *) const) &
217 "manager"_a, "options"_a, "mode"_a = "w",
218 "header"_a = nullptr);
219 cls.def("writeFits",
220 (void (Mask<MaskPixelT>::*)(fits::Fits &, fits::CompressionOptions const *,
221 daf::base::PropertySet const *) const) &
223 "fits"_a, "options"_a, "header"_a = nullptr);
224 cls.def_static("readFits", (Mask<MaskPixelT>(*)(std::string const &, int))Mask<MaskPixelT>::readFits,
225 "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
226 cls.def_static("readFits",
227 (Mask<MaskPixelT>(*)(fits::MemFileManager &, int))Mask<MaskPixelT>::readFits,
228 "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
229 cls.def_static("interpret", Mask<MaskPixelT>::interpret);
230 cls.def("subset", &Mask<MaskPixelT>::subset, "bbox"_a, "origin"_a = PARENT);
231 cls.def("getAsString", &Mask<MaskPixelT>::getAsString);
232 cls.def("clearAllMaskPlanes", &Mask<MaskPixelT>::clearAllMaskPlanes);
233 cls.def("clearMaskPlane", &Mask<MaskPixelT>::clearMaskPlane);
234 cls.def("setMaskPlaneValues", &Mask<MaskPixelT>::setMaskPlaneValues);
235 cls.def_static("parseMaskPlaneMetadata", Mask<MaskPixelT>::parseMaskPlaneMetadata);
236 cls.def_static("clearMaskPlaneDict", Mask<MaskPixelT>::clearMaskPlaneDict);
237 cls.def_static("removeMaskPlane", Mask<MaskPixelT>::removeMaskPlane);
238 cls.def("removeAndClearMaskPlane", &Mask<MaskPixelT>::removeAndClearMaskPlane, "name"_a,
239 "removeFromDefault"_a = false);
240 cls.def_static("getMaskPlane", Mask<MaskPixelT>::getMaskPlane);
241 cls.def_static("getPlaneBitMask",
242 (MaskPixelT(*)(const std::string &))Mask<MaskPixelT>::getPlaneBitMask);
243 cls.def_static("getPlaneBitMask",
244 (MaskPixelT(*)(const std::vector<std::string> &))Mask<MaskPixelT>::getPlaneBitMask);
245 cls.def_static("getNumPlanesMax", Mask<MaskPixelT>::getNumPlanesMax);
246 cls.def_static("getNumPlanesUsed", Mask<MaskPixelT>::getNumPlanesUsed);
247 cls.def("getMaskPlaneDict", &Mask<MaskPixelT>::getMaskPlaneDict);
248 cls.def("printMaskPlanes", &Mask<MaskPixelT>::printMaskPlanes);
249 cls.def_static("addMaskPlanesToMetadata", Mask<MaskPixelT>::addMaskPlanesToMetadata);
250 cls.def("conformMaskPlanes", &Mask<MaskPixelT>::conformMaskPlanes);
251 cls.def_static("addMaskPlane", (int (*)(const std::string &))Mask<MaskPixelT>::addMaskPlane);
252 });
253}
254
255template <typename PixelT>
256static PyImage<PixelT> declareImage(lsst::cpputils::python::WrapperCollection &wrappers,
257 const std::string &suffix) {
258 return wrappers.wrapType(PyImage<PixelT>(wrappers.module, ("Image" + suffix).c_str()), [](auto &mod,
259 auto &cls) {
260 /* Constructors */
261 cls.def(py::init<unsigned int, unsigned int, PixelT>(), "width"_a, "height"_a, "intialValue"_a = 0);
262 cls.def(py::init<lsst::geom::Extent2I const &, PixelT>(), "dimensions"_a = lsst::geom::Extent2I(),
263 "initialValue"_a = 0);
264 cls.def(py::init<lsst::geom::Box2I const &, PixelT>(), "bbox"_a, "initialValue"_a = 0);
265 cls.def(py::init<Image<PixelT> const &, lsst::geom::Box2I const &, ImageOrigin const, const bool>(),
266 "rhs"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
267 cls.def(py::init<ndarray::Array<PixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(),
268 "array"_a, "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
269 cls.def(py::init<std::string const &, int, std::shared_ptr<daf::base::PropertySet>,
270 lsst::geom::Box2I const &, ImageOrigin, bool>(),
271 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
272 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false);
273 cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<daf::base::PropertySet>,
274 lsst::geom::Box2I const &, ImageOrigin, bool>(),
275 "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
276 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false);
277 cls.def(py::init<fits::Fits &, std::shared_ptr<daf::base::PropertySet>, lsst::geom::Box2I const &,
278 ImageOrigin, bool>(),
279 "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
280 "allowUnsafe"_a = false);
281
282 /* Operators */
283 cls.def("__iadd__", [](Image<PixelT> &self, PixelT const &other) { return self += other; });
284 cls.def("__iadd__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self += other; });
285 cls.def("__iadd__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
286 return self += other;
287 });
288 cls.def("__isub__", [](Image<PixelT> &self, PixelT const &other) { return self -= other; });
289 cls.def("__isub__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self -= other; });
290 cls.def("__isub__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
291 return self -= other;
292 });
293 cls.def("__imul__", [](Image<PixelT> &self, PixelT const &other) { return self *= other; });
294 cls.def("__imul__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self *= other; });
295 cls.def("__itruediv__", [](Image<PixelT> &self, PixelT const &other) { return self /= other; });
296 cls.def("__itruediv__",
297 [](Image<PixelT> &self, Image<PixelT> const &other) { return self /= other; });
298
299 /* Members */
300 cls.def("scaledPlus", &Image<PixelT>::scaledPlus);
301 cls.def("scaledMinus", &Image<PixelT>::scaledMinus);
302 cls.def("scaledMultiplies", &Image<PixelT>::scaledMultiplies);
303 cls.def("scaledDivides", &Image<PixelT>::scaledDivides);
304
305 cls.def("subset", &Image<PixelT>::subset, "bbox"_a, "origin"_a = PARENT);
306
307 cls.def("writeFits",
308 (void (Image<PixelT>::*)(std::string const &, daf::base::PropertySet const *,
309 std::string const &) const) &
310 Image<PixelT>::writeFits,
311 "fileName"_a, "metadata"_a = nullptr, "mode"_a = "w");
312 cls.def("writeFits",
314 daf::base::PropertySet const *, std::string const &)
315 const) &
316 Image<PixelT>::writeFits,
317 "manager"_a, "metadata"_a = nullptr, "mode"_a = "w");
318 cls.def("writeFits",
319 (void (Image<PixelT>::*)(fits::Fits &, daf::base::PropertySet const *) const) &
320 Image<PixelT>::writeFits,
321 "fitsfile"_a, "metadata"_a = nullptr);
322 cls.def("writeFits",
323 (void (Image<PixelT>::*)(std::string const &, fits::CompressionOptions const *,
324 std::string const &, daf::base::PropertySet const *,
325 image::Mask<image::MaskPixel> const *) const) &
326 Image<PixelT>::writeFits,
327 "filename"_a, "options"_a, "mode"_a = "w",
328 "header"_a = nullptr,
329 "mask"_a = nullptr);
330 cls.def("writeFits",
332 std::string const &, daf::base::PropertySet const *,
333 image::Mask<image::MaskPixel> const *) const) &
334 Image<PixelT>::writeFits,
335 "manager"_a, "options"_a, "mode"_a = "w",
336 "header"_a = nullptr,
337 "mask"_a = nullptr);
338 cls.def("writeFits",
340 daf::base::PropertySet const *,
341 image::Mask<image::MaskPixel> const *) const) &
342 Image<PixelT>::writeFits,
343 "fits"_a, "options"_a, "header"_a = nullptr,
344 "mask"_a = nullptr);
345
346 cls.def_static("readFits", (Image<PixelT>(*)(std::string const &, int))Image<PixelT>::readFits,
347 "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
348 cls.def_static("readFits", (Image<PixelT>(*)(fits::MemFileManager &, int))Image<PixelT>::readFits,
349 "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
350 cls.def("sqrt", &Image<PixelT>::sqrt);
351 });
352}
353
354template <typename PixelT>
355static void declareDecoratedImage(lsst::cpputils::python::WrapperCollection &wrappers,
356 std::string const &suffix) {
357 wrappers.wrapType(
358 PyDecoratedImage<PixelT>(wrappers.module, ("DecoratedImage" + suffix).c_str()),
359 [](auto &mod, auto &cls) {
360 cls.def(py::init<const lsst::geom::Extent2I &>(), "dimensions"_a = lsst::geom::Extent2I());
361 cls.def(py::init<const lsst::geom::Box2I &>(), "bbox"_a);
362 cls.def(py::init<std::shared_ptr<Image<PixelT>>>(), "rhs"_a);
363 cls.def(py::init<DecoratedImage<PixelT> const &, const bool>(), "rhs"_a, "deep"_a = false);
364 cls.def(py::init<std::string const &, const int, lsst::geom::Box2I const &, ImageOrigin const,
365 bool>(),
366 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "bbox"_a = lsst::geom::Box2I(),
367 "origin"_a = PARENT, "allowUnsafe"_a = false);
368
369 cls.def("getMetadata", &DecoratedImage<PixelT>::getMetadata);
370 cls.def("setMetadata", &DecoratedImage<PixelT>::setMetadata);
371 cls.def("getWidth", &DecoratedImage<PixelT>::getWidth);
372 cls.def("getHeight", &DecoratedImage<PixelT>::getHeight);
373 cls.def("getX0", &DecoratedImage<PixelT>::getX0);
374 cls.def("getY0", &DecoratedImage<PixelT>::getY0);
375 cls.def("getDimensions", &DecoratedImage<PixelT>::getDimensions);
376 cls.def("swap", &DecoratedImage<PixelT>::swap);
377 cls.def("writeFits",
378 py::overload_cast<std::string const &, daf::base::PropertySet const *,
379 std::string const &>(&DecoratedImage<PixelT>::writeFits,
380 py::const_),
381 "filename"_a, "metadata"_a = nullptr,
382 "mode"_a = "w");
383 cls.def("writeFits",
384 py::overload_cast<std::string const &, fits::CompressionOptions const *,
385 daf::base::PropertySet const *, std::string const &>(
386 &DecoratedImage<PixelT>::writeFits, py::const_),
387 "filename"_a, "options"_a, "metadata"_a = nullptr,
388 "mode"_a = "w");
389 cls.def("getImage", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
390 cls.def_property_readonly("image", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
391 cls.def("getGain", &DecoratedImage<PixelT>::getGain);
392 cls.def("setGain", &DecoratedImage<PixelT>::setGain);
393 });
394}
395
396/* Declare ImageSlice operators separately since they are only instantiated for float double */
397template <typename PixelT>
398static void addImageSliceOperators(
399 py::classh<Image<PixelT>, ImageBase<PixelT>> &cls) {
400 cls.def(
401 "__add__",
402 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self + other; },
403 py::is_operator());
404 cls.def(
405 "__sub__",
406 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self - other; },
407 py::is_operator());
408 cls.def(
409 "__mul__",
410 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self * other; },
411 py::is_operator());
412 cls.def(
413 "__truediv__",
414 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self / other; },
415 py::is_operator());
416 cls.def("__iadd__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
417 self += other;
418 return self;
419 });
420 cls.def("__isub__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
421 self -= other;
422 return self;
423 });
424 cls.def("__imul__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
425 self *= other;
426 return self;
427 });
428 cls.def("__itruediv__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
429 self /= other;
430 return self;
431 });
432}
433
434template <typename PixelT, typename PyClass>
435static void addGeneralizedCopyConstructors(PyClass &cls) {
436 cls.def(py::init<Image<int> const &, const bool>(), "rhs"_a, "deep"_a = false);
437 cls.def(py::init<Image<float> const &, const bool>(), "rhs"_a, "deep"_a = false);
438 cls.def(py::init<Image<double> const &, const bool>(), "rhs"_a, "deep"_a = false);
439 cls.def(py::init<Image<std::uint16_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
440 cls.def(py::init<Image<std::uint64_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
441
442 cls.def("convertI", [](Image<PixelT> const &self) { return Image<int>(self, true); });
443 cls.def("convertF", [](Image<PixelT> const &self) { return Image<float>(self, true); });
444 cls.def("convertD", [](Image<PixelT> const &self) { return Image<double>(self, true); });
445 cls.def("convertU", [](Image<PixelT> const &self) { return Image<std::uint16_t>(self, true); });
446 cls.def("convertL", [](Image<PixelT> const &self) { return Image<std::uint64_t>(self, true); });
447
448 cls.def("convertFloat", [](Image<PixelT> const &self) { return Image<float>(self, true); });
449 cls.def("convertDouble", [](Image<PixelT> const &self) { return Image<double>(self, true); });
450}
451} // namespace
453 wrappers.addSignatureDependency("lsst.daf.base");
454 wrappers.addSignatureDependency("lsst.geom");
455 wrappers.wrapType(py::enum_<ImageOrigin>(wrappers.module, "ImageOrigin"), [](auto &mod, auto &enm) {
456 enm.value("PARENT", ImageOrigin::PARENT);
457 enm.value("LOCAL", ImageOrigin::LOCAL);
458 enm.export_values();
459 });
460
461 declareImageBase<int>(wrappers, "I");
462 declareImageBase<float>(wrappers, "F");
463 declareImageBase<double>(wrappers, "D");
464 declareImageBase<std::uint16_t>(wrappers, "U");
465 declareImageBase<std::uint64_t>(wrappers, "L");
466
467 // Mask must be declared before Image because a mask is used as a default value in at least one method
468 declareMask<MaskPixel>(wrappers, "X");
469
470 auto clsImageI = declareImage<int>(wrappers, "I");
471 auto clsImageF = declareImage<float>(wrappers, "F");
472 auto clsImageD = declareImage<double>(wrappers, "D");
473 auto clsImageU = declareImage<std::uint16_t>(wrappers, "U");
474 auto clsImageL = declareImage<std::uint64_t>(wrappers, "L");
475
476 // Add generalized copy constructors
477 addGeneralizedCopyConstructors<int>(clsImageI);
478 addGeneralizedCopyConstructors<float>(clsImageF);
479 addGeneralizedCopyConstructors<double>(clsImageD);
480 addGeneralizedCopyConstructors<std::uint16_t>(clsImageU);
481 addGeneralizedCopyConstructors<std::uint64_t>(clsImageL);
482
483 // Add slice operators only for float and double
484 addImageSliceOperators<float>(clsImageF);
485 addImageSliceOperators<double>(clsImageD);
486
487 declareDecoratedImage<int>(wrappers, "I");
488 declareDecoratedImage<float>(wrappers, "F");
489 declareDecoratedImage<double>(wrappers, "D");
490 declareDecoratedImage<std::uint16_t>(wrappers, "U");
491 declareDecoratedImage<std::uint64_t>(wrappers, "L");
492
493 // Declare constructors for casting all exposure types to to float and double
494 // (the only two types of casts that Python supports)
495 declareCastConstructor<int, float>(clsImageF);
496 declareCastConstructor<int, double>(clsImageD);
497
498 declareCastConstructor<float, double>(clsImageD);
499
500 declareCastConstructor<double, float>(clsImageF);
501
502 declareCastConstructor<std::uint16_t, float>(clsImageF);
503 declareCastConstructor<std::uint16_t, double>(clsImageD);
504
505 declareCastConstructor<std::uint64_t, float>(clsImageF);
506 declareCastConstructor<std::uint64_t, double>(clsImageD);
507
508 // Note: wrap both the Image and MaskedImage versions of imagesOverlap in the MaskedImage wrapper,
509 // as wrapping the Image version here results in it being invisible in lsst.afw.image
510 wrappers.wrap([](auto &mod) { mod.def("bboxFromMetadata", &bboxFromMetadata); });
511}
512} // namespace image
513} // namespace afw
514} // namespace lsst
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:242
Lifetime-management for memory that goes into FITS memory files.
Definition fits.h:126
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition ImageBase.h:102
void setXY0(lsst::geom::Point2I const origin)
Set the ImageBase's origin.
Definition ImageBase.h:434
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition ImageBase.h:445
typename ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
Definition ImageBase.h:149
A class to represent a 2-dimensional array of pixels.
Definition Image.h:51
Represent a 2-dimensional array of bitmask pixels.
Definition Mask.h:82
A helper class for subdividing pybind11 module across multiple translation units (i....
Definition python.h:242
void addSignatureDependency(std::string const &name)
Indicate an external module that provides a type used in function/method signatures.
Definition python.h:357
void wrap(WrapperCallback function)
Add a set of wrappers without defining a class.
Definition python.h:369
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
pybind11::module module
The module object passed to the PYBIND11_MODULE block that contains this WrapperCollection.
Definition python.h:448
const int DEFAULT_HDU
Specify that the default HDU should be read.
void checkBounds(geom::Point2I const &index, geom::Box2I const &bbox)
Definition indexing.h:30
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
Definition Image.cc:681
void wrapImage(lsst::cpputils::python::WrapperCollection &wrappers)
Definition _image.cc:452
Point< int, 2 > Point2I
Definition Point.h:321
Options controlling image compression with FITS.
g2d::python::Image< double > Image
Definition test_image.cc:14