32 namespace lsst {
namespace meas {
namespace base {
34 #define USE_WEIGHT 0 // zweight is only set, not used. It isn't even set if this is false
44 typedef Eigen::Matrix<double, FittedModel::NPARAM, FittedModel::NPARAM> Matrix;
45 typedef Eigen::Matrix<double, FittedModel::NPARAM, 1> Vector;
47 template<
typename PixelT>
48 explicit Fit2d(afw::image::Image<PixelT>
const& im) :
wide(32),
rast(*
new std::vector<Raster>(
wide*
wide)) {
49 ncols = im.getWidth();
50 nrows = im.getHeight();
110 static void dcalc2(Fit2d *fit,
111 Fit2d::Vector
const &el,
112 Fit2d::Matrix *
alpha,
127 }
else if (s <= 0.0) {
142 for (
int i = 0, nrast = fit->rast.size(); i != nrast; i++) {
143 double const dx = (fit->rast[i].x -
x0)/s;
144 double const dy = (fit->rast[i].y -
y0)/s;
145 double const d = hypot(dx, dy);
147 if (d >= fit->dc2zmin && d <= fit->
dc2zmax) {
148 double const arg = exp(-d*d/2.0);
149 double const funct = a*arg +
b;
152 df << arg, 1.0, a*arg*dx/s, a*arg*dy/s, a*arg*(dx*dx/s + dy*dy/s);
154 double const r = fit->rast[i].zo - funct;
157 *alpha += df*df.transpose();
167 fit->stnew = sqrt(fit->chnew/nu);
174 static void curf2(Fit2d *fit) {
179 if (fit->iter == 0) {
180 dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
181 if (fit->status != 0) {
184 fit->nref = fit->nin;
190 fit->chold = fit->chnew;
191 fit->stold = fit->stnew;
192 fit->elold = fit->elnew;
193 fit->sgold = fit->sgnew;
194 fit->beold = fit->benew;
195 fit->alold = fit->alnew;
200 for (
int poor = 0; poor != NPLIM; ++poor) {
202 if (fit->alnew(j, j) == 0.0) {
207 fit->alpha(j, k) = fit->alnew(j, k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
209 fit->alpha(j, j) = 1.0 + fit->flamd;
215 fit->alpha.computeInverse();
217 Eigen::FullPivLU<Fit2d::Matrix> alphaLU(fit->alpha);
218 if (!alphaLU.isInvertible()) {
222 fit->alpha = alphaLU.inverse();
230 fit->elnew[j] += fit->benew[k]*fit->alpha(j,k)/sqrt(fit->alnew(j, j)*fit->alnew(k, k));
236 dcalc2(fit, fit->elnew, &fit->alnew, &fit->benew);
243 fit->sgnew[j] = fit->stnew*sqrt(fabs(fit->alpha(j, j)/fit->alnew(j, j)));
248 if (fit->status == 0.0 && fit->stnew <= fit->stold) {
249 fit->flamd = fit->flamd/fit->xlamd;
255 fit->flamd = 3.0*fit->flamd;
256 fit->chnew = fit->chold;
257 fit->stnew = fit->stold;
258 fit->elnew = fit->elold;
259 fit->sgnew = fit->sgold;
260 fit->benew = fit->beold;
261 fit->alnew = fit->alold;
269 static void cond2(Fit2d *fit) {
273 if (fit->iter <= 3) {
277 if (fit->flamd < fit->flamdok) {
284 if (fit->status < 0) {
291 if (fit->chnew <= 0.0) {
307 if (ex > fit->lost || ey > fit->lost) {
314 double const ratio = (fit->stnew - fit->stold)/fit->stnew;
315 if (ratio > fit->ratiomin) {
317 }
else if (fit->iter > fit->nitmax) {
328 template<
typename PixelT>
329 static void fg2(afw::image::Image<PixelT>
const& im,
330 double x0,
double y0,
336 int ix0 =
static_cast<int>(x0 + 0.5);
337 int iy0 =
static_cast<int>(y0 + 0.5);
338 if(ix0 < fit->
tooclose || im.getWidth() - ix0 < fit->tooclose ||
339 iy0 < fit->tooclose || im.getHeight() - iy0 < fit->tooclose) {
345 double peak = im(jx0, jy0);
349 double const w = fit->wide/2;
350 int xl =
static_cast<int>(ix0 - w + 0.5);
354 int xh =
static_cast<int>(xl + 2*w + 0.5);
355 if (xh > im.getWidth()) {
358 int yl =
static_cast<int>(iy0 - w + 0.5);
362 int yh =
static_cast<int>(yl + 2*w + 0.5);
363 if (yh > im.getHeight()) {
367 double sky = im(xl, yl);
369 for (
int y = yl;
y != yh; ++
y) {
370 for (
int x = xl;
x != xh; ++
x) {
371 fit->rast[put].x =
x;
372 fit->rast[put].y =
y;
373 fit->rast[put].zo = im(
x,
y);
375 fit->rast[put].zweight = 1.0;
377 if (im(
x,
y) < sky) {
380 double const ex =
x - ix0;
381 double const ey =
y - iy0;
382 double const er = hypot(ex, ey);
383 if (er <= fit->
lost) {
384 if (im(
x,
y) > peak) {
393 fit->rast.resize(put);
400 double xmax = xh - 1;
402 double ymax = yh - 1;
403 double const test = 0.5*(im(ix0, iy0) + sky);
404 for (
int x = ix0;
x < xh - 1; ++
x) {
405 if (im(
x + 1, iy0) <= test) {
406 double a = test - im(
x, iy0);
407 double b = im(
x + 1, iy0) - im(
x, iy0);
409 xmax =
x + ((b == 0.0) ? 0.5 : a/
b);
413 for (
int x = ix0;
x > 0; --
x) {
414 if (im(
x - 1, iy0) <= test) {
415 double a = test - im(
x, iy0);
416 double b = im(
x - 1, iy0) - im(
x, iy0);
418 xmin =
x - ((b == 0.0) ? 0.5 : a/
b);
422 for (
int y = iy0;
y < yh - 1; ++
y) {
423 if (im(ix0,
y + 1) <= test) {
424 double a = test - im(ix0,
y);
425 double b = im(ix0,
y + 1) - im(ix0,
y);
427 ymax =
y + ((b == 0.0) ? 0.5 : a/
b);
431 for (
int y = iy0;
y > 0; --
y) {
432 if (im(ix0,
y - 1) <= test) {
433 double a = test - im(ix0,
y);
434 double b = im(ix0,
y - 1) - im(ix0,
y);
436 ymin =
y - ((b == 0.0) ? 0.5 : a/
b);
451 fit->elnew = fit->param;
460 template<
typename PixelT>
461 FittedModel twodg(afw::image::Image<PixelT>
const& im,
472 fg2(im, x0, y0, &fit);
473 if (fit.status != 0) {
475 std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
477 return FittedModel(fit.status, params);
482 for (fit.iter = 0; fit.status == 0; ++fit.iter) {
488 std::copy(&fit.elnew[0], &fit.elnew[0] + fit.elnew.size(), params.begin());
490 return FittedModel(fit.status, params, fit.iter, fit.flamd, fit.chnew);
495 #define MAKE_TWODG(IMAGE_T) \
496 template FittedModel twodg(IMAGE_T const& im, double x0, double y0)
502 boost::array<FlagDefinition,GaussianCentroidAlgorithm::N_FLAGS>
const & getFlagDefinitions() {
503 static boost::array<FlagDefinition,GaussianCentroidAlgorithm::N_FLAGS>
const flagDefs = {{
504 {
"flag",
"general failure flag, set if anything went wrong"},
505 {
"flag_noPeak",
"Fitted Centroid has a negative peak"}
514 std::string
const &
name,
520 _centroidExtractor(schema, name, true)
523 getFlagDefinitions().begin(), getFlagDefinitions().end());
527 template<
typename PixelT>
546 result.
x = center.getX();
547 result.
y = center.getY();
552 int x =
static_cast<int>(center.getX() + 0.5);
553 int y =
static_cast<int>(center.getY() + 0.5);
580 #define MAKE_FIT_CENTROID(IMAGE_T) \
581 template afw::geom::Point2D GaussianCentroidAlgorithm::fitCentroid(IMAGE_T const &, double, double)
588 std::string
const &
name,
593 for (
auto flag = getFlagDefinitions().begin() + 1; flag < getFlagDefinitions().end(); ++flag) {
594 mapper.
addMapping(mapper.getInputSchema().find<afw::table::Flag>(
595 mapper.getInputSchema().join(
name, flag->name)).key);
Defines the fields and offsets for a table.
GaussianCentroidAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
double indexToPosition(double ind)
Convert image index to image position.
table::Key< std::string > name
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.
Eigen matrix objects that present a view into an ndarray::Array.
virtual void fail(afw::table::SourceRecord &measRecord, MeasurementError *error=NULL) const
std::vector< Raster > & rast
afw::table::Schema schema
A mapping between the keys of two Schemas, used to copy data between them.
A reusable struct for centroid measurements.
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Point< double, 2 > Point2D
static afw::geom::Point2D fitCentroid(afw::image::Image< PixelT > const &im, double x0, double y0)
x0, y0 is an initial guess for position, column
CentroidElement x
x (column) coordinate of the measured position
ImagePtr getImage(bool const noThrow=false) const
Return a (Ptr to) the MaskedImage's image.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
table::Key< table::Array< Kernel::Pixel > > image
FlagDefinition getDefinition(int i) const
MaskedImageT getMaskedImage()
Return the MaskedImage.
std::vector< double > params
A C++ control class to handle GaussianCentroidAlgorithm's configuration.
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
void setValue(afw::table::BaseRecord &record, int i, bool value) const
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
#define LSST_EXCEPT(type,...)
#define MAKE_TWODG(IMAGE_T)
Algorithm provides no uncertainy information at all.
A FunctorKey for CentroidResult.
afw::table::Key< double > b
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
CentroidElement y
y (row) coordinate of the measured position
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=NULL) const
#define MAKE_FIT_CENTROID(IMAGE_T)
Record class that contains measurements made on a single exposure.
A class to represent a 2-dimensional array of pixels.
CentroidResultKey _centroidKey
static FlagHandler addFields(afw::table::Schema &schema, std::string const &prefix, FlagDefinition const *begin, FlagDefinition const *end)
SafeCentroidExtractor _centroidExtractor