23 #include "ndarray/eigen.h"
24 #include "lsst/afw/table/Source.h"
32 namespace lsst {
namespace meas {
namespace base {
34 FlagDefinitionList flagDefinitions;
41 return flagDefinitions;
45 #define USE_WEIGHT 0 // zweight is only set, not used. It isn't even set if this is false
55 typedef Eigen::Matrix<double, FittedModel::NPARAM, FittedModel::NPARAM> Matrix;
56 typedef Eigen::Matrix<double, FittedModel::NPARAM, 1> Vector;
58 template<
typename PixelT>
59 explicit Fit2d(afw::image::Image<PixelT>
const& im) :
wide(32),
rast(
wide*
wide) {
60 ncols = im.getWidth();
61 nrows = im.getHeight();
118 static void dcalc2(Fit2d *fit,
119 Fit2d::Vector
const &el,
120 Fit2d::Matrix *
alpha,
135 }
else if (s <= 0.0) {
150 for (
int i = 0, nrast = fit->rast.size(); i != nrast; i++) {
151 double const dx = (fit->rast[i].x - x0)/s;
152 double const dy = (fit->rast[i].y - y0)/s;
153 double const d = hypot(dx, dy);
155 if (d >= fit->dc2zmin && d <= fit->
dc2zmax) {
156 double const arg = exp(-d*d/2.0);
157 double const funct = a*arg + b;
160 df << arg, 1.0, a*arg*dx/s, a*arg*dy/s, a*arg*(dx*dx/s + dy*dy/s);
162 double const r = fit->rast[i].zo - funct;
165 *alpha += df*df.transpose();
175 fit->stnew = sqrt(fit->chnew/nu);
182 static void curf2(Fit2d *fit) {
187 if (fit->iter == 0) {
188 dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
189 if (fit->status != 0) {
192 fit->nref = fit->nin;
198 fit->chold = fit->chnew;
199 fit->stold = fit->stnew;
200 fit->elold = fit->elnew;
201 fit->sgold = fit->sgnew;
202 fit->beold = fit->benew;
203 fit->alold = fit->alnew;
208 for (
int poor = 0; poor != NPLIM; ++poor) {
210 if (fit->alnew(j, j) == 0.0) {
215 fit->alpha(j, k) = fit->alnew(j, k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
217 fit->alpha(j, j) = 1.0 + fit->flamd;
223 fit->alpha.computeInverse();
225 Eigen::FullPivLU<Fit2d::Matrix> alphaLU(fit->alpha);
226 if (!alphaLU.isInvertible()) {
230 fit->alpha = alphaLU.inverse();
238 fit->elnew[j] += fit->benew[k]*fit->alpha(j,k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
244 dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
251 fit->sgnew[j] = fit->stnew*sqrt(fabs(fit->alpha(j, j)/fit->alnew(j, j)));
256 if (fit->status == 0.0 && fit->stnew <= fit->stold) {
257 fit->flamd = fit->flamd/fit->xlamd;
263 fit->flamd = 3.0*fit->flamd;
264 fit->chnew = fit->chold;
265 fit->stnew = fit->stold;
266 fit->elnew = fit->elold;
267 fit->sgnew = fit->sgold;
268 fit->benew = fit->beold;
269 fit->alnew = fit->alold;
277 static void cond2(Fit2d *fit) {
281 if (fit->iter <= 3) {
285 if (fit->flamd < fit->flamdok) {
292 if (fit->status < 0) {
299 if (fit->chnew <= 0.0) {
315 if (ex > fit->lost || ey > fit->lost) {
322 double const ratio = (fit->stnew - fit->stold)/fit->stnew;
323 if (ratio > fit->ratiomin) {
325 }
else if (fit->iter > fit->nitmax) {
336 template<
typename PixelT>
337 static void fg2(afw::image::Image<PixelT>
const& im,
338 double x0,
double y0,
344 int ix0 =
static_cast<int>(x0 + 0.5);
345 int iy0 =
static_cast<int>(y0 + 0.5);
346 if(ix0 < fit->
tooclose || im.getWidth() - ix0 < fit->tooclose ||
347 iy0 < fit->tooclose || im.getHeight() - iy0 < fit->tooclose) {
353 double peak = im(jx0, jy0);
357 double const w = fit->wide/2;
358 int xl =
static_cast<int>(ix0 - w + 0.5);
362 int xh =
static_cast<int>(xl + 2*w + 0.5);
363 if (xh > im.getWidth()) {
366 int yl =
static_cast<int>(iy0 - w + 0.5);
370 int yh =
static_cast<int>(yl + 2*w + 0.5);
371 if (yh > im.getHeight()) {
375 double sky = im(xl, yl);
377 for (
int y = yl;
y != yh; ++
y) {
378 for (
int x = xl;
x != xh; ++
x) {
379 fit->rast[put].x =
x;
380 fit->rast[put].y =
y;
381 fit->rast[put].zo = im(
x,
y);
383 fit->rast[put].zweight = 1.0;
385 if (im(
x,
y) < sky) {
388 double const ex =
x - ix0;
389 double const ey =
y - iy0;
390 double const er = hypot(ex, ey);
391 if (er <= fit->
lost) {
392 if (im(
x,
y) > peak) {
401 fit->rast.resize(put);
408 double xmax = xh - 1;
410 double ymax = yh - 1;
411 double const test = 0.5*(im(ix0, iy0) + sky);
412 for (
int x = ix0;
x < xh - 1; ++
x) {
413 if (im(
x + 1, iy0) <= test) {
414 double a = test - im(
x, iy0);
415 double b = im(
x + 1, iy0) - im(
x, iy0);
417 xmax =
x + ((b == 0.0) ? 0.5 : a/b);
421 for (
int x = ix0;
x > 0; --
x) {
422 if (im(
x - 1, iy0) <= test) {
423 double a = test - im(
x, iy0);
424 double b = im(
x - 1, iy0) - im(
x, iy0);
426 xmin =
x - ((b == 0.0) ? 0.5 : a/b);
430 for (
int y = iy0;
y < yh - 1; ++
y) {
431 if (im(ix0,
y + 1) <= test) {
432 double a = test - im(ix0,
y);
433 double b = im(ix0,
y + 1) - im(ix0,
y);
435 ymax =
y + ((b == 0.0) ? 0.5 : a/b);
439 for (
int y = iy0;
y > 0; --
y) {
440 if (im(ix0,
y - 1) <= test) {
441 double a = test - im(ix0,
y);
442 double b = im(ix0,
y - 1) - im(ix0,
y);
444 ymin =
y - ((b == 0.0) ? 0.5 : a/b);
459 fit->elnew = fit->param;
468 template<
typename PixelT>
469 FittedModel twodg(afw::image::Image<PixelT>
const& im,
480 fg2(im, x0, y0, &fit);
481 if (fit.status != 0) {
483 std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
485 return FittedModel(fit.status, params);
490 for (fit.iter = 0; fit.status == 0; ++fit.iter) {
496 std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
498 return FittedModel(fit.status, params, fit.iter, fit.flamd, fit.chnew);
503 #define MAKE_TWODG(IMAGE_T) \
504 template FittedModel twodg(IMAGE_T const& im, double x0, double y0)
515 std::string
const & name,
516 afw::table::Schema & schema
522 getFlagDefinitions())),
524 _centroidChecker(schema, name, ctrl.doFootprintCheck, ctrl.maxDistToPeak)
529 template<
typename PixelT>
537 return afw::geom::Point2D(xCen, yCen);
542 afw::table::SourceRecord & measRecord,
543 afw::image::Exposure<float>
const & exposure
546 afw::geom::Point2D center = _centroidExtractor(measRecord, _flagHandler);
548 result.
x = center.getX();
549 result.
y = center.getY();
550 measRecord.set(_centroidKey, result);
551 typedef afw::image::Image<float> ImageT;
552 ImageT
const& image = *exposure.getMaskedImage().getImage();
554 int x =
static_cast<int>(center.getX() + 0.5);
555 int y =
static_cast<int>(center.getY() + 0.5);
571 measRecord.set(_centroidKey, result);
572 _centroidChecker(measRecord);
583 #define MAKE_FIT_CENTROID(IMAGE_T) \
584 template afw::geom::Point2D GaussianCentroidAlgorithm::fitCentroid(IMAGE_T const &, double, double)
591 std::string
const & name,
592 afw::table::SchemaMapper & mapper
599 if (mapper.getInputSchema().getNames().count(
600 mapper.getInputSchema().join(name, flag.
name)) == 0)
continue;
601 afw::table::Key<afw::table::Flag> key = mapper.getInputSchema().find<afw::table::Flag>(
602 name +
"_" + flag.
name).key;
603 mapper.addMapping(key);
GaussianCentroidAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...
A reusable struct for centroid measurements.
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
Exception to be thrown when a measurement algorithm experiences a known failure mode.
static FlagDefinition const FAILURE
Utility class for handling flag fields that indicate the failure modes of an algorithm.
std::vector< double > params
std::vector< Raster > rast
static FlagDefinitionList const & getFlagDefinitions()
A C++ control class to handle GaussianCentroidAlgorithm's configuration.
_centroidExtractor(schema, name)
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
Set the flag field corresponding to the given flag index.
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
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...
Algorithm provides no uncertainy information at all.
A FunctorKey for CentroidResult.
#define MAKE_TWODG(IMAGE_T)
CentroidElement y
y (row) coordinate of the measured position
static FlagDefinition const NO_PEAK
vector-type utility class to build a collection of FlagDefinitions
std::size_t size() const
return the current size (number of defined elements) of the collection
#define MAKE_FIT_CENTROID(IMAGE_T)