32 #include "boost/format.hpp"
60 struct compareSpanByYX :
61 public std::binary_function<Span::ConstPtr, Span::ConstPtr, bool> {
62 int operator()(Span::ConstPtr a, Span::ConstPtr
b) {
84 ) : lsst::daf::base::Citizen(typeid(this)),
88 _peaks(PeakTable::makeMinimalSchema()),
94 lsst::pex::exceptions::InvalidParameterError,
95 str(
boost::format(
"Number of spans requested is -ve: %d") % nspan));
105 afw::table::Schema
const & peakSchema,
108 ) : lsst::daf::base::Citizen(typeid(this)),
111 _bbox(geom::Box2I()),
118 lsst::pex::exceptions::InvalidParameterError,
119 str(
boost::format(
"Number of spans requested is -ve: %d") % nspan));
128 ) : lsst::daf::base::Citizen(typeid(this)),
132 _peaks(PeakTable::makeMinimalSchema()),
140 for (
int i = y0; i <= y1; ++i) {
150 ) : lsst::daf::base::Citizen(typeid(this)),
154 _peaks(PeakTable::makeMinimalSchema()),
157 int const r2 =
static_cast<int>(radius*radius + 0.5);
158 int const r =
static_cast<int>(std::sqrt(static_cast<double>(r2)));
160 for (
int i = -r; i <= r; ++i) {
161 int hlen =
static_cast<int>(std::sqrt(static_cast<double>(r2 - i*i)));
162 addSpan(center.getY() + i, center.getX() - hlen, center.getX() + hlen);
168 geom::ellipses::Ellipse
const & ellipse,
170 ) : lsst::daf::base::Citizen(typeid(this)),
173 _bbox(geom::Box2I()),
174 _peaks(PeakTable::makeMinimalSchema()),
178 geom::ellipses::PixelRegion pr(ellipse);
180 geom::ellipses::PixelRegion::Iterator spanIter = pr.begin(), end = pr.end();
184 if (!spanIter->isEmpty()) {
192 Footprint::SpanList
const & spans,
194 ) : lsst::daf::base::Citizen(typeid(this)),
197 _bbox(geom::Box2I()),
198 _peaks(PeakTable::makeMinimalSchema()),
202 _spans.reserve(spans.size());
203 for(SpanList::const_iterator i(spans.begin()); i != spans.end(); ++i) {
209 : lsst::daf::base::Citizen(typeid(this)),
213 _peaks(other.getPeaks().getTable(), other.getPeaks().begin(), other.getPeaks().end(), true),
214 _region(other._region)
217 _spans.reserve(other._spans.size());
218 for(SpanList::const_iterator i(other._spans.begin());
219 i != other._spans.end(); ++i
224 _normalized = other._normalized;
228 Footprint::~Footprint() {
232 PTR(PeakRecord)
Footprint::addPeak(
float fx,
float fy,
float value) {
233 PTR(PeakRecord) p = getPeaks().addNew();
238 p->setPeakValue(value);
247 SortPeaks(afw::table::Key<float>
const & key) : _key(key) {}
250 return a.
get(_key) > b.
get(_key);
254 afw::table::Key<float> _key;
259 void Footprint::sortPeaks(afw::table::Key<float>
const & key) {
260 getPeaks().sort(SortPeaks(key.isValid() ? key : PeakTable::getPeakValueKey()));
266 bool Footprint::contains(
271 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
272 if ((*siter)->contains(pix.getX(), pix.getY())) {
284 struct ClipSpansPredicate :
public std::unary_function<PTR(Span) const&, bool> {
289 bool operator()(
PTR(Span)
const& spanPtr)
const {
290 Span
const& span = *spanPtr;
291 int const y = span.getY();
298 struct ClipPeaksPredicate :
public std::unary_function<PeakRecord const&, bool> {
303 bool operator()(
PTR(PeakRecord)
const& peak)
const {
310 _spans.erase(std::remove_if(_spans.begin(), _spans.end(), ClipSpansPredicate(bbox)), _spans.end());
311 for (SpanList::const_iterator ss = _spans.begin(); ss != _spans.end(); ++ss) {
313 span.getX0() = std::max(span.getX0(), bbox.
getMinX());
314 span.getX1() = std::min(span.getX1(), bbox.
getMaxX());
318 _peaks.getInternal().erase(std::remove_if(_peaks.getInternal().begin(), _peaks.getInternal().end(),
319 ClipPeaksPredicate(bbox)), _peaks.getInternal().end());
321 if (_spans.empty()) {
335 assert(!_spans.empty());
340 sort(_spans.begin(), _spans.end(), compareSpanByYX());
342 Footprint::SpanList::iterator ptr = _spans.begin(), end = _spans.end();
343 Span *lspan = ptr->get();
346 _area = lspan->getWidth();
347 int minX = lspan->_x0, minY=
y, maxX=x1;
351 for (; ptr != end; ++ptr) {
352 Span *rspan = ptr->get();
353 if (rspan->_y == y) {
354 if (rspan->_x0 <= x1 + 1) {
355 if (rspan->_x1 > x1) {
357 _area += rspan->_x1 - x1;
359 x1 = lspan->_x1 = rspan->_x1;
361 if(x1 > maxX) maxX = x1;
364 ptr = _spans.erase(ptr);
374 _area += rspan->getWidth();
375 if(rspan->_x1 > maxX) maxX = rspan->_x1;
378 _area += rspan->getWidth();
385 if(lspan->_x0 < minX) minX = lspan->_x0;
386 if(x1 > maxX) maxX = x1;
393 Span
const& Footprint::addSpan(
399 return addSpan(y, x1, x0);
402 PTR(Span) sp(new Span(y, x0, x1));
403 _spans.push_back(sp);
405 _area += sp->getWidth();
417 return addSpan(span._y, span._x0, span._x1);
420 const Span& Footprint::addSpan(
425 return addSpan(span._y + dy, span._x0 + dx, span._x1 + dx);
428 const Span& Footprint::addSpanInSeries(
434 return addSpanInSeries(y, x1, x0);
436 if (_spans.size() == 0) {
437 const Span& s = addSpan(y, x0, x1);
442 PTR(Span) lastspan = _spans.back();
443 if ((y == lastspan->getY()) &&
444 (x0 == (lastspan->getX1() + 1))) {
447 _area += (1 + x1 -
x0);
451 if (!((y > lastspan->getY()) ||
452 (x0 > (lastspan->getX1() + 1)))) {
454 lsst::pex::exceptions::InvalidParameterError,
455 str(
boost::format(
"addSpanInSeries: new span %i,[%i,%i] is NOT in series after last span "
457 y % x0 % x1 % lastspan->getY() % lastspan->getX0() % lastspan->getX1()));
459 const Span& s = addSpan(y, x0, x1);
468 for (SpanList::iterator i = _spans.begin(); i != _spans.end(); ++i){
483 double xc = 0, yc = 0;
484 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
486 int const y = span->getY();
487 int const x0 = span->getX0();
488 int const x1 = span->getX1();
489 int const npix = x1 - x0 + 1;
492 xc += npix*0.5*(x1 + x0);
497 return geom::
Point2D(xc/_area, yc/_area);
500 geom::ellipses::Quadrupole
504 double const xc = cen.getX();
505 double const yc = cen.getY();
507 double sumxx = 0, sumxy = 0, sumyy = 0;
508 for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
510 int const y = span->getY();
511 int const x0 = span->getX0();
512 int const x1 = span->getX1();
513 int const npix = x1 - x0 + 1;
515 for (
int x = x0;
x <= x1; ++
x) {
516 sumxx += (
x - xc)*(
x - xc);
518 sumxy += npix*(0.5*(x1 +
x0) - xc)*(y - yc);
519 sumyy += npix*(y - yc)*(y - yc);
522 return geom::ellipses::Quadrupole(sumxx/_area, sumyy/_area, sumxy/_area);
532 template<
bool overwriteId,
typename PixelT>
535 Footprint::SpanList
const& _spans,
537 boost::uint64_t
const id,
540 std::set<boost::uint64_t> *oldIds=NULL
557 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
559 "Footprint's host Image of size (%dx%d)") %
564 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
565 str(
boost::format(
"Id 0x%x sets bits in the protected mask 0x%x") %
id % mask));
568 typename std::set<boost::uint64_t>::const_iterator pos;
570 pos = oldIds->begin();
572 for (Footprint::SpanList::const_iterator spi = _spans.begin(); spi != _spans.end(); ++spi) {
575 int const sy0 = span->getY() - y0;
576 if (sy0 < 0 || sy0 >= height) {
580 int sx0 = span->getX0() -
x0;
584 int sx1 = span->getX1() -
x0;
585 int const swidth = (sx1 >=
width) ? width - sx0 : sx1 - sx0 + 1;
588 end = ptr + swidth; ptr != end; ++ptr) {
590 long val = *ptr & ~mask;
591 if (val != 0 and oldIds != NULL) {
592 pos = oldIds->insert(pos, val);
594 *ptr = (*ptr & mask) +
id;
603 template<
typename PixelT>
607 int const ix0 = img.
getX0();
608 int const iy0 = img.
getY0();
614 _spans.reserve(old.size());
617 for (SpanList::iterator s = old.begin(); s != old.end(); ++s) {
618 int const y = (*s)->getY();
619 int const x0 = (*s)->getX0();
620 int const x1 = (*s)->getX1();
621 typename ImageT::x_iterator img_it = img.
row_begin(y - iy0) + (x0 - ix0);
624 for (leftx = x0; leftx <= x1; ++leftx, ++img_it) {
625 if (*img_it != zero) {
634 img_it = img.
row_begin(y - iy0) + (x1 - ix0);
635 for (rightx = x1; rightx >= leftx; --rightx, --img_it) {
636 if (*img_it != zero) {
640 addSpanInSeries(y, leftx, rightx);
645 template<
typename PixelT>
647 Footprint::insertIntoImage(
649 boost::uint64_t
const id,
653 static_cast<void>(doInsertIntoImage<false>(_region, _spans, idImage,
id, region));
656 template<
typename PixelT>
658 Footprint::insertIntoImage(
660 boost::uint64_t
const id,
663 std::set<boost::uint64_t> *oldIds,
667 if (
id > std::size_t(std::numeric_limits<PixelT>::max())) {
669 lsst::pex::exceptions::OutOfRangeError,
670 "id out of range for image type"
674 doInsertIntoImage<true>(_region, _spans, idImage,
id, region, mask, oldIds);
676 doInsertIntoImage<false>(_region, _spans, idImage,
id, region, mask, oldIds);
680 void Footprint::include(std::vector<
PTR(
Footprint)>
const & others,
bool ignoreSelf) {
681 if (others.empty())
return;
688 for (std::vector<
PTR(
Footprint)>::const_iterator i = others.begin(); i != others.end(); ++i) {
691 boost::uint16_t bits = 0x1;
696 for (std::vector<
PTR(
Footprint)>::const_iterator i = others.begin(); i != others.end(); ++i) {
699 FootprintSet fpSet(mask, Threshold(bits, Threshold::BITMASK));
700 if (fpSet.getFootprints()->empty()) {
702 }
else if (fpSet.getFootprints()->size() == 1u) {
703 _spans.swap(fpSet.getFootprints()->front()->getSpans());
706 for (std::vector<
PTR(
Footprint)>::const_iterator i = fpSet.getFootprints()->begin();
707 i != fpSet.getFootprints()->end(); ++i) {
708 _spans.insert(_spans.end(), (**i).getSpans().begin(), (**i).getSpans().end());
716 class FootprintFactory :
public table::io::PersistableFactory {
719 virtual PTR(table::io::Persistable)
720 read(InputArchive const & archive, CatalogVector const & catalogs)
const {
723 result->readSpans(catalogs.front());
724 result->readPeaks(catalogs.back());
728 explicit FootprintFactory(std::
string const &
name) : table::io::PersistableFactory(
name) {}
735 class FootprintPersistenceHelper :
private boost::noncopyable {
737 table::Schema spanSchema;
738 table::Key<int> spanY;
739 table::Key<int> spanX0;
740 table::Key<int> spanX1;
742 static FootprintPersistenceHelper
const &
get() {
743 static FootprintPersistenceHelper instance;
748 FootprintPersistenceHelper() :
750 spanY(spanSchema.addField<int>(
"y",
"row position of span",
"pixels")),
751 spanX0(spanSchema.addField<int>(
"x0",
"first column of span (inclusive)",
"pixels")),
752 spanX1(spanSchema.addField<int>(
"x1",
"first column of span (inclusive)",
"pixels"))
754 spanSchema.getCitizen().markPersistent();
758 std::string getFootprintPersistenceName() {
return "Footprint"; }
762 FootprintFactory registration(getFootprintPersistenceName());
766 std::string Footprint::getPersistenceName()
const {
return getFootprintPersistenceName(); }
768 std::string Footprint::getPythonModule()
const {
return "lsst.afw.detection"; }
770 void Footprint::write(OutputArchiveHandle & handle)
const {
771 FootprintPersistenceHelper
const & keys = FootprintPersistenceHelper::get();
773 spanCat.reserve(_spans.size());
774 for (SpanList::const_iterator i = _spans.begin(); i != _spans.end(); ++i) {
775 PTR(afw::table::BaseRecord) record = spanCat.addNew();
776 record->set(keys.spanY, (**i).getY());
777 record->set(keys.spanX0, (**i).getX0());
778 record->set(keys.spanX1, (**i).getX1());
780 handle.saveCatalog(spanCat);
781 afw::table::
BaseCatalog peakCat = handle.makeCatalog(_peaks.getSchema());
782 peakCat.insert(peakCat.end(), _peaks.begin(), _peaks.end(), true);
783 handle.saveCatalog(peakCat);
787 FootprintPersistenceHelper
const & keys = FootprintPersistenceHelper::get();
789 addSpan(i->get(keys.spanY), i->get(keys.spanX0), i->get(keys.spanX1));
794 if (!peakCat.getSchema().contains(PeakTable::makeMinimalSchema())) {
796 afw::table::SchemaMapper mapper(peakCat.getSchema());
797 mapper.addMinimalSchema(PeakTable::makeMinimalSchema());
798 afw::table::Key<float> oldX = peakCat.getSchema()[
"x"];
799 afw::table::Key<float> oldY = peakCat.getSchema()[
"y"];
800 afw::table::Key<float> oldPeakValue = peakCat.getSchema()[
"value"];
801 mapper.addMapping(oldX,
"f.x");
802 mapper.addMapping(oldY,
"f.y");
803 mapper.addMapping(oldPeakValue,
"peakValue");
805 _peaks.
reserve(peakCat.size());
807 PTR(PeakRecord) newPeak = _peaks.addNew();
808 newPeak->assign(*i, mapper);
809 newPeak->setIx(
int(newPeak->getFx()));
810 newPeak->setIy(
int(newPeak->getFy()));
815 _peaks.reserve(peakCat.size());
816 for (afw::table::
BaseCatalog::const_iterator i = peakCat.begin(); i != peakCat.end(); ++i) {
817 _peaks.addNew()->assign(*i);
825 _region = other._region;
829 _spans.reserve(other._spans.size());
830 for(SpanList::const_iterator i(other._spans.begin());
831 i != other._spans.end(); ++i
836 _normalized = other._normalized;
840 _peaks =
PeakCatalog(other.getPeaks().getTable(), other.getPeaks().begin(), other.getPeaks().end(),
true);
844 template<
typename MaskT>
845 void Footprint::intersectMask(
855 SpanList::iterator s(_spans.begin());
856 while((*s)->getY() < maskBBox.
getMinY() && s != _spans.end()){
862 SpanList maskedSpans;
864 for( ; s != _spans.end(); ++s) {
889 for(
int x = x0;
x <= x1; ++
x, ++mIter) {
890 if((*mIter & bitmask) != 0) {
896 PTR(Span) maskedSpan(new Span(y, x0,
x- 1));
897 maskedSpans.push_back(maskedSpan);
898 maskedArea += maskedSpan->getWidth();
907 PTR(Span) maskedSpan(new Span(y, x0, x1));
908 maskedSpans.push_back(maskedSpan);
909 maskedArea += maskedSpan->getWidth();
913 _spans = maskedSpans;
914 _bbox.clip(maskBBox);
921 geom::Box2I const& region,
939 for (
int y = tBoxI.getBeginY(); y < tBoxI.getEndY(); ++y) {
943 for (
int x = tBoxI.getBeginX(); x < tBoxI.getEndX(); ++
x) {
945 int const xSource =
std::floor(0.5 + p.getX());
946 int const ySource =
std::floor(0.5 + p.getY());
955 fpNew->addSpan(y, start, x - 1);
959 fpNew->addSpan(y, start, tBoxI.getMaxX());
965 PeakCatalog::const_iterator
iter = this->getPeaks().begin();
966 iter != this->getPeaks().end();
970 fpNew->addPeak(tp.getX(), tp.getY(),
iter->getPeakValue());
974 fpNew->clipTo(region);
982 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
"Footprint isn't normalized");
984 int const width = getBBox().getWidth(), height = getBBox().getHeight();
985 if (height <= 2 || _spans.size() <= 2) {
987 return boost::make_shared<Footprint>(*this);
993 int const xStart = getBBox().getMinX(), yStart = getBBox().getMinY();
994 std::vector<
bool> rowBefore(width, false);
995 std::vector<
bool> rowNow(width, false);
996 std::vector<
bool> rowAfter(width, false);
999 int const yEnd = _spans.back()->getY();
1002 SpanList::const_iterator readAhead = _spans.begin();
1003 for (; readAhead != _spans.end() && (*readAhead)->getY() == yStart; ++readAhead) {
1004 std::fill(rowNow.begin() + (*readAhead)->getX0() - xStart,
1005 rowNow.begin() + (*readAhead)->getX1() + 1 - xStart,
1008 for (; readAhead != _spans.end() && (*readAhead)->getY() == yStart + 1; ++readAhead) {
1009 std::fill(rowAfter.begin() + (*readAhead)->getX0() - xStart,
1010 rowAfter.begin() + (*readAhead)->getX1() + 1 - xStart,
1014 for (SpanList::const_iterator ss = _spans.begin(); ss != _spans.end(); ++ss) {
1015 int const y = (*ss)->getY();
1016 if (y == yStart || y == yEnd) {
1018 edges->addSpanInSeries(y, (*ss)->getX0(), (*ss)->getX1());
1023 rowBefore.assign(rowNow.begin(), rowNow.end());
1024 rowNow.assign(rowAfter.begin(), rowAfter.end());
1026 std::fill(rowAfter.begin(), rowAfter.end(),
false);
1027 for (; readAhead != _spans.end() && (*readAhead)->getY() <=
y; ++readAhead) {}
1028 for (; readAhead != _spans.end() && (*readAhead)->getY() == y + 1; ++readAhead) {
1029 std::fill(rowAfter.begin() + (*readAhead)->getX0() - xStart,
1030 rowAfter.begin() + (*readAhead)->getX1() + 1 - xStart,
1037 int x0 = (*ss)->getX0();
1039 for (
int x = x0 + 1, i = x0 + 1 - xStart; x < (*ss)->getX1(); ++
x, ++i) {
1041 if (rowBefore[i] && rowAfter[i]) {
1044 edges->addSpanInSeries(y, x0, x - 1);
1046 }
else if (!rowBefore[i] || !rowAfter[i]) {
1053 int const x1 = (*ss)->getX1();
1055 edges->addSpanInSeries(y, x0, x1);
1057 edges->addSpanInSeries(y, x1, x1);
1071 bool _checkNormalized(
Footprint const& foot) {
1074 if (
copy.getArea() != foot.getArea()) {
1077 if (
copy.getSpans().size() != foot.getSpans().size()) {
1080 Footprint::SpanList
const& spansa = foot.getSpans();
1081 Footprint::SpanList
const& spansb =
copy.getSpans();
1082 Footprint::SpanList::const_iterator spa = spansa.begin();
1083 Footprint::SpanList::const_iterator spb = spansb.begin();
1084 for (; spa != spansa.end(); ++spa, ++spb) {
1085 if ((*spa)->getY() != (*spb)->getY()) {
1088 if ((*spa)->getX0() != (*spb)->getX0()) {
1091 if ((*spa)->getX1() != (*spb)->getX1()) {
1100 template<
typename MaskT>
1103 typename lsst::afw::
image::Mask<MaskT>::Ptr const& mask,
1112 template<typename MaskT>
1114 image::Mask<MaskT> *mask,
1119 int const width =
static_cast<int>(mask->getWidth());
1120 int const height =
static_cast<int>(mask->getHeight());
1122 for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
1123 siter != foot.getSpans().end(); ++siter) {
1125 int const y = span->getY() - mask->getY0();
1126 if (y < 0 || y >= height) {
1130 int x0 = span->getX0() - mask->getX0();
1131 int x1 = span->getX1() - mask->getX0();
1132 x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 :
x0);
1133 x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1);
1136 end = mask->x_at(x1 + 1, y); ptr != end; ++ptr) {
1146 template<
typename MaskT>
1152 int const width =
static_cast<int>(mask->
getWidth());
1153 int const height =
static_cast<int>(mask->
getHeight());
1155 for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
1156 siter != foot.getSpans().end(); ++siter) {
1158 int const y = span->getY() - mask->getY0();
1159 if (y < 0 || y >= height) {
1163 int x0 = span->getX0() - mask->
getX0();
1164 int x1 = span->getX1() - mask->
getX0();
1165 x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 :
x0);
1166 x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1);
1169 end = mask->
x_at(x1 + 1, y); ptr != end; ++ptr) {
1179 template<
typename MaskT>
1185 for (std::vector<
PTR(
Footprint)>::const_iterator fiter = footprints.begin();
1186 fiter != footprints.end(); ++fiter) {
1195 template<
typename MaskT>
1206 template<
typename ImageT>
1207 class SetFootprint :
public FootprintFunctor<ImageT> {
1209 SetFootprint(ImageT
const&
image,
1210 typename ImageT::Pixel value) :
1211 FootprintFunctor<ImageT>(image),
_value(value) {}
1214 void operator()(
typename ImageT::xy_locator loc,
int,
int) {
1218 typename ImageT::Pixel
_value;
1222 template<
typename ImageT>
1226 typename ImageT::Pixel
const value
1228 SetFootprint<ImageT> setit(*image, value);
1234 template<
typename ImageT>
1238 typename ImageT::Pixel
const value
1243 template<
typename ImageT>
1247 typename ImageT::Pixel
const value
1249 SetFootprint<ImageT> setit(*image, value);
1250 for (std::vector<
PTR(
Footprint)>::const_iterator fiter = footprints.begin(),
1251 end = footprints.end(); fiter != end; ++fiter) {
1252 setit.apply(**fiter);
1262 template <
typename IDPixelT>
1263 static void set_footprint_id(
1269 for (Footprint::SpanList::const_iterator i = foot.getSpans().begin();
1270 i != foot.getSpans().end(); ++i) {
1272 for (typename image::Image<IDPixelT>::x_iterator ptr =
1273 idImage->x_at(span->getX0() + dx, span->getY() + dy),
1274 end = ptr + span->getWidth(); ptr != end; ++ptr) {
1280 template <
typename IDPixelT>
1282 set_footprint_array_ids(
1285 bool const relativeIDs
1289 for (std::vector<
PTR(
Footprint)>::const_iterator fiter = footprints.begin();
1290 fiter != footprints.end(); ++fiter) {
1299 set_footprint_id<IDPixelT>(idImage, *foot,
id);
1303 template void set_footprint_array_ids<int>(
1305 std::vector<PTR(Footprint)>
const& footprints,
1306 bool const relativeIDs);
1315 template <
typename IDImageT>
1316 typename boost::shared_ptr<image::Image<IDImageT> > setFootprintArrayIDs(
1318 bool const relativeIDs
1320 std::vector<PTR(Footprint)>::const_iterator fiter = footprints.begin();
1321 if (fiter == footprints.end()) {
1323 lsst::pex::exceptions::InvalidParameterError,
1324 "You didn't provide any footprints"
1329 typename image::Image<IDImageT>::Ptr idImage(
1330 new image::Image<IDImageT>(foot->getRegion())
1336 set_footprint_array_ids<IDImageT>(idImage, footprints, relativeIDs);
1341 template image::Image<
int>::Ptr setFootprintArrayIDs(
1343 bool const relativeIDs);
1347 template <typename IDImageT>
1348 typename boost::shared_ptr<image::Image<IDImageT> > setFootprintID(
1357 set_footprint_id<IDImageT>(idImage, *foot,
id);
1371 class StructuringElement
1374 enum class Shape { CIRCLE, DIAMOND };
1375 typedef std::vector<Span>::const_iterator const_iterator;
1376 StructuringElement(
Shape shape,
int radius);
1377 StructuringElement(
int left,
int right,
int up,
int down);
1378 const_iterator begin()
const {
return _widths.begin(); }
1379 const_iterator end()
const {
return _widths.end(); }
1380 int getYRange()
const {
return _yRange; }
1383 std::vector<Span> _widths;
1392 StructuringElement::StructuringElement(
Shape shape,
int radius) {
1393 _yRange = 2*radius + 1;
1394 _widths.reserve(_yRange);
1397 for (
auto dy = -radius; dy <= radius; dy++) {
1398 int dx =
static_cast<int>(sqrt(radius*radius - dy*dy));
1399 _widths.push_back(Span(dy, -dx, dx));
1402 case Shape::DIAMOND:
1403 for (
auto dy = -radius; dy <= radius; dy++) {
1404 int dx = radius - abs(dy);
1405 _widths.push_back(Span(dy, -dx, dx));
1415 StructuringElement::StructuringElement(
int left,
int right,
int up,
int down) {
1416 _yRange = up + down + 1;
1417 _widths.reserve(_yRange);
1418 for (
auto dy = 1; dy <= up; dy++) {
1419 _widths.push_back(Span(dy, 0, 0));
1421 for (
auto dy = -1; dy >= -down; dy--) {
1422 _widths.push_back(Span(dy, 0, 0));
1424 _widths.push_back(Span(0, -left, right));
1433 StructuringElement const& element
1441 std::map<
int, std::set<std::pair<
int,
int>>> spans;
1445 for (auto spanIter = foot.getSpans().cbegin(); spanIter != foot.getSpans().cend(); ++spanIter) {
1446 for (
auto elementIter = element.begin(); elementIter != element.end(); ++elementIter) {
1447 int const xmin = (*spanIter)->getX0() + elementIter->getX0();
1448 int const xmax = (*spanIter)->getX1() + elementIter->getX1();
1449 int const yval = (*spanIter)->getY() + elementIter->getY();
1450 spans[yval].insert(std::make_pair(xmin, xmax));
1454 std::set<std::pair<int, int>> newSpans;
1455 for (
auto span = spans[yval].cbegin(); span != spans[yval].cend(); ++span) {
1456 int const start = span->first;
1457 int end = span->second;
1461 while (span != spans[yval].cend() && span->first <= (end+1)) {
1462 end = std::max(end, span++->second);
1464 newSpans.insert(std::make_pair(start, end));
1473 for (
auto y = spans.cbegin(); y != spans.cend(); ++
y) {
1474 for (
auto x = y->second.cbegin(); x != y->second.cend(); ++
x) {
1475 grown->addSpanInSeries(y->first, x->first, x->second);
1480 grown->getPeaks() =
PeakCatalog(foot.getPeaks().getTable(), foot.getPeaks().begin(),
1481 foot.getPeaks().end(),
true);
1496 int m,
y, xmin, xmax;
1503 bool comparePrimaryRun(PrimaryRun
const& first, PrimaryRun
const& second) {
1504 if (first.y != second.y) {
1505 return first.y < second.y;
1506 }
else if (first.m != second.m) {
1507 return first.m < second.m;
1509 return first.xmin < second.xmin;
1513 class ComparePrimaryRunY{
1515 bool operator()(PrimaryRun
const& pr,
int yval) {
1518 bool operator()(
int yval, PrimaryRun
const& pr) {
1523 class ComparePrimaryRunM{
1525 bool operator()(PrimaryRun
const& pr,
int mval) {
1528 bool operator()(
int mval, PrimaryRun
const& pr) {
1537 PTR(Footprint) shrinkFootprintImpl(
1538 Footprint const& foot,
1539 StructuringElement const& element
1542 PTR(Footprint) shrunk(new Footprint(0, foot.getRegion()));
1545 std::vector<PrimaryRun> primaryRuns;
1546 for (auto spanIter = foot.getSpans().begin(); spanIter != foot.getSpans().end(); ++spanIter) {
1548 for (
auto it = element.begin(); it != element.end(); ++it, ++
m) {
1549 if ((it->getX1() - it->getX0()) <= ((*spanIter)->getX1() - (*spanIter)->getX0())) {
1550 int xmin = (*spanIter)->getX0() - it->getX0();
1551 int xmax = (*spanIter)->getX1() - it->getX1();
1552 int y = (*spanIter)->getY() - it->getY();
1553 primaryRuns.push_back(PrimaryRun({
m,
y, xmin, xmax}));
1560 std::sort(primaryRuns.begin(), primaryRuns.end(), comparePrimaryRun);
1562 for (
int y = primaryRuns.front().y; y <= primaryRuns.back().y; ++
y) {
1563 auto yRange = std::equal_range(primaryRuns.begin(), primaryRuns.end(),
y, ComparePrimaryRunY());
1568 if (std::distance(yRange.first, yRange.second) < element.getYRange()) {
1577 std::list<PrimaryRun> goodRuns;
1579 for (
int m = 0; m < element.getYRange(); ++
m) {
1580 auto mRange = std::equal_range(yRange.first, yRange.second, m, ComparePrimaryRunM());
1581 if (mRange.first == mRange.second) {
1588 std::list<PrimaryRun> candidateRuns;
1589 int start_x = mRange.first->xmin;
1590 int end_x = mRange.first->xmax;
1591 for (
auto run = mRange.first+1;
run != mRange.second; ++
run) {
1592 if (
run->xmin > end_x) {
1594 candidateRuns.push_back(PrimaryRun{
m,
y, start_x, end_x});
1595 start_x =
run->xmin;
1602 candidateRuns.push_back(PrimaryRun{
m,
y, start_x, end_x});
1611 std::list<PrimaryRun> newlist;
1612 for (
auto good = goodRuns.begin(); good != goodRuns.end(); ++good) {
1613 for (
auto cand = candidateRuns.begin(); cand != candidateRuns.end(); ++cand) {
1614 int start = std::max(good->xmin, cand->xmin);
1615 int end = std::min(good->xmax, cand->xmax);
1617 newlist.push_back(PrimaryRun({
m,
y, start, end}));
1625 for (
auto run = goodRuns.begin();
run != goodRuns.end(); ++
run) {
1626 shrunk->addSpan(
run->y,
run->xmin,
run->xmax);
1630 shrunk->normalize();
1635 for (
auto peakIter = foot.getPeaks().begin(); peakIter != foot.getPeaks().end(); peakIter++) {
1636 if (shrunk->contains(peakIter->getI())) {
1637 shrunk->getPeaks().addNew()->assign(*peakIter);
1647 PTR(Footprint) _mergeFootprints(Footprint const& aFoot, Footprint const& bFoot) {
1648 PTR(Footprint) foot(new Footprint());
1653 if (aPeak.empty()) {
1654 if (!bPeak.empty()) {
1655 peaks =
PeakCatalog(bPeak.getTable(), bPeak.begin(), bPeak.end(),
true);
1658 if (bPeak.empty()) {
1659 peaks =
PeakCatalog(aPeak.getTable(), aPeak.begin(), aPeak.end(),
true);
1661 if (aPeak.getSchema() == bPeak.getSchema()) {
1664 peaks.
reserve(aPeak.size() + bPeak.size());
1665 peaks.insert(peaks.end(), aPeak.begin(), aPeak.end(),
true);
1666 peaks.insert(peaks.end(), bPeak.begin(), bPeak.end(),
true);
1669 pex::exceptions::InvalidParameterError,
1670 "Cannot merge Footprints when Peaks have different Schemas"
1676 Footprint::SpanList
const& aSpans = aFoot.getSpans();
1677 Footprint::SpanList
const& bSpans = bFoot.getSpans();
1678 Footprint::SpanList::const_iterator aSpan = aSpans.begin();
1679 Footprint::SpanList::const_iterator bSpan = bSpans.begin();
1680 Footprint::SpanList::const_iterator aEnd = aSpans.end();
1681 Footprint::SpanList::const_iterator bEnd = bSpans.end();
1683 foot->getSpans().reserve(std::max(aSpans.size(), bSpans.size()));
1685 while ((aSpan != aEnd) && (bSpan != bEnd)) {
1686 int y = (*aSpan)->getY();
1687 int x0 = (*aSpan)->getX0();
1688 int x1 = (*aSpan)->getX1();
1689 int yb = (*bSpan)->getY();
1690 int xb0 = (*bSpan)->getX0();
1691 int xb1 = (*bSpan)->getX1();
1693 if ((y < yb) || (y == yb && (x1 < (xb0-1)))) {
1695 foot->addSpanInSeries(y, x0, x1);
1699 if ((yb < y) || (y == yb && (xb1 < (x0-1)))) {
1701 foot->addSpanInSeries(yb, xb0, xb1);
1708 x0 = std::min(x0, xb0);
1709 x1 = std::max(x1, xb1);
1714 if ((aSpan != aEnd) &&
1715 ((*aSpan)->getY() ==
y) &&
1716 ((*aSpan)->getX0() <= (x1+1))) {
1718 x1 = std::max(x1, (*aSpan)->getX1());
1722 if ((bSpan != bEnd) &&
1723 ((*bSpan)->getY() ==
y) &&
1724 ((*bSpan)->getX0() <= (x1+1))) {
1726 x1 = std::max(x1, (*bSpan)->getX1());
1732 foot->addSpanInSeries(y, x0, x1);
1737 for (; aSpan != aEnd; ++aSpan) {
1738 foot->addSpanInSeries((*aSpan)->getY(), (*aSpan)->getX0(), (*aSpan)->getX1());
1741 for (; bSpan != bEnd; ++bSpan) {
1742 foot->addSpanInSeries((*bSpan)->getY(), (*bSpan)->getX0(), (*bSpan)->getX1());
1751 return _mergeFootprints(foot1, foot2);
1755 if (!foot1.isNormalized() || !foot2.isNormalized()) {
1757 lsst::pex::exceptions::InvalidParameterError,
1758 "mergeFootprints(const Footprints) requires normalize()d Footprints.");
1760 return _mergeFootprints(foot1, foot2);
1773 typedef boost::uint16_t dtype;
1774 typedef boost::uint16_t itype;
1776 const itype nil = 0xffff;
1782 int const x0 = bbox.
getMinX();
1783 int const y0 = bbox.
getMinY();
1785 for (
size_t i=0; i<foots.size(); ++i) {
1787 set_footprint_id<itype>(argmin, *foots[i], i, -
x0, -
y0);
1788 set_footprint_id<dtype>(dist, *foots[i], 1, -
x0, -
y0);
1792 int const width = dist->
getWidth();
1795 for (
int y = 0; y !=
height; ++
y) {
1798 for (
int x = 0; x !=
width; ++
x, ++dim.x(), ++aim.x()) {
1799 if (dim(0, 0) == 1) {
1806 dim(0, 0) = width +
height;
1810 dtype ndist = dim(0,-1) + 1;
1811 if (ndist < dim(0,0)) {
1813 aim(0,0) = aim(0,-1);
1818 dtype ndist = dim(-1,0) + 1;
1819 if (ndist < dim(0,0)) {
1821 aim(0,0) = aim(-1,0);
1828 for (
int y = height - 1; y >= 0; --
y) {
1831 for (
int x = width - 1; x >= 0; --
x, --dim.x(), --aim.x()) {
1834 if (y + 1 < height) {
1835 dtype ndist = dim(0,1) + 1;
1836 if (ndist < dim(0,0)) {
1838 aim(0,0) = aim(0,1);
1842 if (x + 1 < width) {
1843 dtype ndist = dim(1,0) + 1;
1844 if (ndist < dim(0,0)) {
1846 aim(0,0) = aim(1,0);
1854 Footprint const& foot,
1858 if (nGrow <= 0 || foot.getNpix() == 0 ) {
1867 Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
1868 return growFootprintImpl(foot, StructuringElement(shape, nGrow));
1883 if (nGrow <= 0 || foot.getNpix() == 0 ) {
1887 return growFootprintImpl(foot, StructuringElement(left ? nGrow: 0, right ? nGrow : 0,
1888 up ? nGrow : 0, down ? nGrow : 0));
1893 Footprint const& foot,
1898 Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
1899 return shrinkFootprintImpl(foot, StructuringElement(shape, nShrink));
1905 typedef boost::uint16_t ImageT;
1913 foot.insertIntoImage(*idImage, 1, fpBBox);
1915 std::vector<geom::Box2I> bboxes;
1930 while (y0 < height) {
1932 for (
int y = y0; y !=
height; ++
y) {
1939 int const x0 = first - begin;
1940 int const x1 = last - begin;
1942 std::fill(first, last + 1, 0);
1949 if (std::find(idImage->at(x0, y), idImage->at(x1 + 1, y), 0) != idImage->at(x1 + 1, y)) {
1952 std::fill(idImage->at(x0, y), idImage->at(x1 + 1, y), 0);
1958 bboxes.push_back(bbox);
1970 template<
typename ImageOrMaskedImageT>
1973 PTR(ImageOrMaskedImageT)
const input,
1974 PTR(ImageOrMaskedImageT) output) {
1975 Footprint::SpanList spans = foot.getSpans();
1977 int const inX0 = input->getX0(), inY0 = input->getY0();
1978 int const outX0 = output->getX0(), outY0 = output->getY0();
1980 int const xMin = std::max(inX0, outX0);
1981 int const xMax = std::min(input->getWidth() + inX0, output->getWidth() + outX0) - 1;
1982 for (Footprint::SpanList::iterator sp = spans.begin();
1983 sp != spans.end(); ++sp) {
1984 int const y = (*sp)->getY();
1985 int const x0 = (*sp)->getX0();
1986 int const x1 = (*sp)->getX1();
1988 int const yInput = y - inY0, yOutput = y - outY0;
1989 if (yInput < 0 || yInput >= input->getHeight() || yOutput < 0 || yOutput >= output->getHeight()) {
1993 int const xStart = std::max(x0, xMin);
1994 int const xStop = std::min(x1, xMax);
1996 typename ImageOrMaskedImageT::const_x_iterator initer = input->x_at(xStart - inX0, yInput);
1997 typename ImageOrMaskedImageT::x_iterator outiter = output->x_at(xStart - outX0, yOutput);
1998 for (
int x = xStart; x <= xStop; ++
x, ++initer, ++outiter) {
2013 psArray *pmGrowFootprintArray(psArray
const *footprints,
2015 assert (footprints->n == 0 || pmIsFootprint(footprints->data[0]));
2017 if (footprints->n == 0) {
2018 return psArrayAlloc(0);
2024 psImage *idImage = pmSetFootprintArrayIDs(footprints,
true);
2028 psKernel *circle = psKernelAlloc(-r, r, -r, r);
2029 assert (circle->image->numRows == 2*r + 1 && circle->image->numCols == circle->image->numRows);
2030 for (
int i = 0; i <= r; ++i) {
2031 for (
int j = 0; j <= r; ++j) {
2032 if (i*i + j*j <= r*r) {
2033 circle->kernel[i][j] =
2034 circle->kernel[i][-j] =
2035 circle->kernel[-i][j] =
2036 circle->kernel[-i][-j] = 1;
2041 psImage *grownIdImage = psImageConvolveDirect(idImage, circle);
2044 psArray *grown = pmFindFootprints(grownIdImage, 0.5, 1);
2045 assert (grown != NULL);
2047 psFree(grownIdImage);
2052 psArray
const *peaks = pmFootprintArrayToPeaks(footprints);
2053 pmPeaksAssignToFootprints(grown, peaks);
2054 psFree((psArray *)peaks);
2066 psArray *pmMergeFootprintArrays(psArray
const *footprints1,
2067 psArray
const *footprints2,
2068 int const includePeaks) {
2069 assert (footprints1->n == 0 || pmIsFootprint(footprints1->data[0]));
2070 assert (footprints2->n == 0 || pmIsFootprint(footprints2->data[0]));
2072 if (footprints1->n == 0 || footprints2->n == 0) {
2073 psArray
const *old = (footprints1->n == 0) ? footprints2 : footprints1;
2075 psArray *merged = psArrayAllocEmpty(old->n);
2076 for (
int i = 0; i < old->n; ++i) {
2077 psArrayAdd(merged, 1, old->data[i]);
2087 pmFootprint *fp1 = footprints1->data[0];
2088 pmFootprint *fp2 = footprints2->data[0];
2089 if (fp1->region.x0 != fp2->region.x0 ||
2090 fp1->region.x1 != fp2->region.x1 ||
2091 fp1->region.y0 != fp2->region.y0 ||
2092 fp1->region.y1 != fp2->region.y1) {
2093 psError(PS_ERR_BAD_PARAMETER_SIZE,
true,
2094 "The two pmFootprint arrays correspnond to different-sized regions");
2102 psImage *idImage = pmSetFootprintArrayIDs(footprints1,
true);
2103 set_footprint_array_ids(idImage, footprints2,
true);
2105 psArray *merged = pmFindFootprints(idImage, 0.5, 1);
2106 assert (merged != NULL);
2112 if (includePeaks & 0x1) {
2113 psArray
const *peaks = pmFootprintArrayToPeaks(footprints1);
2114 pmPeaksAssignToFootprints(merged, peaks);
2115 psFree((psArray *)peaks);
2118 if (includePeaks & 0x2) {
2119 psArray
const *peaks = pmFootprintArrayToPeaks(footprints2);
2120 pmPeaksAssignToFootprints(merged, peaks);
2121 psFree((psArray *)peaks);
2134 pmPeaksAssignToFootprints(psArray *footprints,
2135 psArray
const *peaks) {
2136 assert (footprints != NULL);
2137 assert (footprints->n == 0 || pmIsFootprint(footprints->data[0]));
2138 assert (peaks != NULL);
2139 assert (peaks->n == 0 || pmIsPeak(peaks->data[0]));
2141 if (footprints->n == 0) {
2143 return psError(PS_ERR_BAD_PARAMETER_SIZE,
true,
"Your list of footprints is empty");
2151 psImage *ids = pmSetFootprintArrayIDs(footprints,
true);
2152 assert (ids != NULL);
2153 assert (ids->type.type == PS_TYPE_S32);
2154 int const y0 = ids->y0;
2155 int const x0 = ids->x0;
2156 int const numRows = ids->numRows;
2157 int const numCols = ids->numCols;
2159 for (
int i = 0; i < peaks->n; ++i) {
2160 pmPeak *peak = peaks->data[i];
2161 int const x = peak->x -
x0;
2162 int const y = peak->y -
y0;
2164 assert (x >= 0 && x < numCols && y >= 0 && y < numRows);
2165 int id = ids->data.S32[
y][x -
x0];
2168 pmFootprint *nfp = pmFootprintAlloc(1, ids);
2169 pmFootprintAddSpan(nfp, y, x, x);
2170 psArrayAdd(footprints, 1, nfp);
2175 assert (
id >= 1 && id <= footprints->n);
2176 pmFootprint *fp = footprints->data[
id - 1];
2177 psArrayAdd(fp->peaks, 5, peak);
2184 for (
int i = 0; i < footprints->n; ++i) {
2185 pmFootprint *fp = footprints->data[i];
2186 fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
2188 for (
int j = 1; j < fp->peaks->n; ++j) {
2189 if (fp->peaks->data[j] == fp->peaks->data[j-1]) {
2190 (void)psArrayRemoveIndex(fp->peaks, j);
2206 psErrorCode pmFootprintCullPeaks(psImage
const *img,
2209 float const nsigma_delta,
2211 float const min_threshold) {
2212 assert (img != NULL);
2213 assert (img->type.type == PS_TYPE_F32);
2214 assert (weight != NULL);
2215 assert (weight->type.type == PS_TYPE_F32);
2216 assert (img->y0 == weight->y0 && img->x0 == weight->x0);
2217 assert (fp != NULL);
2219 if (fp->peaks == NULL || fp->peaks->n == 0) {
2224 subRegion.x0 = fp->bbox.x0;
2225 subRegion.x1 = fp->bbox.x1 + 1;
2226 subRegion.y0 = fp->bbox.y0;
2227 subRegion.y1 = fp->bbox.y1 + 1;
2228 psImage
const *subImg = psImageSubset((psImage *)img, subRegion);
2229 psImage
const *subWt = psImageSubset((psImage *)weight, subRegion);
2230 assert (subImg != NULL && subWt != NULL);
2238 psArray *brightPeaks = psArrayAlloc(0);
2239 psFree(brightPeaks->data);
2240 brightPeaks->data = psMemIncrRefCounter(fp->peaks->data);
2244 for (
int i = 1; i < fp->peaks->n; ++i) {
2245 pmPeak
const *peak = fp->peaks->data[i];
2246 int x = peak->x - subImg->x0;
2247 int y = peak->y - subImg->y0;
2252 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
2253 float const stdev = std::sqrt(subWt->data.F32[y][x]);
2254 float threshold = subImg->data.F32[
y][
x] - nsigma_delta*
stdev;
2256 #if 1 // min_threshold is assumed to be below the detection threshold,
2258 (void)psArrayRemoveIndex(fp->peaks, i);
2262 #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once
2263 threshold = min_threshold;
2266 if (threshold > subImg->data.F32[y][x]) {
2267 threshold = subImg->data.F32[
y][
x] - 10*FLT_EPSILON;
2270 int const peak_id = 1;
2272 pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
2274 psImage *idImg = pmSetFootprintID(peakFootprint, peak_id);
2275 psFree(peakFootprint);
2278 for (j = 0; j < i; ++j) {
2279 pmPeak
const *peak2 = fp->peaks->data[j];
2280 int x2 = peak2->x - subImg->x0;
2281 int y2 = peak2->y - subImg->y0;
2282 int const peak2_id = idImg->data.S32[y2][x2];
2284 if (peak2_id == peak_id) {
2286 (void)psArrayRemoveIndex(fp->peaks, i);
2299 psFree(brightPeaks);
2300 psFree((psImage *)subImg);
2301 psFree((psImage *)subWt);
2310 pmFootprintArrayCullPeaks(psImage
const *img,
2311 psImage
const *weight,
2312 psArray *footprints,
2313 float const nsigma_delta,
2315 float const min_threshold) {
2316 for (
int i = 0; i < footprints->n; ++i) {
2317 pmFootprint *fp = footprints->data[i];
2318 if (pmFootprintCullPeaks(img, weight, fp, nsigma_delta, min_threshold) != PS_ERR_NONE) {
2319 return psError(PS_ERR_UNKNOWN,
false,
"Culling pmFootprint %d", fp->id);
2330 psArray *pmFootprintArrayToPeaks(psArray
const *footprints) {
2331 assert(footprints != NULL);
2332 assert(footprints->n == 0 || pmIsFootprint(footprints->data[0]));
2335 for (
int i = 0; i < footprints->n; ++i) {
2336 pmFootprint
const *fp = footprints->data[i];
2337 npeak += fp->peaks->n;
2340 psArray *peaks = psArrayAllocEmpty(npeak);
2342 for (
int i = 0; i < footprints->n; ++i) {
2343 pmFootprint
const *fp = footprints->data[i];
2344 for (
int j = 0; j < fp->peaks->n; ++j) {
2345 psArrayAdd(peaks, 1, fp->peaks->data[j]);
2360 void Footprint::intersectMask(
2366 PTR(Footprint) const& foot,
2367 image::Mask<image::
MaskPixel>::Ptr const& mask,
2373 CONST_PTR(std::vector<
PTR(Footprint)>) const& footprints,
2378 std::vector<
PTR(Footprint)> const& footprints,
2382 Footprint const& foot, image::
MaskPixel const bitmask);
2385 Footprint const& foot, image::
MaskPixel const bitmask);
2387 #define INSTANTIATE_NUMERIC(TYPE) \
2389 TYPE setImageFromFootprint(image::Image<TYPE> *image, \
2390 Footprint const& footprint, \
2391 TYPE const value); \
2393 TYPE setImageFromFootprintList(image::Image<TYPE> *image, \
2394 std::vector<PTR(Footprint)> const& footprints, \
2395 TYPE const value); \
2397 TYPE setImageFromFootprintList(image::Image<TYPE> *image, \
2398 CONST_PTR(std::vector<PTR(Footprint)>) footprints, \
2399 TYPE const value); \
2401 void copyWithinFootprint(Footprint const&, \
2402 PTR(lsst::afw::image::Image<TYPE>) const, \
2403 PTR(lsst::afw::image::Image<TYPE>)); \
2405 void copyWithinFootprint(Footprint const&, \
2406 PTR(lsst::afw::image::MaskedImage<TYPE>) const, \
2407 PTR(lsst::afw::image::MaskedImage<TYPE>)); \
2409 void Footprint::clipToNonzero(lsst::afw::image::Image<TYPE> const&); \
2412 INSTANTIATE_NUMERIC(
float);
2413 INSTANTIATE_NUMERIC(
double);
2415 INSTANTIATE_NUMERIC(boost::uint16_t);
2416 INSTANTIATE_NUMERIC(
int);
2417 INSTANTIATE_NUMERIC(boost::uint64_t);
2420 #define INSTANTIATE_MASK(PIXEL) \
2422 void Footprint::insertIntoImage( \
2423 lsst::afw::image::Image<PIXEL>& idImage, \
2424 boost::uint64_t const id, \
2425 geom::Box2I const& region=geom::Box2I() \
2428 void Footprint::insertIntoImage( \
2429 lsst::afw::image::Image<PIXEL>& idImage, \
2430 boost::uint64_t const id, \
2431 bool const overwriteId, long const idMask, \
2432 std::set<boost::uint64_t> *oldIds, \
2433 geom::Box2I const& region=geom::Box2I() \
2436 INSTANTIATE_MASK(boost::uint16_t);
2437 INSTANTIATE_MASK(
int);
2438 INSTANTIATE_MASK(boost::uint64_t);
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)
Declare the Kernel class and subclasses.
Extent2I const getDimensions() const
A coordinate class intended to represent absolute positions.
table::Key< std::string > name
void shift(Extent2I const &offset)
Shift the position of the box by the given offset.
for(FootprintList::const_iterator ptr=feet->begin(), end=feet->end();ptr!=end;++ptr)
tbl::Key< double > weight
x_iterator x_at(int x, int y) const
Return an x_iterator to the point (x, y) in the image.
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
bool contains(Point2I const &point) const
Return true if the box contains the point.
CatalogT< BaseRecord > BaseCatalog
Include files required for standard LSST Exception handling.
boost::uint16_t MaskPixel
void include(Point2I const &point)
Expand this to ensure that this->contains(point).
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.
definition of the Trace messaging facilities
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Point< double, 2 > Point2D
geom::Box2I getBBox(ImageOrigin origin=PARENT) const
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)
Extent< int, 2 > Extent2I
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
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
void ImageT ImageT int float saturatedPixelValue int const width
afw::table::CatalogT< PeakRecord > PeakCatalog
Represent a 2-dimensional array of bitmask pixels.
geom::Box2I const & _bbox
void include(Point2D const &point)
Expand this to ensure that this->contains(point).
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
int getHeight() const
Return the number of rows in the image.
bool isEmpty() const
Return true if the box contains no points.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
CatalogIterator< typename Internal::const_iterator > const_iterator
void ImageT ImageT int float saturatedPixelValue int const height
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.
void reserve(size_type n)
Increase the capacity of the catalog to the given size.
#define LSST_EXCEPT(type,...)
std::vector< lsst::afw::geom::Box2I > footprintToBBoxList(Footprint const &foot)
Extent< int, N > floor(Extent< double, N > const &input)
lsst::afw::detection::Footprint Footprint
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
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
xy_locator xy_at(int x, int y) const
x_iterator row_begin(int y) const
A floating-point coordinate rectangle geometry.
boost::shared_ptr< Footprint > mergeFootprints(Footprint const &foot1, Footprint const &foot2)
Record class that represents a peak in a Footprint.
int getWidth() const
Return the number of columns in the image.
A class to represent a 2-dimensional array of pixels.
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.