LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
GaussianCentroid.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 #include "ndarray/eigen.h"
24 #include "lsst/afw/table/Source.h"
26 
27 #include <algorithm>
28 #include "Eigen/Core"
29 #include "Eigen/LU"
30 
31 
32 namespace lsst { namespace meas { namespace base {
33 namespace {
34 #define USE_WEIGHT 0 // zweight is only set, not used. It isn't even set if this is false
35 struct Raster {
36  int x, y; // x, y index of rastered pixel
37  double zo; // pixel's value
38 #if USE_WEIGHT
39  double zweight; // weight for the pixel
40 #endif
41 };
42 
43 struct Fit2d {
44  typedef Eigen::Matrix<double, FittedModel::NPARAM, FittedModel::NPARAM> Matrix;
45  typedef Eigen::Matrix<double, FittedModel::NPARAM, 1> Vector;
46 
47  template<typename PixelT>
48  explicit Fit2d(afw::image::Image<PixelT> const& im) : wide(32), rast(wide*wide) {
49  ncols = im.getWidth();
50  nrows = im.getHeight();
51 
52  dc2zmin = 0.3;
53  dc2zmax = 3.5;
54  tooclose = 3;
55  toosmall = 1.5;
56  nitmax = 15;
57  flamdok = 1.0e-7;
58  ratiomin = -1.0e-7;
59  lost = 3.5;
60  xlamd = 5.0;
61 
62  iter = 0;
63  flamd = 1.0;
64  }
65 
66  int wide; // patch of image being fitted is wide*wide
67  std::vector<Raster> rast; // The pixels being fitted, thought of as a raster scan
68  int nin;
69  int nref;
70  int iter;
71  int tooclose;
72  Vector param;
73  Matrix alpha;
74  Vector beta;
75  Vector elold;
76  Vector elnew;
77  Vector sgold;
78  Vector sgnew;
79  Matrix alold;
80  Matrix alnew;
81  Vector beold;
82  Vector benew;
83  double chisq;
84  double chold;
85  double stold;
86  double chnew;
87  double stnew;
88  double flamd;
89  double flamdok;
90  double xlamd;
91  double ratiomin;
92  int nitmax;
93  double dc2zmin;
94  double dc2zmax;
95  double lost;
96  double toosmall; // minimum acceptable width
97  int ncols; // number of columns in image
98  int nrows; // number of rows in image
99  int status; // status of processing
100 };
101 
102 /************************************************************************************************************/
107 static void dcalc2(Fit2d *fit, // the struct carrying all the fit information
108  Fit2d::Vector const &el, // current parameters of the fit
109  Fit2d::Matrix *alpha, // desired alpha matrix
110  Fit2d::Vector *beta // desired beta vector
111  ) {
112 /*
113  * Pass arguments and initialize
114  */
115  double const a = el[FittedModel::PEAK];
116  double const b = el[FittedModel::SKY];
117  double const x0 = el[FittedModel::X0];
118  double const y0 = el[FittedModel::Y0];
119  double const s = el[FittedModel::SIGMA];
120 
121  if (a <= 0.0) {
122  fit->status = FittedModel::BAD_A;
123  return;
124  } else if (s <= 0.0) {
125  fit->status = FittedModel::BAD_WIDTH;
126  return;
127  } else {
128  fit->status = 0;
129  }
130 
131  beta->setZero();
132  alpha->setZero();
133 
134  fit->nin = 0;
135  fit->chnew = 0.0;
136 /*
137  * Examine all pixels in raster
138  */
139  for (int i = 0, nrast = fit->rast.size(); i != nrast; i++) {
140  double const dx = (fit->rast[i].x - x0)/s;
141  double const dy = (fit->rast[i].y - y0)/s;
142  double const d = hypot(dx, dy);
143 
144  if (d >= fit->dc2zmin && d <= fit->dc2zmax) {
145  double const arg = exp(-d*d/2.0);
146  double const funct = a*arg + b;
147 
148  Fit2d::Vector df;
149  df << arg, 1.0, a*arg*dx/s, a*arg*dy/s, a*arg*(dx*dx/s + dy*dy/s);
150 
151  double const r = fit->rast[i].zo - funct; // residual
152  fit->chnew += r*r;
153  *beta += r*df;
154  *alpha += df*df.transpose(); // outer product
155 
156  fit->nin++;
157  }
158  }
159  int nu = fit->nin - (FittedModel::NPARAM + 1); // number of degrees of freedom
160  if (nu <= 0) {
161  fit->status = FittedModel::TOO_FEW;
162  return;
163  }
164  fit->stnew = sqrt(fit->chnew/nu);
165 }
166 
167 /************************************************************************************************************/
168 /*
169  * From Bevington's CURFIT
170  */
171 static void curf2(Fit2d *fit) {
172 /*
173  * Initialization
174  */
175  fit->status = 0;
176  if (fit->iter == 0) {
177  dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
178  if (fit->status != 0) {
179  return;
180  }
181  fit->nref = fit->nin;
182  fit->stnew = sqrt(fit->chnew/(fit->nref - (FittedModel::NPARAM + 1)));
183  }
184 /*
185  * Save Current Parameters
186  */
187  fit->chold = fit->chnew;
188  fit->stold = fit->stnew;
189  fit->elold = fit->elnew;
190  fit->sgold = fit->sgnew;
191  fit->beold = fit->benew;
192  fit->alold = fit->alnew;
193 /*
194  * Previous Call To DCALC Used To Fill Current
195  */
196  int const NPLIM = 4;
197  for (int poor = 0; poor != NPLIM; ++poor) {
198  for (int j = 0; j != FittedModel::NPARAM; ++j) {
199  if (fit->alnew(j, j) == 0.0) {
200  fit->status = FittedModel::DIAGONAL;
201  return;
202  }
203  for (int k = 0; k != FittedModel::NPARAM; ++k) {
204  fit->alpha(j, k) = fit->alnew(j, k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
205  }
206  fit->alpha(j, j) = 1.0 + fit->flamd;
207  }
208 /*
209  * Inversion.
210  */
211 #if 0
212  fit->alpha.computeInverse(); // has no way to check if inverse succeeded
213 #else
214  Eigen::FullPivLU<Fit2d::Matrix> alphaLU(fit->alpha);
215  if (!alphaLU.isInvertible()) {
216  fit->status = -1;
217  return;
218  }
219  fit->alpha = alphaLU.inverse();
220 #endif
221 
222 /*
223  * New Elements
224  */
225  for (int j = 0; j != FittedModel::NPARAM; ++j) {
226  for (int k = 0; k != FittedModel::NPARAM; ++k) {
227  fit->elnew[j] += fit->benew[k]*fit->alpha(j,k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
228  }
229  }
230 /*
231  * Compute Current Chi-Squared And Next ALPHA+BETA
232  */
233  dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
234  if (fit->status == FittedModel::TOO_FEW) {
235  return;
236  }
237  fit->stnew = sqrt(fit->chnew/(fit->nref - (FittedModel::NPARAM + 1)));
238 
239  for (int j = 0; j != FittedModel::NPARAM; ++j) {
240  fit->sgnew[j] = fit->stnew*sqrt(fabs(fit->alpha(j, j)/fit->alnew(j, j)));
241  }
242 /*
243  * Quick Return If Solution Got Better
244  */
245  if (fit->status == 0.0 && fit->stnew <= fit->stold) {
246  fit->flamd = fit->flamd/fit->xlamd;
247  return;
248  }
249 /*
250  * Undo Solution And Try Again
251  */
252  fit->flamd = 3.0*fit->flamd;
253  fit->chnew = fit->chold;
254  fit->stnew = fit->stold;
255  fit->elnew = fit->elold;
256  fit->sgnew = fit->sgold;
257  fit->benew = fit->beold;
258  fit->alnew = fit->alold;
259  }
260 }
261 
262 /************************************************************************************************************/
263 /*
264  * Test of convergence or fatal errors
265  */
266 static void cond2(Fit2d *fit) {
267 /*
268  * Ignore CURF errors for these conditions
269  */
270  if (fit->iter <= 3) {
271  fit->status = 0;
272  return;
273  }
274  if (fit->flamd < fit->flamdok) {
275  fit->status = FittedModel::ALMOST;
276  return;
277  }
278 /*
279  * Catch Fatal Errors
280  */
281  if (fit->status < 0) {
282  return;
283  }
284  if (fit->nin < FittedModel::NPARAM + 1) {
285  fit->status = FittedModel::TOO_FEW;
286  return;
287  }
288  if (fit->chnew <= 0.0) {
289  fit->status = FittedModel::CHI_SQUARED;
290  return;
291  }
292  if (fit->elnew[FittedModel::X0] < 0.0 || fit->elnew[FittedModel::X0] > fit->ncols ||
293  fit->elnew[FittedModel::Y0] < 0.0 || fit->elnew[FittedModel::Y0] > fit->nrows) {
294  fit->status = FittedModel::RANGE;
295  return;
296  }
297  if (fit->elnew[FittedModel::SIGMA] < 0.0) {
298  fit->status = FittedModel::BAD_WIDTH;
299  return;
300  }
301 
302  double const ex = fabs(fit->param[FittedModel::X0] - fit->elnew[FittedModel::X0]);
303  double const ey = fabs(fit->param[FittedModel::Y0] - fit->elnew[FittedModel::Y0]);
304  if (ex > fit->lost || ey > fit->lost) {
305  fit->status = FittedModel::LOST;
306  return;
307  }
308 /*
309  * Test for convergence
310  */
311  double const ratio = (fit->stnew - fit->stold)/fit->stnew;
312  if (ratio > fit->ratiomin) {
313  fit->status = (fit->flamd < 0.001) ? FittedModel::CONVERGE : FittedModel::POOR;
314  } else if (fit->iter > fit->nitmax) {
315  fit->status = FittedModel::ITERATE;
316  } else {
317  fit->status = 0;
318  }
319 }
320 
321 /************************************************************************************************************/
322 /*
323  * First guess for 2-D Gaussian
324  */
325 template<typename PixelT>
326 static void fg2(afw::image::Image<PixelT> const& im,
327  double x0, double y0,
328  Fit2d *fit
329  ) {
330 /*
331  * Sanity Check
332  */
333  int ix0 = static_cast<int>(x0 + 0.5);
334  int iy0 = static_cast<int>(y0 + 0.5);
335  if(ix0 < fit->tooclose || im.getWidth() - ix0 < fit->tooclose ||
336  iy0 < fit->tooclose || im.getHeight() - iy0 < fit->tooclose) {
337  fit->status = FittedModel::BAD_GUESS;
338  return;
339  }
340  int jx0 = ix0;
341  int jy0 = iy0;
342  double peak = im(jx0, jy0);
343 /*
344  * Extract interesting portion
345  */
346  double const w = fit->wide/2;
347  int xl = static_cast<int>(ix0 - w + 0.5);
348  if (xl < 0) {
349  xl = 0;
350  }
351  int xh = static_cast<int>(xl + 2*w + 0.5);
352  if (xh > im.getWidth()) {
353  xh = im.getWidth();
354  }
355  int yl = static_cast<int>(iy0 - w + 0.5);
356  if (yl < 0) {
357  yl = 0;
358  }
359  int yh = static_cast<int>(yl + 2*w + 0.5);
360  if (yh > im.getHeight()) {
361  yh = im.getHeight();
362  }
363 
364  double sky = im(xl, yl);
365  int put = 0;
366  for (int y = yl; y != yh; ++y) {
367  for (int x = xl; x != xh; ++x) {
368  fit->rast[put].x = x;
369  fit->rast[put].y = y;
370  fit->rast[put].zo = im(x, y);
371 #if USE_WEIGHT
372  fit->rast[put].zweight = 1.0;
373 #endif
374  if (im(x, y) < sky) {
375  sky = im(x, y);
376  }
377  double const ex = x - ix0;
378  double const ey = y - iy0;
379  double const er = hypot(ex, ey);
380  if (er <= fit->lost) {
381  if (im(x, y) > peak) {
382  jx0 = x;
383  jy0 = y;
384  peak = im(x, y);
385  }
386  }
387  put++;
388  }
389  }
390  fit->rast.resize(put);
391  ix0 = jx0;
392  iy0 = jy0;
393 /*
394  * Look For FWHM
395  */
396  double xmin = xl;
397  double xmax = xh - 1;
398  double ymin = yl;
399  double ymax = yh - 1;
400  double const test = 0.5*(im(ix0, iy0) + sky); // pixel value of half-maximum above sky
401  for (int x = ix0; x < xh - 1; ++x) {
402  if (im(x + 1, iy0) <= test) {
403  double a = test - im(x, iy0);
404  double b = im(x + 1, iy0) - im(x, iy0);
405 
406  xmax = x + ((b == 0.0) ? 0.5 : a/b);
407  break;
408  }
409  }
410  for (int x = ix0; x > 0; --x) {
411  if (im(x - 1, iy0) <= test) {
412  double a = test - im(x, iy0);
413  double b = im(x - 1, iy0) - im(x, iy0);
414 
415  xmin = x - ((b == 0.0) ? 0.5 : a/b);
416  break;
417  }
418  }
419  for (int y = iy0; y < yh - 1; ++y) {
420  if (im(ix0, y + 1) <= test) {
421  double a = test - im(ix0, y);
422  double b = im(ix0, y + 1) - im(ix0, y);
423 
424  ymax = y + ((b == 0.0) ? 0.5 : a/b);
425  break;
426  }
427  }
428  for (int y = iy0; y > 0; --y) {
429  if (im(ix0, y - 1) <= test) {
430  double a = test - im(ix0, y);
431  double b = im(ix0, y - 1) - im(ix0, y);
432 
433  ymin = y - ((b == 0.0) ? 0.5 : a/b);
434  break;
435  }
436  }
437 /*
438  * Assemble the fitting vector
439  */
440  fit->param[FittedModel::PEAK] = im(ix0, iy0) - sky;
441  fit->param[FittedModel::SKY] = sky;
442  fit->param[FittedModel::X0] = x0;
443  fit->param[FittedModel::Y0] = y0;
444  fit->param[FittedModel::SIGMA] = 0.5*((xmax - xmin)+(ymax - ymin))/2.354;
445  if (fit->param[FittedModel::SIGMA] < fit->toosmall) {
446  fit->param[FittedModel::SIGMA] = fit->toosmall;
447  }
448  fit->elnew = fit->param;
449 
450  fit->status = 0;
451 }
452 
453 /************************************************************************************************************/
457 template<typename PixelT>
458 FittedModel twodg(afw::image::Image<PixelT> const& im,
459  double x0,
460  double y0
461  ) {
462 /*
463  * Initialize the fitting structure
464  */
465  Fit2d fit(im);
466 /*
467  * Initialization
468  */
469  fg2(im, x0, y0, &fit);
470  if (fit.status != 0) {
471  std::vector<double> params(FittedModel::NPARAM);
472  std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
473 
474  return FittedModel(fit.status, params);
475  }
476 /*
477  * Find best-fit model
478  */
479  for (fit.iter = 0; fit.status == 0; ++fit.iter) {
480  curf2(&fit);
481  cond2(&fit);
482  }
483 
484  std::vector<double> params(FittedModel::NPARAM);
485  std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
486 
487  return FittedModel(fit.status, params, fit.iter, fit.flamd, fit.chnew);
488 }
489 //
490 // Explicit instantiations
491 //
492 #define MAKE_TWODG(IMAGE_T) \
493  template FittedModel twodg(IMAGE_T const& im, double x0, double y0)
494 
495 MAKE_TWODG(afw::image::Image<float>);
496 MAKE_TWODG(afw::image::Image<double>);
497 MAKE_TWODG(afw::image::Image<int>);
498 
499 std::array<FlagDefinition,GaussianCentroidAlgorithm::N_FLAGS> const & getFlagDefinitions() {
500  static std::array<FlagDefinition,GaussianCentroidAlgorithm::N_FLAGS> const flagDefs = {{
501  {"flag", "general failure flag, set if anything went wrong"},
502  {"flag_noPeak", "Fitted Centroid has a negative peak"}
503  }};
504  return flagDefs;
505 }
506 
507 } // end anonymous namespace
508 
510  Control const & ctrl,
511  std::string const & name,
513 ) : _ctrl(ctrl),
514  _centroidKey(
515  CentroidResultKey::addFields(schema, name, "centroid from Gaussian Centroid algorithm", NO_UNCERTAINTY)
516  ),
517  _flagHandler(FlagHandler::addFields(schema, name,
518  getFlagDefinitions().begin(), getFlagDefinitions().end())),
519  _centroidExtractor(schema, name, true),
520  _centroidChecker(schema, name, ctrl.doFootprintCheck, ctrl.maxDistToPeak)
521 {
522 }
523 
524 
525 template<typename PixelT>
527  double x,
528  double y
529 ) {
530  base::FittedModel fit = base::twodg(image, x, y);
531  double const xCen = fit.params[base::FittedModel::X0];
532  double const yCen = fit.params[base::FittedModel::Y0];
533  return afw::geom::Point2D(xCen, yCen);
534 }
535 
536 
538  afw::table::SourceRecord & measRecord,
539  afw::image::Exposure<float> const & exposure
540 ) const {
541  // get our current best guess about the centroid: either a centroider measurement or peak.
542  afw::geom::Point2D center = _centroidExtractor(measRecord, _flagHandler);
543  CentroidResult result;
544  result.x = center.getX();
545  result.y = center.getY();
546  measRecord.set(_centroidKey, result); // better than NaN
547  typedef afw::image::Image<float> ImageT;
548  ImageT const& image = *exposure.getMaskedImage().getImage();
549 
550  int x = static_cast<int>(center.getX() + 0.5);
551  int y = static_cast<int>(center.getY() + 0.5);
552 
553  x -= image.getX0(); // work in image Pixel coordinates
554  y -= image.getY0();
555 
556  FittedModel fit = twodg(image, x, y); // here's the fitter
557  if (fit.params[FittedModel::PEAK] <= 0) {
558  throw LSST_EXCEPT(
561  NO_PEAK
562  );
563  }
564  result.x = lsst::afw::image::indexToPosition(image.getX0()) + fit.params[FittedModel::X0];
565  result.y = lsst::afw::image::indexToPosition(image.getY0()) + fit.params[FittedModel::Y0];
566  _flagHandler.setValue(measRecord, FAILURE, false); // if we had a suspect flag, we'd set that instead
567  measRecord.set(_centroidKey, result);
568  _centroidChecker(measRecord);
569 }
570 
571 
573  _flagHandler.handleFailure(measRecord, error);
574 }
575 
576 //
577 // Explicit instantiations
578 //
579 #define MAKE_FIT_CENTROID(IMAGE_T) \
580  template afw::geom::Point2D GaussianCentroidAlgorithm::fitCentroid(IMAGE_T const &, double, double)
581 
582 MAKE_FIT_CENTROID(afw::image::Image<float>);
583 MAKE_FIT_CENTROID(afw::image::Image<double>);
584 
586  Control const & ctrl,
587  std::string const & name,
588  afw::table::SchemaMapper & mapper
589 ) :
590  CentroidTransform{name, mapper}
591 {
592  for (auto flag = getFlagDefinitions().begin() + 1; flag < getFlagDefinitions().end(); ++flag) {
593  mapper.addMapping(mapper.getInputSchema().find<afw::table::Flag>(
594  mapper.getInputSchema().join(name, flag->name)).key);
595  }
596 }
597 
598 }}} // namespace lsst::meas::base
599 
600 
int y
int iter
Defines the fields and offsets for a table.
Definition: Schema.h:44
int tooclose
GaussianCentroidAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
int nref
int ncols
std::vector< Raster > rast
double xlamd
Matrix alold
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:54
table::Key< std::string > name
Definition: ApCorrMap.cc:71
Vector beold
virtual void fail(afw::table::SourceRecord &measRecord, MeasurementError *error=NULL) const
Handle an exception thrown by the current algorithm by setting flags in the given record...
afw::table::Schema schema
Definition: GaussianPsf.cc:41
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:19
A reusable struct for centroid measurements.
Vector elold
Vector sgold
static afw::geom::Point2D fitCentroid(afw::image::Image< PixelT > const &im, double x0, double y0)
Compute centroids with 2-D Gaussian fitter.
CentroidElement x
x (column) coordinate of the measured position
ImagePtr getImage(bool const noThrow=false) const
Return a (Ptr to) the MaskedImage&#39;s image.
Definition: MaskedImage.h:875
std::array< FlagDefinition, BlendednessAlgorithm::N_FLAGS > const & getFlagDefinitions()
Definition: Blendedness.cc:215
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Definition: exceptions.h:48
Vector benew
int nrows
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
Definition: BaseRecord.h:145
int const x0
Definition: saturated.cc:45
FlagDefinition getDefinition(std::size_t i) const
Return the FlagDefinition object that corresponds to a particular enum value.
Definition: FlagHandler.h:172
Matrix alpha
Vector param
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
Vector sgnew
double stnew
def error
Definition: log.py:103
Utility class for handling flag fields that indicate the failure modes of an algorithm.
Definition: FlagHandler.h:73
Matrix alnew
double toosmall
MaskedImageT getMaskedImage()
Return the MaskedImage.
Definition: Exposure.h:153
double w
Definition: CoaddPsf.cc:57
std::vector< double > params
double dc2zmin
double flamd
A C++ control class to handle GaussianCentroidAlgorithm&#39;s configuration.
int wide
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Definition: saturated.cc:47
double dc2zmax
double x
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
Set the flag field corresponding to the given enum value.
Definition: FlagHandler.h:188
double chold
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
double stold
int nin
double chisq
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
GaussianCentroidTransform(Control const &ctrl, std::string const &name, afw::table::SchemaMapper &mapper)
double flamdok
int nitmax
double zo
#define MAKE_TWODG(IMAGE_T)
int status
double chnew
Algorithm provides no uncertainy information at all.
Definition: constants.h:42
Vector elnew
A FunctorKey for CentroidResult.
afw::table::Key< double > b
CentroidElement y
y (row) coordinate of the measured position
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=NULL) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
Definition: FlagHandler.cc:77
Point< double, 2 > Point2D
Definition: Point.h:288
#define MAKE_FIT_CENTROID(IMAGE_T)
Record class that contains measurements made on a single exposure.
Definition: Source.h:80
double ratiomin
int const y0
Definition: saturated.cc:45
double lost
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:416
Base for centroid measurement transformations.
Vector beta
Key< T > addMapping(Key< T > const &inputKey, bool doReplace=false)
Add a new field to the output Schema that is a copy of a field in the input Schema.