lsst.meas.base  14.0-21-gb9e430a+6
CentroidUtilities.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2014 LSST Corporation.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #include <cmath>
26 
27 namespace lsst { namespace meas { namespace base {
28 
30  x(std::numeric_limits<CentroidElement>::quiet_NaN()),
31  y(std::numeric_limits<CentroidElement>::quiet_NaN()),
32  xSigma(std::numeric_limits<ErrElement>::quiet_NaN()),
33  ySigma(std::numeric_limits<ErrElement>::quiet_NaN()),
34  x_y_Cov(std::numeric_limits<ErrElement>::quiet_NaN())
35 {}
36 
37 Centroid const CentroidResult::getCentroid() const { return Centroid(x, y); }
38 
39 void CentroidResult::setCentroid(Centroid const & centroid) {
40  x = centroid.getX();
41  y = centroid.getY();
42 }
43 
45  CentroidCov m;
46  m <<
49  return m;
50 }
51 
53  xSigma = std::sqrt(matrix(0, 0));
54  ySigma = std::sqrt(matrix(1, 1));
55  x_y_Cov = matrix(0, 1);
56 }
57 
59  xSigma = _xSigma;
60  ySigma = _ySigma;
61  x_y_Cov = 0.0;
62 }
63 
65  afw::table::Schema & schema,
66  std::string const & name,
67  std::string const & doc,
68  UncertaintyEnum uncertainty
69 ) {
72  schema,
73  name,
74  doc,
75  "pixel"
76  );
77  if (uncertainty != NO_UNCERTAINTY) {
80  sigma[0] = schema.addField<ErrElement>(
81  schema.join(name, "xSigma"), "1-sigma uncertainty on x position", "pixel"
82  );
83  sigma[1] = schema.addField<ErrElement>(
84  schema.join(name, "ySigma"), "1-sigma uncertainty on y position", "pixel"
85  );
86  if (uncertainty == FULL_COVARIANCE) {
87  cov.push_back(
88  schema.addField<ErrElement>(
89  schema.join(name, "x_y_Cov"), "uncertainty covariance in x and y", "pixel^2"
90  )
91  );
92  }
93  r._centroidErr = afw::table::CovarianceMatrixKey<ErrElement,2>(sigma, cov);
94  }
95  return r;
96 }
97 
98 namespace {
99 
100 std::vector<std::string> getNameVector() {
102  v.push_back("x");
103  v.push_back("y");
104  return v;
105 }
106 
107 } // anonymous
108 
110  _centroid(s)
111 {
112  static std::vector<std::string> names = getNameVector(); // C++11 TODO: just use initializer list
113  try {
114  _centroidErr = afw::table::CovarianceMatrixKey<ErrElement,2>(s, names);
115  } catch (pex::exceptions::NotFoundError &) {}
116 }
117 
119  CentroidResult r;
120  r.setCentroid(record.get(_centroid));
121  if (_centroidErr.isValid()) {
122  r.setCentroidErr(record.get(_centroidErr));
123  }
124  return r;
125 }
126 
127 void CentroidResultKey::set(afw::table::BaseRecord & record, CentroidResult const & value) const {
128  record.set(_centroid, value.getCentroid());
129  if (_centroidErr.isValid()) {
130  record.set(_centroidErr, value.getCentroidErr());
131  }
132 }
133 
135  std::string const & name,
136  afw::table::SchemaMapper & mapper
137 ) :
138  BaseTransform{name}
139 {
140  // Map the flag through to the output
141  mapper.addMapping(mapper.getInputSchema().find<afw::table::Flag>(name + "_flag").key);
142 
143  // Add keys for the coordinates
144  auto & s = mapper.editOutputSchema();
145  _coordKey = afw::table::CoordKey::addFields(s, name, "ICRS coordinates");
146 
147  // If the centroid has an error key we also include one on the celestial
148  // coordinates; otherwise, it isn't necessary. Note that if we provide for
149  // errors in celestial coordinates, we always need the full covariance.
150  if (CentroidResultKey(mapper.getInputSchema()[name]).getCentroidErr().isValid()) {
153  sigma[0] = s.addField<ErrElement>(s.join(name, "raSigma"), "Uncertainty on RA", "rad");
154  sigma[1] = s.addField<ErrElement>(s.join(name, "decSigma"), "Uncertainty on dec", "rad");
155  cov[0] = s.addField<ErrElement>(s.join(name, "ra_dec_Cov"),
156  "Uncertainty covariance in RA and dec", "rad^2");
157  _coordErrKey = afw::table::CovarianceMatrixKey<ErrElement,2>(sigma, cov);
158  }
159 
160 }
161 
163  afw::table::SourceCatalog const & inputCatalog,
164  afw::table::BaseCatalog & outputCatalog,
165  afw::geom::SkyWcs const & wcs,
166  afw::image::Calib const & calib
167 ) const {
168  checkCatalogSize(inputCatalog, outputCatalog);
169  CentroidResultKey centroidResultKey(inputCatalog.getSchema()[_name]);
170 
171  afw::table::SourceCatalog::const_iterator inSrc = inputCatalog.begin();
172  afw::table::BaseCatalog::iterator outSrc = outputCatalog.begin();
173 
174  for (; inSrc != inputCatalog.end() && outSrc != outputCatalog.end(); ++inSrc, ++outSrc) {
175  CentroidResult centroidResult = centroidResultKey.get(*inSrc);
176 
177  _coordKey.set(*outSrc, wcs.pixelToSky(centroidResult.getCentroid()));
178 
179  if (centroidResultKey.getCentroidErr().isValid()) {
180  CentroidCov centroidCov = centroidResult.getCentroidErr();
181  if (!(std::isnan(centroidCov(0,0)) || std::isnan(centroidCov(1,1)))) {
182  auto transform = wcs.linearizePixelToSky(centroidResult.getCentroid(),
183  afw::geom::radians).getLinear().getMatrix();
184  _coordErrKey.set(*outSrc, (transform * centroidResult.getCentroidErr().cast<double>() *
185  transform.transpose()).cast<ErrElement>());
186  }
187  }
188  }
189 }
190 
191 // Add a key "flag_resetToPeak" if something is wrong with the centroid
192 // Save a key to this algorithm's Centroid, as well as the general failure flag
194  afw::table::Schema & schema,
195  std::string const & name,
196  bool doFootprintCheck,
197  double maxDistFromPeak
198 ) : _doFootprintCheck(doFootprintCheck), _maxDistFromPeak(maxDistFromPeak)
199 {
200  _resetKey = schema.addField<afw::table::Flag>(schema.join(name, "flag_resetToPeak"),
201  "set if CentroidChecker reset the centroid");
202  _failureKey = schema.find<lsst::afw::table::Flag>(schema.join(name, "flag")).key;
203  _xKey = schema.find<CentroidElement>(schema.join(name, "x")).key;
204  _yKey = schema.find<CentroidElement>(schema.join(name, "y")).key;
205 }
206 
207 // Set the centroid to the first footprint if the centroid is eithe more than _maxDistFromPeak
208 // pixels from the centroid, or if it is outside the footprint.
210  afw::table::SourceRecord & record
211 ) const {
212  CentroidElement x = record.get(_xKey);
213  CentroidElement y = record.get(_yKey);
214 
215  if (!_doFootprintCheck && _maxDistFromPeak < 0.0) {
216  return false;
217  }
218  PTR(afw::detection::Footprint) footprint = record.getFootprint();
219  if (!footprint) {
220  throw LSST_EXCEPT(
222  "No Footprint attached to record");
223  }
224  if (footprint->getPeaks().empty()) {
225  throw LSST_EXCEPT(
227  "Footprint has no peaks; cannot verify centroid."
228  );
229  }
230  CentroidElement footX = footprint->getPeaks().front().getFx();
231  CentroidElement footY = footprint->getPeaks().front().getFy();
232  double distsq = (x - footX) * (x - footX) + (y - footY) * (y - footY);
233  if ((_doFootprintCheck && !footprint->contains(lsst::afw::geom::Point2I(lsst::afw::geom::Point2D(x, y)))) ||
234  ((_maxDistFromPeak > 0) && (distsq > _maxDistFromPeak*_maxDistFromPeak))) {
235  record.set(_xKey, footX);
236  record.set(_yKey, footY);
237  record.set(_failureKey, true);
238  record.set(_resetKey, true);
239  return true;
240  }
241  return false;
242 }
243 }}} // lsst::meas::base
Centroid const getCentroid() const
Return a Point object containing the measured x and y.
ErrElement ySigma
1-Sigma uncertainty on y (sqrt of variance)
static PointKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
virtual void set(BaseRecord &record, coord::IcrsCoord const &value) const
virtual void set(afw::table::BaseRecord &record, CentroidResult const &value) const
Set a CentroidResult in the given record.
UncertaintyEnum
An enum used to specify how much uncertainty information measurement algorithms provide.
Definition: constants.h:41
AngleUnit constexpr radians
std::string join(std::string const &a, std::string const &b) const
A reusable struct for centroid measurements.
ErrElement xSigma
1-Sigma uncertainty on x (sqrt of variance)
bool isValid() const
Return True if the centroid key is valid.
The full covariance matrix is provided.
Definition: constants.h:44
std::shared_ptr< Footprint > getFootprint() const
STL namespace.
CentroidElement x
x (column) coordinate of the measured position
#define PTR(...)
SchemaItem< T > find(std::string const &name) const
void setCentroid(Centroid const &centroid)
Set the struct fields from the given Point object.
Key< T > addField(Field< T > const &field, bool doReplace=false)
Field< T >::Value get(Key< T > const &key) const
CentroidChecker(afw::table::Schema &schema, std::string const &name, bool inside=true, double maxDistFromPeak=-1.0)
Check source record for an centroid algorithm called name, noting if the centroid already set by the ...
static CoordKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc)
string name
float ErrElement
Definition: constants.h:53
afw::table::Key< double > sigma
STL class.
CentroidResult()
Constructor; initializes everything to NaN.
T push_back(T... args)
ErrElement x_y_Cov
x,y term in the uncertainty convariance matrix
static CentroidResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc, UncertaintyEnum uncertainty)
Add the appropriate fields to a Schema, and return a CentroidResultKey that manages them...
double x
coord::IcrsCoord pixelToSky(Point2D const &pixel) const
bool operator()(afw::table::SourceRecord &record) const
Set the centroid to the first footprint if the centroid is either more than _dist pixels from the foo...
CentroidTransform(std::string const &name, afw::table::SchemaMapper &mapper)
#define LSST_EXCEPT(type,...)
STL class.
AffineTransform linearizePixelToSky(coord::IcrsCoord const &coord, AngleUnit const &skyUnit) const
Base::const_iterator const_iterator
Matrix const getMatrix() const
Algorithm provides no uncertainy information at all.
Definition: constants.h:42
Abstract base class for all C++ measurement transformations.
Definition: Transform.h:83
virtual void set(BaseRecord &record, Eigen::Matrix< T, N, N > const &value) const
virtual void operator()(afw::table::SourceCatalog const &inputCatalog, afw::table::BaseCatalog &outputCatalog, afw::geom::SkyWcs const &wcs, afw::image::Calib const &calib) const
A FunctorKey for CentroidResult.
T isnan(T... args)
void set(Key< T > const &key, U const &value)
CentroidElement y
y (row) coordinate of the measured position
Eigen::Matrix< ErrElement, 2, 2, Eigen::DontAlign > CentroidCov
Definition: constants.h:57
afw::geom::Point< CentroidElement, 2 > Centroid
Definition: constants.h:56
CentroidResultKey()
Default constructor; instance will not be usuable unless subsequently assigned to.
void checkCatalogSize(afw::table::BaseCatalog const &cat1, afw::table::BaseCatalog const &cat2) const
Ensure that catalogs have the same size.
Definition: Transform.h:102
double CentroidElement
Definition: constants.h:54
virtual CentroidResult get(afw::table::BaseRecord const &record) const
Get a CentroidResult from the given record.
T sqrt(T... args)
m
CentroidCov const getCentroidErr() const
Return the 2x2 symmetric covariance matrix, with rows and columns ordered (x, y)
void setCentroidErr(CentroidCov const &matrix)
Set the struct uncertainty fields from the given matrix, with rows and columns ordered (x...