LSST Applications g180d380827+770a9040cc,g2079a07aa2+86d27d4dc4,g2305ad1205+09cfdadad9,g2bbee38e9b+c6a8a0fb72,g337abbeb29+c6a8a0fb72,g33d1c0ed96+c6a8a0fb72,g3a166c0a6a+c6a8a0fb72,g3ddfee87b4+1ea5e09c42,g48712c4677+7e2ea9cd42,g487adcacf7+301d09421d,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+96fcb956a6,g64a986408d+23540ee355,g858d7b2824+23540ee355,g864b0138d7+aa38e45daa,g95921f966b+d83dc58ecd,g991b906543+23540ee355,g99cad8db69+7f13b58a93,g9c22b2923f+e2510deafe,g9ddcbc5298+9a081db1e4,ga1e77700b3+03d07e1c1f,gb0e22166c9+60f28cb32d,gb23b769143+23540ee355,gba4ed39666+c2a2e4ac27,gbb8dafda3b+49e7449578,gbd998247f1+585e252eca,gc120e1dc64+1bbfa184e1,gc28159a63d+c6a8a0fb72,gc3e9b769f7+385ea95214,gcf0d15dbbd+1ea5e09c42,gdaeeff99f8+f9a426f77a,ge6526c86ff+1bccc98490,ge79ae78c31+c6a8a0fb72,gee10cc3b42+585e252eca,w.2024.18
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"
26#include "lsst/utils/python.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::class_<ImageBase<PixelT>, std::shared_ptr<ImageBase<PixelT>>>;
46
47template <typename PixelT>
48using PyImage = py::class_<Image<PixelT>, std::shared_ptr<Image<PixelT>>, ImageBase<PixelT>>;
49
50template <typename PixelT>
51using PyDecoratedImage = py::class_<DecoratedImage<PixelT>, std::shared_ptr<DecoratedImage<PixelT>>>;
52
53template <typename MaskPixelT>
54using PyMask = py::class_<Mask<MaskPixelT>, std::shared_ptr<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::utils::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("getX0", &ImageBase<PixelT>::getX0);
88 cls.def("getY0", &ImageBase<PixelT>::getY0);
89 cls.def("getXY0", &ImageBase<PixelT>::getXY0);
90 cls.def("positionToIndex", &ImageBase<PixelT>::positionToIndex, "position"_a, "xOrY"_a);
91 cls.def("indexToPosition", &ImageBase<PixelT>::indexToPosition, "index"_a, "xOrY"_a);
92 cls.def("getDimensions", &ImageBase<PixelT>::getDimensions);
93 cls.def("getArray", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray);
94 cls.def_property("array", (Array(ImageBase<PixelT>::*)()) & ImageBase<PixelT>::getArray,
95 [](ImageBase<PixelT> &self, ndarray::Array<PixelT const, 2, 0> const &array) {
96 // Avoid self-assignment, which is invoked when a Python in-place operator is
97 // used.
98 if (array.shallow() != self.getArray().shallow()) {
99 self.getArray().deep() = array;
100 }
101 });
102 cls.def("setXY0",
103 (void (ImageBase<PixelT>::*)(lsst::geom::Point2I const)) & ImageBase<PixelT>::setXY0,
104 "xy0"_a);
105 cls.def("setXY0", (void (ImageBase<PixelT>::*)(int const, int const)) & ImageBase<PixelT>::setXY0,
106 "x0"_a, "y0"_a);
107 cls.def("getBBox", &ImageBase<PixelT>::getBBox, "origin"_a = PARENT);
108
109 cls.def("set", [](ImageBase<PixelT> &img, PixelT val) { img = val; });
110 cls.def(
111 "_set",
112 [](ImageBase<PixelT> &img, geom::Point2I const &index, PixelT val, ImageOrigin origin) {
113 python::checkBounds(index, img.getBBox(origin));
114 img.get(index, origin) = val;
115 },
116 "index"_a, "value"_a, "origin"_a);
117 cls.def(
118 "_get",
119 [](ImageBase<PixelT> &img, geom::Point2I const &index, ImageOrigin origin) {
120 python::checkBounds(index, img.getBBox(origin));
121 return img.get(index, origin);
122 },
123 "index"_a, "origin"_a);
124 });
125}
126
127template <typename MaskPixelT>
128static void declareMask(lsst::utils::python::WrapperCollection &wrappers, std::string const &suffix) {
129 wrappers.wrapType(PyMask<MaskPixelT>(wrappers.module, ("Mask" + suffix).c_str()), [](auto &mod,
130 auto &cls) {
131 /* Constructors */
132 cls.def(py::init<unsigned int, unsigned int, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
133 "width"_a, "height"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
134 cls.def(py::init<unsigned int, unsigned int, MaskPixelT,
135 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
136 "width"_a, "height"_a, "initialValue"_a,
137 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
138 cls.def(py::init<lsst::geom::Extent2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
139 "dimensions"_a = lsst::geom::Extent2I(),
140 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
141 cls.def(py::init<lsst::geom::Extent2I const &, MaskPixelT,
142 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
143 "dimensions"_a = lsst::geom::Extent2I(), "initialValue"_a,
144 "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
145 cls.def(py::init<lsst::geom::Box2I const &, typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
146 "bbox"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
147 cls.def(py::init<lsst::geom::Box2I const &, MaskPixelT,
148 typename Mask<MaskPixelT>::MaskPlaneDict const &>(),
149 "bbox"_a, "initialValue"_a, "planeDefs"_a = typename Mask<MaskPixelT>::MaskPlaneDict());
150 cls.def(py::init<const Mask<MaskPixelT> &, const bool>(), "src"_a, "deep"_a = false);
151 cls.def(py::init<const Mask<MaskPixelT> &, const lsst::geom::Box2I &, ImageOrigin const,
152 const bool>(),
153 "src"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
154 cls.def(py::init<ndarray::Array<MaskPixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(),
155 "array"_a, "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
156 cls.def(py::init<std::string const &, int, std::shared_ptr<lsst::daf::base::PropertySet>,
157 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
158 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
159 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
160 "allowUnsafe"_a = false);
161 cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<lsst::daf::base::PropertySet>,
162 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
163 "manager"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
164 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "conformMasks"_a = false,
165 "allowUnsafe"_a = false);
166 cls.def(py::init<fits::Fits &, std::shared_ptr<lsst::daf::base::PropertySet>,
167 lsst::geom::Box2I const &, ImageOrigin, bool, bool>(),
168 "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
169 "conformMasks"_a = false, "allowUnsafe"_a = false);
170
171 /* Operators */
172 cls.def("__ior__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self |= other; });
173 cls.def("__ior__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self |= other; });
174 cls.def("__ior__", [](Mask<MaskPixelT> &self, int other) { return self |= other; });
175 cls.def("__iand__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self &= other; });
176 cls.def("__iand__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self &= other; });
177 cls.def("__iand__", [](Mask<MaskPixelT> &self, int other) { return self &= other; });
178 cls.def("__ixor__", [](Mask<MaskPixelT> &self, Mask<MaskPixelT> &other) { return self ^= other; });
179 cls.def("__ixor__", [](Mask<MaskPixelT> &self, MaskPixelT const other) { return self ^= other; });
180 cls.def("__ixor__", [](Mask<MaskPixelT> &self, int other) { return self ^= other; });
181
182 /* Members */
183 cls.def("swap", (void (Mask<MaskPixelT>::*)(Mask<MaskPixelT> &)) & Mask<MaskPixelT>::swap);
184 cls.def("writeFits",
185 (void (Mask<MaskPixelT>::*)(std::string const &,
186 daf::base::PropertySet const *,
187 std::string const &) const) &
188 Mask<MaskPixelT>::writeFits,
189 "fileName"_a, "metadata"_a = nullptr, "mode"_a = "w");
190 cls.def("writeFits",
191 (void (Mask<MaskPixelT>::*)(fits::MemFileManager &,
192 daf::base::PropertySet const *,
193 std::string const &) const) &
194 Mask<MaskPixelT>::writeFits,
195 "manager"_a, "metadata"_a = nullptr, "mode"_a = "w");
196 cls.def("writeFits",
197 (void (Mask<MaskPixelT>::*)(fits::Fits &, daf::base::PropertySet const *)
198 const) &
199 Mask<MaskPixelT>::writeFits,
200 "fitsfile"_a, "metadata"_a = nullptr);
201 cls.def("writeFits",
202 (void (Mask<MaskPixelT>::*)(std::string const &, fits::ImageWriteOptions const &,
203 std::string const &,
204 daf::base::PropertySet const *) const) &
205 Mask<MaskPixelT>::writeFits,
206 "filename"_a, "options"_a, "mode"_a = "w",
207 "header"_a = nullptr);
208 cls.def("writeFits",
209 (void (Mask<MaskPixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
210 std::string const &,
211 daf::base::PropertySet const *) const) &
212 Mask<MaskPixelT>::writeFits,
213 "manager"_a, "options"_a, "mode"_a = "w",
214 "header"_a = nullptr);
215 cls.def("writeFits",
216 (void (Mask<MaskPixelT>::*)(fits::Fits &, fits::ImageWriteOptions const &,
217 daf::base::PropertySet const *) const) &
218 Mask<MaskPixelT>::writeFits,
219 "fits"_a, "options"_a, "header"_a = nullptr);
220 cls.def_static("readFits", (Mask<MaskPixelT>(*)(std::string const &, int))Mask<MaskPixelT>::readFits,
221 "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
222 cls.def_static("readFits",
223 (Mask<MaskPixelT>(*)(fits::MemFileManager &, int))Mask<MaskPixelT>::readFits,
224 "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
225 cls.def_static("interpret", Mask<MaskPixelT>::interpret);
226 cls.def("subset", &Mask<MaskPixelT>::subset, "bbox"_a, "origin"_a = PARENT);
227 cls.def("getAsString", &Mask<MaskPixelT>::getAsString);
228 cls.def("clearAllMaskPlanes", &Mask<MaskPixelT>::clearAllMaskPlanes);
229 cls.def("clearMaskPlane", &Mask<MaskPixelT>::clearMaskPlane);
230 cls.def("setMaskPlaneValues", &Mask<MaskPixelT>::setMaskPlaneValues);
231 cls.def_static("parseMaskPlaneMetadata", Mask<MaskPixelT>::parseMaskPlaneMetadata);
232 cls.def_static("clearMaskPlaneDict", Mask<MaskPixelT>::clearMaskPlaneDict);
233 cls.def_static("removeMaskPlane", Mask<MaskPixelT>::removeMaskPlane);
234 cls.def("removeAndClearMaskPlane", &Mask<MaskPixelT>::removeAndClearMaskPlane, "name"_a,
235 "removeFromDefault"_a = false);
236 cls.def_static("getMaskPlane", Mask<MaskPixelT>::getMaskPlane);
237 cls.def_static("getPlaneBitMask",
238 (MaskPixelT(*)(const std::string &))Mask<MaskPixelT>::getPlaneBitMask);
239 cls.def_static("getPlaneBitMask",
240 (MaskPixelT(*)(const std::vector<std::string> &))Mask<MaskPixelT>::getPlaneBitMask);
241 cls.def_static("getNumPlanesMax", Mask<MaskPixelT>::getNumPlanesMax);
242 cls.def_static("getNumPlanesUsed", Mask<MaskPixelT>::getNumPlanesUsed);
243 cls.def("getMaskPlaneDict", &Mask<MaskPixelT>::getMaskPlaneDict);
244 cls.def("printMaskPlanes", &Mask<MaskPixelT>::printMaskPlanes);
245 cls.def_static("addMaskPlanesToMetadata", Mask<MaskPixelT>::addMaskPlanesToMetadata);
246 cls.def("conformMaskPlanes", &Mask<MaskPixelT>::conformMaskPlanes);
247 cls.def_static("addMaskPlane", (int (*)(const std::string &))Mask<MaskPixelT>::addMaskPlane);
248 });
249}
250
251template <typename PixelT>
252static PyImage<PixelT> declareImage(lsst::utils::python::WrapperCollection &wrappers,
253 const std::string &suffix) {
254 return wrappers.wrapType(PyImage<PixelT>(wrappers.module, ("Image" + suffix).c_str()), [](auto &mod,
255 auto &cls) {
256 /* Constructors */
257 cls.def(py::init<unsigned int, unsigned int, PixelT>(), "width"_a, "height"_a, "intialValue"_a = 0);
258 cls.def(py::init<lsst::geom::Extent2I const &, PixelT>(), "dimensions"_a = lsst::geom::Extent2I(),
259 "initialValue"_a = 0);
260 cls.def(py::init<lsst::geom::Box2I const &, PixelT>(), "bbox"_a, "initialValue"_a = 0);
261 cls.def(py::init<Image<PixelT> const &, lsst::geom::Box2I const &, ImageOrigin const, const bool>(),
262 "rhs"_a, "bbox"_a, "origin"_a = PARENT, "deep"_a = false);
263 cls.def(py::init<ndarray::Array<PixelT, 2, 1> const &, bool, lsst::geom::Point2I const &>(),
264 "array"_a, "deep"_a = false, "xy0"_a = lsst::geom::Point2I());
265 cls.def(py::init<std::string const &, int, std::shared_ptr<daf::base::PropertySet>,
266 lsst::geom::Box2I const &, ImageOrigin, bool>(),
267 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "metadata"_a = nullptr,
268 "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT, "allowUnsafe"_a = false);
269 cls.def(py::init<fits::MemFileManager &, int, std::shared_ptr<daf::base::PropertySet>,
270 lsst::geom::Box2I const &, ImageOrigin, bool>(),
271 "manager"_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::Fits &, std::shared_ptr<daf::base::PropertySet>, lsst::geom::Box2I const &,
274 ImageOrigin, bool>(),
275 "fitsFile"_a, "metadata"_a = nullptr, "bbox"_a = lsst::geom::Box2I(), "origin"_a = PARENT,
276 "allowUnsafe"_a = false);
277
278 /* Operators */
279 cls.def("__iadd__", [](Image<PixelT> &self, PixelT const &other) { return self += other; });
280 cls.def("__iadd__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self += other; });
281 cls.def("__iadd__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
282 return self += other;
283 });
284 cls.def("__isub__", [](Image<PixelT> &self, PixelT const &other) { return self -= other; });
285 cls.def("__isub__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self -= other; });
286 cls.def("__isub__", [](Image<PixelT> &self, lsst::afw::math::Function2<double> const &other) {
287 return self -= other;
288 });
289 cls.def("__imul__", [](Image<PixelT> &self, PixelT const &other) { return self *= other; });
290 cls.def("__imul__", [](Image<PixelT> &self, Image<PixelT> const &other) { return self *= other; });
291 cls.def("__itruediv__", [](Image<PixelT> &self, PixelT const &other) { return self /= other; });
292 cls.def("__itruediv__",
293 [](Image<PixelT> &self, Image<PixelT> const &other) { return self /= other; });
294
295 /* Members */
296 cls.def("scaledPlus", &Image<PixelT>::scaledPlus);
297 cls.def("scaledMinus", &Image<PixelT>::scaledMinus);
298 cls.def("scaledMultiplies", &Image<PixelT>::scaledMultiplies);
299 cls.def("scaledDivides", &Image<PixelT>::scaledDivides);
300
301 cls.def("subset", &Image<PixelT>::subset, "bbox"_a, "origin"_a = PARENT);
302
303 cls.def("writeFits",
304 (void (Image<PixelT>::*)(std::string const &, daf::base::PropertySet const *,
305 std::string const &) const) &
306 Image<PixelT>::writeFits,
307 "fileName"_a, "metadata"_a = nullptr, "mode"_a = "w");
308 cls.def("writeFits",
309 (void (Image<PixelT>::*)(fits::MemFileManager &,
310 daf::base::PropertySet const *, std::string const &)
311 const) &
312 Image<PixelT>::writeFits,
313 "manager"_a, "metadata"_a = nullptr, "mode"_a = "w");
314 cls.def("writeFits",
315 (void (Image<PixelT>::*)(fits::Fits &, daf::base::PropertySet const *) const) &
316 Image<PixelT>::writeFits,
317 "fitsfile"_a, "metadata"_a = nullptr);
318 cls.def("writeFits",
319 (void (Image<PixelT>::*)(std::string const &, fits::ImageWriteOptions const &,
320 std::string const &, daf::base::PropertySet const *,
321 image::Mask<image::MaskPixel> const *) const) &
322 Image<PixelT>::writeFits,
323 "filename"_a, "options"_a, "mode"_a = "w",
324 "header"_a = nullptr,
325 "mask"_a = nullptr);
326 cls.def("writeFits",
327 (void (Image<PixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
328 std::string const &, daf::base::PropertySet const *,
329 image::Mask<image::MaskPixel> const *) const) &
330 Image<PixelT>::writeFits,
331 "manager"_a, "options"_a, "mode"_a = "w",
332 "header"_a = nullptr,
333 "mask"_a = nullptr);
334 cls.def("writeFits",
335 (void (Image<PixelT>::*)(fits::Fits &, fits::ImageWriteOptions const &,
336 daf::base::PropertySet const *,
337 image::Mask<image::MaskPixel> const *) const) &
338 Image<PixelT>::writeFits,
339 "fits"_a, "options"_a, "header"_a = nullptr,
340 "mask"_a = nullptr);
341
342 cls.def_static("readFits", (Image<PixelT>(*)(std::string const &, int))Image<PixelT>::readFits,
343 "filename"_a, "hdu"_a = fits::DEFAULT_HDU);
344 cls.def_static("readFits", (Image<PixelT>(*)(fits::MemFileManager &, int))Image<PixelT>::readFits,
345 "manager"_a, "hdu"_a = fits::DEFAULT_HDU);
346 cls.def("sqrt", &Image<PixelT>::sqrt);
347 });
348}
349
350template <typename PixelT>
351static void declareDecoratedImage(lsst::utils::python::WrapperCollection &wrappers,
352 std::string const &suffix) {
353 wrappers.wrapType(
354 PyDecoratedImage<PixelT>(wrappers.module, ("DecoratedImage" + suffix).c_str()),
355 [](auto &mod, auto &cls) {
356 cls.def(py::init<const lsst::geom::Extent2I &>(), "dimensions"_a = lsst::geom::Extent2I());
357 cls.def(py::init<const lsst::geom::Box2I &>(), "bbox"_a);
358 cls.def(py::init<std::shared_ptr<Image<PixelT>>>(), "rhs"_a);
359 cls.def(py::init<DecoratedImage<PixelT> const &, const bool>(), "rhs"_a, "deep"_a = false);
360 cls.def(py::init<std::string const &, const int, lsst::geom::Box2I const &, ImageOrigin const,
361 bool>(),
362 "fileName"_a, "hdu"_a = fits::DEFAULT_HDU, "bbox"_a = lsst::geom::Box2I(),
363 "origin"_a = PARENT, "allowUnsafe"_a = false);
364
365 cls.def("getMetadata", &DecoratedImage<PixelT>::getMetadata);
366 cls.def("setMetadata", &DecoratedImage<PixelT>::setMetadata);
367 cls.def("getWidth", &DecoratedImage<PixelT>::getWidth);
368 cls.def("getHeight", &DecoratedImage<PixelT>::getHeight);
369 cls.def("getX0", &DecoratedImage<PixelT>::getX0);
370 cls.def("getY0", &DecoratedImage<PixelT>::getY0);
371 cls.def("getDimensions", &DecoratedImage<PixelT>::getDimensions);
372 cls.def("swap", &DecoratedImage<PixelT>::swap);
373 cls.def("writeFits",
374 py::overload_cast<std::string const &, daf::base::PropertySet const *,
375 std::string const &>(&DecoratedImage<PixelT>::writeFits,
376 py::const_),
377 "filename"_a, "metadata"_a = nullptr,
378 "mode"_a = "w");
379 cls.def("writeFits",
380 py::overload_cast<std::string const &, fits::ImageWriteOptions const &,
381 daf::base::PropertySet const *, std::string const &>(
382 &DecoratedImage<PixelT>::writeFits, py::const_),
383 "filename"_a, "options"_a, "metadata"_a = nullptr,
384 "mode"_a = "w");
385 cls.def("getImage", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
386 cls.def_property_readonly("image", py::overload_cast<>(&DecoratedImage<PixelT>::getImage));
387 cls.def("getGain", &DecoratedImage<PixelT>::getGain);
388 cls.def("setGain", &DecoratedImage<PixelT>::setGain);
389 });
390}
391
392/* Declare ImageSlice operators separately since they are only instantiated for float double */
393template <typename PixelT>
394static void addImageSliceOperators(
395 py::class_<Image<PixelT>, std::shared_ptr<Image<PixelT>>, ImageBase<PixelT>> &cls) {
396 cls.def(
397 "__add__",
398 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self + other; },
399 py::is_operator());
400 cls.def(
401 "__sub__",
402 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self - other; },
403 py::is_operator());
404 cls.def(
405 "__mul__",
406 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self * other; },
407 py::is_operator());
408 cls.def(
409 "__truediv__",
410 [](Image<PixelT> const &self, ImageSlice<PixelT> const &other) { return self / other; },
411 py::is_operator());
412 cls.def("__iadd__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
413 self += other;
414 return self;
415 });
416 cls.def("__isub__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
417 self -= other;
418 return self;
419 });
420 cls.def("__imul__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
421 self *= other;
422 return self;
423 });
424 cls.def("__itruediv__", [](Image<PixelT> &self, ImageSlice<PixelT> const &other) {
425 self /= other;
426 return self;
427 });
428}
429
430template <typename PixelT, typename PyClass>
431static void addGeneralizedCopyConstructors(PyClass &cls) {
432 cls.def(py::init<Image<int> const &, const bool>(), "rhs"_a, "deep"_a = false);
433 cls.def(py::init<Image<float> const &, const bool>(), "rhs"_a, "deep"_a = false);
434 cls.def(py::init<Image<double> const &, const bool>(), "rhs"_a, "deep"_a = false);
435 cls.def(py::init<Image<std::uint16_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
436 cls.def(py::init<Image<std::uint64_t> const &, const bool>(), "rhs"_a, "deep"_a = false);
437
438 cls.def("convertI", [](Image<PixelT> const &self) { return Image<int>(self, true); });
439 cls.def("convertF", [](Image<PixelT> const &self) { return Image<float>(self, true); });
440 cls.def("convertD", [](Image<PixelT> const &self) { return Image<double>(self, true); });
441 cls.def("convertU", [](Image<PixelT> const &self) { return Image<std::uint16_t>(self, true); });
442 cls.def("convertL", [](Image<PixelT> const &self) { return Image<std::uint64_t>(self, true); });
443
444 cls.def("convertFloat", [](Image<PixelT> const &self) { return Image<float>(self, true); });
445 cls.def("convertDouble", [](Image<PixelT> const &self) { return Image<double>(self, true); });
446}
447} // namespace
448void wrapImage(lsst::utils::python::WrapperCollection &wrappers) {
449 wrappers.addSignatureDependency("lsst.daf.base");
450 wrappers.addSignatureDependency("lsst.geom");
451 wrappers.wrapType(py::enum_<ImageOrigin>(wrappers.module, "ImageOrigin"), [](auto &mod, auto &enm) {
452 enm.value("PARENT", ImageOrigin::PARENT);
453 enm.value("LOCAL", ImageOrigin::LOCAL);
454 enm.export_values();
455 });
456
457 declareImageBase<int>(wrappers, "I");
458 declareImageBase<float>(wrappers, "F");
459 declareImageBase<double>(wrappers, "D");
460 declareImageBase<std::uint16_t>(wrappers, "U");
461 declareImageBase<std::uint64_t>(wrappers, "L");
462
463 // Mask must be declared before Image because a mask is used as a default value in at least one method
464 declareMask<MaskPixel>(wrappers, "X");
465
466 auto clsImageI = declareImage<int>(wrappers, "I");
467 auto clsImageF = declareImage<float>(wrappers, "F");
468 auto clsImageD = declareImage<double>(wrappers, "D");
469 auto clsImageU = declareImage<std::uint16_t>(wrappers, "U");
470 auto clsImageL = declareImage<std::uint64_t>(wrappers, "L");
471
472 // Add generalized copy constructors
473 addGeneralizedCopyConstructors<int>(clsImageI);
474 addGeneralizedCopyConstructors<float>(clsImageF);
475 addGeneralizedCopyConstructors<double>(clsImageD);
476 addGeneralizedCopyConstructors<std::uint16_t>(clsImageU);
477 addGeneralizedCopyConstructors<std::uint64_t>(clsImageL);
478
479 // Add slice operators only for float and double
480 addImageSliceOperators<float>(clsImageF);
481 addImageSliceOperators<double>(clsImageD);
482
483 declareDecoratedImage<int>(wrappers, "I");
484 declareDecoratedImage<float>(wrappers, "F");
485 declareDecoratedImage<double>(wrappers, "D");
486 declareDecoratedImage<std::uint16_t>(wrappers, "U");
487 declareDecoratedImage<std::uint64_t>(wrappers, "L");
488
489 // Declare constructors for casting all exposure types to to float and double
490 // (the only two types of casts that Python supports)
491 declareCastConstructor<int, float>(clsImageF);
492 declareCastConstructor<int, double>(clsImageD);
493
494 declareCastConstructor<float, double>(clsImageD);
495
496 declareCastConstructor<double, float>(clsImageF);
497
498 declareCastConstructor<std::uint16_t, float>(clsImageF);
499 declareCastConstructor<std::uint16_t, double>(clsImageD);
500
501 declareCastConstructor<std::uint64_t, float>(clsImageF);
502 declareCastConstructor<std::uint64_t, double>(clsImageD);
503
504 // Note: wrap both the Image and MaskedImage versions of imagesOverlap in the MaskedImage wrapper,
505 // as wrapping the Image version here results in it being invisible in lsst.afw.image
506 wrappers.wrap([](auto &mod) { mod.def("bboxFromMetadata", &bboxFromMetadata); });
507}
508} // namespace image
509} // namespace afw
510} // namespace lsst
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 Function taking two arguments.
Definition Function.h:259
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::utils::python::WrapperCollection &wrappers)
Definition _image.cc:448
Point< int, 2 > Point2I
Definition Point.h:321
writeFits(filename, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
Definition stamps.py:40
STL namespace.
ImageT val
Definition CR.cc:146