52 bool comparePrimaryRun(PrimaryRun
const&
first, PrimaryRun
const&
second) {
53 if (first.y != second.y) {
54 return first.y < second.y;
55 }
else if (first.m != second.m) {
56 return first.m < second.m;
58 return first.xmin < second.xmin;
62 class ComparePrimaryRunY {
64 bool operator()(PrimaryRun
const& pr,
int yval) {
return pr.y < yval; }
65 bool operator()(
int yval, PrimaryRun
const& pr) {
return yval < pr.y; }
68 class ComparePrimaryRunM {
70 bool operator()(PrimaryRun
const& pr,
int mval) {
return pr.m < mval; }
71 bool operator()(
int mval, PrimaryRun
const& pr) {
return mval < pr.m; }
80 bool spansOverlap(Span
const&
a, Span
const&
b,
bool compareY =
true) {
83 yTruth = a.getY() == b.getY();
85 return (yTruth && ((a.getMaxX() >= b.getMinX() && a.getMinX() <= b.getMinX()) ||
86 (b.getMaxX() >= a.getMinX() && b.getMinX() <= a.getMinX())))
98 bool spansContiguous(Span
const& a, Span
const& b,
bool compareY =
true) {
101 yTruth = a.getY() == b.getY();
103 return (yTruth && ((a.getMaxX() + 1 >= b.getMinX() && a.getMinX() <= b.getMinX()) ||
104 (b.getMaxX() + 1 >= a.getMinX() && b.getMinX() <= a.getMinX())))
120 template <
typename T,
bool invert>
124 auto maskBBox = mask.
getBBox();
125 for (
auto const& spn : spanSet) {
128 bool started =
false;
131 if (y < maskBBox.getMinY() || y > maskBBox.getMaxY()) {
138 int startX =
std::max(spn.getMinX(), maskBBox.getMinX());
139 int endX =
std::min(spn.getMaxX(), maskBBox.getMaxX());
140 for (
int x = startX;
x <= endX; ++
x) {
142 bool pixelCompare = mask.
get0(
x, y) & bitmask;
146 pixelCompare = !pixelCompare;
163 }
else if (started) {
171 return std::make_shared<SpanSet>(
std::move(newVec));
178 SpanSet::SpanSet() : _spanVector(), _bbox(), _area(0) {}
187 for (
int i = beginY; i < _bbox.
getEndY(); ++i) {
188 _spanVector.push_back(
Span(i, beginX, maxX));
195 if (_spanVector.empty()) {
209 if (_spanVector.size() == 0) {
220 void SpanSet::_runNormalize() {
226 std::sort(_spanVector.begin(), _spanVector.end());
231 newSpans.
reserve(_spanVector.size());
233 newSpans.push_back(*_spanVector.begin());
239 for (
auto iter = ++(_spanVector.begin());
iter != _spanVector.end(); ++
iter) {
240 auto& newSpansEnd = newSpans.back();
241 if (spansContiguous(newSpansEnd, *
iter)) {
242 newSpansEnd =
Span(newSpansEnd.getY(),
std::min(newSpansEnd.getMinX(),
iter->getMinX()),
253 void SpanSet::_initialize() {
265 int minX = _spanVector[0].getMinX();
266 int maxX = _spanVector[0].getMaxX();
269 for (
const auto&
span : _spanVector) {
270 if (
span.getMinX() < minX) {
271 minX =
span.getMinX();
273 if (
span.getMaxX() > maxX) {
274 maxX =
span.getMaxX();
277 _area +=
span.getMaxX() -
span.getMinX() + 1;
322 void SpanSet::_label(
325 auto currentIndex = spn.
getY();
326 if (currentIndex > 0) {
328 for (
auto const& tup : sortMap[currentIndex - 1]) {
329 if (!labelVector[tup.first] && spansOverlap(spn, *(tup.second),
false)) {
330 labelVector[tup.first] = currentLabel;
331 _label(*(tup.second), labelVector, currentLabel, sortMap);
335 if (currentIndex <= _spanVector.back().getY() - 1) {
337 for (
auto& tup : sortMap[currentIndex + 1]) {
338 if (!labelVector[tup.first] && spansOverlap(spn, *(tup.second),
false)) {
339 labelVector[tup.first] = currentLabel;
340 _label(*(tup.second), labelVector, currentLabel, sortMap);
353 for (
auto const& spn : _spanVector) {
357 for (
auto const& currentSpan : _spanVector) {
358 if (!labelVector[index]) {
359 labelVector[index] = currentLabel;
360 _label(currentSpan, labelVector, currentLabel, sortMap);
375 auto labeledPair = _makeLabels();
380 return labeledPair.second <= 2;
384 auto labeledPair = _makeLabels();
385 auto labels = labeledPair.first;
386 auto numberOfLabels = labeledPair.second;
394 if (numberOfLabels == 1) {
395 subRegions.
push_back(std::make_shared<SpanSet>());
398 subRegions.
reserve(numberOfLabels - 1);
402 for (
std::size_t i = 0; i < _spanVector.size(); ++i) {
403 subSpanLists[labels[i] - 1].
push_back(_spanVector[i]);
406 for (
std::size_t i = 0; i < numberOfLabels - 1; ++i) {
407 subRegions.
push_back(std::make_shared<SpanSet>(subSpanLists[i]));
414 setMask(tempMask, static_cast<image::MaskPixel>(1));
416 erodedSpanSet->clearMask(tempMask, static_cast<image::MaskPixel>(1));
422 return makeShift(x, y);
427 return makeShift(offset.getX(), offset.getY());
433 tempVec.
reserve(_spanVector.size());
434 for (
auto const& spn : _spanVector) {
437 return std::make_shared<SpanSet>(
std::move(tempVec),
false);
445 for (
auto const& spn : _spanVector) {
452 return std::make_shared<SpanSet>(
std::move(tempVec),
false);
457 for (
auto const& otherSpan : other) {
458 for (
auto const& spn : _spanVector) {
459 if (spansOverlap(otherSpan, spn)) {
473 for (
auto const& otherSpn : other) {
475 for (
auto const& spn : _spanVector) {
495 for (
auto& spn : _spanVector) {
506 double xc = 0, yc = 0;
507 for (
auto const& spn : _spanVector) {
508 int const y = spn.
getY();
511 int const npix = x1 - x0 + 1;
514 xc += npix * 0.5 * (x1 + x0);
525 double const xc = cen.getX();
526 double const yc = cen.getY();
528 double sumxx = 0, sumxy = 0, sumyy = 0;
529 for (
auto const& spn : _spanVector) {
530 int const y = spn.
getY();
531 int const x0 = spn.
getX0();
532 int const x1 = spn.
getX1();
533 int const npix = x1 - x0 + 1;
535 for (
int x = x0; x <= x1; ++
x) {
536 sumxx += (x - xc) * (x - xc);
538 sumxy += npix * (0.5 * (x1 + x0) - xc) * (y - yc);
539 sumyy += npix * (y - yc) * (y - yc);
549 return dilated(*stencilToSpanSet);
554 if (other.
size() == 0) {
555 return std::make_shared<SpanSet>(_spanVector.begin(), _spanVector.end(),
false);
561 for (
auto const& spn : _spanVector) {
562 for (
auto const& otherSpn : other) {
563 int const xmin = spn.
getMinX() + otherSpn.getMinX();
564 int const xmax = spn.
getMaxX() + otherSpn.getMaxX();
565 int const yval = spn.
getY() + otherSpn.getY();
566 tempVec.push_back(
Span(yval, xmin, xmax));
570 return std::make_shared<SpanSet>(
std::move(tempVec));
577 return eroded(*stencilToSpanSet);
582 if (other.
size() == 0 || this->
size() == 0) {
583 return std::make_shared<SpanSet>(_spanVector.begin(), _spanVector.end(),
false);
591 for (
auto const& spn : _spanVector) {
593 for (
auto const& otherSpn : other) {
594 if ((otherSpn.getMaxX() - otherSpn.getMinX()) <= (spn.
getMaxX() - spn.
getMinX())) {
597 int y = spn.
getY() - otherSpn.getY();
608 for (
int y = primaryRuns.
front().y; y <= primaryRuns.
back().y; ++
y) {
616 auto otherYRange = other.
back().getY() - other.
front().getY() + 1;
617 if (
std::distance(yRange.first, yRange.second) < otherYRange) {
628 for (
int m = 0;
m < otherYRange; ++
m) {
629 auto mRange =
std::equal_range(yRange.first, yRange.second,
m, ComparePrimaryRunM());
630 if ((mRange.first == mRange.second)) {
637 int startX = mRange.first->xmin;
638 int endX = mRange.first->xmax;
639 for (
auto run = mRange.first + 1;
run != mRange.second; ++
run) {
640 if (
run->xmin > endX) {
642 candidateRuns.
push_back(PrimaryRun{
m,
y, startX, endX});
650 candidateRuns.
push_back(PrimaryRun{
m,
y, startX, endX});
659 for (
auto& good : goodRuns) {
660 for (
auto& cand : candidateRuns) {
661 int start =
std::max(good.xmin, cand.xmin);
672 for (
auto&
run : goodRuns) {
676 return std::make_shared<SpanSet>(
std::move(tempVec));
681 return _spanVector == other._spanVector;
686 return _spanVector != other._spanVector;
695 for (
auto dy = -r; dy <= r; ++dy) {
696 int dx =
static_cast<int>(sqrt(r * r - dy * dy));
697 tempVec.
push_back(
Span(dy + offset.getY(), -dx + offset.getX(), dx + offset.getX()));
701 for (
auto dy = -r; dy <= r; ++dy) {
702 int dx = r -
abs(dy);
703 tempVec.
push_back(
Span(dy + offset.getY(), -dx + offset.getX(), dx + offset.getX()));
707 for (
auto dy = -r; dy <= r; ++dy) {
709 tempVec.
push_back(
Span(dy + offset.getY(), -dx + offset.getX(), dx + offset.getX()));
713 return std::make_shared<SpanSet>(
std::move(tempVec),
false);
718 return std::make_shared<SpanSet>(pr.
begin(), pr.
end());
724 return std::make_shared<SpanSet>();
727 if (other == *
this) {
728 return std::make_shared<SpanSet>(this->_spanVector);
731 auto otherIter = other.
begin();
732 for (
auto const& spn : _spanVector) {
733 while (otherIter != other.
end() && otherIter->getY() <= spn.
getY()) {
734 if (spansOverlap(spn, *otherIter)) {
737 auto newSpan =
Span(spn.
getY(), newMin, newMax);
738 tempVec.push_back(newSpan);
743 return std::make_shared<SpanSet>(
std::move(tempVec));
749 return std::make_shared<SpanSet>(this->
begin(), this->
end());
752 if (other == *
this) {
753 return std::make_shared<SpanSet>();
762 auto otherIter = other.
begin();
763 for (
auto const& spn : _spanVector) {
765 bool spanStarted =
false;
767 while (otherIter != other.
end() && otherIter->getY() <= spn.
getY()) {
768 if (spansOverlap(spn, *otherIter)) {
784 if (spn.
getMinX() < otherIter->getMinX()) {
785 tempVec.push_back(
Span(spn.
getY(), spn.
getMinX(), otherIter->getMinX() - 1));
791 if (spn.
getMaxX() > otherIter->getMaxX()) {
793 spanBottom = otherIter->getMaxX() + 1;
802 if (spn.
getMaxX() > otherIter->getMaxX()) {
804 spanBottom = otherIter->getMaxX() + 1;
808 if (otherIter->getMaxX() > spn.
getMaxX()) {
822 tempVec.push_back(
Span(spn));
825 return std::make_shared<SpanSet>(
std::move(tempVec));
836 tempVec.
insert(tempVec.
end(), _spanVector.begin(), _spanVector.end());
839 return std::make_shared<SpanSet>(
std::move(tempVec));
862 for (
auto const& tc : toPoints) {
877 newBoxPoints.
clear();
882 auto oldBoxPointIter = oldBoxPoints.cbegin();
883 for (
int x = newBBoxI.
getBeginX(); x < newBBoxI.
getEndX(); ++
x, ++oldBoxPointIter) {
884 auto p = *oldBoxPointIter;
885 int const xSource =
std::floor(0.5 + p.getX());
886 int const ySource =
std::floor(0.5 + p.getY());
902 return std::make_shared<SpanSet>(
std::move(tempVec));
905 template <
typename ImageT>
914 auto setterFunc = [](
lsst::geom::Point2I const& point, ImageT& out, ImageT in) { out = in; };
918 tmpSpan->applyFunctor(setterFunc, image, val);
924 "Footprint Bounds Outside image, set doClip to true");
928 template <
typename T>
931 auto targetArray = target.
getArray();
935 T bitmask) { maskVal |= bitmask; };
939 template <
typename T>
942 auto targetArray = target.
getArray();
946 T bitmask) { maskVal &= ~bitmask; };
950 template <
typename T>
952 return maskIntersect<T, false>(*
this,
other, bitmask);
955 template <
typename T>
957 return maskIntersect<T, true>(*
this,
other, bitmask);
960 template <
typename T>
962 auto comparator = [bitmask](
T pixelValue) {
return (pixelValue & bitmask); };
963 auto spanSetFromMask =
fromMask(other, comparator);
964 return union_(*spanSetFromMask);
969 class SpanSetPersistenceHelper {
976 static SpanSetPersistenceHelper
const&
get() {
977 static SpanSetPersistenceHelper instance;
982 SpanSetPersistenceHelper(
const SpanSetPersistenceHelper&) =
delete;
983 SpanSetPersistenceHelper&
operator=(
const SpanSetPersistenceHelper&) =
delete;
986 SpanSetPersistenceHelper(SpanSetPersistenceHelper&&) =
delete;
987 SpanSetPersistenceHelper&
operator=(SpanSetPersistenceHelper&&) =
delete;
990 SpanSetPersistenceHelper()
992 spanY(spanSetSchema.addField<
int>(
"y",
"The row of the span",
"pixel")),
993 spanX0(spanSetSchema.addField<
int>(
"x0",
"First column of span (inclusive)",
"pixel")),
994 spanX1(spanSetSchema.addField<
int>(
"x1",
"Second column of span (inclusive)",
"pixel")) {}
997 std::string getSpanSetPersistenceName() {
return "SpanSet"; }
999 class SpanSetFactory :
public table::io::PersistableFactory {
1002 CatalogVector
const& catalogs)
const override {
1006 auto spansCatalog = catalogs.front();
1008 auto const&
keys = SpanSetPersistenceHelper::get();
1011 tempVec.
reserve(spansCatalog.size());
1012 for (
auto const&
val : spansCatalog) {
1015 return std::make_shared<SpanSet>(
std::move(tempVec));
1017 explicit SpanSetFactory(
std::string const&
name) : table::io::PersistableFactory(name) {}
1022 SpanSetFactory registration(getSpanSetPersistenceName());
1026 std::string SpanSet::getPersistenceName()
const {
return getSpanSetPersistenceName(); }
1029 auto const&
keys = SpanSetPersistenceHelper::get();
1030 auto spanCat = handle.makeCatalog(
keys.spanSetSchema);
1031 spanCat.reserve(
size());
1032 for (
auto const&
val : *
this) {
1033 auto record = spanCat.addNew();
1034 record->set(
keys.spanY,
val.getY());
1035 record->set(
keys.spanX0,
val.getX0());
1036 record->set(
keys.spanX1,
val.getX1());
1038 handle.saveCatalog(spanCat);
1043 #define INSTANTIATE_IMAGE_TYPE(T) \ 1044 template void SpanSet::setImage<T>(image::Image<T> & image, T val, \ 1045 lsst::geom::Box2I const& region = lsst::geom::Box2I(), \ 1046 bool doClip = false) const; 1048 #define INSTANTIATE_MASK_TYPE(T) \ 1049 template void SpanSet::setMask<T>(image::Mask<T> & target, T bitmask) const; \ 1050 template void SpanSet::clearMask<T>(image::Mask<T> & target, T bitmask) const; \ 1051 template std::shared_ptr<SpanSet> SpanSet::intersect<T>(image::Mask<T> const& other, T bitmask) const; \ 1052 template std::shared_ptr<SpanSet> SpanSet::intersectNot<T>(image::Mask<T> const& other, T bitmask) \ 1054 template std::shared_ptr<SpanSet> SpanSet::union_<T>(image::Mask<T> const& other, T bitmask) const;
An ellipse core with quadrupole moments as parameters.
std::shared_ptr< SpanSet > union_(SpanSet const &other) const
Create a new SpanSet that contains all points from two SpanSets.
std::shared_ptr< geom::SpanSet > findEdgePixels() const
Select pixels within the SpanSet which touch its edge.
Angle abs(Angle const &a)
std::vector< std::shared_ptr< geom::SpanSet > > split() const
Split a discontinuous SpanSet into multiple SpanSets which are contiguous.
static std::shared_ptr< T > dynamicCast(std::shared_ptr< Persistable > const &ptr)
Dynamically cast a shared_ptr.
bool operator!=(SpanSet const &other) const
Stencil
An enumeration class which describes the shapes.
std::shared_ptr< SpanSet > intersect(SpanSet const &other) const
Determine the common points between two SpanSets, and create a new SpanSet.
Key< Flag > const & target
bool contains(SpanSet const &other) const
Check if a SpanSet instance entirely contains another SpanSet.
A floating-point coordinate rectangle geometry.
const_iterator end() const
static std::shared_ptr< geom::SpanSet > fromMask(image::Mask< T > const &mask, UnaryPredicate comparator=details::AnyBitSetFunctor< T >())
Create a SpanSet from a mask.
A compact representation of a collection of pixels.
A range of pixels within one row of an Image.
void include(Point2D const &point) noexcept
Expand this to ensure that this->contains(point).
void applyFunctor(Functor &&func, Args &&... args) const
Apply functor on individual elements from the supplied parameters.
std::shared_ptr< SpanSet > shiftedBy(int x, int y) const
Return a new SpanSet shifted by specified amount.
bool isEmpty() const noexcept
Return true if the box contains no points.
std::shared_ptr< SpanSet > dilated(int r, Stencil s=Stencil::CIRCLE) const
Perform a set dilation operation, and return a new object.
#define INSTANTIATE_IMAGE_TYPE(T)
typename ndarray::Array< T, N, C >::Reference::Reference Reference
table::Schema spanSetSchema
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.
const_iterator begin() const
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 ...
int getMaxX() const noexcept
Maximum x-value.
Relationship invert(Relationship r)
Given the relationship between two sets A and B (i.e.
ItemVariant const * other
bool isContiguous() const
Defines if the SpanSet is simply contiguous.
std::vector< Point2I > getCorners() const
Get the corner points.
ellipses::Quadrupole computeShape() const
Compute the shape parameters for the distribution of points in the SpanSet.
int getEndY() const noexcept
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.
lsst::geom::Point2D computeCentroid() const
Compute the point about which the SpanSet's first moment is zero.
bool contains(int x) const noexcept
Point< double, 2 > Point2D
int getBeginY() const noexcept
lsst::geom::Box2I getBBox() const
Return a new integer box which is the minimum size to contain the pixels.
Point2I const getMin() const noexcept
A pixelized region containing all pixels whose centers are within an Ellipse.
A base class for image defects.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Represent a 2-dimensional array of bitmask pixels.
int getMaxY() const noexcept
Iterator end() const
Iterator range over Spans whose pixels are within the Ellipse.
int getBeginX() const noexcept
int getWidth() const noexcept
const_reference front() const
int getMaxX() const noexcept
int getMinX() const noexcept
Minimum x-value.
int getMinX() const noexcept
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Reports attempts to access elements outside a valid range of indices.
SpanSet()
Default constructor.
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)
size_type getArea() const
Return the number of pixels in the SpanSet.
int getEndX() const noexcept
void setMask(lsst::afw::image::Mask< T > &target, T bitmask) const
Set a Mask at pixels defined by the SpanSet.
bool overlaps(Box2I const &other) const noexcept
Return true if any points in other are also in this.
#define INSTANTIATE_MASK_TYPE(T)
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
const_reference back() const
io::OutputArchiveHandle OutputArchiveHandle
std::shared_ptr< SpanSet > clippedTo(lsst::geom::Box2I const &box) const
Return a new SpanSet which has all pixel values inside specified box.
std::shared_ptr< SpanSet > transformedBy(lsst::geom::LinearTransform const &t) const
Return a new SpanSet who's pixels are the product of applying the specified transformation.
void clearMask(lsst::afw::image::Mask< T > &target, T bitmask) const
Unset a Mask at pixels defined by the SpanSet.
SpanSet & operator=(SpanSet const &)=default
int getX1() const noexcept
Return the ending x-value.
bool overlaps(SpanSet const &other) const
Specifies if this SpanSet overlaps with another SpanSet.
int getY() const noexcept
Return the y-value.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
details::ImageNdGetter< T, inA, inB > ndImage(ndarray::Array< T, inA, inB > const &array, lsst::geom::Point2I xy0=lsst::geom::Point2I())
Marks a ndarray to be interpreted as an image when applying a functor from a SpanSet.
bool operator==(SpanSet const &other) const
Compute equality between two SpanSets.
An integer coordinate rectangle.
PixelConstReference get0(int x, int y) const
A class to represent a 2-dimensional array of pixels.
Iterator begin() const
Iterator range over Spans whose pixels are within the Ellipse.
std::shared_ptr< SpanSet > eroded(int r, Stencil s=Stencil::CIRCLE) const
Perform a set erosion, and return a new object.
int getMinY() const noexcept
int getX0() const noexcept
Return the starting x-value.
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.
T emplace_back(T... args)