LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
PixelFlags.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 /*
3  * LSST Data Management System
4  * Copyright 2008-2013 LSST Corporation.
5  *
6  * This product includes software developed by the
7  * LSST Project (http://www.lsst.org/).
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the LSST License Statement and
20  * the GNU General Public License along with this program. If not,
21  * see <http://www.lsstcorp.org/LegalNotices/>.
22  */
23 
24 #include <cctype> // ::tolower
25 #include <algorithm> // std::transform
26 #include <cmath>
27 
28 #include "ndarray/eigen.h"
29 
30 #include "lsst/afw/detection/Psf.h"
32 #include "lsst/afw/table/Source.h"
34 
35 namespace lsst { namespace meas { namespace base {
36 namespace {
37 template <typename MaskedImageT>
38 class FootprintBits : public afw::detection::FootprintFunctor<MaskedImageT> {
39 public:
40  explicit FootprintBits(MaskedImageT const& mimage) :
41  afw::detection::FootprintFunctor<MaskedImageT>(mimage), _bits(0)
42  {}
43 
45  void reset() {
46  _bits = 0x0;
47  }
48  virtual void reset(afw::detection::Footprint const&) {}
49 
51  void operator()(typename MaskedImageT::xy_locator loc,
52  int x,
53  int y
54  ) {
55  _bits |= loc.mask(0, 0);
56  }
57 
59  typename MaskedImageT::Mask::Pixel getBits() const { return _bits; }
60 private:
61  typename MaskedImageT::Mask::Pixel _bits;
62 };
63 
64 typedef afw::image::MaskedImage<float> MaskedImageF;
65 
66 void updateFlags(PixelFlagsAlgorithm::KeyMap const & maskFlagToPixelFlag, const FootprintBits<MaskedImageF> & func,
67  afw::table::SourceRecord & measRecord) {
68  for (auto const & i: maskFlagToPixelFlag) {
69  try {
70  if (func.getBits() & MaskedImageF::Mask::getPlaneBitMask(i.first)) {
71  measRecord.set(i.second, true);
72  }
73  }
74  catch (pex::exceptions::InvalidParameterError & err) {
75  throw LSST_EXCEPT(FatalAlgorithmError, err.what());
76  }
77  }
78  }
79 } // end anonymous namespace
80 
82  Control const & ctrl,
83  std::string const & name,
85 ) : _ctrl(ctrl) {
86  // Add generic keys first, which don't correspond to specific mask planes
87  _generalFailureKey = schema.addField<afw::table::Flag>(name + "_flag",
88  "general failure flag, set if anything went wring");
89  _offImageKey = schema.addField<afw::table::Flag>(name+"_flag" + "_offimage",
90  "Source center is off image");
91  // Set all the flags that correspond to mask planes anywhere in the footprint
92  _anyKeys["EDGE"] = schema.addField<afw::table::Flag>(name + "_flag_edge",
93  "Source is outside usable exposure region (masked EDGE or NO_DATA)");
94  _anyKeys["INTRP"] = schema.addField<afw::table::Flag>(name + "_flag_interpolated",
95  "Interpolated pixel in the Source footprint");
96  _anyKeys["SAT"] = schema.addField<afw::table::Flag>(name + "_flag_saturated",
97  "Saturated pixel in the Source footprint");
98  _anyKeys["CR"] = schema.addField<afw::table::Flag>(name + "_flag_cr",
99  "Cosmic ray in the Source footprint");
100  _anyKeys["BAD"] = schema.addField<afw::table::Flag>(name + "_flag_bad",
101  "Bad pixel in the Source footprint");
102  _anyKeys["SUSPECT"] = schema.addField<afw::table::Flag>(name + "_flag_suspect",
103  "Source's footprint includes suspect pixels");
104  // Flags that correspond to mask bits which occur in the center of the object
105  _centerKeys["INTRP"] = schema.addField<afw::table::Flag>(name + "_flag_interpolatedCenter",
106  "Interpolated pixel in the Source center");
107  _centerKeys["SAT"] = schema.addField<afw::table::Flag>(name + "_flag_saturatedCenter",
108  "Saturated pixel in the Source center");
109  _centerKeys["CR"] = schema.addField<afw::table::Flag>(name + "_flag_crCenter",
110  "Cosmic ray in the Source center");
111  _centerKeys["SUSPECT"] = schema.addField<afw::table::Flag>(name + "_flag_suspectCenter",
112  "Source's center is close to suspect pixels");
113 
114  // Read in the flags passed from the configuration, and add them to the schema
115  for (auto const & i: _ctrl.masksFpCenter) {
116  std::string maskName(i);
117  std::transform(maskName.begin(), maskName.end(), maskName.begin(), ::tolower);
118  _centerKeys[i] = schema.addField<afw::table::Flag>(name + "_flag_" + maskName + "Center",
119  "Source center is close to "+ i + " pixels");
120  }
121 
122  for (auto const & i: _ctrl.masksFpAnywhere) {
123  std::string maskName(i);
124  std::transform(maskName.begin(), maskName.end(), maskName.begin(), ::tolower);
125  _anyKeys[i] = schema.addField<afw::table::Flag>(name + "_flag_" + maskName,
126  "Source footprint includes " + i + " pixels");
127  }
128 }
129 
131  afw::table::SourceRecord & measRecord,
132  afw::image::Exposure<float> const & exposure
133 ) const {
134 
135  MaskedImageF mimage = exposure.getMaskedImage();
136  FootprintBits<MaskedImageF> func(mimage);
137 
138  // Check if the measRecord has a valid centroid key, i.e. it was centroided
139  afw::geom::Point2D center;
140  if (measRecord.getTable()->getCentroidKey().isValid()) {
141  center = measRecord.getCentroid();
142  // Catch NAN in centroid estimate
143  if (std::isnan(center.getX()) || std::isnan(center.getY())) {
144  throw LSST_EXCEPT(pex::exceptions::RuntimeError,
145  "Center point passed to PixelFlagsAlgorithm is NaN");
146  }
147  }
148  else {
149  // Set the general failure flag because using the Peak might affect
150  // the current measurement
151  measRecord.set(_generalFailureKey, true);
152  // Attempting to set pixel flags with no centroider, the center will
153  // be determined though the peak pixel. The first peak in the
154  // footprint (supplied by the measurement framework) should be the
155  // highest peak so that one will be used as a proxy for the central
156  // tendency of the distribution of flux for the record.
157  PTR(afw::detection::Footprint) footprint = measRecord.getFootprint();
158  // If there is no footprint or the footprint contains no peaks, throw
159  // a runtime error.
160  if (!footprint || footprint->getPeaks().empty()) {
161  throw LSST_EXCEPT(pex::exceptions::RuntimeError, "No footprint, or no footprint peaks detected");
162  }
163  else {
164  center.setX(footprint->getPeaks().front().getFx());
165  center.setY(footprint->getPeaks().front().getFy());
166  }
167  }
168 
169  // Catch centroids off the image
170  if (!mimage.getBBox().contains(afw::geom::Point2I(center))) {
171  measRecord.set(_offImageKey, true);
172  measRecord.set(_anyKeys.at("EDGE"), true);
173  }
174 
175  // Check for bits set in the source's Footprint
176  afw::detection::Footprint const & footprint(*measRecord.getFootprint());
177  func.apply(footprint);
178 
179  // Set the EDGE flag if the bitmask has NO_DATA set
180  try {
181  if (func.getBits() & MaskedImageF::Mask::getPlaneBitMask("NO_DATA")) {
182  measRecord.set(_anyKeys.at("EDGE"), true);
183  }
184  } catch (pex::exceptions::InvalidParameterError & err) {
185  throw LSST_EXCEPT(FatalAlgorithmError, err.what());
186  }
187 
188  // update the source record for the any keys
189  updateFlags(_anyKeys, func, measRecord);
190 
191  // Check for bits set in the 3x3 box around the center
192  afw::geom::Point2I llc(afw::image::positionToIndex(center.getX()) - 1,
193  afw::image::positionToIndex(center.getY()) - 1);
194 
195  afw::detection::Footprint const middle(afw::geom::BoxI(llc, afw::geom::ExtentI(3))); // central 3x3
196  func.apply(middle);
197 
198  // Update the flags which have to do with the center of the footprint
199  updateFlags(_centerKeys, func, measRecord);
200 }
201 
203  measRecord.set(_generalFailureKey, true);
204 }
205 
206 }}} // namespace lsst::meas::base
207 
int y
std::map< std::string, afw::table::Key< afw::table::Flag > > KeyMap
Definition: PixelFlags.h:81
Defines the fields and offsets for a table.
Definition: Schema.h:44
table::Key< std::string > name
Definition: ApCorrMap.cc:71
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
virtual void fail(afw::table::SourceRecord &measRecord, MeasurementError *error=NULL) const
Definition: PixelFlags.cc:202
MaskedImageT::Mask::Pixel _bits
Definition: PixelFlags.cc:61
afw::table::Schema schema
Definition: GaussianPsf.cc:41
boost::shared_ptr< Footprint > getFootprint() const
Definition: Source.h:88
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Definition: exceptions.h:48
PixelFlagsAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
Definition: PixelFlags.cc:81
An integer coordinate rectangle.
Definition: Box.h:53
def error
Definition: log.py:103
CentroidSlotDefinition::MeasValue getCentroid() const
Get the value of the Centroid slot measurement.
Definition: Source.h:902
std::vector< std::string > masksFpAnywhere
&quot;List of mask planes to be searched for which occur anywhere within a footprint. &quot; &quot;If any of the pla...
Definition: PixelFlags.h:49
MaskedImageT getMaskedImage()
Return the MaskedImage.
Definition: Exposure.h:148
afw::table::Key< afw::table::Flag > _generalFailureKey
Definition: PixelFlags.h:87
double x
afw::table::Key< afw::table::Flag > _offImageKey
Definition: PixelFlags.h:88
A set of pixels in an Image.
Definition: Footprint.h:62
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
std::vector< std::string > masksFpCenter
&quot;List of mask planes to be searched for which occur in the center of a footprint. &quot; &quot;If any of the pl...
Definition: PixelFlags.h:46
boost::shared_ptr< SourceTable const > getTable() const
Definition: Source.h:92
A C++ control class to handle PixelFlagsAlgorithm&#39;s configuration.
Definition: PixelFlags.h:42
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Definition: PixelFlags.cc:130
lsst::afw::detection::Footprint Footprint
Definition: Source.h:60
#define PTR(...)
Definition: base.h:41
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
Definition: BaseRecord.h:145
Record class that contains measurements made on a single exposure.
Definition: Source.h:80