41 #include "boost/format.hpp"
67 typedef std::shared_ptr<IdSpan>
Ptr;
68 typedef std::shared_ptr<const IdSpan>
ConstPtr;
70 explicit IdSpan(
int id,
int y,
int x0,
int x1) : id(id), y(y), x0(x0), x1(x1) {}
78 struct IdSpanCompar :
public std::binary_function<const IdSpan::ConstPtr, const IdSpan::ConstPtr, bool> {
82 }
else if(a->id > b->id) {
87 }
else if (a->y > b->y) {
90 return (a->x0 < b->x0) ?
true :
false;
102 while (
id != aliases[
id]) {
103 resolved =
id = aliases[
id];
112 namespace algorithms {
114 namespace geom = lsst::afw::geom;
115 namespace math = lsst::afw::math;
117 namespace detection = lsst::afw::detection;
118 namespace pexLogging = lsst::pex::logging;
122 template<
typename ImageT,
typename MaskT>
124 double const bkgd, MaskT
const , MaskT
const saturBit, MaskT
const badMask,
125 bool const debias,
bool const grow);
127 template<
typename ImageT>
128 bool condition_3(ImageT *estimate,
double const peak,
129 double const mean_ns,
double const mean_we,
double const mean_swne,
double const mean_nwse,
131 double const dmean_ns,
double const dmean_we,
double const dmean_swne,
double const dmean_nwse,
132 double const thresH,
double const thresV,
double const thresD,
133 double const cond3Fac
139 template<
typename ImageT>
141 typedef typename std::shared_ptr<CRPixel> Ptr;
143 CRPixel(
int _col,
int _row, ImageT _val,
int _id = -1) :
149 bool operator< (
const CRPixel& a)
const {
166 template<
typename ImageT>
167 int CRPixel<ImageT>::i = 0;
169 template<
typename ImageT>
170 struct Sort_CRPixel_by_id {
171 bool operator() (CRPixel<ImageT>
const & a, CRPixel<ImageT>
const &
b)
const {
182 template <
typename MaskedImageT>
183 bool is_cr_pixel(
typename MaskedImageT::Image::Pixel *corr,
184 typename MaskedImageT::xy_locator loc,
185 double const minSigma,
186 double const thresH,
double const thresV,
double const thresD,
188 double const cond3Fac
191 typedef typename MaskedImageT::Image::Pixel ImagePixel;
195 ImagePixel
const v_00 = loc.image(0, 0);
207 ImagePixel
const mean_we = (loc.image(-1, 0) + loc.image( 1, 0))/2;
208 ImagePixel
const mean_ns = (loc.image( 0, 1) + loc.image( 0, -1))/2;
209 ImagePixel
const mean_swne = (loc.image(-1, -1) + loc.image( 1, 1))/2;
210 ImagePixel
const mean_nwse = (loc.image(-1, 1) + loc.image( 1, -1))/2;
213 if (v_00 < -minSigma) {
217 double const thres_sky_sigma = minSigma*sqrt(loc.variance(0, 0));
219 if (v_00 < mean_ns + thres_sky_sigma &&
220 v_00 < mean_we + thres_sky_sigma &&
221 v_00 < mean_swne + thres_sky_sigma &&
222 v_00 < mean_nwse + thres_sky_sigma) {
231 double const dv_00 = sqrt(loc.variance( 0, 0));
233 double const dmean_we = sqrt(loc.variance(-1, 0) + loc.variance( 1, 0))/2;
234 double const dmean_ns = sqrt(loc.variance( 0, 1) + loc.variance( 0, -1))/2;
235 double const dmean_swne = sqrt(loc.variance(-1, -1) + loc.variance( 1, 1))/2;
236 double const dmean_nwse = sqrt(loc.variance(-1, 1) + loc.variance( 1, -1))/2;
238 if (!condition_3(corr,
239 v_00 - bkgd, mean_ns - bkgd, mean_we - bkgd, mean_swne - bkgd, mean_nwse - bkgd,
240 dv_00, dmean_ns, dmean_we, dmean_swne, dmean_nwse,
241 thresH, thresV, thresD, cond3Fac)){
247 *corr +=
static_cast<ImagePixel
>(bkgd);
257 template <
typename MaskedImageT>
259 std::vector<CRPixel<typename MaskedImageT::Image::Pixel> >& crpixels,
262 int const x0,
int const x1,
264 double const minSigma,
265 double const thresH,
double const thresV,
double const thresD,
267 double const cond3Fac,
271 typedef typename MaskedImageT::Image::Pixel MImagePixel;
272 typename MaskedImageT::xy_locator loc = image.xy_at(x0 - 1, y);
274 int const imageX0 = image.getX0();
275 int const imageY0 = image.getY0();
277 for (
int x = x0 - 1;
x <= x1 + 1; ++
x) {
278 MImagePixel corr = 0;
279 if (is_cr_pixel<MaskedImageT>(&corr, loc, minSigma, thresH, thresV, thresD,
282 crpixels.push_back(CRPixel<MImagePixel>(
x + imageX0, y + imageY0, loc.image()));
286 extras->
addSpan(y + imageY0,
x + imageX0,
x + imageX0);
296 template <
typename ImageT>
299 CountsInCR(ImageT
const& mimage,
double const bkgd) :
300 detection::FootprintFunctor<ImageT>(mimage),
305 void operator()(
typename ImageT::xy_locator loc,
312 virtual void reset() {
316 double getCounts()
const {
return _sum; }
326 template <
typename ImageT>
327 static void reinstateCrPixels(
329 std::vector<CRPixel<typename ImageT::Pixel> >
const& crpixels
332 if (crpixels.empty())
return;
334 typedef typename std::vector<CRPixel<typename ImageT::Pixel> >::const_iterator crpixel_iter;
335 for (crpixel_iter crp = crpixels.begin(), end = crpixels.end(); crp < end - 1 ; ++crp) {
336 *image->at(crp->col - image->getX0(), crp->row - image->getY0()) = crp->val;
345 template <
typename MaskedImageT>
346 std::vector<detection::Footprint::Ptr>
353 typedef typename MaskedImageT::Image ImageT;
354 typedef typename ImageT::Pixel ImagePixel;
355 typedef typename MaskedImageT::Mask::Pixel
MaskPixel;
358 double const minSigma = policy.
getDouble(
"minSigma");
359 double const minDn = policy.
getDouble(
"min_DN");
360 double const cond3Fac = policy.
getDouble(
"cond3_fac");
361 double const cond3Fac2 = policy.
getDouble(
"cond3_fac2");
362 int const niteration = policy.
getInt(
"niteration");
364 int const nCrPixelMax = policy.
getInt(
"nCrPixelMax");
372 throw LSST_EXCEPT(pexExcept::NotFoundError,
"Psf is unable to return a kernel");
375 kernel->computeImage(psfImage,
true);
377 int const xc = kernel->getCtrX();
378 int const yc = kernel->getCtrY();
380 double const I0 = psfImage(xc, yc);
381 double const thresH = cond3Fac2*(0.5*(psfImage(xc - 1, yc) + psfImage(xc + 1, yc)))/I0;
382 double const thresV = cond3Fac2*(0.5*(psfImage(xc, yc - 1) + psfImage(xc, yc + 1)))/I0;
383 double const thresD = cond3Fac2*(0.25*(psfImage(xc - 1, yc - 1) + psfImage(xc + 1, yc + 1) +
384 psfImage(xc - 1, yc + 1) + psfImage(xc + 1, yc - 1)))/I0;
388 MaskPixel
const badBit = mimage.getMask()->getPlaneBitMask(
"BAD");
389 MaskPixel
const crBit = mimage.getMask()->getPlaneBitMask(
"CR");
390 MaskPixel
const interpBit = mimage.getMask()->getPlaneBitMask(
"INTRP");
391 MaskPixel
const saturBit = mimage.getMask()->getPlaneBitMask(
"SAT");
392 MaskPixel
const nodataBit = mimage.getMask()->getPlaneBitMask(
"NO_DATA");
394 MaskPixel
const badMask = (badBit | interpBit | saturBit | nodataBit);
398 int const ncol = mimage.getWidth();
399 int const nrow = mimage.getHeight();
401 std::vector<CRPixel<ImagePixel> > crpixels;
402 typedef typename std::vector<CRPixel<ImagePixel> >::iterator crpixel_iter;
403 typedef typename std::vector<CRPixel<ImagePixel> >::reverse_iterator crpixel_riter;
405 for (
int j = 1; j < nrow - 1; ++j) {
406 typename MaskedImageT::xy_locator loc = mimage.xy_at(1, j);
408 for (
int i = 1; i < ncol - 1; ++i, ++loc.x()) {
410 if (!is_cr_pixel<MaskedImageT>(&corr, loc, minSigma,
411 thresH, thresV, thresD, bkgd, cond3Fac)) {
417 if (loc.mask() & badMask) {
420 if ((loc.mask(-1, 1) | loc.mask(0, 1) | loc.mask(1, 1) |
421 loc.mask(-1, 0) | loc.mask(1, 0) |
422 loc.mask(-1, -1) | loc.mask(0, -1) | loc.mask(1, -1)) & interpBit) {
431 crpixels.push_back(CRPixel<ImagePixel>(i + mimage.getX0(), j + mimage.getY0(), loc.image()));
434 if (static_cast<int>(crpixels.size()) > nCrPixelMax) {
435 reinstateCrPixels(mimage.getImage().get(), crpixels);
437 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
438 (
boost::format(
"Too many CR pixels (max %d)") % nCrPixelMax).str());
446 std::vector<int> aliases;
447 aliases.reserve(1 + crpixels.size()/2);
449 std::vector<detection::IdSpan::Ptr> spans;
450 spans.reserve(aliases.capacity());
452 aliases.push_back(0);
460 if (!crpixels.empty()) {
462 int x0 = -1, x1 = -1, y = -1;
465 CRPixel<ImagePixel> dummy(0, -1, 0, -1);
466 crpixels.push_back(dummy);
468 for (crpixel_iter crp = crpixels.begin(); crp < crpixels.end() - 1 ; ++crp) {
473 aliases.push_back(crp->id);
481 if (crp[1].
row == crp[0].
row && crp[1].
col == crp[0].
col + 1) {
486 assert (y >= 0 && x0 >= 0 && x1 >= 0);
495 if (crpixels.size() > 0) {
496 for (crpixel_iter cp = crpixels.begin(); cp != crpixels.end() - 1; cp++) {
498 assert(cp->col >= 0);
499 assert(cp->row >= 0);
502 assert(crpixels[crpixels.size()-1].id == -1);
503 assert(crpixels[crpixels.size()-1].col == 0);
504 assert(crpixels[crpixels.size()-1].row == -1);
507 for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end(); sp != end; sp++) {
508 assert((*sp)->id >= 0);
509 assert((*sp)->y >= 0);
510 assert((*sp)->x0 >= 0);
511 assert((*sp)->x1 >= (*sp)->x0);
512 for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; sp2++) {
513 assert((*sp2)->y >= (*sp)->y);
514 if ((*sp2)->y == (*sp)->y) {
515 assert((*sp2)->x0 > (*sp)->x1);
523 for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end();
525 int const y = (*sp)->y;
526 int const x0 = (*sp)->x0;
527 int const x1 = (*sp)->x1;
530 for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; ++sp2) {
531 if ((*sp2)->y == y) {
535 }
else if ((*sp2)->y != (y + 1)) {
538 }
else if ((*sp2)->x0 > (x1 + 1)) {
541 }
else if ((*sp2)->x1 >= (x0 - 1)) {
557 for (
unsigned int i = 0; i != spans.size(); ++i) {
564 if (spans.size() > 0) {
571 std::vector<detection::Footprint::Ptr> CRs;
573 if (spans.size() > 0) {
574 int id = spans[0]->id;
576 for (
unsigned int i = i0; i <= spans.size(); ++i) {
577 if (i == spans.size() || spans[i]->id !=
id) {
580 for (; i0 < i; ++i0) {
581 cr->addSpan(spans[i0]->y, spans[i0]->x0, spans[i0]->x1);
586 if (i < spans.size()) {
592 reinstateCrPixels(mimage.getImage().get(), crpixels);
596 CountsInCR<ImageT> CountDN(*mimage.getImage(), bkgd);
597 for (std::vector<detection::Footprint::Ptr>::iterator cr = CRs.begin(), end = CRs.end();
601 pexLogging::TTrace<10>(
"algorithms.CR",
"CR at (%d, %d) has %g DN",
602 (*cr)->getBBox().getMinX(), (*cr)->getBBox().getMinY(), CountDN.getCounts());
603 if (CountDN.getCounts() < minDn) {
604 pexLogging::TTrace<11>(
"algorithms.CR",
"Erasing CR");
615 bool const debias_values =
true;
617 pexLogging::TTrace<2>(
"algorithms.CR",
"Removing initial list of CRs");
618 removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
619 #if 0 // Useful to see phase 2 in ds9; debugging only
621 mimage.getMask()->getPlaneBitMask(
"DETECTED"));
630 bool too_many_crs =
false;
632 for (
int i = 0; i != niteration && !too_many_crs; ++i) {
633 pexLogging::TTrace<1>(
"algorithms.CR",
"Starting iteration %d", i);
634 for (std::vector<detection::Footprint::Ptr>::iterator fiter = CRs.begin();
635 fiter != CRs.end(); fiter++) {
642 int const npix = (om) ? om->getNpix() : 0;
644 if (npix == cr->getNpix()) {
652 for (detection::Footprint::SpanList::const_iterator siter = cr->getSpans().begin();
653 siter != cr->getSpans().end(); siter++) {
654 detection::Span::Ptr
const span = *siter;
662 int const y = span->getY() - mimage.getY0();
663 if (y < 2 || y >= nrow - 2) {
666 int x0 = span->getX0() - mimage.getX0();
667 int x1 = span->getX1() - mimage.getX0();
668 x0 = (x0 < 2) ? 2 : (x0 > ncol - 3) ? ncol - 3 : x0;
669 x1 = (x1 < 2) ? 2 : (x1 > ncol - 3) ? ncol - 3 : x1;
671 checkSpanForCRs(&extra, crpixels, y - 1, x0, x1, mimage,
672 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
673 checkSpanForCRs(&extra, crpixels, y, x0, x1, mimage,
674 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
675 checkSpanForCRs(&extra, crpixels, y + 1, x0, x1, mimage,
676 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
680 if (nextra + static_cast<int>(crpixels.size()) > nCrPixelMax) {
688 for (detection::Footprint::SpanList::const_iterator siter = espans.begin();
689 siter != espans.end(); siter++) {
690 cr->addSpan(**siter);
713 if (keep || too_many_crs) {
714 if (crpixels.size() > 0) {
715 int const imageX0 = mimage.getX0();
716 int const imageY0 = mimage.getY0();
718 std::sort(crpixels.begin(), crpixels.end());
720 crpixel_riter rend = crpixels.rend();
721 for (crpixel_riter crp = crpixels.rbegin(); crp != rend; ++crp) {
725 mimage.at(crp->col - imageX0, crp->row - imageY0).image() = crp->val;
729 if (
true || nextra > 0) {
731 pexLogging::TTrace<2>(
"algorithms.CR",
"Removing final list of CRs, grow = %d", grow);
732 removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
738 static_cast<MaskPixel
>(crBit | interpBit));
742 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
743 (
boost::format(
"Too many CR pixels (max %d)") % nCrPixelMax).str());
754 template<
typename ImageT>
755 bool condition_3(ImageT *estimate,
757 double const mean_ns,
758 double const mean_we,
759 double const mean_swne,
760 double const mean_nwse,
762 double const dmean_ns,
763 double const dmean_we,
764 double const dmean_swne,
765 double const dmean_nwse,
769 double const cond3Fac
772 if (thresV*(peak - cond3Fac*dpeak) > mean_ns + cond3Fac*dmean_ns) {
773 *estimate = (ImageT)mean_ns;
777 if (thresH*(peak - cond3Fac*dpeak) > mean_we + cond3Fac*dmean_we) {
782 if (thresD*(peak - cond3Fac*dpeak) > mean_swne + cond3Fac*dmean_swne) {
783 *estimate = mean_swne;
787 if (thresD*(peak - cond3Fac*dpeak) > mean_nwse + cond3Fac*dmean_nwse) {
788 *estimate = mean_nwse;
799 template <
typename MaskedImageT>
802 RemoveCR(MaskedImageT
const& mimage,
804 typename MaskedImageT::Mask::Pixel badMask,
807 ) : detection::FootprintFunctor<MaskedImageT>(mimage),
809 _ncol(mimage.getWidth()),
810 _nrow(mimage.getHeight()),
816 void operator()(
typename MaskedImageT::xy_locator loc,
820 typedef typename MaskedImageT::Image::Pixel MImagePixel;
821 MImagePixel min = std::numeric_limits<MImagePixel>::max();
824 MImagePixel
const minval =
_bkgd - 2*sqrt(loc.variance());
828 if (x - 2 >= 0 && x + 2 <
_ncol) {
833 MImagePixel
const v_m2 = loc.image(-2, 0);
834 MImagePixel
const v_m1 = loc.image(-1, 0);
835 MImagePixel
const v_p1 = loc.image( 1, 0);
836 MImagePixel
const v_p2 = loc.image( 2, 0);
838 MImagePixel
const tmp =
841 if (tmp > minval && tmp < min) {
850 if (y - 2 >= 0 && y + 2 <
_nrow) {
855 MImagePixel
const v_m2 = loc.image(0, -2);
856 MImagePixel
const v_m1 = loc.image(0, -1);
857 MImagePixel
const v_p1 = loc.image(0, 1);
858 MImagePixel
const v_p2 = loc.image(0, 2);
860 MImagePixel
const tmp =
863 if (tmp > minval && tmp < min) {
872 if (x - 2 >= 0 && x + 2 <
_ncol && y - 2 >= 0 && y + 2 <
_nrow) {
877 MImagePixel
const v_m2 = loc.image(-2, -2);
878 MImagePixel
const v_m1 = loc.image(-1, -1);
879 MImagePixel
const v_p1 = loc.image( 1, 1);
880 MImagePixel
const v_p2 = loc.image( 2, 2);
882 MImagePixel
const tmp =
885 if (tmp > minval && tmp < min) {
894 if (x - 2 >= 0 && x + 2 <
_ncol && y - 2 >= 0 && y + 2 <
_nrow) {
899 MImagePixel
const v_m2 = loc.image( 2, -2);
900 MImagePixel
const v_m1 = loc.image( 1, -1);
901 MImagePixel
const v_p1 = loc.image(-1, 1);
902 MImagePixel
const v_p2 = loc.image(-2, 2);
904 MImagePixel
const tmp =
907 if (tmp > minval && tmp < min) {
921 std::pair<bool, MImagePixel const> val_h =
923 std::pair<bool, MImagePixel const> val_v =
928 min =
_bkgd + sqrt(loc.variance())*
_rand.gaussian();
936 min = (val_v.second + val_h.second)/2;
948 pexLogging::TTrace<5>(
"algorithms.CR",
"Adopted min==%g at (%d, %d) (ngood=%d)",
949 static_cast<double>(min), x, y, ngood);
970 template<
typename ImageT,
typename MaskT>
972 std::vector<detection::Footprint::Ptr> & CRs,
975 MaskT
const saturBit,
993 RemoveCR<image::MaskedImage<ImageT, MaskT> > removeCR(mi, bkgd, badMask, debias, rand);
995 for (std::vector<detection::Footprint::Ptr>::reverse_iterator fiter = CRs.rbegin();
996 fiter != CRs.rend(); ++fiter) {
1002 if (grow && cr->getNpix() < 100) {
1004 bool const isotropic =
false;
1008 if (saturPixels->getNpix() > 0) {
1013 }
catch(lsst::pex::exceptions::LengthError &) {
1020 removeCR.apply(*cr);
1029 #define INSTANTIATE(TYPE) \
1031 std::vector<detection::Footprint::Ptr> \
1032 findCosmicRays(lsst::afw::image::MaskedImage<TYPE> &image, \
1033 detection::Psf const &psf, \
1034 double const bkgd, \
1035 lsst::pex::policy::Policy const& policy, \
An include file to include the header files for lsst::afw::geom.
double const min2GaussianBias
Mean value of the minimum of two N(0,1) variates.
a container for holding hierarchical configuration data in memory.
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
IdSpan(int id, int y, int x0, int x1)
bool operator()(const IdSpan::ConstPtr a, const IdSpan::ConstPtr b)
table::Key< table::Array< Kernel::Pixel > > image
boost::shared_ptr< Kernel const > ConstPtr
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
std::shared_ptr< IdSpan > Ptr
MaskPtr getMask(bool const noThrow=false) const
Return a (Ptr to) the MaskedImage's mask.
A class to manipulate images, masks, and variance as a single object.
std::vector< std::shared_ptr< lsst::afw::detection::Footprint > > findCosmicRays(MaskedImageT &image, lsst::afw::detection::Psf const &psf, double const bkgd, lsst::pex::policy::Policy const &policy, bool const keep=false)
Find cosmic rays in an Image, and mask and remove them.
#define LSST_EXCEPT(type,...)
std::shared_ptr< const IdSpan > ConstPtr
std::pair< bool, typename MaskedImageT::Image::Pixel > singlePixel(int x, int y, MaskedImageT const &image, bool horizontal, double minval)
Random number generator class.
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.
int resolve_alias(const std::vector< int > &aliases, int id)
boost::shared_ptr< math::Kernel const > getLocalKernel(geom::Point2D position=makeNullPoint(), image::Color color=image::Color()) const
Return a FixedKernel corresponding to the Psf image at the given point.
int getInt(const std::string &name) const
afw::table::Key< double > b
Implementation of the Class MaskedImage.
Include files required for standard LSST Exception handling.
A polymorphic base class for representing an image's Point Spread Function.
image::Image< Pixel > Image
Image type returned by computeImage.
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.
double getDouble(const std::string &name) const
MaskedImageT::Mask::Pixel _badMask