19template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
22template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
26template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
29template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
32template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
35template <
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
55 const itype nil = 0xffff;
63 foot->getSpans()->setImage(*argmin,
static_cast<itype
>(i));
64 foot->getSpans()->setImage(*dist,
static_cast<dtype>(1));
69 int const height = dist->getHeight();
70 int const width = dist->getWidth();
73 for (
int y = 0;
y != height; ++
y) {
76 for (
int x = 0;
x != width; ++
x, ++dim.x(), ++aim.x()) {
84 dim(0, 0) = width + height;
88 dtype ndist = dim(0,-1) + 1;
89 if (ndist < dim(0,0)) {
96 dtype ndist = dim(-1,0) + 1;
97 if (ndist < dim(0,0)) {
106 for (
int y = height - 1;
y >= 0; --
y) {
109 for (
int x = width - 1;
x >= 0; --
x, --dim.x(), --aim.x()) {
112 if (
y + 1 < height) {
113 dtype ndist = dim(0,1) + 1;
114 if (ndist < dim(0,0)) {
121 dtype ndist = dim(1,0) + 1;
122 if (ndist < dim(0,0)) {
145template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
151 int S = halfsize*2 + 1;
154 xy_loc pix = img.
xy_at(halfsize,halfsize);
156 for (
int i=0; i<S; ++i) {
157 for (
int j=0; j<S; ++j) {
158 locs.
push_back(pix.cache_location(j-halfsize, i-halfsize));
163 ImagePixelT vals[S*S];
164 for (
int y=halfsize;
y<H-halfsize; ++
y) {
167 inpix !=
end; ++inpix.x(), ++optr) {
168 for (
int i=0; i<SS; ++i)
169 vals[i] = inpix[locs[i]];
176 for (
int y=0;
y<2*halfsize; ++
y) {
179 iy = H - 1 - (
y-halfsize);
182 for (; iptr !=
end; ++iptr,++optr)
185 for (
int y=halfsize;
y<H-halfsize; ++
y) {
188 for (; iptr !=
end; ++iptr,++optr)
193 for (; iptr !=
end; ++iptr,++optr)
223template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
230 int cx = peak.getIx();
231 int cy = peak.getIy();
232 int ix0 = img.
getX0();
233 int iy0 = img.
getY0();
246 for (s = 0; s <
std::max(DW,DH); s += S) {
248 for (p=0; p<S; p++) {
288 for (
int i=0; i<(8*L); i++,
x += dx,
y += dy) {
292 if (i % (2*L) == 0) {
295 dx = ( leg % 2) * (-1 + 2*(leg/2));
297 dy = ((leg+1) % 2) * ( 1 - 2*(leg/2));
300 int px = cx +
x - ix0;
301 int py = cy +
y - iy0;
303 if (px < 0 || px >= iW || py < 0 || py >= iH)
306 ImagePixelT pix = (*shadowingImg)(px,
py);
313 const double A = 0.3;
319 ds0 = (double(
y) / double(
x)) - A;
322 for (shx=1; shx<=S; shx++) {
323 int xsign = (
x>0?1:-1);
325 psx = cx +
x + (xsign*shx) - ix0;
326 if (psx < 0 || psx >= iW)
329 for (shy = lround(shx * ds0);
330 shy <= lround(shx * ds1); shy++) {
331 psy = cy +
y + xsign*shy - iy0;
332 if (psy < 0 || psy >= iH)
334 img(psx, psy) =
std::min(img(psx, psy), pix);
340 ds0 = (double(
x) / double(
y)) - A;
343 for (shy=1; shy<=S; shy++) {
344 int ysign = (
y>0?1:-1);
345 psy = cy +
y + (ysign*shy) - iy0;
346 if (psy < 0 || psy >= iH)
349 for (shx = lround(shy * ds0);
350 shx <= lround(shy * ds1); shx++) {
351 psx = cx +
x + ysign*shx - ix0;
352 if (psx < 0 || psx >= iW)
354 img(psx, psy) =
std::min(img(psx, psy), pix);
360 shadowingImg->assign(img);
364static double _get_contrib_r_to_footprint(
int x,
int y,
370 int dx = sp.getX0() -
x;
383 int dy = sp.getY() -
y;
384 minr2 =
std::min(minr2, (
double)(mindx*mindx + dy*dy));
387 return 1. / (1. + minr2);
391template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
397 int strayFluxOptions,
402 double clipStrayFluxFraction,
417 int ix0 = img.
getX0();
418 int iy0 = img.
getY0();
423 for (
size_t i=0; i<tfoots.size(); ++i) {
430 bool always = (strayFluxOptions & STRAYFLUX_TO_POINT_SOURCES_ALWAYS);
435 if (strayFluxOptions & STRAYFLUX_NEAREST_FOOTPRINT) {
445 if (!always && ispsf.
size()) {
448 auto empty = std::make_shared<det::Footprint>();
450 for (
size_t i=0; i<tfoots.size(); ++i) {
452 templist.push_back(empty);
454 templist.push_back(tfoots[i]);
457 footlist = &templist;
459 nearestFootprint(*footlist, nearest, dist);
469 tsum->row_begin(
y - sumy0) + (x0 - sumx0);
472 double contrib[tfoots.size()];
474 for (
int x = x0;
x <= x1; ++
x, ++tsum_it, ++in_it) {
478 if ((*tsum_it > 0) || (*in_it).image() <= 0) {
482 if (strayFluxOptions & STRAYFLUX_R_TO_FOOTPRINT) {
484 for (
size_t i=0; i<tfoots.size(); ++i) {
487 }
else if (strayFluxOptions & STRAYFLUX_NEAREST_FOOTPRINT) {
488 for (
size_t i=0; i<tfoots.size(); ++i) {
495 for (
size_t i=0; i<tfoots.size(); ++i) {
500 contrib[i] = 1. / (1. + dx*dx + dy*dy);
506 bool ptsrcs = always;
508 for (
size_t i=0; i<tfoots.size(); ++i) {
510 if ((!ptsrcs) && ispsf.
size() && ispsf[i]) {
513 if (contrib[i] == -1.0) {
514 contrib[i] = _get_contrib_r_to_footprint(
x,
y, tfoots[i]);
520 STRAYFLUX_TO_POINT_SOURCES_WHEN_NECESSARY)) {
524 for (
size_t i=0; i<tfoots.size(); ++i) {
525 if (contrib[i] == -1.0) {
526 contrib[i] = _get_contrib_r_to_footprint(
x,
y, tfoots[i]);
533 double strayclip = (clipStrayFluxFraction * csum);
535 for (
size_t i=0; i<tfoots.size(); ++i) {
537 if ((!ptsrcs) && ispsf.
size() && ispsf[i]) {
542 if (contrib[i] < strayclip) {
549 for (
size_t i=0; i<tfoots.size(); ++i) {
550 if (contrib[i] == 0.) {
554 double p = (contrib[i] / csum) * (*in_it).image();
557 strayfoot[i] = std::make_shared<det::Footprint>();
563 strayvar[i].
push_back((*in_it).variance());
569 for (
size_t i=0; i<tfoots.size(); ++i) {
571 strayfoot[i]->setSpans(std::make_shared<afwGeom::SpanSet>(straySpans[i]));
580 ndarray::Array<ImagePixelT,1,1> himg = heavy->getImageArray();
584 typename ndarray::Array<ImagePixelT,1,1>::Iterator hpix;
585 typename ndarray::Array<MaskPixelT,1,1>::Iterator mpix;
586 typename ndarray::Array<VariancePixelT,1,1>::Iterator vpix;
588 assert((
size_t)strayfoot[i]->getArea() == straypix[i].size());
590 for (spix = straypix[i].begin(),
591 smask = straymask[i].begin(),
592 svar = strayvar [i].begin(),
594 mpix = heavy->getMaskArray().begin(),
595 vpix = heavy->getVarianceArray().begin();
596 spix != straypix[i].
end();
597 ++spix, ++smask, ++svar, ++hpix, ++mpix, ++vpix) {
607template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
617 for (
size_t i=0; i<timgs.
size(); ++i) {
633 tsum->row_begin(
y - sumy0) + (copyx0 - sumx0);
634 for (; in_it != inend; ++in_it, ++tsum_it) {
635 *tsum_it +=
std::max((ImagePixelT)0.,
static_cast<ImagePixelT
>(*in_it));
690template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
702 int strayFluxOptions,
703 double clipStrayFluxFraction
706 if (timgs.
size() != tfoots.size()) {
708 (boost::format(
"Template images must be the same length as template footprints (%d vs %d)")
709 % timgs.
size() % tfoots.size()).str());
712 for (
size_t i=0; i<timgs.
size(); ++i) {
713 if (!timgs[i]->getBBox().contains(tfoots[i]->getBBox())) {
715 "Template image MUST contain template footprint");
719 "Image bbox MUST contain parent footprint");
730 bool findStrayFlux = (strayFluxOptions & ASSIGN_STRAYFLUX);
732 int ix0 = img.
getX0();
733 int iy0 = img.
getY0();
741 if (!tsum->getBBox().contains(foot.
getBBox())) {
743 "Template sum image MUST contain parent footprint");
750 _sum_templates(timgs, tsum);
753 for (
size_t i=0; i<timgs.
size(); ++i) {
757 port->setXY0(timg->getXY0());
771 timg->row_begin(
y - ty0) + (copyx0 - tx0);
774 tsum->row_begin(
y - sumy0) + (copyx0 - sumx0);
776 port->row_begin(
y - ty0) + (copyx0 - tx0);
777 for (; tptr != tend; ++tptr, ++in_it, ++out_it, ++tsum_it) {
781 double frac =
std::max((ImagePixelT)0.,
static_cast<ImagePixelT
>(*tptr)) / (*tsum_it);
793 if ((ispsf.
size() > 0) && (ispsf.
size() != timgs.
size())) {
795 (boost::format(
"'ispsf' must be the same length as templates (%d vs %d)")
796 % ispsf.
size() % timgs.
size()).str());
800 (boost::format(
"'pkx' and 'pky' must be the same length as templates (%d,%d vs %d)")
803 _find_stray_flux(foot, tsum, img, strayFluxOptions, tfoots,
804 ispsf, pkx, pky, clipStrayFluxFraction, strays);
826 int cx,
int cy,
bool forward=
true)
827 : _real(real), _cx(cx), _cy(cy), _forward(forward)
837 return _real == other;
840 return _real != other;
843 return _real <= other;
846 return _real < other;
849 return _real >= other;
852 return _real > other;
856 return (_real == other._real) &&
857 (_cx == other._cx) && (_cy == other._cy) &&
858 (_forward == other._forward);
861 return !(*
this == other);
882 return _real >= _end;
888 return _real->getX0() - _cx;
890 return _cx - _real->getX1();
895 return _real->getX1() - _cx;
897 return _cx - _real->getX0();
901 return std::abs(_real->getY() - _cy);
904 return _real->getX0();
907 return _real->getX1();
910 return _real->getY();
972template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
979 auto sfoot = std::make_shared<det::Footprint>();
987 afwGeom::SpanSet::const_iterator peakspan =
994 if (peakspan == spans.
begin()) {
998 "Failed to find span containing (%i,%i): before the beginning of this footprint", cx, cy);
1010 LOGL_WARN(_log,
"Failed to find span containing (%i,%i): nearest is %i, [%i,%i]. "
1011 "Footprint bbox is [%i,%i],[%i,%i]",
1018 LOGL_DEBUG(_log,
"Span containing (%i,%i): (x=[%i,%i], y=%i)",
1059 int fdxlo = fwd.
dxlo();
1060 int bdxlo = back.
dxlo();
1067 for (fend = fwd; fend.
notDone(); ++fend) {
1068 if (fend.
dy() != dy)
1071 for (bend = back; bend.
notDone(); ++bend) {
1072 if (bend.
dy() != dy)
1076 LOGL_DEBUG(_log,
"dy=%i, fy=%i, fx=[%i, %i], by=%i, fx=[%i, %i], fdx=%i, bdx=%i",
1077 dy, fy, fwd.
x0(), fwd.
x1(), by, back.
x0(), back.
x1(),
1081 if (bdxlo > fdxlo) {
1086 while ((fwd != fend) && (fwd.
dxhi() < bdxlo)) {
1091 LOGL_DEBUG(_log,
"Advanced to forward span %i, [%i, %i]",
1092 fy, fwd.
x0(), fwd.
x1());
1095 }
else if (fdxlo > bdxlo) {
1100 while ((back != bend) && (back.
dxhi() < fdxlo)) {
1105 LOGL_DEBUG(_log,
"Advanced to backward span %i, [%i, %i]",
1106 by, back.
x0(), back.
x1());
1111 if ((back == bend) || (fwd == fend)) {
1130 LOGL_DEBUG(_log,
"Adding span fwd %i, [%i, %i], back %i, [%i, %i]",
1131 fy, cx+dxlo, cx+dxhi, by, cx-dxhi, cx-dxlo);
1142 LOGL_DEBUG(_log,
"Stepped forward to span %i, [%i, %i]",
1143 fwd.
y(), fwd.
x0(), fwd.
x1());
1150 LOGL_DEBUG(_log,
"Stepped backward to span %i, [%i, %i]",
1151 back.
y(), back.
x0(), back.
x1());
1155 if ((back == bend) || (fwd == fend)) {
1170 sfoot->setSpans(std::make_shared<afwGeom::SpanSet>(
std::move(tmpSpans)));
1186template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
1197 bool* patchedEdges) {
1201 *patchedEdges =
false;
1203 int cx = peak.getIx();
1204 int cy = peak.getIy();
1220 "Image too small for symmetrized footprint");
1225 bool touchesEdge =
false;
1227 LOGL_DEBUG(_log,
"Checking footprint for EDGE bits");
1230 MaskPixelT edgebit =
mask->getPlaneBitMask(
"EDGE");
1231 for (afwGeom::SpanSet::const_iterator fwd=spans.
begin();
1232 fwd != spans.
end(); ++fwd) {
1233 int x0 = fwd->getX0();
1234 int x1 = fwd->getX1();
1236 mask->x_at(x0 -
mask->getX0(), fwd->getY() -
mask->getY0());
1237 for (
int x=x0;
x<=x1; ++
x, ++xiter) {
1238 if ((*xiter) & edgebit) {
1247 LOGL_DEBUG(_log,
"Footprint includes an EDGE pixel.");
1255 afwGeom::SpanSet::const_iterator fwd = spans.
begin();
1256 afwGeom::SpanSet::const_iterator back = spans.
end()-1;
1260 for (; fwd <= back; fwd++, back--) {
1261 int fy = fwd->getY();
1262 int by = back->getY();
1264 for (
int fx=fwd->getX0(), bx=back->getX1();
1273 assert(theimg->getBBox(image::PARENT).contains(
geom::Point2I(fx, fy)));
1274 assert(theimg->getBBox(image::PARENT).contains(
geom::Point2I(bx, by)));
1281 ImagePixelT pix =
std::min(pixf, pixb);
1283 pix =
std::max(pix,
static_cast<ImagePixelT
>(0));
1302 LOGL_DEBUG(_log,
"Footprint touches EDGE: start bbox [%i,%i],[%i,%i]",
1306 for (fwd = ospans.
begin(); fwd != ospans.
end(); ++fwd) {
1307 int y = fwd->getY();
1308 int x = fwd->getX0();
1310 int ym = cy + (cy -
y);
1311 int xm = cx + (cx -
x);
1321 LOGL_DEBUG(_log,
"Footprint touches EDGE: grown bbox [%i,%i],[%i,%i]",
1326 sfoot->
getSpans()->copyImage(*targetimg, *targetimg2);
1328 LOGL_DEBUG(_log,
"Symmetric footprint spans:");
1330 for (fwd = sspans.
begin(); fwd != sspans.
end(); ++fwd) {
1331 LOGL_DEBUG(_log,
" %s", fwd->toString().c_str());
1337 for (fwd = ospans.
begin(); fwd != ospans.
end(); ++fwd) {
1338 int y = fwd->getY();
1339 int x0 = fwd->getX0();
1340 int x1 = fwd->getX1();
1342 int ym = cy + (cy -
y);
1343 int xm0 = cx + (cx - x0);
1344 int xm1 = cx + (cx - x1);
1355 x0 = cx + (cx - (imbb.
getMinX() - 1));
1358 x1 = cx + (cx - (imbb.
getMaxX() + 1));
1360 LOGL_DEBUG(_log,
"Span y=%i, x=[%i,%i] has mirror (%i,[%i,%i]) out-of-bounds; clipped to %i,[%i,%i]",
1361 y, fwd->getX0(), fwd->getX1(), ym, xm1, xm0,
y, x0, x1);
1365 targetimg2->x_at(x0 - targetimg2->getX0(),
y - targetimg2->getY0());
1366 for (
int x=x0;
x<=x1; ++
x, ++outiter, ++initer) {
1367 *outiter = initer.
image();
1372 targetimg = targetimg2;
1375 *patchedEdges = touchesEdge;
1383template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
1388 ImagePixelT thresh) {
1397 for (afwGeom::SpanSet::const_iterator sp = spans->begin(); sp != spans->end(); ++sp) {
1398 int const y = sp->getY();
1399 int const x0 = sp->getX0();
1400 int const x1 = sp->getX1();
1403 for (xiter = img->x_at(x0 - img->getX0(),
y - img->getY0()),
x=x0;
x<=x1; ++
x, ++xiter) {
1404 if (*xiter >= thresh) {
1416template<
typename ImagePixelT,
typename MaskPixelT,
typename VariancePixelT>
1421 ImagePixelT thresh) {
1425 auto significant = std::make_shared<det::Footprint>();
1426 significant->setPeakSchema(sfoot->getPeaks().getSchema());
1428 int const x0 = img->getX0(), y0 = img->getY0();
1431 for (afwGeom::SpanSet::const_iterator ss = edgeSpans->begin(); ss != edgeSpans->end(); ++ss) {
1433 int const y = span.
getY();
1436 bool onSpan =
false;
1438 for (;
x <= span.
getX1(); ++
x, ++iter) {
1439 if (*iter >= thresh) {
1442 }
else if (onSpan) {
1451 significant->setSpans(std::make_shared<afwGeom::SpanSet>(
std::move(tmpSpans)));
Key< Flag > const & target
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
table::Key< double > sigma1
LSST DM logging module built on log4cxx.
#define LOGL_WARN(logger, message...)
Log a warn-level message using a varargs/printf style interface.
#define LOG_GET(logger)
Returns a Log object associated with logger.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
This is a convenience class used in symmetrizeFootprint, wrapping the idea of iterating through a Spa...
bool operator<(const SpanSet::const_iterator &other)
RelativeSpanIterator(SpanSet::const_iterator const &real, SpanSet const &arr, int cx, int cy, bool forward=true)
bool operator!=(const SpanSet::const_iterator &other)
RelativeSpanIterator operator++(int dummy)
RelativeSpanIterator operator++()
bool operator!=(RelativeSpanIterator &other)
bool operator>(const SpanSet::const_iterator &other)
bool operator==(RelativeSpanIterator &other)
bool operator<=(const SpanSet::const_iterator &other)
bool operator>=(const SpanSet::const_iterator &other)
bool operator==(const SpanSet::const_iterator &other)
Record class that represents a peak in a Footprint.
A range of pixels within one row of an Image.
bool contains(int x) const noexcept
int getY() const noexcept
Return the y-value.
int getX0() const noexcept
Return the starting x-value.
int getX1() const noexcept
Return the ending x-value.
A compact representation of a collection of pixels.
const_iterator end() const
const_iterator begin() const
std::vector< Span >::const_iterator const_iterator
int getX0() const
Return the image's column-origin.
xy_locator xy_at(int x, int y) const
Return an xy_locator at the point (x, y) in the image.
typename _view_t::xy_locator xy_locator
An xy_locator.
typename _const_view_t::x_iterator const_x_iterator
A const iterator for traversing the pixels in a row.
int getWidth() const
Return the number of columns in the image.
int getY0() const
Return the image's row-origin.
int getHeight() const
Return the number of rows in the image.
x_iterator row_begin(int y) const
Return an x_iterator to the start of the y'th row.
x_iterator row_end(int y) const
Return an x_iterator to the end of the y'th row.
typename _view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
A class to represent a 2-dimensional array of pixels.
Ref< ImagePixelT >::type image()
Return (a reference to) the image part of the Pixel pointed at by the iterator.
Ref< MaskPixelT >::type mask()
Return (a reference to) the mask part of the Pixel pointed at by the iterator.
Ref< VariancePixelT >::type variance()
Return (a reference to) the variance part of the Pixel pointed at by the iterator.
An iterator to the MaskedImage.
A const locator for the MaskedImage.
A class to manipulate images, masks, and variance as a single object.
int getX0() const
Return the image's column-origin.
lsst::geom::Box2I getBBox(ImageOrigin const origin=PARENT) const
int getY0() const
Return the image's row-origin.
x_iterator row_begin(int y) const
Return an x_iterator to the start of the image.
x_iterator x_at(int x, int y) const
Return an x_iterator at the point (x, y)
MaskPtr getMask() const
Return a (shared_ptr to) the MaskedImage's mask.
ImagePtr getImage() const
Return a (shared_ptr to) the MaskedImage's image.
MaskPixelT mask() const
Return the mask part of a Pixel.
ImagePixelT image() const
Return the image part of a Pixel.
VariancePixelT variance() const
Return the variance part of a Pixel.
Schema getSchema() const
Return the schema associated with the catalog's table.
An integer coordinate rectangle.
void clip(Box2I const &other) noexcept
Shrink this to ensure that other.contains(*this).
int getMinY() const noexcept
void include(Point2I const &point)
Expand this to ensure that this->contains(point).
int getMinX() const noexcept
int getWidth() const noexcept
int getMaxX() const noexcept
bool contains(Point2I const &point) const noexcept
Return true if the box contains the point.
int getMaxY() const noexcept
Extent2I const getDimensions() const noexcept
Reports attempts to exceed implementation-defined length limits for some classes.
Reports errors that are due to events beyond the control of the program.