24#include "pybind11/pybind11.h"
25#include "pybind11/stl.h"
27#include "ndarray/pybind11.h"
36using namespace pybind11::literals;
44template <
typename PixelT>
47template <
typename PixelT>
50template <
typename PixelT>
53template <
typename MaskPixelT>
64template <
typename FromPixelT,
typename ToPixelT>
65static void declareCastConstructor(PyImage<ToPixelT> &cls) {
69template <
typename PixelT>
72 wrappers.
wrapType(PyImageBase<PixelT>(wrappers.module, (
"ImageBase" + suffix).c_str()), [](
auto &mod,
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());
81 cls.def(
"assign", &ImageBase<PixelT>::assign,
"rhs"_a,
"bbox"_a = lsst::geom::Box2I(),
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) {
98 if (array.shallow() != self.getArray().shallow()) {
99 self.getArray().deep() = array;
105 cls.def(
"setXY0", (
void (ImageBase<PixelT>::*)(
int const,
int const)) & ImageBase<
PixelT>::setXY0,
109 cls.def(
"set", [](ImageBase<PixelT> &img, PixelT
val) { img =
val; });
112 [](ImageBase<PixelT> &img,
geom::Point2I const &index, PixelT
val, ImageOrigin origin) {
114 img.get(index, origin) =
val;
116 "index"_a,
"value"_a,
"origin"_a);
119 [](ImageBase<PixelT> &img,
geom::Point2I const &index, ImageOrigin origin) {
121 return img.get(index, origin);
123 "index"_a,
"origin"_a);
127template <
typename MaskPixelT>
129 wrappers.
wrapType(PyMask<MaskPixelT>(wrappers.module, (
"Mask" + suffix).c_str()), [](
auto &mod,
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,
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);
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; });
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; });
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; });
186 daf::base::PropertySet const *,
187 std::string const &) const) &
189 "fileName"_a,
"metadata"_a = nullptr,
"mode"_a =
"w");
192 daf::base::PropertySet const *,
193 std::string const &) const) &
195 "manager"_a,
"metadata"_a = nullptr,
"mode"_a =
"w");
200 "fitsfile"_a,
"metadata"_a = nullptr);
204 daf::base::PropertySet const *) const) &
206 "filename"_a,
"options"_a,
"mode"_a =
"w",
207 "header"_a = nullptr);
209 (
void (
Mask<MaskPixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
211 daf::base::PropertySet const *) const) &
213 "manager"_a,
"options"_a,
"mode"_a =
"w",
214 "header"_a = nullptr);
217 daf::base::PropertySet const *) const) &
219 "fits"_a,
"options"_a,
"header"_a = nullptr);
222 cls.def_static(
"readFits",
235 "removeFromDefault"_a =
false);
237 cls.def_static(
"getPlaneBitMask",
239 cls.def_static(
"getPlaneBitMask",
251template <
typename PixelT>
254 return wrappers.
wrapType(PyImage<PixelT>(wrappers.module, (
"Image" + suffix).c_str()), [](
auto &mod,
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);
279 cls.def(
"__iadd__", [](Image<PixelT> &self, PixelT const &other) { return self += other; });
282 return self += other;
284 cls.def(
"__isub__", [](
Image<PixelT> &self, PixelT
const &other) {
return self -= other; });
287 return self -= other;
289 cls.def(
"__imul__", [](
Image<PixelT> &self, PixelT
const &other) {
return self *= other; });
291 cls.def(
"__itruediv__", [](
Image<PixelT> &self, PixelT
const &other) {
return self /= other; });
292 cls.def(
"__itruediv__",
304 (
void (
Image<PixelT>::*)(
std::string const &, daf::base::PropertySet const *,
305 std::string const &) const) &
307 "fileName"_a,
"metadata"_a = nullptr,
"mode"_a =
"w");
310 daf::base::PropertySet const *,
std::string const &)
313 "manager"_a,
"metadata"_a = nullptr,
"mode"_a =
"w");
315 (
void (
Image<PixelT>::*)(fits::Fits &, daf::base::PropertySet const *) const) &
317 "fitsfile"_a,
"metadata"_a = nullptr);
319 (
void (
Image<PixelT>::*)(
std::string const &, fits::ImageWriteOptions const &,
320 std::string const &, daf::base::PropertySet const *,
323 "filename"_a,
"options"_a,
"mode"_a =
"w",
324 "header"_a = nullptr,
327 (
void (
Image<PixelT>::*)(fits::MemFileManager &, fits::ImageWriteOptions const &,
328 std::string const &, daf::base::PropertySet const *,
331 "manager"_a,
"options"_a,
"mode"_a =
"w",
332 "header"_a = nullptr,
335 (
void (
Image<PixelT>::*)(fits::Fits &, fits::ImageWriteOptions const &,
336 daf::base::PropertySet const *,
339 "fits"_a,
"options"_a,
"header"_a = nullptr,
350template <
typename PixelT>
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,
362 "fileName"_a,
"hdu"_a = fits::DEFAULT_HDU,
"bbox"_a = lsst::geom::Box2I(),
363 "origin"_a = PARENT,
"allowUnsafe"_a = false);
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);
374 py::overload_cast<std::string const &, daf::base::PropertySet const *,
375 std::string const &>(&DecoratedImage<PixelT>::writeFits,
377 "filename"_a,
"metadata"_a = nullptr,
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,
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);
393template <
typename PixelT>
394static void addImageSliceOperators(
398 [](
Image<PixelT> const &self, ImageSlice<PixelT>
const &other) {
return self + other; },
402 [](
Image<PixelT> const &self, ImageSlice<PixelT>
const &other) {
return self - other; },
406 [](
Image<PixelT> const &self, ImageSlice<PixelT>
const &other) {
return self * other; },
410 [](
Image<PixelT> const &self, ImageSlice<PixelT>
const &other) {
return self / other; },
412 cls.def(
"__iadd__", [](
Image<PixelT> &self, ImageSlice<PixelT>
const &other) {
416 cls.def(
"__isub__", [](
Image<PixelT> &self, ImageSlice<PixelT>
const &other) {
420 cls.def(
"__imul__", [](
Image<PixelT> &self, ImageSlice<PixelT>
const &other) {
424 cls.def(
"__itruediv__", [](
Image<PixelT> &self, ImageSlice<PixelT>
const &other) {
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);
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);
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");
464 declareMask<MaskPixel>(wrappers,
"X");
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");
473 addGeneralizedCopyConstructors<int>(clsImageI);
474 addGeneralizedCopyConstructors<float>(clsImageF);
475 addGeneralizedCopyConstructors<double>(clsImageD);
476 addGeneralizedCopyConstructors<std::uint16_t>(clsImageU);
477 addGeneralizedCopyConstructors<std::uint64_t>(clsImageL);
480 addImageSliceOperators<float>(clsImageF);
481 addImageSliceOperators<double>(clsImageD);
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");
491 declareCastConstructor<int, float>(clsImageF);
492 declareCastConstructor<int, double>(clsImageD);
494 declareCastConstructor<float, double>(clsImageD);
496 declareCastConstructor<double, float>(clsImageF);
498 declareCastConstructor<std::uint16_t, float>(clsImageF);
499 declareCastConstructor<std::uint16_t, double>(clsImageD);
501 declareCastConstructor<std::uint64_t, float>(clsImageF);
502 declareCastConstructor<std::uint64_t, double>(clsImageD);
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
typename ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
A Function taking two arguments.
A helper class for subdividing pybind11 module across multiple translation units (i....
void addSignatureDependency(std::string const &name)
Indicate an external module that provides a type used in function/method signatures.
void wrap(WrapperCallback function)
Add a set of wrappers without defining a class.
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...
const int DEFAULT_HDU
Specify that the default HDU should be read.
void checkBounds(geom::Point2I const &index, geom::Box2I const &bbox)
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
void wrapImage(lsst::cpputils::python::WrapperCollection &wrappers)
writeFits(filename, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
g2d::python::Image< double > Image
g2d::python::Image< bool > Mask