41 #include "boost/format.hpp"
67 typedef boost::shared_ptr<IdSpan>
Ptr;
68 typedef boost::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) {
85 return (a->y < b->y) ?
true :
false;
96 while (
id != aliases[
id]) {
97 resolved =
id = aliases[
id];
106 namespace algorithms {
108 namespace geom = lsst::afw::geom;
109 namespace math = lsst::afw::math;
111 namespace detection = lsst::afw::detection;
112 namespace pexLogging = lsst::pex::logging;
116 template<
typename ImageT,
typename MaskT>
118 double const bkgd, MaskT
const , MaskT
const saturBit, MaskT
const badMask,
119 bool const debias,
bool const grow);
121 template<
typename ImageT>
122 bool condition_3(ImageT *estimate,
double const peak,
123 double const mean_ns,
double const mean_we,
double const mean_swne,
double const mean_nwse,
125 double const dmean_ns,
double const dmean_we,
double const dmean_swne,
double const dmean_nwse,
126 double const thresH,
double const thresV,
double const thresD,
127 double const cond3Fac
133 template<
typename ImageT>
135 typedef typename boost::shared_ptr<CRPixel> Ptr;
137 CRPixel(
int _col,
int _row, ImageT _val,
int _id = -1) :
143 bool operator< (
const CRPixel& a)
const {
160 template<
typename ImageT>
161 int CRPixel<ImageT>::i = 0;
163 template<
typename ImageT>
164 struct Sort_CRPixel_by_id {
165 bool operator() (CRPixel<ImageT>
const & a, CRPixel<ImageT>
const &
b)
const {
176 template <
typename MaskedImageT>
177 bool is_cr_pixel(
typename MaskedImageT::Image::Pixel *corr,
178 typename MaskedImageT::xy_locator loc,
179 double const minSigma,
180 double const thresH,
double const thresV,
double const thresD,
182 double const cond3Fac
185 typedef typename MaskedImageT::Image::Pixel ImagePixel;
189 ImagePixel
const v_00 = loc.image(0, 0);
201 ImagePixel
const mean_we = (loc.image(-1, 0) + loc.image( 1, 0))/2;
202 ImagePixel
const mean_ns = (loc.image( 0, 1) + loc.image( 0, -1))/2;
203 ImagePixel
const mean_swne = (loc.image(-1, -1) + loc.image( 1, 1))/2;
204 ImagePixel
const mean_nwse = (loc.image(-1, 1) + loc.image( 1, -1))/2;
207 if (v_00 < -minSigma) {
211 double const thres_sky_sigma = minSigma*sqrt(loc.variance(0, 0));
213 if (v_00 < mean_ns + thres_sky_sigma &&
214 v_00 < mean_we + thres_sky_sigma &&
215 v_00 < mean_swne + thres_sky_sigma &&
216 v_00 < mean_nwse + thres_sky_sigma) {
225 double const dv_00 = sqrt(loc.variance( 0, 0));
227 double const dmean_we = sqrt(loc.variance(-1, 0) + loc.variance( 1, 0))/2;
228 double const dmean_ns = sqrt(loc.variance( 0, 1) + loc.variance( 0, -1))/2;
229 double const dmean_swne = sqrt(loc.variance(-1, -1) + loc.variance( 1, 1))/2;
230 double const dmean_nwse = sqrt(loc.variance(-1, 1) + loc.variance( 1, -1))/2;
232 if (!condition_3(corr,
233 v_00 - bkgd, mean_ns - bkgd, mean_we - bkgd, mean_swne - bkgd, mean_nwse - bkgd,
234 dv_00, dmean_ns, dmean_we, dmean_swne, dmean_nwse,
235 thresH, thresV, thresD, cond3Fac)){
241 *corr +=
static_cast<ImagePixel
>(bkgd);
251 template <
typename MaskedImageT>
253 std::vector<CRPixel<typename MaskedImageT::Image::Pixel> >& crpixels,
256 int const x0,
int const x1,
258 double const minSigma,
259 double const thresH,
double const thresV,
double const thresD,
261 double const cond3Fac,
265 typedef typename MaskedImageT::Image::Pixel MImagePixel;
266 typename MaskedImageT::xy_locator loc = image.xy_at(x0 - 1, y);
268 int const imageX0 = image.getX0();
269 int const imageY0 = image.getY0();
271 for (
int x = x0 - 1;
x <= x1 + 1; ++
x) {
272 MImagePixel corr = 0;
273 if (is_cr_pixel<MaskedImageT>(&corr, loc, minSigma, thresH, thresV, thresD,
276 crpixels.push_back(CRPixel<MImagePixel>(
x + imageX0, y + imageY0, loc.image()));
280 extras->
addSpan(y + imageY0,
x + imageX0,
x + imageX0);
290 template <
typename ImageT>
293 CountsInCR(ImageT
const& mimage,
double const bkgd) :
294 detection::FootprintFunctor<ImageT>(mimage),
299 void operator()(
typename ImageT::xy_locator loc,
306 virtual void reset() {
310 double getCounts()
const {
return _sum; }
320 template <
typename ImageT>
321 static void reinstateCrPixels(
323 std::vector<CRPixel<typename ImageT::Pixel> >
const& crpixels
326 if (crpixels.empty())
return;
328 typedef typename std::vector<CRPixel<typename ImageT::Pixel> >::const_iterator crpixel_iter;
329 for (crpixel_iter crp = crpixels.begin(), end = crpixels.end(); crp < end - 1 ; ++crp) {
330 *image->at(crp->col - image->getX0(), crp->row - image->getY0()) = crp->val;
339 template <
typename MaskedImageT>
340 std::vector<detection::Footprint::Ptr>
347 typedef typename MaskedImageT::Image ImageT;
348 typedef typename ImageT::Pixel ImagePixel;
349 typedef typename MaskedImageT::Mask::Pixel
MaskPixel;
352 double const minSigma = policy.
getDouble(
"minSigma");
353 double const minDn = policy.
getDouble(
"min_DN");
354 double const cond3Fac = policy.
getDouble(
"cond3_fac");
355 double const cond3Fac2 = policy.
getDouble(
"cond3_fac2");
356 int const niteration = policy.
getInt(
"niteration");
358 int const nCrPixelMax = policy.
getInt(
"nCrPixelMax");
368 throw LSST_EXCEPT(pexExcept::NotFoundError,
"Psf is unable to return a kernel");
371 kernel->computeImage(psfImage,
true);
373 int const xc = kernel->getCtrX();
374 int const yc = kernel->getCtrY();
376 double const I0 = psfImage(xc, yc);
377 double const thresH = cond3Fac2*(0.5*(psfImage(xc - 1, yc) + psfImage(xc + 1, yc)))/I0;
378 double const thresV = cond3Fac2*(0.5*(psfImage(xc, yc - 1) + psfImage(xc, yc + 1)))/I0;
379 double const thresD = cond3Fac2*(0.25*(psfImage(xc - 1, yc - 1) + psfImage(xc + 1, yc + 1) +
380 psfImage(xc - 1, yc + 1) + psfImage(xc + 1, yc - 1)))/I0;
384 MaskPixel
const badBit = mimage.getMask()->getPlaneBitMask(
"BAD");
385 MaskPixel
const crBit = mimage.getMask()->getPlaneBitMask(
"CR");
386 MaskPixel
const interpBit = mimage.getMask()->getPlaneBitMask(
"INTRP");
387 MaskPixel
const saturBit = mimage.getMask()->getPlaneBitMask(
"SAT");
389 MaskPixel
const badMask = (badBit | interpBit | saturBit);
393 int const ncol = mimage.getWidth();
394 int const nrow = mimage.getHeight();
396 std::vector<CRPixel<ImagePixel> > crpixels;
397 typedef typename std::vector<CRPixel<ImagePixel> >::iterator crpixel_iter;
398 typedef typename std::vector<CRPixel<ImagePixel> >::reverse_iterator crpixel_riter;
400 for (
int j = 1; j < nrow - 1; ++j) {
401 typename MaskedImageT::xy_locator loc = mimage.xy_at(1, j);
403 for (
int i = 1; i < ncol - 1; ++i, ++loc.x()) {
405 if (!is_cr_pixel<MaskedImageT>(&corr, loc, minSigma,
406 thresH, thresV, thresD, bkgd, cond3Fac)) {
412 if (loc.mask() & badMask) {
415 if ((loc.mask(-1, 1) | loc.mask(0, 1) | loc.mask(1, 1) |
416 loc.mask(-1, 0) | loc.mask(1, 0) |
417 loc.mask(-1, -1) | loc.mask(0, -1) | loc.mask(1, -1)) & interpBit) {
426 crpixels.push_back(CRPixel<ImagePixel>(i + mimage.getX0(), j + mimage.getY0(), loc.image()));
429 if (static_cast<int>(crpixels.size()) > nCrPixelMax) {
430 reinstateCrPixels(mimage.getImage().get(), crpixels);
432 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
433 (
boost::format(
"Too many CR pixels (max %d)") % nCrPixelMax).str());
441 std::vector<int> aliases;
442 aliases.reserve(1 + crpixels.size()/2);
444 std::vector<detection::IdSpan::Ptr> spans;
445 spans.reserve(aliases.capacity());
447 aliases.push_back(0);
455 if (!crpixels.empty()) {
457 int x0 = -1, x1 = -1, y = -1;
460 CRPixel<ImagePixel> dummy(0, -1, 0, -1);
461 crpixels.push_back(dummy);
463 for (crpixel_iter crp = crpixels.begin(); crp < crpixels.end() - 1 ; ++crp) {
468 aliases.push_back(crp->id);
476 if (crp[1].
row == crp[0].
row && crp[1].
col == crp[0].
col + 1) {
481 assert (y >= 0 && x0 >= 0 && x1 >= 0);
490 if (crpixels.size() > 0) {
491 for (crpixel_iter cp = crpixels.begin(); cp != crpixels.end() - 1; cp++) {
493 assert(cp->col >= 0);
494 assert(cp->row >= 0);
497 assert(crpixels[crpixels.size()-1].id == -1);
498 assert(crpixels[crpixels.size()-1].col == 0);
499 assert(crpixels[crpixels.size()-1].row == -1);
502 for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end(); sp != end; sp++) {
503 assert((*sp)->id >= 0);
504 assert((*sp)->y >= 0);
505 assert((*sp)->x0 >= 0);
506 assert((*sp)->x1 >= (*sp)->x0);
507 for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; sp2++) {
508 assert((*sp2)->y >= (*sp)->y);
509 if ((*sp2)->y == (*sp)->y) {
510 assert((*sp2)->x0 > (*sp)->x1);
518 for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end();
520 int const y = (*sp)->y;
521 int const x0 = (*sp)->x0;
522 int const x1 = (*sp)->x1;
525 for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; ++sp2) {
526 if ((*sp2)->y == y) {
530 }
else if ((*sp2)->y != (y + 1)) {
533 }
else if ((*sp2)->x0 > (x1 + 1)) {
536 }
else if ((*sp2)->x1 >= (x0 - 1)) {
552 for (
unsigned int i = 0; i != spans.size(); ++i) {
559 if (spans.size() > 0) {
566 std::vector<detection::Footprint::Ptr> CRs;
568 if (spans.size() > 0) {
569 int id = spans[0]->id;
571 for (
unsigned int i = i0; i <= spans.size(); ++i) {
572 if (i == spans.size() || spans[i]->id !=
id) {
575 for (; i0 < i; ++i0) {
576 cr->addSpan(spans[i0]->y, spans[i0]->x0, spans[i0]->x1);
581 if (i < spans.size()) {
587 reinstateCrPixels(mimage.getImage().get(), crpixels);
591 CountsInCR<ImageT> CountDN(*mimage.getImage(), bkgd);
592 for (std::vector<detection::Footprint::Ptr>::iterator cr = CRs.begin(), end = CRs.end();
596 pexLogging::TTrace<10>(
"algorithms.CR",
"CR at (%d, %d) has %g DN",
597 (*cr)->getBBox().getMinX(), (*cr)->getBBox().getMinY(), CountDN.getCounts());
598 if (CountDN.getCounts() < minDn) {
599 pexLogging::TTrace<11>(
"algorithms.CR",
"Erasing CR");
610 bool const debias_values =
true;
612 pexLogging::TTrace<2>(
"algorithms.CR",
"Removing initial list of CRs");
613 removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
614 #if 0 // Useful to see phase 2 in ds9; debugging only
616 mimage.getMask()->getPlaneBitMask(
"DETECTED"));
625 bool too_many_crs =
false;
627 for (
int i = 0; i != niteration && !too_many_crs; ++i) {
628 pexLogging::TTrace<1>(
"algorithms.CR",
"Starting iteration %d", i);
629 for (std::vector<detection::Footprint::Ptr>::iterator fiter = CRs.begin();
630 fiter != CRs.end(); fiter++) {
637 int const npix = (om) ? om->getNpix() : 0;
639 if (npix == cr->getNpix()) {
647 for (detection::Footprint::SpanList::const_iterator siter = cr->getSpans().begin();
648 siter != cr->getSpans().end(); siter++) {
649 detection::Span::Ptr
const span = *siter;
657 int const y = span->getY() - mimage.getY0();
658 if (y < 2 || y >= nrow - 2) {
661 int x0 = span->getX0() - mimage.getX0();
662 int x1 = span->getX1() - mimage.getX0();
663 x0 = (x0 < 2) ? 2 : (x0 > ncol - 3) ? ncol - 3 : x0;
664 x1 = (x1 < 2) ? 2 : (x1 > ncol - 3) ? ncol - 3 : x1;
666 checkSpanForCRs(&extra, crpixels, y - 1, x0, x1, mimage,
667 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
668 checkSpanForCRs(&extra, crpixels, y, x0, x1, mimage,
669 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
670 checkSpanForCRs(&extra, crpixels, y + 1, x0, x1, mimage,
671 minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
675 if (nextra + static_cast<int>(crpixels.size()) > nCrPixelMax) {
683 for (detection::Footprint::SpanList::const_iterator siter = espans.begin();
684 siter != espans.end(); siter++) {
685 cr->addSpan(**siter);
708 if (keep || too_many_crs) {
709 if (crpixels.size() > 0) {
710 int const imageX0 = mimage.getX0();
711 int const imageY0 = mimage.getY0();
713 std::sort(crpixels.begin(), crpixels.end());
715 crpixel_riter rend = crpixels.rend();
716 for (crpixel_riter crp = crpixels.rbegin(); crp != rend; ++crp) {
720 mimage.at(crp->col - imageX0, crp->row - imageY0).image() = crp->val;
724 if (
true || nextra > 0) {
726 pexLogging::TTrace<2>(
"algorithms.CR",
"Removing final list of CRs, grow = %d", grow);
727 removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
733 static_cast<MaskPixel
>(crBit | interpBit));
737 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
738 (
boost::format(
"Too many CR pixels (max %d)") % nCrPixelMax).str());
749 template<
typename ImageT>
750 bool condition_3(ImageT *estimate,
752 double const mean_ns,
753 double const mean_we,
754 double const mean_swne,
755 double const mean_nwse,
757 double const dmean_ns,
758 double const dmean_we,
759 double const dmean_swne,
760 double const dmean_nwse,
764 double const cond3Fac
767 if (thresV*(peak - cond3Fac*dpeak) > mean_ns + cond3Fac*dmean_ns) {
768 *estimate = (ImageT)mean_ns;
772 if (thresH*(peak - cond3Fac*dpeak) > mean_we + cond3Fac*dmean_we) {
777 if (thresD*(peak - cond3Fac*dpeak) > mean_swne + cond3Fac*dmean_swne) {
778 *estimate = mean_swne;
782 if (thresD*(peak - cond3Fac*dpeak) > mean_nwse + cond3Fac*dmean_nwse) {
783 *estimate = mean_nwse;
794 template <
typename MaskedImageT>
797 RemoveCR(MaskedImageT
const& mimage,
799 typename MaskedImageT::Mask::Pixel badMask,
802 ) : detection::FootprintFunctor<MaskedImageT>(mimage),
804 _ncol(mimage.getWidth()),
805 _nrow(mimage.getHeight()),
811 void operator()(
typename MaskedImageT::xy_locator loc,
815 typedef typename MaskedImageT::Image::Pixel MImagePixel;
816 MImagePixel min = std::numeric_limits<MImagePixel>::max();
819 MImagePixel
const minval =
_bkgd - 2*sqrt(loc.variance());
823 if (x - 2 >= 0 && x + 2 <
_ncol) {
828 MImagePixel
const v_m2 = loc.image(-2, 0);
829 MImagePixel
const v_m1 = loc.image(-1, 0);
830 MImagePixel
const v_p1 = loc.image( 1, 0);
831 MImagePixel
const v_p2 = loc.image( 2, 0);
833 MImagePixel
const tmp =
836 if (tmp > minval && tmp < min) {
845 if (y - 2 >= 0 && y + 2 <
_nrow) {
850 MImagePixel
const v_m2 = loc.image(0, -2);
851 MImagePixel
const v_m1 = loc.image(0, -1);
852 MImagePixel
const v_p1 = loc.image(0, 1);
853 MImagePixel
const v_p2 = loc.image(0, 2);
855 MImagePixel
const tmp =
858 if (tmp > minval && tmp < min) {
867 if (x - 2 >= 0 && x + 2 <
_ncol && y - 2 >= 0 && y + 2 <
_nrow) {
872 MImagePixel
const v_m2 = loc.image(-2, -2);
873 MImagePixel
const v_m1 = loc.image(-1, -1);
874 MImagePixel
const v_p1 = loc.image( 1, 1);
875 MImagePixel
const v_p2 = loc.image( 2, 2);
877 MImagePixel
const tmp =
880 if (tmp > minval && tmp < min) {
889 if (x - 2 >= 0 && x + 2 <
_ncol && y - 2 >= 0 && y + 2 <
_nrow) {
894 MImagePixel
const v_m2 = loc.image( 2, -2);
895 MImagePixel
const v_m1 = loc.image( 1, -1);
896 MImagePixel
const v_p1 = loc.image(-1, 1);
897 MImagePixel
const v_p2 = loc.image(-2, 2);
899 MImagePixel
const tmp =
902 if (tmp > minval && tmp < min) {
916 std::pair<bool, MImagePixel const> val_h =
918 std::pair<bool, MImagePixel const> val_v =
923 min =
_bkgd + sqrt(loc.variance())*
_rand.gaussian();
931 min = (val_v.second + val_h.second)/2;
943 pexLogging::TTrace<5>(
"algorithms.CR",
"Adopted min==%g at (%d, %d) (ngood=%d)",
944 static_cast<double>(min), x, y, ngood);
965 template<
typename ImageT,
typename MaskT>
967 std::vector<detection::Footprint::Ptr> & CRs,
970 MaskT
const saturBit,
988 RemoveCR<image::MaskedImage<ImageT, MaskT> > removeCR(mi, bkgd, badMask, debias, rand);
990 for (std::vector<detection::Footprint::Ptr>::reverse_iterator fiter = CRs.rbegin();
991 fiter != CRs.rend(); ++fiter) {
997 if (grow && cr->getNpix() < 100) {
999 bool const isotropic =
false;
1003 if (saturPixels->getNpix() > 0) {
1008 }
catch(lsst::pex::exceptions::LengthError &) {
1015 removeCR.apply(*cr);
1024 #define INSTANTIATE(TYPE) \
1026 std::vector<detection::Footprint::Ptr> \
1027 findCosmicRays(lsst::afw::image::MaskedImage<TYPE> &image, \
1028 detection::Psf const &psf, \
1029 double const bkgd, \
1030 lsst::pex::policy::Policy const& policy, \
int getInt(const std::string &name) const
An include file to include the header files for lsst::afw::geom.
std::vector< boost::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.
double const min2GaussianBias
Mean value of the minimum of two N(0,1) variates.
Include files required for standard LSST Exception handling.
boost::uint16_t MaskPixel
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.
#define INSTANTIATE(MATCH)
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)
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.
boost::shared_ptr< IdSpan > Ptr
#define LSST_EXCEPT(type,...)
double getDouble(const std::string &name) const
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.
boost::shared_ptr< const IdSpan > ConstPtr
afw::table::Key< double > b
Implementation of the Class MaskedImage.
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.
MaskedImageT::Mask::Pixel _badMask