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>,
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>);
95template <
typename Pixel,
typename PyClass>
96void declareSetMaskMethod(PyClass &cls) {
97 cls.def(
"setMask", (
void (SpanSet::*)(
image::Mask<
Pixel> &,
Pixel) const) & SpanSet::setMask);
100template <
typename Pixel,
typename PyClass>
101void declareClearMaskMethod(PyClass &cls) {
102 cls.def(
"clearMask", (
void (SpanSet::*)(
image::Mask<
Pixel> &,
Pixel) const) & SpanSet::clearMask);
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",
125 SpanSet::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) {
167 (
void (SpanSet::*)(
image::Image<ImageT> &, ImageT,
lsst::
geom::Box2I const &, bool) const) &
169 "image"_a,
"val"_a,
"region"_a =
lsst::
geom::Box2I(),
"doClip"_a = false);
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.
std::vector< std::shared_ptr< geom::SpanSet > > split() const
Split a discontinuous SpanSet into multiple SpanSets which are contiguous.
std::shared_ptr< geom::SpanSet > findEdgePixels() const
Select pixels within the SpanSet which touch its edge.
Represent a 2-dimensional array of bitmask pixels.
void wrapSpanSet(lsst::utils::python::WrapperCollection &)
std::int32_t MaskPixel
default type for Masks and MaskedImage Masks
float VariancePixel
default type for MaskedImage variance images
float Pixel
Typedefs to be used for pixel values.