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 =
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, \
boost::shared_ptr< const IdSpan > ConstPtr
boost::uint16_t MaskPixel
An include file to include the header files for lsst::afw::geom.
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.
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.
boost::shared_ptr< Kernel const > ConstPtr
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
double getDouble(const std::string &name) const
int getInt(const std::string &name) const
boost::shared_ptr< IdSpan > Ptr
table::Key< table::Array< Kernel::Pixel > > image
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
bool operator()(const IdSpan::ConstPtr a, const IdSpan::ConstPtr b)
A class to manipulate images, masks, and variance as a single object.
IdSpan(int id, int y, int x0, int x1)
#define LSST_EXCEPT(type,...)
lsst::afw::math::Random & _rand
MaskPtr getMask(bool const noThrow=false) const
Return a (Ptr to) the MaskedImage's mask.
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)
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.
Include files required for standard LSST Exception handling.
MaskedImageT::Mask::Pixel _badMask