28 #include "ndarray/eigen.h"
30 #include "lsst/afw/detection/Psf.h"
31 #include "lsst/afw/table/Source.h"
32 #include "lsst/afw/geom/Point.h"
33 #include "lsst/afw/geom/SpanSet.h"
36 namespace lsst {
namespace meas {
namespace base {
38 template <
typename MaskedImageT>
41 explicit FootprintBits() :
_bits(0) {}
48 void operator()(lsst::afw::geom::Point2I
const & point,
49 typename MaskedImageT::Mask::Pixel
const & value) {
54 typename MaskedImageT::Mask::Pixel getBits()
const {
return _bits; }
56 typename MaskedImageT::Mask::Pixel
_bits;
59 typedef afw::image::MaskedImage<float> MaskedImageF;
62 afw::table::SourceRecord & measRecord) {
63 for (
auto const & i: maskFlagToPixelFlag) {
65 if (func.getBits() & MaskedImageF::Mask::getPlaneBitMask(i.first)) {
66 measRecord.set(i.second,
true);
69 catch (pex::exceptions::InvalidParameterError & err) {
70 throw LSST_EXCEPT(FatalAlgorithmError, err.what());
78 std::string
const & name,
79 afw::table::Schema & schema
82 _generalFailureKey = schema.addField<afw::table::Flag>(name +
"_flag",
83 "general failure flag, set if anything went wring");
84 _offImageKey = schema.addField<afw::table::Flag>(name+
"_flag" +
"_offimage",
85 "Source center is off image");
87 _anyKeys[
"EDGE"] = schema.addField<afw::table::Flag>(name +
"_flag_edge",
88 "Source is outside usable exposure region (masked EDGE or NO_DATA)");
89 _anyKeys[
"INTRP"] = schema.addField<afw::table::Flag>(name +
"_flag_interpolated",
90 "Interpolated pixel in the Source footprint");
91 _anyKeys[
"SAT"] = schema.addField<afw::table::Flag>(name +
"_flag_saturated",
92 "Saturated pixel in the Source footprint");
93 _anyKeys[
"CR"] = schema.addField<afw::table::Flag>(name +
"_flag_cr",
94 "Cosmic ray in the Source footprint");
95 _anyKeys[
"BAD"] = schema.addField<afw::table::Flag>(name +
"_flag_bad",
96 "Bad pixel in the Source footprint");
97 _anyKeys[
"SUSPECT"] = schema.addField<afw::table::Flag>(name +
"_flag_suspect",
98 "Source's footprint includes suspect pixels");
100 _centerKeys[
"INTRP"] = schema.addField<afw::table::Flag>(name +
"_flag_interpolatedCenter",
101 "Interpolated pixel in the Source center");
102 _centerKeys[
"SAT"] = schema.addField<afw::table::Flag>(name +
"_flag_saturatedCenter",
103 "Saturated pixel in the Source center");
104 _centerKeys[
"CR"] = schema.addField<afw::table::Flag>(name +
"_flag_crCenter",
105 "Cosmic ray in the Source center");
106 _centerKeys[
"SUSPECT"] = schema.addField<afw::table::Flag>(name +
"_flag_suspectCenter",
107 "Source's center is close to suspect pixels");
111 std::string maskName(i);
112 std::transform(maskName.begin(), maskName.end(), maskName.begin(), ::tolower);
113 _centerKeys[i] = schema.addField<afw::table::Flag>(name +
"_flag_" + maskName +
"Center",
114 "Source center is close to "+ i +
" pixels");
118 std::string maskName(i);
119 std::transform(maskName.begin(), maskName.end(), maskName.begin(), ::tolower);
120 _anyKeys[i] = schema.addField<afw::table::Flag>(name +
"_flag_" + maskName,
121 "Source footprint includes " + i +
" pixels");
126 afw::table::SourceRecord & measRecord,
127 afw::image::Exposure<float>
const & exposure
130 MaskedImageF mimage = exposure.getMaskedImage();
131 FootprintBits<MaskedImageF> func;
134 afw::geom::Point2D center;
135 if (measRecord.getTable()->getCentroidKey().isValid()) {
136 center = measRecord.getCentroid();
138 if (std::isnan(center.getX()) || std::isnan(center.getY())) {
139 throw LSST_EXCEPT(pex::exceptions::RuntimeError,
140 "Center point passed to PixelFlagsAlgorithm is NaN");
146 measRecord.set(_generalFailureKey,
true);
152 PTR(afw::detection::Footprint) footprint = measRecord.getFootprint();
155 if (!footprint || footprint->getPeaks().empty()) {
156 throw LSST_EXCEPT(pex::exceptions::RuntimeError,
"No footprint, or no footprint peaks detected");
159 center.setX(footprint->getPeaks().front().getFx());
160 center.setY(footprint->getPeaks().front().getFy());
165 if (!mimage.getBBox().contains(afw::geom::Point2I(center))) {
166 measRecord.set(_offImageKey,
true);
167 measRecord.set(_anyKeys.at(
"EDGE"),
true);
171 afw::detection::Footprint
const & footprint(*measRecord.getFootprint());
172 footprint.getSpans()->clippedTo(mimage.getBBox())->applyFunctor(func, *(mimage.getMask()));
176 if (func.getBits() & MaskedImageF::Mask::getPlaneBitMask(
"NO_DATA")) {
177 measRecord.set(_anyKeys.at(
"EDGE"),
true);
179 }
catch (pex::exceptions::InvalidParameterError & err) {
184 updateFlags(_anyKeys, func, measRecord);
187 afw::geom::Point2I llc(afw::image::positionToIndex(center.getX()) - 1,
188 afw::image::positionToIndex(center.getY()) - 1);
191 auto spans = std::make_shared<afw::geom::SpanSet>(afw::geom::Box2I(llc, afw::geom::ExtentI(3)));
192 afw::detection::Footprint
const middle(spans);
193 middle.getSpans()->clippedTo(mimage.getBBox())->applyFunctor(func, *(mimage.getMask()));
196 updateFlags(_centerKeys, func, measRecord);
201 measRecord.set(_generalFailureKey,
true);
std::map< std::string, afw::table::Key< afw::table::Flag > > KeyMap
virtual void fail(afw::table::SourceRecord &measRecord, MeasurementError *error=nullptr) const
Handle an exception thrown by the current algorithm by setting flags in the given record...
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Exception to be thrown when a measurement algorithm experiences a fatal error.
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
PixelFlagsAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
A C++ control class to handle PixelFlagsAlgorithm's configuration.
MaskedImageT::Mask::Pixel _bits
std::vector< std::string > masksFpCenter
"List of mask planes to be searched for which occur in the center of a footprint. " "If any of the pl...
This is the algorithm for PixelFlags.
std::vector< std::string > masksFpAnywhere
"List of mask planes to be searched for which occur anywhere within a footprint. " "If any of the pla...