24#include "pybind11/pybind11.h"
26#include "pybind11/stl.h"
33#include "ndarray/pybind11.h"
34#include "ndarray/Array.h"
41using namespace pybind11::literals;
49using PySpanSet = py::class_<SpanSet, std::shared_ptr<SpanSet>>;
51template <
typename Pixel,
typename PyClass>
52void 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>,
75template <
typename Pixel,
typename PyClass>
76void 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>,
95template <
typename Pixel,
typename PyClass>
96void declareSetMaskMethod(
PyClass &cls) {
100template <
typename Pixel,
typename PyClass>
101void declareClearMaskMethod(
PyClass &cls) {
105template <
typename Pixel,
typename PyClass>
106void declareIntersectMethod(
PyClass &cls) {
110 "other"_a,
"bitmask"_a);
116 return self.intersect(*tempSpanSet);
121template <
typename Pixel,
typename PyClass>
122void declareIntersectNotMethod(
PyClass &cls) {
123 cls.def(
"intersectNot",
126 "other"_a,
"bitmask"_a);
132 return self.intersectNot(*tempSpanSet);
137template <
typename Pixel,
typename PyClass>
138void declareUnionMethod(
PyClass &cls) {
141 "other"_a,
"bitmask"_a);
147 return self.union_(*tempSpanSet);
152template <
typename ImageT,
typename PyClass>
153void declareCopyImage(
PyClass &cls) {
154 cls.def(
"copyImage", &SpanSet::copyImage<ImageT>);
157template <
typename ImageT,
typename PyClass>
158void declareCopyMaskedImage(
PyClass &cls) {
161 cls.def(
"copyMaskedImage", &SpanSet::copyMaskedImage<ImageT, MaskPixel, VariancePixel>);
164template <
typename ImageT,
typename PyClass>
165void declareSetImage(
PyClass &cls) {
172template <
typename MaskPixel,
typename PyClass>
173void declarefromMask(
PyClass &cls) {
180template <
typename Pixel,
typename PyClass>
181void declareMaskMethods(
PyClass &cls) {
182 declareSetMaskMethod<Pixel>(cls);
183 declareClearMaskMethod<Pixel>(cls);
184 declareIntersectMethod<Pixel>(cls);
185 declareIntersectNotMethod<Pixel>(cls);
186 declareUnionMethod<Pixel>(cls);
189template <
typename Pixel,
typename PyClass>
190void declareImageTypes(
PyClass &cls) {
191 declareFlattenMethod<Pixel>(cls);
192 declareUnflattenMethod<Pixel>(cls);
193 declareCopyImage<Pixel>(cls);
194 declareCopyMaskedImage<Pixel>(cls);
195 declareSetImage<Pixel>(cls);
198void 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);
206void 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",
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);
336void 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);
static std::shared_ptr< geom::SpanSet > fromMask(image::Mask< T > const &mask, UnaryPredicate comparator=details::AnyBitSetFunctor< T >())
Create a SpanSet from a mask.
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, lsst::geom::Point2I offset=lsst::geom::Point2I())
Factory function for creating SpanSets from a Stencil.
void setImage(image::Image< ImageT > &image, ImageT val, lsst::geom::Box2I const ®ion=lsst::geom::Box2I(), bool doClip=false) const
Set the values of an Image at points defined by the SpanSet.
std::shared_ptr< SpanSet > union_(SpanSet const &other) const
Create a new SpanSet that contains all points from two SpanSets.
std::shared_ptr< SpanSet > intersect(SpanSet const &other) const
Determine the common points between two SpanSets, and create a new SpanSet.
void setMask(lsst::afw::image::Mask< T > &target, T bitmask) const
Set a Mask at pixels defined by the SpanSet.
std::vector< std::shared_ptr< geom::SpanSet > > split() const
Split a discontinuous SpanSet into multiple SpanSets which are contiguous.
void clearMask(lsst::afw::image::Mask< T > &target, T bitmask) const
Unset a Mask at pixels defined by the SpanSet.
std::shared_ptr< geom::SpanSet > findEdgePixels() const
Select pixels within the SpanSet which touch its edge.
std::shared_ptr< SpanSet > intersectNot(SpanSet const &other) const
Determine the common points between a SpanSet and the logical inverse of a second SpanSet and return ...
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.