32 #include "boost/format.hpp"
49 #include <boost/archive/text_iarchive.hpp>
50 #include <boost/archive/text_oarchive.hpp>
51 #include <boost/archive/xml_iarchive.hpp>
52 #include <boost/archive/xml_oarchive.hpp>
53 #include <boost/archive/binary_iarchive.hpp>
54 #include <boost/archive/binary_oarchive.hpp>
55 #include <boost/serialization/shared_ptr.hpp>
56 #include <boost/serialization/vector.hpp>
58 using boost::serialization::make_nvp;
72 struct compareSpanByYX :
73 public std::binary_function<Span::ConstPtr, Span::ConstPtr, bool> {
74 int operator()(Span::ConstPtr a, Span::ConstPtr
b) {
96 ) : lsst::daf::base::Citizen(typeid(this)),
105 lsst::pex::exceptions::InvalidParameterError,
106 str(
boost::format(
"Number of spans requested is -ve: %d") % nspan));
113 ) : lsst::daf::base::Citizen(typeid(this)),
124 for (
int i = y0; i <= y1; ++i) {
134 ) : lsst::daf::base::Citizen(typeid(this)),
140 int const r2 =
static_cast<int>(radius*radius + 0.5);
141 int const r =
static_cast<int>(std::sqrt(static_cast<double>(r2)));
143 for (
int i = -r; i <= r; ++i) {
144 int hlen =
static_cast<int>(std::sqrt(static_cast<double>(r2 - i*i)));
145 addSpan(center.getY() + i, center.getX() - hlen, center.getX() + hlen);
151 geom::ellipses::Ellipse
const & ellipse,
153 ) : lsst::daf::base::Citizen(typeid(this)),
156 _bbox(geom::Box2I()),
160 geom::ellipses::PixelRegion pr(ellipse);
162 geom::ellipses::PixelRegion::Iterator spanIter = pr.begin(), end = pr.end();
166 if (!spanIter->isEmpty()) {
174 Footprint::SpanList
const & spans,
176 ) : lsst::daf::base::Citizen(typeid(this)),
179 _bbox(geom::Box2I()),
183 _spans.reserve(spans.size());
184 for(SpanList::const_iterator i(spans.begin()); i != spans.end(); ++i) {
190 : lsst::daf::base::Citizen(typeid(this)),
193 _region(other._region)
196 _spans.reserve(other._spans.size());
197 for(SpanList::const_iterator i(other._spans.begin());
198 i != other._spans.end(); ++i
203 _normalized = other._normalized;
206 _peaks.reserve(other._peaks.size());
207 for(PeakList::const_iterator i(other._peaks.begin()); i != other._peaks.end(); ++i) {
208 _peaks.push_back(
PTR(Peak)(
new Peak(**i)));
212 Footprint::~Footprint() {
215 bool Footprint::contains(
220 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
221 if ((*siter)->contains(pix.getX(), pix.getY())) {
231 Footprint::SpanList::iterator it = _spans.begin();
232 for (; it != _spans.end();) {
233 Span *sp = it->get();
234 if ((sp->getY() < bbox.
getMinY()) ||
235 (sp->getY() > bbox.
getMaxY())) {
237 it = _spans.erase(it);
240 if ((sp->getX0() > bbox.
getMaxX()) ||
241 (sp->getX1() < bbox.
getMinX())) {
243 it = _spans.erase(it);
247 if (sp->getX0() < bbox.
getMinX()) {
251 if (sp->getX1() > bbox.
getMaxX()) {
258 Footprint::PeakList::iterator pit = _peaks.begin();
259 for (; pit != _peaks.end();) {
260 Peak *pk = pit->get();
262 pit = _peaks.erase(pit);
268 if (_spans.empty()) {
282 assert(!_spans.empty());
287 sort(_spans.begin(), _spans.end(), compareSpanByYX());
289 Footprint::SpanList::iterator ptr = _spans.begin(), end = _spans.end();
290 Span *lspan = ptr->get();
293 _area = lspan->getWidth();
294 int minX = lspan->_x0, minY=
y, maxX=x1;
298 for (; ptr != end; ++ptr) {
299 Span *rspan = ptr->get();
300 if (rspan->_y == y) {
301 if (rspan->_x0 <= x1 + 1) {
302 if (rspan->_x1 > x1) {
304 _area += rspan->_x1 - x1;
306 x1 = lspan->_x1 = rspan->_x1;
308 if(x1 > maxX) maxX = x1;
311 ptr = _spans.erase(ptr);
321 _area += rspan->getWidth();
322 if(rspan->_x1 > maxX) maxX = rspan->_x1;
325 _area += rspan->getWidth();
332 if(lspan->_x0 < minX) minX = lspan->_x0;
333 if(x1 > maxX) maxX = x1;
340 Span
const& Footprint::addSpan(
346 return addSpan(y, x1, x0);
349 PTR(Span) sp(new Span(y, x0, x1));
350 _spans.push_back(sp);
352 _area += sp->getWidth();
364 return addSpan(span._y, span._x0, span._x1);
367 const Span& Footprint::addSpan(
372 return addSpan(span._y + dy, span._x0 + dx, span._x1 + dx);
375 const Span& Footprint::addSpanInSeries(
381 return addSpanInSeries(y, x1, x0);
383 if (_spans.size() == 0) {
384 const Span& s = addSpan(y, x0, x1);
389 PTR(Span) lastspan = _spans.back();
390 if ((y == lastspan->getY()) &&
391 (x0 == (lastspan->getX1() + 1))) {
394 _area += (1 + x1 -
x0);
398 if (!((y > lastspan->getY()) ||
399 (x0 > (lastspan->getX1() + 1)))) {
401 lsst::pex::exceptions::InvalidParameterError,
402 str(
boost::format(
"addSpanInSeries: new span %i,[%i,%i] is NOT in series after last span "
404 y % x0 % x1 % lastspan->getY() % lastspan->getX0() % lastspan->getX1()));
406 const Span& s = addSpan(y, x0, x1);
415 for (SpanList::iterator i = _spans.begin(); i != _spans.end(); ++i){
430 double xc = 0, yc = 0;
431 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
433 int const y = span->getY();
434 int const x0 = span->getX0();
435 int const x1 = span->getX1();
436 int const npix = x1 - x0 + 1;
439 xc += npix*0.5*(x1 + x0);
444 return geom::
Point2D(xc/_area, yc/_area);
447 geom::ellipses::Quadrupole
451 double const xc = cen.getX();
452 double const yc = cen.getY();
454 double sumxx = 0, sumxy = 0, sumyy = 0;
455 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
457 int const y = span->getY();
458 int const x0 = span->getX0();
459 int const x1 = span->getX1();
460 int const npix = x1 - x0 + 1;
462 for (
int x = x0;
x <= x1; ++
x) {
463 sumxx += (
x - xc)*(
x - xc);
465 sumxy += npix*(0.5*(x1 +
x0) - xc)*(y - yc);
466 sumyy += npix*(y - yc)*(y - yc);
469 return geom::ellipses::Quadrupole(sumxx/_area, sumyy/_area, sumxy/_area);
479 template<
bool overwriteId,
typename PixelT>
482 Footprint::SpanList
const& _spans,
484 boost::uint64_t
const id,
487 std::set<boost::uint64_t> *oldIds=NULL
490 int width, height,
x0,
y0;
504 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
506 "Footprint's host Image of size (%dx%d)") %
511 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
512 str(
boost::format(
"Id 0x%x sets bits in the protected mask 0x%x") %
id % mask));
515 typename std::set<boost::uint64_t>::const_iterator pos;
517 pos = oldIds->begin();
519 for (Footprint::SpanList::const_iterator spi = _spans.begin(); spi != _spans.end(); ++spi) {
522 int const sy0 = span->getY() - y0;
523 if (sy0 < 0 || sy0 >= height) {
527 int sx0 = span->getX0() -
x0;
531 int sx1 = span->getX1() -
x0;
532 int const swidth = (sx1 >= width) ? width - sx0 : sx1 - sx0 + 1;
535 end = ptr + swidth; ptr != end; ++ptr) {
537 long val = *ptr & ~mask;
538 if (val != 0 and oldIds != NULL) {
539 pos = oldIds->insert(pos, val);
541 *ptr = (*ptr & mask) +
id;
550 template<
typename PixelT>
554 int const ix0 = img.
getX0();
555 int const iy0 = img.
getY0();
558 for (SpanList::iterator s = _spans.begin(); s < _spans.end(); ++s) {
559 int const y = (*s)->getY();
560 int const x0 = (*s)->getX0();
561 int const x1 = (*s)->getX1();
562 typename ImageT::x_iterator img_it = img.
row_begin(y - iy0) + (x0 - ix0);
565 for (leftx = x0; leftx <= x1; ++leftx, ++img_it) {
566 if (*img_it != zero) {
578 img_it = img.
row_begin(y - iy0) + (x1 - ix0);
579 for (rightx = x1; rightx >= leftx; --rightx, --img_it) {
580 if (*img_it != zero) {
594 if (_spans.empty()) {
601 template<
typename PixelT>
603 Footprint::insertIntoImage(
605 boost::uint64_t
const id,
609 static_cast<void>(doInsertIntoImage<false>(_region, _spans, idImage,
id, region));
612 template<
typename PixelT>
614 Footprint::insertIntoImage(
616 boost::uint64_t
const id,
619 std::set<boost::uint64_t> *oldIds,
625 lsst::pex::exceptions::OutOfRangeError,
626 "id out of range for image type"
630 doInsertIntoImage<true>(_region, _spans, idImage,
id, region, mask, oldIds);
632 doInsertIntoImage<false>(_region, _spans, idImage,
id, region, mask, oldIds);
636 void Footprint::include(std::vector<
PTR(
Footprint)>
const & others) {
637 if (others.empty())
return;
639 for (std::vector<
PTR(
Footprint)>::const_iterator i = others.begin(); i != others.end(); ++i) {
642 boost::uint16_t bits = 0x1;
645 for (std::vector<
PTR(
Footprint)>::const_iterator i = others.begin(); i != others.end(); ++i) {
648 FootprintSet fpSet(mask, Threshold(bits, Threshold::BITMASK));
649 if (fpSet.getFootprints()->size() != 1u) {
651 pex::exceptions::RuntimeError,
652 (
boost::format(
"Footprint::include() result is disjoint; got %d distinct Footprints")
653 % fpSet.getFootprints()->size()).str()
656 _spans.swap(fpSet.getFootprints()->front()->getSpans());
662 class FootprintFactory :
public table::io::PersistableFactory {
665 virtual PTR(table::io::Persistable)
666 read(InputArchive const & archive, CatalogVector const & catalogs)
const {
669 result->readSpans(catalogs.front());
670 result->readPeaks(catalogs.back());
674 explicit FootprintFactory(std::
string const & name) : table::io::PersistableFactory(name) {}
681 class FootprintPersistenceHelper :
private boost::noncopyable {
692 static FootprintPersistenceHelper
const &
get() {
693 static FootprintPersistenceHelper instance;
698 FootprintPersistenceHelper() :
700 spanY(spanSchema.addField<int>(
"y",
"row position of span",
"pixels")),
701 spanX0(spanSchema.addField<int>(
"x0",
"first column of span (inclusive)",
"pixels")),
702 spanX1(spanSchema.addField<int>(
"x1",
"first column of span (inclusive)",
"pixels")),
704 peakX(peakSchema.addField<float>(
"x",
"column position of peak",
"pixels")),
705 peakY(peakSchema.addField<float>(
"y",
"column position of peak",
"pixels")),
706 peakValue(peakSchema.addField<float>(
"value",
"value of peak pixel",
"pixels"))
708 spanSchema.getCitizen().markPersistent();
709 peakSchema.getCitizen().markPersistent();
713 std::string getFootprintPersistenceName() {
return "Footprint"; }
717 FootprintFactory registration(getFootprintPersistenceName());
721 std::string Footprint::getPersistenceName()
const {
return getFootprintPersistenceName(); }
723 std::string Footprint::getPythonModule()
const {
return "lsst.afw.detection"; }
725 void Footprint::write(OutputArchiveHandle & handle)
const {
726 FootprintPersistenceHelper
const & keys = FootprintPersistenceHelper::get();
728 spanCat.reserve(_spans.size());
729 for (SpanList::const_iterator i = _spans.begin(); i != _spans.end(); ++i) {
730 PTR(afw::table::BaseRecord) record = spanCat.addNew();
731 record->set(keys.spanY, (**i).getY());
732 record->set(keys.spanX0, (**i).getX0());
733 record->set(keys.spanX1, (**i).getX1());
735 handle.saveCatalog(spanCat);
736 afw::table::
BaseCatalog peakCat = handle.makeCatalog(keys.peakSchema);
737 peakCat.reserve(_peaks.size());
738 for (PeakList::const_iterator i = _peaks.begin(); i != _peaks.end(); ++i) {
739 PTR(afw::table::BaseRecord) record = peakCat.addNew();
740 record->set(keys.peakX, (**i).getFx());
741 record->set(keys.peakY, (**i).getFy());
742 record->set(keys.peakValue, (**i).getPeakValue());
744 handle.saveCatalog(peakCat);
748 FootprintPersistenceHelper
const & keys = FootprintPersistenceHelper::get();
750 addSpan(i->get(keys.spanY), i->get(keys.spanX0), i->get(keys.spanX1));
755 FootprintPersistenceHelper
const & keys = FootprintPersistenceHelper::get();
758 boost::make_shared<Peak>(i->get(keys.peakX), i->get(keys.peakY), i->get(keys.peakValue))
763 template <
typename Archive>
764 void Footprint::serialize(Archive & ar,
const unsigned int version) {
765 ar & make_nvp(
"spans", _spans);
766 ar & make_nvp(
"peaks", _peaks);
767 ar & make_nvp(
"area", _area);
768 ar & make_nvp(
"normalized", _normalized);
770 int x0,
y0, width, height;
771 int rx0, ry0, rwidth, rheight;
772 if(Archive::is_saving::value) {
786 ar & make_nvp(
"x0", x0) & make_nvp(
"y0", y0) & make_nvp(
"width", width) & make_nvp(
"height", height);
787 ar & make_nvp(
"rx0", rx0) & make_nvp(
"ry0", ry0) & make_nvp(
"rwidth", rwidth)
788 & make_nvp(
"rheight", rheight);
790 if(Archive::is_loading::value) {
796 template void Footprint::serialize(boost::archive::text_oarchive &,
unsigned int const);
797 template void Footprint::serialize(boost::archive::text_iarchive &,
unsigned int const);
798 template void Footprint::serialize(boost::archive::xml_oarchive &,
unsigned int const);
799 template void Footprint::serialize(boost::archive::xml_iarchive &,
unsigned int const);
800 template void Footprint::serialize(boost::archive::binary_oarchive &,
unsigned int const);
801 template void Footprint::serialize(boost::archive::binary_iarchive &,
unsigned int const);
804 _region = other._region;
808 _spans.reserve(other._spans.size());
809 for(SpanList::const_iterator i(other._spans.begin());
810 i != other._spans.end(); ++i
815 _normalized = other._normalized;
820 _peaks.reserve(other._peaks.size());
821 for(PeakList::iterator i(other._peaks.begin()); i != other._peaks.end(); ++i) {
822 _peaks.push_back(
PTR(Peak)(
new Peak(**i)));
827 template<
typename MaskT>
828 void Footprint::intersectMask(
838 SpanList::iterator s(_spans.begin());
839 while((*s)->getY() < maskBBox.
getMinY() && s != _spans.end()){
845 SpanList maskedSpans;
847 for( ; s != _spans.end(); ++s) {
872 for(
int x = x0;
x <= x1; ++
x, ++mIter) {
873 if((*mIter & bitmask) != 0) {
879 PTR(Span) maskedSpan(new Span(y, x0,
x- 1));
880 maskedSpans.push_back(maskedSpan);
881 maskedArea += maskedSpan->getWidth();
890 PTR(Span) maskedSpan(new Span(y, x0, x1));
891 maskedSpans.push_back(maskedSpan);
892 maskedArea += maskedSpan->getWidth();
896 _spans = maskedSpans;
897 _bbox.clip(maskBBox);
904 geom::Box2I const& region,
922 for (
int y = tBoxI.getBeginY(); y < tBoxI.getEndY(); ++y) {
926 for (
int x = tBoxI.getBeginX(); x < tBoxI.getEndX(); ++
x) {
928 int const xSource =
std::floor(0.5 + p.getX());
929 int const ySource =
std::floor(0.5 + p.getY());
938 fpNew->addSpan(y, start, x - 1);
942 fpNew->addSpan(y, start, tBoxI.getMaxX());
946 fpNew->clipTo(region);
956 bool _checkNormalized(Footprint
const& foot) {
957 Footprint
copy(foot);
959 if (
copy.getArea() != foot.getArea()) {
962 if (
copy.getSpans().size() != foot.getSpans().size()) {
965 Footprint::SpanList
const& spansa = foot.getSpans();
966 Footprint::SpanList
const& spansb =
copy.getSpans();
967 Footprint::SpanList::const_iterator spa = spansa.begin();
968 Footprint::SpanList::const_iterator spb = spansb.begin();
969 for (; spa != spansa.end(); ++spa, ++spb) {
970 if ((*spa)->getY() != (*spb)->getY()) {
973 if ((*spa)->getX0() != (*spb)->getX0()) {
976 if ((*spa)->getX1() != (*spb)->getX1()) {
985 template<
typename MaskT>
987 PTR(Footprint) const& fp,
988 typename lsst::afw::
image::Mask<MaskT>::Ptr const& mask,
991 PTR(Footprint) newFp(new Footprint());
997 template<typename MaskT>
999 image::Mask<MaskT> *mask,
1000 Footprint const& foot,
1004 int const width =
static_cast<int>(mask->getWidth());
1005 int const height =
static_cast<int>(mask->getHeight());
1007 for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
1008 siter != foot.getSpans().end(); ++siter) {
1010 int const y = span->getY() - mask->getY0();
1011 if (y < 0 || y >= height) {
1015 int x0 = span->getX0() - mask->getX0();
1016 int x1 = span->getX1() - mask->getX0();
1017 x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 :
x0);
1018 x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1);
1021 end = mask->x_at(x1 + 1, y); ptr != end; ++ptr) {
1031 template<
typename MaskT>
1034 Footprint
const& foot,
1037 int const width =
static_cast<int>(mask->
getWidth());
1038 int const height =
static_cast<int>(mask->
getHeight());
1040 for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
1041 siter != foot.getSpans().end(); ++siter) {
1043 int const y = span->getY() - mask->getY0();
1044 if (y < 0 || y >= height) {
1048 int x0 = span->getX0() - mask->
getX0();
1049 int x1 = span->getX1() - mask->
getX0();
1050 x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 :
x0);
1051 x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1);
1054 end = mask->
x_at(x1 + 1, y); ptr != end; ++ptr) {
1064 template<
typename MaskT>
1067 std::vector<
PTR(Footprint)>
const& footprints,
1070 for (std::vector<
PTR(Footprint)>::const_iterator fiter = footprints.begin();
1071 fiter != footprints.end(); ++fiter) {
1080 template<
typename MaskT>
1083 CONST_PTR(std::vector<
PTR(Footprint)>)
const & footprints,
1091 template<
typename ImageT>
1092 class SetFootprint :
public FootprintFunctor<ImageT> {
1094 SetFootprint(ImageT
const&
image,
1095 typename ImageT::Pixel value) :
1096 FootprintFunctor<ImageT>(image),
_value(value) {}
1099 void operator()(
typename ImageT::xy_locator loc,
int,
int) {
1103 typename ImageT::Pixel
_value;
1107 template<
typename ImageT>
1110 Footprint
const& foot,
1111 typename ImageT::Pixel
const value
1113 SetFootprint<ImageT> setit(*image, value);
1119 template<
typename ImageT>
1123 typename ImageT::Pixel
const value
1128 template<
typename ImageT>
1131 std::vector<
PTR(Footprint)>
const& footprints,
1132 typename ImageT::Pixel
const value
1134 SetFootprint<ImageT> setit(*image, value);
1135 for (std::vector<
PTR(Footprint)>::const_iterator fiter = footprints.begin(),
1136 end = footprints.end(); fiter != end; ++fiter) {
1137 setit.apply(**fiter);
1147 template <
typename IDPixelT>
1148 static void set_footprint_id(
1150 Footprint
const& foot,
1154 for (Footprint::SpanList::const_iterator i = foot.getSpans().begin();
1155 i != foot.getSpans().end(); ++i) {
1157 for (typename image::Image<IDPixelT>::x_iterator ptr =
1158 idImage->x_at(span->getX0() + dx, span->getY() + dy),
1159 end = ptr + span->getWidth(); ptr != end; ++ptr) {
1165 template <
typename IDPixelT>
1167 set_footprint_array_ids(
1169 std::vector<
PTR(Footprint)>
const& footprints,
1170 bool const relativeIDs
1174 for (std::vector<
PTR(Footprint)>::const_iterator fiter = footprints.begin();
1175 fiter != footprints.end(); ++fiter) {
1184 set_footprint_id<IDPixelT>(idImage, *foot,
id);
1188 template void set_footprint_array_ids<int>(
1190 std::vector<PTR(Footprint)>
const& footprints,
1191 bool const relativeIDs);
1200 template <
typename IDImageT>
1201 typename boost::shared_ptr<image::Image<IDImageT> > setFootprintArrayIDs(
1202 std::vector<
PTR(Footprint)>
const& footprints,
1203 bool const relativeIDs
1205 std::vector<PTR(Footprint)>::const_iterator fiter = footprints.begin();
1206 if (fiter == footprints.end()) {
1208 lsst::pex::exceptions::InvalidParameterError,
1209 "You didn't provide any footprints"
1214 typename image::Image<IDImageT>::Ptr idImage(
1215 new image::Image<IDImageT>(foot->getRegion())
1221 set_footprint_array_ids<IDImageT>(idImage, footprints, relativeIDs);
1226 template image::Image<
int>::Ptr setFootprintArrayIDs(
1227 std::vector<
PTR(Footprint)> const& footprints,
1228 bool const relativeIDs);
1232 template <typename IDImageT>
1233 typename boost::shared_ptr<image::Image<IDImageT> > setFootprintID(
1242 set_footprint_id<IDImageT>(idImage, *foot,
id);
1256 class StructuringElement
1259 enum class Shape { CIRCLE, DIAMOND };
1260 typedef std::vector<Span>::const_iterator const_iterator;
1261 StructuringElement(
Shape shape,
int radius);
1262 StructuringElement(
int left,
int right,
int up,
int down);
1263 const_iterator begin()
const {
return _widths.begin(); }
1264 const_iterator end()
const {
return _widths.end(); }
1265 int getYRange()
const {
return _yRange; }
1268 std::vector<Span> _widths;
1277 StructuringElement::StructuringElement(
Shape shape,
int radius) {
1278 _yRange = 2*radius + 1;
1279 _widths.reserve(_yRange);
1282 for (
auto dy = -radius; dy <= radius; dy++) {
1283 int dx =
static_cast<int>(sqrt(radius*radius - dy*dy));
1284 _widths.push_back(Span(dy, -dx, dx));
1287 case Shape::DIAMOND:
1288 for (
auto dy = -radius; dy <= radius; dy++) {
1289 int dx = radius - abs(dy);
1290 _widths.push_back(Span(dy, -dx, dx));
1300 StructuringElement::StructuringElement(
int left,
int right,
int up,
int down) {
1301 _yRange = up + down + 1;
1302 _widths.reserve(_yRange);
1303 for (
auto dy = 1; dy <= up; dy++) {
1304 _widths.push_back(Span(dy, 0, 0));
1306 for (
auto dy = -1; dy >= -down; dy--) {
1307 _widths.push_back(Span(dy, 0, 0));
1309 _widths.push_back(Span(0, -left, right));
1316 PTR(Footprint) growFootprintImpl(
1317 Footprint const& foot,
1318 StructuringElement const& element
1321 PTR(Footprint) grown(new Footprint(0, foot.getRegion()));
1325 for (auto spanIter = foot.getSpans().begin(); spanIter != foot.getSpans().end(); spanIter++) {
1326 for (
auto it = element.begin(); it != element.end(); it++) {
1327 int xmin = (*spanIter)->getX0() + it->getX0();
1328 int xmax = (*spanIter)->getX1() + it->getX1();
1329 grown->addSpan((*spanIter)->getY() + it->getY(), xmin, xmax);
1348 int m,
y, xmin, xmax;
1355 bool comparePrimaryRun(PrimaryRun
const& first, PrimaryRun
const& second) {
1356 if (first.y != second.y) {
1357 return first.y < second.y;
1358 }
else if (first.m != second.m) {
1359 return first.m < second.m;
1361 return first.xmin < second.xmin;
1365 class ComparePrimaryRunY{
1367 bool operator()(PrimaryRun
const& pr,
int yval) {
1370 bool operator()(
int yval, PrimaryRun
const& pr) {
1375 class ComparePrimaryRunM{
1377 bool operator()(PrimaryRun
const& pr,
int mval) {
1380 bool operator()(
int mval, PrimaryRun
const& pr) {
1389 PTR(Footprint) shrinkFootprintImpl(
1390 Footprint const& foot,
1391 StructuringElement const& element
1394 PTR(Footprint) shrunk(new Footprint(0, foot.getRegion()));
1397 std::vector<PrimaryRun> primaryRuns;
1398 for (auto spanIter = foot.getSpans().begin(); spanIter != foot.getSpans().end(); ++spanIter) {
1400 for (
auto it = element.begin(); it != element.end(); ++it, ++m) {
1401 if ((it->getX1() - it->getX0()) <= ((*spanIter)->getX1() - (*spanIter)->getX0())) {
1402 int xmin = (*spanIter)->getX0() - it->getX0();
1403 int xmax = (*spanIter)->getX1() - it->getX1();
1404 int y = (*spanIter)->getY() - it->getY();
1405 primaryRuns.push_back(PrimaryRun({m,
y, xmin, xmax}));
1412 std::sort(primaryRuns.begin(), primaryRuns.end(), comparePrimaryRun);
1414 for (
int y = primaryRuns.front().y; y <= primaryRuns.back().y; ++
y) {
1415 auto yRange = std::equal_range(primaryRuns.begin(), primaryRuns.end(),
y, ComparePrimaryRunY());
1420 if (std::distance(yRange.first, yRange.second) < element.getYRange()) {
1429 std::list<PrimaryRun> goodRuns;
1431 for (
int m = 0; m < element.getYRange(); ++m) {
1432 auto mRange = std::equal_range(yRange.first, yRange.second, m, ComparePrimaryRunM());
1433 if (mRange.first == mRange.second) {
1440 std::list<PrimaryRun> candidateRuns;
1441 int start_x = mRange.first->xmin;
1442 int end_x = mRange.first->xmax;
1443 for (
auto run = mRange.first+1;
run != mRange.second; ++
run) {
1444 if (
run->xmin > end_x) {
1446 candidateRuns.push_back(PrimaryRun{m,
y, start_x, end_x});
1447 start_x =
run->xmin;
1454 candidateRuns.push_back(PrimaryRun{m,
y, start_x, end_x});
1463 std::list<PrimaryRun> newlist;
1464 for (
auto good = goodRuns.begin(); good != goodRuns.end(); ++good) {
1465 for (
auto cand = candidateRuns.begin(); cand != candidateRuns.end(); ++cand) {
1466 int start =
std::max(good->xmin, cand->xmin);
1467 int end =
std::min(good->xmax, cand->xmax);
1469 newlist.push_back(PrimaryRun({m,
y, start, end}));
1477 for (
auto run = goodRuns.begin();
run != goodRuns.end(); ++
run) {
1478 shrunk->addSpan(
run->y,
run->xmin,
run->xmax);
1482 shrunk->normalize();
1490 PTR(Footprint) _mergeFootprints(Footprint const& aFoot, Footprint const& bFoot) {
1491 PTR(Footprint) foot(new Footprint());
1493 Footprint::PeakList const& aPeaks = aFoot.getPeaks();
1494 Footprint::PeakList const& bPeaks = bFoot.getPeaks();
1495 Footprint::PeakList & peaks = foot->getPeaks();
1496 peaks.reserve(aPeaks.size() + bPeaks.size());
1497 peaks.insert(peaks.begin(), aPeaks.begin(), aPeaks.end());
1498 peaks.insert(peaks.end()-1, bPeaks.begin(), bPeaks.end());
1499 assert(peaks.size() == (aPeaks.size() + bPeaks.size()));
1501 Footprint::SpanList const& aSpans = aFoot.getSpans();
1502 Footprint::SpanList const& bSpans = bFoot.getSpans();
1503 Footprint::SpanList::const_iterator aSpan = aSpans.begin();
1504 Footprint::SpanList::const_iterator bSpan = bSpans.begin();
1505 Footprint::SpanList::const_iterator aEnd = aSpans.end();
1506 Footprint::SpanList::const_iterator bEnd = bSpans.end();
1508 foot->getSpans().reserve(std::
max(aSpans.size(), bSpans.size()));
1510 while ((aSpan != aEnd) && (bSpan != bEnd)) {
1511 int y = (*aSpan)->getY();
1512 int x0 = (*aSpan)->getX0();
1513 int x1 = (*aSpan)->getX1();
1514 int yb = (*bSpan)->getY();
1515 int xb0 = (*bSpan)->getX0();
1516 int xb1 = (*bSpan)->getX1();
1518 if ((y < yb) || (y == yb && (x1 < (xb0-1)))) {
1520 foot->addSpanInSeries(y, x0, x1);
1524 if ((yb < y) || (y == yb && (xb1 < (x0-1)))) {
1526 foot->addSpanInSeries(yb, xb0, xb1);
1539 if ((aSpan != aEnd) &&
1540 ((*aSpan)->getY() ==
y) &&
1541 ((*aSpan)->getX0() <= (x1+1))) {
1543 x1 =
std::max(x1, (*aSpan)->getX1());
1547 if ((bSpan != bEnd) &&
1548 ((*bSpan)->getY() ==
y) &&
1549 ((*bSpan)->getX0() <= (x1+1))) {
1551 x1 =
std::max(x1, (*bSpan)->getX1());
1557 foot->addSpanInSeries(y, x0, x1);
1562 for (; aSpan != aEnd; ++aSpan) {
1563 foot->addSpanInSeries((*aSpan)->getY(), (*aSpan)->getX0(), (*aSpan)->getX1());
1566 for (; bSpan != bEnd; ++bSpan) {
1567 foot->addSpanInSeries((*bSpan)->getY(), (*bSpan)->getX0(), (*bSpan)->getX1());
1576 return _mergeFootprints(foot1, foot2);
1580 if (!foot1.isNormalized() || !foot2.isNormalized()) {
1582 lsst::pex::exceptions::InvalidParameterError,
1583 "mergeFootprints(const Footprints) requires normalize()d Footprints.");
1585 return _mergeFootprints(foot1, foot2);
1598 typedef boost::uint16_t dtype;
1599 typedef boost::uint16_t itype;
1601 const itype nil = 0xffff;
1607 int const x0 = bbox.
getMinX();
1608 int const y0 = bbox.
getMinY();
1610 for (
size_t i=0; i<foots.size(); ++i) {
1612 set_footprint_id<itype>(argmin, *foots[i], i, -
x0, -
y0);
1613 set_footprint_id<dtype>(dist, *foots[i], 1, -
x0, -
y0);
1617 int const width = dist->
getWidth();
1620 for (
int y = 0; y != height; ++
y) {
1623 for (
int x = 0; x != width; ++
x, ++dim.x(), ++aim.x()) {
1624 if (dim(0, 0) == 1) {
1631 dim(0, 0) = width + height;
1635 dtype ndist = dim(0,-1) + 1;
1636 if (ndist < dim(0,0)) {
1638 aim(0,0) = aim(0,-1);
1643 dtype ndist = dim(-1,0) + 1;
1644 if (ndist < dim(0,0)) {
1646 aim(0,0) = aim(-1,0);
1653 for (
int y = height - 1; y >= 0; --
y) {
1656 for (
int x = width - 1; x >= 0; --
x, --dim.x(), --aim.x()) {
1659 if (y + 1 < height) {
1660 dtype ndist = dim(0,1) + 1;
1661 if (ndist < dim(0,0)) {
1663 aim(0,0) = aim(0,1);
1667 if (x + 1 < width) {
1668 dtype ndist = dim(1,0) + 1;
1669 if (ndist < dim(0,0)) {
1671 aim(0,0) = aim(1,0);
1679 Footprint const& foot,
1683 if (nGrow <= 0 || foot.getNpix() == 0 ) {
1692 Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
1693 return growFootprintImpl(foot, StructuringElement(shape, nGrow));
1708 if (nGrow <= 0 || foot.getNpix() == 0 ) {
1712 return growFootprintImpl(foot, StructuringElement(left ? nGrow: 0, right ? nGrow : 0,
1713 up ? nGrow : 0, down ? nGrow : 0));
1717 Footprint const& foot,
1722 Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
1723 return shrinkFootprintImpl(foot, StructuringElement(shape, nShrink));
1729 typedef boost::uint16_t ImageT;
1737 foot.insertIntoImage(*idImage, 1, fpBBox);
1739 std::vector<geom::Box2I> bboxes;
1754 while (y0 < height) {
1756 for (
int y = y0; y != height; ++
y) {
1763 int const x0 = first - begin;
1764 int const x1 = last - begin;
1766 std::fill(first, last + 1, 0);
1772 for (++y; y != height; ++
y) {
1773 if (std::find(idImage->at(x0, y), idImage->at(x1 + 1, y), 0) != idImage->at(x1 + 1, y)) {
1776 std::fill(idImage->at(x0, y), idImage->at(x1 + 1, y), 0);
1782 bboxes.push_back(bbox);
1794 template<
typename ImageOrMaskedImageT>
1797 PTR(ImageOrMaskedImageT)
const input,
1798 PTR(ImageOrMaskedImageT) output) {
1799 Footprint::SpanList spans = foot.getSpans();
1800 for (Footprint::SpanList::iterator sp = spans.begin();
1801 sp != spans.end(); ++sp) {
1802 int y = (*sp)->getY();
1803 int x0 = (*sp)->getX0();
1804 int x1 = (*sp)->getX1();
1805 typename ImageOrMaskedImageT::const_x_iterator initer = input->x_at(
1806 x0 - input->getX0(), y - input->getY0());
1807 typename ImageOrMaskedImageT::x_iterator outiter = output->x_at(
1808 x0 - output->getX0(), y - output->getY0());
1809 for (
int x=x0; x <= x1; ++
x, ++initer, ++outiter) {
1824 psArray *pmGrowFootprintArray(psArray
const *footprints,
1826 assert (footprints->n == 0 || pmIsFootprint(footprints->data[0]));
1828 if (footprints->n == 0) {
1829 return psArrayAlloc(0);
1835 psImage *idImage = pmSetFootprintArrayIDs(footprints,
true);
1839 psKernel *circle = psKernelAlloc(-r, r, -r, r);
1840 assert (circle->image->numRows == 2*r + 1 && circle->image->numCols == circle->image->numRows);
1841 for (
int i = 0; i <= r; ++i) {
1842 for (
int j = 0; j <= r; ++j) {
1843 if (i*i + j*j <= r*r) {
1844 circle->kernel[i][j] =
1845 circle->kernel[i][-j] =
1846 circle->kernel[-i][j] =
1847 circle->kernel[-i][-j] = 1;
1852 psImage *grownIdImage = psImageConvolveDirect(idImage, circle);
1855 psArray *grown = pmFindFootprints(grownIdImage, 0.5, 1);
1856 assert (grown != NULL);
1858 psFree(grownIdImage);
1863 psArray
const *peaks = pmFootprintArrayToPeaks(footprints);
1864 pmPeaksAssignToFootprints(grown, peaks);
1865 psFree((psArray *)peaks);
1877 psArray *pmMergeFootprintArrays(psArray
const *footprints1,
1878 psArray
const *footprints2,
1879 int const includePeaks) {
1880 assert (footprints1->n == 0 || pmIsFootprint(footprints1->data[0]));
1881 assert (footprints2->n == 0 || pmIsFootprint(footprints2->data[0]));
1883 if (footprints1->n == 0 || footprints2->n == 0) {
1884 psArray
const *old = (footprints1->n == 0) ? footprints2 : footprints1;
1886 psArray *merged = psArrayAllocEmpty(old->n);
1887 for (
int i = 0; i < old->n; ++i) {
1888 psArrayAdd(merged, 1, old->data[i]);
1898 pmFootprint *fp1 = footprints1->data[0];
1899 pmFootprint *fp2 = footprints2->data[0];
1900 if (fp1->region.x0 != fp2->region.x0 ||
1901 fp1->region.x1 != fp2->region.x1 ||
1902 fp1->region.y0 != fp2->region.y0 ||
1903 fp1->region.y1 != fp2->region.y1) {
1904 psError(PS_ERR_BAD_PARAMETER_SIZE,
true,
1905 "The two pmFootprint arrays correspnond to different-sized regions");
1913 psImage *idImage = pmSetFootprintArrayIDs(footprints1,
true);
1914 set_footprint_array_ids(idImage, footprints2,
true);
1916 psArray *merged = pmFindFootprints(idImage, 0.5, 1);
1917 assert (merged != NULL);
1923 if (includePeaks & 0x1) {
1924 psArray
const *peaks = pmFootprintArrayToPeaks(footprints1);
1925 pmPeaksAssignToFootprints(merged, peaks);
1926 psFree((psArray *)peaks);
1929 if (includePeaks & 0x2) {
1930 psArray
const *peaks = pmFootprintArrayToPeaks(footprints2);
1931 pmPeaksAssignToFootprints(merged, peaks);
1932 psFree((psArray *)peaks);
1945 pmPeaksAssignToFootprints(psArray *footprints,
1946 psArray
const *peaks) {
1947 assert (footprints != NULL);
1948 assert (footprints->n == 0 || pmIsFootprint(footprints->data[0]));
1949 assert (peaks != NULL);
1950 assert (peaks->n == 0 || pmIsPeak(peaks->data[0]));
1952 if (footprints->n == 0) {
1954 return psError(PS_ERR_BAD_PARAMETER_SIZE,
true,
"Your list of footprints is empty");
1962 psImage *ids = pmSetFootprintArrayIDs(footprints,
true);
1963 assert (ids != NULL);
1964 assert (ids->type.type == PS_TYPE_S32);
1965 int const y0 = ids->y0;
1966 int const x0 = ids->x0;
1967 int const numRows = ids->numRows;
1968 int const numCols = ids->numCols;
1970 for (
int i = 0; i < peaks->n; ++i) {
1971 pmPeak *peak = peaks->data[i];
1972 int const x = peak->x -
x0;
1973 int const y = peak->y -
y0;
1975 assert (x >= 0 && x < numCols && y >= 0 && y < numRows);
1976 int id = ids->data.S32[
y][x -
x0];
1979 pmFootprint *nfp = pmFootprintAlloc(1, ids);
1980 pmFootprintAddSpan(nfp, y, x, x);
1981 psArrayAdd(footprints, 1, nfp);
1986 assert (
id >= 1 && id <= footprints->n);
1987 pmFootprint *fp = footprints->data[
id - 1];
1988 psArrayAdd(fp->peaks, 5, peak);
1995 for (
int i = 0; i < footprints->n; ++i) {
1996 pmFootprint *fp = footprints->data[i];
1997 fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
1999 for (
int j = 1; j < fp->peaks->n; ++j) {
2000 if (fp->peaks->data[j] == fp->peaks->data[j-1]) {
2001 (void)psArrayRemoveIndex(fp->peaks, j);
2017 psErrorCode pmFootprintCullPeaks(psImage
const *img,
2018 psImage
const *weight,
2020 float const nsigma_delta,
2022 float const min_threshold) {
2023 assert (img != NULL);
2024 assert (img->type.type == PS_TYPE_F32);
2025 assert (weight != NULL);
2026 assert (weight->type.type == PS_TYPE_F32);
2027 assert (img->y0 == weight->y0 && img->x0 == weight->x0);
2028 assert (fp != NULL);
2030 if (fp->peaks == NULL || fp->peaks->n == 0) {
2035 subRegion.x0 = fp->bbox.x0;
2036 subRegion.x1 = fp->bbox.x1 + 1;
2037 subRegion.y0 = fp->bbox.y0;
2038 subRegion.y1 = fp->bbox.y1 + 1;
2039 psImage
const *subImg = psImageSubset((psImage *)img, subRegion);
2040 psImage
const *subWt = psImageSubset((psImage *)weight, subRegion);
2041 assert (subImg != NULL && subWt != NULL);
2049 psArray *brightPeaks = psArrayAlloc(0);
2050 psFree(brightPeaks->data);
2051 brightPeaks->data = psMemIncrRefCounter(fp->peaks->data);
2055 for (
int i = 1; i < fp->peaks->n; ++i) {
2056 pmPeak
const *peak = fp->peaks->data[i];
2057 int x = peak->x - subImg->x0;
2058 int y = peak->y - subImg->y0;
2063 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
2064 float const stdev = std::sqrt(subWt->data.F32[y][x]);
2065 float threshold = subImg->data.F32[
y][
x] - nsigma_delta*
stdev;
2067 #if 1 // min_threshold is assumed to be below the detection threshold,
2069 (void)psArrayRemoveIndex(fp->peaks, i);
2073 #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once
2074 threshold = min_threshold;
2077 if (threshold > subImg->data.F32[y][x]) {
2078 threshold = subImg->data.F32[
y][
x] - 10*FLT_EPSILON;
2081 int const peak_id = 1;
2083 pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
2085 psImage *idImg = pmSetFootprintID(peakFootprint, peak_id);
2086 psFree(peakFootprint);
2089 for (j = 0; j < i; ++j) {
2090 pmPeak
const *peak2 = fp->peaks->data[j];
2091 int x2 = peak2->x - subImg->x0;
2092 int y2 = peak2->y - subImg->y0;
2093 int const peak2_id = idImg->data.S32[y2][x2];
2095 if (peak2_id == peak_id) {
2097 (void)psArrayRemoveIndex(fp->peaks, i);
2110 psFree(brightPeaks);
2111 psFree((psImage *)subImg);
2112 psFree((psImage *)subWt);
2121 pmFootprintArrayCullPeaks(psImage
const *img,
2122 psImage
const *weight,
2123 psArray *footprints,
2124 float const nsigma_delta,
2126 float const min_threshold) {
2127 for (
int i = 0; i < footprints->n; ++i) {
2128 pmFootprint *fp = footprints->data[i];
2129 if (pmFootprintCullPeaks(img, weight, fp, nsigma_delta, min_threshold) != PS_ERR_NONE) {
2130 return psError(PS_ERR_UNKNOWN,
false,
"Culling pmFootprint %d", fp->id);
2141 psArray *pmFootprintArrayToPeaks(psArray
const *footprints) {
2142 assert(footprints != NULL);
2143 assert(footprints->n == 0 || pmIsFootprint(footprints->data[0]));
2146 for (
int i = 0; i < footprints->n; ++i) {
2147 pmFootprint
const *fp = footprints->data[i];
2148 npeak += fp->peaks->n;
2151 psArray *peaks = psArrayAllocEmpty(npeak);
2153 for (
int i = 0; i < footprints->n; ++i) {
2154 pmFootprint
const *fp = footprints->data[i];
2155 for (
int j = 0; j < fp->peaks->n; ++j) {
2156 psArrayAdd(peaks, 1, fp->peaks->data[j]);
2171 void Footprint::intersectMask(
2177 PTR(Footprint) const& foot,
2178 image::Mask<image::
MaskPixel>::Ptr const& mask,
2184 CONST_PTR(std::vector<
PTR(Footprint)>) const& footprints,
2189 std::vector<
PTR(Footprint)> const& footprints,
2193 Footprint const& foot, image::
MaskPixel const bitmask);
2196 Footprint const& foot, image::
MaskPixel const bitmask);
2198 #define INSTANTIATE_NUMERIC(TYPE) \
2200 TYPE setImageFromFootprint(image::Image<TYPE> *image, \
2201 Footprint const& footprint, \
2202 TYPE const value); \
2204 TYPE setImageFromFootprintList(image::Image<TYPE> *image, \
2205 std::vector<PTR(Footprint)> const& footprints, \
2206 TYPE const value); \
2208 TYPE setImageFromFootprintList(image::Image<TYPE> *image, \
2209 CONST_PTR(std::vector<PTR(Footprint)>) footprints, \
2210 TYPE const value); \
2212 void copyWithinFootprint(Footprint const&, \
2213 PTR(lsst::afw::image::Image<TYPE>) const, \
2214 PTR(lsst::afw::image::Image<TYPE>)); \
2216 void copyWithinFootprint(Footprint const&, \
2217 PTR(lsst::afw::image::MaskedImage<TYPE>) const, \
2218 PTR(lsst::afw::image::MaskedImage<TYPE>)); \
2220 void Footprint::clipToNonzero(lsst::afw::image::Image<TYPE> const&); \
2223 INSTANTIATE_NUMERIC(
float);
2224 INSTANTIATE_NUMERIC(
double);
2226 INSTANTIATE_NUMERIC(boost::uint16_t);
2227 INSTANTIATE_NUMERIC(
int);
2228 INSTANTIATE_NUMERIC(boost::uint64_t);
2231 #define INSTANTIATE_MASK(PIXEL) \
2233 void Footprint::insertIntoImage( \
2234 lsst::afw::image::Image<PIXEL>& idImage, \
2235 boost::uint64_t const id, \
2236 geom::Box2I const& region=geom::Box2I() \
2239 void Footprint::insertIntoImage( \
2240 lsst::afw::image::Image<PIXEL>& idImage, \
2241 boost::uint64_t const id, \
2242 bool const overwriteId, long const idMask, \
2243 std::set<boost::uint64_t> *oldIds, \
2244 geom::Box2I const& region=geom::Box2I() \
2247 INSTANTIATE_MASK(boost::uint16_t);
2248 INSTANTIATE_MASK(
int);
2249 INSTANTIATE_MASK(boost::uint64_t);
Defines the fields and offsets for a table.
void nearestFootprint(std::vector< boost::shared_ptr< Footprint >> const &foots, lsst::afw::image::Image< boost::uint16_t >::Ptr argmin, lsst::afw::image::Image< boost::uint16_t >::Ptr dist)
boost::uint16_t MaskPixel
Declare the Kernel class and subclasses.
x_iterator row_begin(int y) const
for(FootprintList::const_iterator ptr=feet->begin(), end=feet->end();ptr!=end;++ptr)
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
CatalogT< BaseRecord > BaseCatalog
geom::Point2D skyToPixel(geom::Angle sky1, geom::Angle sky2) const
Convert from sky coordinates (e.g. RA/dec) to pixel positions.
boost::shared_ptr< Footprint > footprintAndMask(boost::shared_ptr< Footprint > const &foot, typename image::Mask< MaskT >::Ptr const &mask, MaskT const bitmask)
Return a Footprint that's the intersection of a Footprint with a Mask.
lsst::afw::detection::Footprint Footprint
definition of the Trace messaging facilities
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
void include(Point2D const &point)
Expand this to ensure that this->contains(point).
Implementation of the WCS standard for a any projection.
void shift(Vector< T, N > const &offset, Array< std::complex< T >, N, C > const &array, int const real_last_dim)
Perform a Fourier-space translation transform.
boost::shared_ptr< coord::Coord > pixelToSky(double pix1, double pix2) const
Convert from pixel position to sky coordinates (e.g. RA/dec)
An integer coordinate rectangle.
table::Key< table::Array< Kernel::Pixel > > image
boost::shared_ptr< Footprint > shrinkFootprint(Footprint const &foot, int nGrow, bool isotropic)
afw::geom::ellipses::Quadrupole Shape
void shift(Extent2I const &offset)
Shift the position of the box by the given offset.
int getWidth() const
Return the number of columns in the image.
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
CatalogIterator< typename Internal::const_iterator > const_iterator
Extent2I const getDimensions() const
Represent a 2-dimensional array of bitmask pixels.
geom::Box2I const & _bbox
x_iterator x_at(int x, int y) const
Return an x_iterator to the point (x, y) in the image.
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
bool contains(Point2I const &point) const
Return true if the box contains the point.
void include(Point2I const &point)
Expand this to ensure that this->contains(point).
MaskT clearMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
(AND ~bitmask) all the Mask's pixels that are in the Footprint; that is, set to zero in the Mask-inte...
ImageT::Pixel setImageFromFootprint(ImageT *image, Footprint const &footprint, typename ImageT::Pixel const value)
Set all image pixels in a Footprint to a given value.
Support for peaks in images.
A coordinate class intended to represent absolute positions.
#define LSST_EXCEPT(type,...)
std::vector< lsst::afw::geom::Box2I > footprintToBBoxList(Footprint const &foot)
bool isEmpty() const
Return true if the box contains no points.
Extent< int, N > floor(Extent< double, N > const &input)
geom::Box2I getBBox(ImageOrigin origin=PARENT) const
MaskT setMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
OR bitmask into all the Mask's pixels that are in the Footprint.
def run
Exit with the status code resulting from running the provided test suite.
afw::table::Key< double > b
Point< double, 2 > Point2D
xy_locator xy_at(int x, int y) const
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
int getHeight() const
Return the number of rows in the image.
A floating-point coordinate rectangle geometry.
boost::shared_ptr< Footprint > mergeFootprints(Footprint const &foot1, Footprint const &foot2)
Extent< int, 2 > Extent2I
Include files required for standard LSST Exception handling.
Utility functions for kernels.
void copyWithinFootprint(Footprint const &foot, boost::shared_ptr< ImageOrMaskedImageT > const input, boost::shared_ptr< ImageOrMaskedImageT > output)
ImageT::Pixel setImageFromFootprintList(ImageT *image, boost::shared_ptr< std::vector< boost::shared_ptr< Footprint >> const > footprints, typename ImageT::Pixel const value)
Set all image pixels in a set of Footprints to a given value.
MaskT setMaskFromFootprintList(lsst::afw::image::Mask< MaskT > *mask, std::vector< boost::shared_ptr< Footprint >> const &footprints, MaskT const bitmask)
OR bitmask into all the Mask's pixels which are in the set of Footprints.