24 #include "pybind11/pybind11.h"
26 #include "pybind11/stl.h"
33 #include "ndarray/pybind11.h"
34 #include "ndarray/Array.h"
41 using namespace pybind11::literals;
49 using PySpanSet = py::class_<SpanSet, std::shared_ptr<SpanSet>>;
51 template <
typename Pixel,
typename PyClass>
52 void declareFlattenMethod(
PyClass &cls) {
54 (ndarray::Array<Pixel, 1, 1>(SpanSet::*)(ndarray::Array<Pixel, 2, 0>
const &,
56 SpanSet::flatten<Pixel, 2, 0>,
59 (ndarray::Array<Pixel, 2, 2>(SpanSet::*)(ndarray::Array<Pixel, 3, 0>
const &,
61 SpanSet::flatten<Pixel, 3, 0>,
64 (
void (SpanSet::*)(ndarray::Array<Pixel, 1, 0>
const &, ndarray::Array<Pixel, 2, 0>
const &,
66 SpanSet::flatten<Pixel, Pixel, 2, 0, 0>,
69 (
void (SpanSet::*)(ndarray::Array<Pixel, 2, 0>
const &, ndarray::Array<Pixel, 3, 0>
const &,
71 SpanSet::flatten<Pixel, Pixel, 3, 0, 0>,
75 template <
typename Pixel,
typename PyClass>
76 void declareUnflattenMethod(
PyClass &cls) {
78 (ndarray::Array<Pixel, 2, 2>(SpanSet::*)(ndarray::Array<Pixel, 1, 0>
const &input)
const) &
79 SpanSet::unflatten<Pixel, 1, 0>);
81 (ndarray::Array<Pixel, 3, 3>(SpanSet::*)(ndarray::Array<Pixel, 2, 0>
const &input)
const) &
82 SpanSet::unflatten<Pixel, 2, 0>);
84 (
void (SpanSet::*)(ndarray::Array<Pixel, 2, 0>
const &, ndarray::Array<Pixel, 1, 0>
const &,
86 SpanSet::unflatten<Pixel, Pixel, 1, 0, 0>,
89 (
void (SpanSet::*)(ndarray::Array<Pixel, 3, 0>
const &, ndarray::Array<Pixel, 2, 0>
const &,
91 SpanSet::unflatten<Pixel, Pixel, 2, 0, 0>,
95 template <
typename Pixel,
typename PyClass>
96 void declareSetMaskMethod(
PyClass &cls) {
100 template <
typename Pixel,
typename PyClass>
101 void declareClearMaskMethod(
PyClass &cls) {
105 template <
typename Pixel,
typename PyClass>
106 void declareIntersectMethod(
PyClass &cls) {
110 "other"_a,
"bitmask"_a);
115 auto tempSpanSet = SpanSet::fromMask(
mask);
116 return self.intersect(*tempSpanSet);
121 template <
typename Pixel,
typename PyClass>
122 void declareIntersectNotMethod(
PyClass &cls) {
123 cls.def(
"intersectNot",
125 SpanSet::intersectNot,
126 "other"_a,
"bitmask"_a);
131 auto tempSpanSet = SpanSet::fromMask(
mask);
132 return self.intersectNot(*tempSpanSet);
137 template <
typename Pixel,
typename PyClass>
138 void declareUnionMethod(
PyClass &cls) {
141 "other"_a,
"bitmask"_a);
146 auto tempSpanSet = SpanSet::fromMask(
mask);
147 return self.union_(*tempSpanSet);
152 template <
typename ImageT,
typename PyClass>
153 void declareCopyImage(
PyClass &cls) {
154 cls.def(
"copyImage", &SpanSet::copyImage<ImageT>);
157 template <
typename ImageT,
typename PyClass>
158 void declareCopyMaskedImage(
PyClass &cls) {
161 cls.def(
"copyMaskedImage", &SpanSet::copyMaskedImage<ImageT, MaskPixel, VariancePixel>);
164 template <
typename ImageT,
typename PyClass>
165 void declareSetImage(
PyClass &cls) {
172 template <
typename MaskPixel,
typename PyClass>
173 void declarefromMask(
PyClass &cls) {
176 return SpanSet::fromMask(
mask, bitmask);
180 template <
typename Pixel,
typename PyClass>
181 void declareMaskMethods(
PyClass &cls) {
182 declareSetMaskMethod<Pixel>(cls);
183 declareClearMaskMethod<Pixel>(cls);
184 declareIntersectMethod<Pixel>(cls);
185 declareIntersectNotMethod<Pixel>(cls);
186 declareUnionMethod<Pixel>(cls);
189 template <
typename Pixel,
typename PyClass>
190 void declareImageTypes(
PyClass &cls) {
191 declareFlattenMethod<Pixel>(cls);
192 declareUnflattenMethod<Pixel>(cls);
193 declareCopyImage<Pixel>(cls);
194 declareCopyMaskedImage<Pixel>(cls);
195 declareSetImage<Pixel>(cls);
198 void declareStencil(lsst::utils::python::WrapperCollection &wrappers) {
199 wrappers.wrapType(py::enum_<Stencil>(wrappers.module,
"Stencil"), [](
auto &mod,
auto &enm) {
200 enm.value(
"CIRCLE", Stencil::CIRCLE);
201 enm.value(
"BOX", Stencil::BOX);
202 enm.value(
"MANHATTAN", Stencil::MANHATTAN);
206 void declareSpanSet(lsst::utils::python::WrapperCollection &wrappers) {
209 wrappers.wrapType(PySpanSet(wrappers.module,
"SpanSet"), [](
auto &mod,
auto &cls) {
211 cls.def(py::init<>());
212 cls.def(py::init<lsst::geom::Box2I>(),
"box"_a);
213 cls.def(py::init<std::vector<Span>, bool>(),
"spans"_a,
"normalize"_a = true);
215 table::io::python::addPersistableMethods<SpanSet>(cls);
218 cls.def(
"getArea", &SpanSet::getArea);
219 cls.def(
"getBBox", &SpanSet::getBBox);
220 cls.def(
"isContiguous", &SpanSet::isContiguous);
221 cls.def(
"shiftedBy", (std::shared_ptr<SpanSet>(SpanSet::*)(int, int) const) & SpanSet::shiftedBy);
222 cls.def(
"shiftedBy", (std::shared_ptr<SpanSet>(SpanSet::*)(lsst::geom::Extent2I const &) const) &
224 cls.def(
"clippedTo", &SpanSet::clippedTo);
225 cls.def(
"transformedBy",
226 (std::shared_ptr<SpanSet>(SpanSet::*)(lsst::geom::LinearTransform const &) const) &
227 SpanSet::transformedBy);
228 cls.def(
"transformedBy",
229 (std::shared_ptr<SpanSet>(SpanSet::*)(lsst::geom::AffineTransform const &) const) &
230 SpanSet::transformedBy);
231 cls.def(
"transformedBy",
232 (std::shared_ptr<SpanSet>(SpanSet::*)(TransformPoint2ToPoint2 const &) const) &
233 SpanSet::transformedBy);
234 cls.def(
"overlaps", &SpanSet::overlaps);
235 cls.def(
"contains", (bool (SpanSet::*)(SpanSet const &) const) & SpanSet::contains);
236 cls.def(
"contains", (bool (SpanSet::*)(lsst::geom::Point2I const &) const) & SpanSet::contains);
237 cls.def(
"computeCentroid", &SpanSet::computeCentroid);
238 cls.def(
"computeShape", &SpanSet::computeShape);
239 cls.def(
"dilated", (std::shared_ptr<SpanSet>(SpanSet::*)(int, Stencil) const) & SpanSet::dilated,
240 "radius"_a,
"stencil"_a = Stencil::CIRCLE);
241 cls.def(
"dilated", (std::shared_ptr<SpanSet>(SpanSet::*)(SpanSet const &) const) & SpanSet::dilated);
242 cls.def(
"eroded", (std::shared_ptr<SpanSet>(SpanSet::*)(int, Stencil) const) & SpanSet::eroded,
243 "radius"_a,
"stencil"_a = Stencil::CIRCLE);
244 cls.def(
"eroded", (std::shared_ptr<SpanSet>(SpanSet::*)(SpanSet const &) const) & SpanSet::eroded);
246 (std::shared_ptr<SpanSet>(SpanSet::*)(SpanSet const &) const) & SpanSet::intersect);
247 cls.def(
"intersectNot",
248 (std::shared_ptr<SpanSet>(SpanSet::*)(SpanSet const &) const) & SpanSet::intersectNot);
249 cls.def(
"union", (std::shared_ptr<SpanSet>(SpanSet::*)(SpanSet const &) const) & SpanSet::union_);
250 cls.def_static(
"fromShape",
251 (std::shared_ptr<SpanSet>(*)(int, Stencil, lsst::geom::Point2I)) & SpanSet::fromShape,
252 "radius"_a,
"stencil"_a = Stencil::CIRCLE,
"offset"_a = lsst::geom::Point2I());
255 [](int r, Stencil s, std::pair<int, int> point) {
256 return SpanSet::fromShape(r, s, lsst::geom::Point2I(point.first, point.second));
259 cls.def_static(
"fromShape",
261 cls.def(
"split", &SpanSet::split);
262 cls.def(
"findEdgePixels", &SpanSet::findEdgePixels);
263 cls.def(
"indices", [](SpanSet
const &
self) -> ndarray::Array<int, 2, 2> {
264 unsigned long dims = 2;
265 ndarray::Array<int, 2, 2> inds = ndarray::allocate(ndarray::makeVector(dims,
self.getArea()));
267 for (
auto const &span :
self) {
268 auto y = span.getY();
269 for (
int x = span.getX0();
x <= span.getX1(); ++
x) {
280 "__eq__", [](SpanSet
const &
self, SpanSet
const &other) ->
bool {
return self == other; },
283 "__ne__", [](SpanSet
const &
self, SpanSet
const &other) ->
bool {
return self != other; },
286 "__iter__", [](SpanSet &
self) {
return py::make_iterator(
self.
begin(),
self.
end()); },
287 py::keep_alive<0, 1>());
288 cls.def(
"__len__", [](SpanSet
const &
self) -> decltype(
self.size()) {
return self.size(); });
289 cls.def(
"__contains__",
290 [](SpanSet &
self, SpanSet
const &other) ->
bool {
return self.contains(other); });
291 cls.def(
"__contains__",
293 cls.def(
"__repr__", [](SpanSet
const &
self) ->
std::string {
296 self.setMask(tempMask,
static_cast<MaskPixel>(1));
297 auto array = tempMask.getArray();
298 auto dims = array.getShape();
303 if (j != dims[1] - 1) {
311 cls.def(
"__str__", [](SpanSet
const &
self) ->
std::string {
313 for (
auto const &span :
self) {
314 os << span.getY() <<
": " << span.getMinX() <<
".." << span.getMaxX() <<
std::endl;
320 declareMaskMethods<MaskPixel>(cls);
322 declareImageTypes<std::uint16_t>(cls);
323 declareImageTypes<std::uint64_t>(cls);
324 declareImageTypes<int>(cls);
325 declareImageTypes<float>(cls);
326 declareImageTypes<double>(cls);
329 declareFlattenMethod<long>(cls);
330 declareUnflattenMethod<long>(cls);
332 declarefromMask<MaskPixel>(cls);
336 void wrapSpanSet(lsst::utils::python::WrapperCollection &wrappers) {
337 wrappers.addSignatureDependency(
"lsst.afw.table.io");
338 wrappers.addSignatureDependency(
"lsst.afw.geom.ellipses");
339 declareStencil(wrappers);
340 declareSpanSet(wrappers);
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
An integer coordinate rectangle.
void wrapSpanSet(lsst::utils::python::WrapperCollection &)
float VariancePixel
default type for MaskedImage variance images
std::int32_t MaskPixel
default type for Masks and MaskedImage Masks
py::class_< PixelAreaBoundedField, std::shared_ptr< PixelAreaBoundedField >, BoundedField > PyClass
float Pixel
Typedefs to be used for pixel values.
A base class for image defects.