LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
SdssCentroid.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 <iostream>
24#include <cmath>
25#include <numeric>
26#include "ndarray/eigen.h"
27#include "lsst/geom/Angle.h"
29#include "lsst/pex/exceptions.h"
34
35namespace lsst {
36namespace meas {
37namespace base {
38namespace {
39FlagDefinitionList flagDefinitions;
40} // namespace
41
42FlagDefinition const SdssCentroidAlgorithm::FAILURE = flagDefinitions.addFailureFlag();
43FlagDefinition const SdssCentroidAlgorithm::EDGE =
44 flagDefinitions.add("flag_edge", "Object too close to edge");
46 flagDefinitions.add("flag_noSecondDerivative", "Vanishing second derivative");
48 flagDefinitions.add("flag_almostNoSecondDerivative", "Almost vanishing second derivative");
49FlagDefinition const SdssCentroidAlgorithm::NOT_AT_MAXIMUM =
50 flagDefinitions.add("flag_notAtMaximum", "Object is not at a maximum");
51
53
54namespace {
55
56/************************************************************************************************************/
57
58float const AMPAST4 = 1.33; // amplitude of `4th order' corr compared to theory
59
60/*
61 * Do the Gaussian quartic interpolation for the position
62 * of the maximum for three equally spaced values vm,v0,vp, assumed to be at
63 * abscissae -1,0,1; the answer is returned as *cen
64 *
65 * Return 0 is all is well, otherwise 1
66 */
67static int inter4(float vm, float v0, float vp, float *cen, bool negative = false) {
68 float const sp = v0 - vp;
69 float const sm = v0 - vm;
70 float const d2 = sp + sm;
71 float const s = 0.5 * (vp - vm);
72
73 if ((!negative && (d2 <= 0.0f || v0 <= 0.0f)) || (negative && (d2 >= 0.0f || v0 >= 0.0f))) {
74 return (1);
75 }
76
77 *cen = s / d2 * (1.0 + AMPAST4 * sp * sm / (d2 * v0));
78
79 return fabs(*cen) < 1 ? 0 : 1;
80}
81
82/*****************************************************************************/
83/*
84 * Calculate error in centroid
85 */
86float astrom_errors(float skyVar, // variance of pixels at the sky level
87 float sourceVar, // variance in peak due to excess counts over sky
88 float A, // abs(peak value in raw image)
89 float tau2, // Object is N(0,tau2)
90 float As, // abs(peak value in smoothed image)
91 float s, // slope across central pixel
92 float d, // curvature at central pixel
93 float sigma, // width of smoothing filter
94 int quarticBad) { // was quartic estimate bad?
95
96 double const k = quarticBad ? 0 : AMPAST4; /* quartic correction coeff */
97 double const sigma2 = sigma * sigma; /* == sigma^2 */
98 double sVar, dVar; /* variances of s and d */
99 double xVar; /* variance of centroid, x */
100
102 return (1e3);
103 }
104
105 if (sigma <= 0) { /* no smoothing; no covariance */
106 sVar = 0.5 * skyVar; /* due to sky */
107 dVar = 6 * skyVar;
108
109 sVar += 0.5 * sourceVar * exp(-1 / (2 * tau2));
110 dVar += sourceVar * (4 * exp(-1 / (2 * tau2)) + 2 * exp(-1 / (2 * tau2)));
111 } else { /* smoothed */
112 sVar = skyVar / (8 * geom::PI * sigma2) * (1 - exp(-1 / sigma2));
113 dVar = skyVar / (2 * geom::PI * sigma2) * (3 - 4 * exp(-1 / (4 * sigma2)) + exp(-1 / sigma2));
114
115 sVar += sourceVar / (12 * geom::PI * sigma2) * (exp(-1 / (3 * sigma2)) - exp(-1 / sigma2));
116 dVar += sourceVar / (3 * geom::PI * sigma2) * (2 - 3 * exp(-1 / (3 * sigma2)) + exp(-1 / sigma2));
117 }
118
119 xVar = sVar * pow(1 / d + k / (4 * As) * (1 - 12 * s * s / (d * d)), 2) +
120 dVar * pow(s / (d * d) - k / (4 * As) * 8 * s * s / (d * d * d), 2);
121
122 return (xVar >= 0 ? sqrt(xVar) : NAN);
123}
124
125/************************************************************************************************************/
126/*
127 * Estimate the position of an object, assuming we know that it's approximately the size of the PSF
128 */
129
130template <typename ImageXy_locatorT, typename VarImageXy_locatorT>
131int doMeasureCentroidImpl(double *xCenter, // output; x-position of object
132 double *dxc, // output; error in xCenter
133 double *yCenter, // output; y-position of object
134 double *dyc, // output; error in yCenter
135 double *sizeX2, double *sizeY2, // output; object widths^2 in x and y directions
136 ImageXy_locatorT im, // Locator for the pixel values
137 VarImageXy_locatorT vim, // Locator for the image containing the variance
138 double smoothingSigma, // Gaussian sigma of already-applied smoothing filter
139 FlagHandler flagHandler) {
140 /*
141 * find a first quadratic estimate
142 */
143 double const d2x = 2 * im(0, 0) - im(-1, 0) - im(1, 0);
144 double const d2y = 2 * im(0, 0) - im(0, -1) - im(0, 1);
145 double const sx = 0.5 * (im(1, 0) - im(-1, 0));
146 double const sy = 0.5 * (im(0, 1) - im(0, -1));
147
148 if (d2x == 0.0 || d2y == 0.0) {
150 }
151 if (d2x < 0.0 || d2y < 0.0) {
153 }
154
155 double const dx0 = sx / d2x;
156 double const dy0 = sy / d2y; // first guess
157
158 if (fabs(dx0) > 10.0 || fabs(dy0) > 10.0) {
160 }
161
162 double vpk = im(0, 0) + 0.5 * (sx * dx0 + sy * dy0); // height of peak in image
163 if (vpk < 0) {
164 vpk = -vpk;
165 }
166 /*
167 * now evaluate maxima on stripes
168 */
169 float m0x = 0, m1x = 0, m2x = 0;
170 float m0y = 0, m1y = 0, m2y = 0;
171
172 int quarticBad = 0;
173 quarticBad += inter4(im(-1, -1), im(0, -1), im(1, -1), &m0x);
174 quarticBad += inter4(im(-1, 0), im(0, 0), im(1, 0), &m1x);
175 quarticBad += inter4(im(-1, 1), im(0, 1), im(1, 1), &m2x);
176
177 quarticBad += inter4(im(-1, -1), im(-1, 0), im(-1, 1), &m0y);
178 quarticBad += inter4(im(0, -1), im(0, 0), im(0, 1), &m1y);
179 quarticBad += inter4(im(1, -1), im(1, 0), im(1, 1), &m2y);
180
181 double xc, yc; // position of maximum
182 double sigmaX2, sigmaY2; // widths^2 in x and y of smoothed object
183
184 if (quarticBad) { // >= 1 quartic interpolator is bad
185 xc = dx0;
186 yc = dy0;
187 sigmaX2 = vpk / d2x; // widths^2 in x
188 sigmaY2 = vpk / d2y; // and y
189 } else {
190 double const smx = 0.5 * (m2x - m0x);
191 double const smy = 0.5 * (m2y - m0y);
192 double const dm2x = m1x - 0.5 * (m0x + m2x);
193 double const dm2y = m1y - 0.5 * (m0y + m2y);
194 double const dx = m1x + dy0 * (smx - dy0 * dm2x); // first quartic approx
195 double const dy = m1y + dx0 * (smy - dx0 * dm2y);
196 double const dx4 = m1x + dy * (smx - dy * dm2x); // second quartic approx
197 double const dy4 = m1y + dx * (smy - dx * dm2y);
198
199 xc = dx4;
200 yc = dy4;
201 sigmaX2 = vpk / d2x - (1 + 6 * dx0 * dx0) / 4; // widths^2 in x
202 sigmaY2 = vpk / d2y - (1 + 6 * dy0 * dy0) / 4; // and y
203 }
204 /*
205 * Now for the errors.
206 */
207 float tauX2 = sigmaX2; // width^2 of _un_ smoothed object
208 float tauY2 = sigmaY2;
209 tauX2 -= smoothingSigma * smoothingSigma; // correct for smoothing
210 tauY2 -= smoothingSigma * smoothingSigma;
211
212 if (tauX2 <= smoothingSigma * smoothingSigma) { // problem; sigmaX2 must be bad
213 tauX2 = smoothingSigma * smoothingSigma;
214 }
215 if (tauY2 <= smoothingSigma * smoothingSigma) { // sigmaY2 must be bad
216 tauY2 = smoothingSigma * smoothingSigma;
217 }
218
219 float const skyVar = (vim(-1, -1) + vim(0, -1) + vim(1, -1) + vim(-1, 0) + vim(1, 0) + vim(-1, 1) +
220 vim(0, 1) + vim(1, 1)) /
221 8.0; // Variance in sky
222 float const sourceVar = vim(0, 0); // extra variance of peak due to its photons
223 float const A = vpk * sqrt((sigmaX2 / tauX2) * (sigmaY2 / tauY2)); // peak of Unsmoothed object
224
225 *xCenter = xc;
226 *yCenter = yc;
227
228 *dxc = astrom_errors(skyVar, sourceVar, A, tauX2, vpk, sx, d2x, fabs(smoothingSigma), quarticBad);
229 *dyc = astrom_errors(skyVar, sourceVar, A, tauY2, vpk, sy, d2y, fabs(smoothingSigma), quarticBad);
230
231 *sizeX2 = tauX2; // return the estimates of the (object size)^2
232 *sizeY2 = tauY2;
233 return 0;
234}
235
236template <typename MaskedImageXy_locatorT>
237int doMeasureCentroidImpl(double *xCenter, // output; x-position of object
238 double *dxc, // output; error in xCenter
239 double *yCenter, // output; y-position of object
240 double *dyc, // output; error in yCenter
241 double *sizeX2, double *sizeY2, // output; object widths^2 in x and y directions
242 double *peakVal, // output; peak of object
243 MaskedImageXy_locatorT mim, // Locator for the pixel values
244 double smoothingSigma, // Gaussian sigma of already-applied smoothing filter
245 bool negative, FlagHandler flagHandler) {
246 /*
247 * find a first quadratic estimate
248 */
249 double const d2x = 2 * mim.image(0, 0) - mim.image(-1, 0) - mim.image(1, 0);
250 double const d2y = 2 * mim.image(0, 0) - mim.image(0, -1) - mim.image(0, 1);
251 double const sx = 0.5 * (mim.image(1, 0) - mim.image(-1, 0));
252 double const sy = 0.5 * (mim.image(0, 1) - mim.image(0, -1));
253
254 if (d2x == 0.0 || d2y == 0.0) {
256 }
257 if ((!negative && (d2x < 0.0 || d2y < 0.0)) || (negative && (d2x > 0.0 || d2y > 0.0))) {
259 }
260
261 double const dx0 = sx / d2x;
262 double const dy0 = sy / d2y; // first guess
263
264 if (fabs(dx0) > 10.0 || fabs(dy0) > 10.0) {
266 }
267
268 double vpk = mim.image(0, 0) + 0.5 * (sx * dx0 + sy * dy0); // height of peak in image
269 // if (vpk < 0) {
270 // vpk = -vpk;
271 //}
272 /*
273 * now evaluate maxima on stripes
274 */
275 float m0x = 0, m1x = 0, m2x = 0;
276 float m0y = 0, m1y = 0, m2y = 0;
277
278 int quarticBad = 0;
279 quarticBad += inter4(mim.image(-1, -1), mim.image(0, -1), mim.image(1, -1), &m0x, negative);
280 quarticBad += inter4(mim.image(-1, 0), mim.image(0, 0), mim.image(1, 0), &m1x, negative);
281 quarticBad += inter4(mim.image(-1, 1), mim.image(0, 1), mim.image(1, 1), &m2x, negative);
282
283 quarticBad += inter4(mim.image(-1, -1), mim.image(-1, 0), mim.image(-1, 1), &m0y, negative);
284 quarticBad += inter4(mim.image(0, -1), mim.image(0, 0), mim.image(0, 1), &m1y, negative);
285 quarticBad += inter4(mim.image(1, -1), mim.image(1, 0), mim.image(1, 1), &m2y, negative);
286
287 double xc, yc; // position of maximum
288 double sigmaX2, sigmaY2; // widths^2 in x and y of smoothed object
289
290 if (quarticBad) { // >= 1 quartic interpolator is bad
291 xc = dx0;
292 yc = dy0;
293 sigmaX2 = vpk / d2x; // widths^2 in x
294 sigmaY2 = vpk / d2y; // and y
295 } else {
296 double const smx = 0.5 * (m2x - m0x);
297 double const smy = 0.5 * (m2y - m0y);
298 double const dm2x = m1x - 0.5 * (m0x + m2x);
299 double const dm2y = m1y - 0.5 * (m0y + m2y);
300 double const dx = m1x + dy0 * (smx - dy0 * dm2x); // first quartic approx
301 double const dy = m1y + dx0 * (smy - dx0 * dm2y);
302 double const dx4 = m1x + dy * (smx - dy * dm2x); // second quartic approx
303 double const dy4 = m1y + dx * (smy - dx * dm2y);
304
305 xc = dx4;
306 yc = dy4;
307 sigmaX2 = vpk / d2x - (1 + 6 * dx0 * dx0) / 4; // widths^2 in x
308 sigmaY2 = vpk / d2y - (1 + 6 * dy0 * dy0) / 4; // and y
309 }
310 /*
311 * Now for the errors.
312 */
313 float tauX2 = sigmaX2; // width^2 of _un_ smoothed object
314 float tauY2 = sigmaY2;
315 tauX2 -= smoothingSigma * smoothingSigma; // correct for smoothing
316 tauY2 -= smoothingSigma * smoothingSigma;
317
318 if (tauX2 <= smoothingSigma * smoothingSigma) { // problem; sigmaX2 must be bad
319 tauX2 = smoothingSigma * smoothingSigma;
320 }
321 if (tauY2 <= smoothingSigma * smoothingSigma) { // sigmaY2 must be bad
322 tauY2 = smoothingSigma * smoothingSigma;
323 }
324
325 float const skyVar =
326 (mim.variance(-1, -1) + mim.variance(0, -1) + mim.variance(1, -1) + mim.variance(-1, 0) +
327 mim.variance(1, 0) + mim.variance(-1, 1) + mim.variance(0, 1) + mim.variance(1, 1)) /
328 8.0; // Variance in sky
329 float const sourceVar = mim.variance(0, 0); // extra variance of peak due to its photons
330 float const A = vpk * sqrt((sigmaX2 / tauX2) * (sigmaY2 / tauY2)); // peak of Unsmoothed object
331
332 *xCenter = xc;
333 *yCenter = yc;
334
335 *dxc = astrom_errors(skyVar, sourceVar, A, tauX2, vpk, sx, d2x, fabs(smoothingSigma), quarticBad);
336 *dyc = astrom_errors(skyVar, sourceVar, A, tauY2, vpk, sy, d2y, fabs(smoothingSigma), quarticBad);
337
338 *sizeX2 = tauX2; // return the estimates of the (object size)^2
339 *sizeY2 = tauY2;
340
341 *peakVal = vpk;
342 return 0;
343}
344
345template <typename MaskedImageT>
347 const int y, MaskedImageT const &mimage, int binX, int binY,
348 FlagHandler _flagHandler) {
349 geom::Point2D const center(x + mimage.getX0(), y + mimage.getY0());
350 afw::geom::ellipses::Quadrupole const &shape = psf->computeShape(center);
351 double const smoothingSigma = shape.getDeterminantRadius();
352#if 0
353 double const nEffective = psf->computeEffectiveArea(); // not implemented yet (#2821)
354#else
355 double const nEffective = 4 * M_PI * smoothingSigma * smoothingSigma; // correct for a Gaussian
356#endif
357
358 std::shared_ptr<afw::math::Kernel const> kernel = psf->getLocalKernel(center);
359 int const kWidth = kernel->getWidth();
360 int const kHeight = kernel->getHeight();
361
362 geom::BoxI bbox(geom::Point2I(x - binX * (2 + kWidth / 2), y - binY * (2 + kHeight / 2)),
363 geom::ExtentI(binX * (3 + kWidth + 1), binY * (3 + kHeight + 1)));
364
365 // image to smooth, a shallow copy
367 if (!mimage.getBBox(afw::image::LOCAL).contains(bbox)) {
368 return std::make_tuple(mimage, 0, SdssCentroidAlgorithm::EDGE.number);
369 }
370 subImage.reset(new MaskedImageT(mimage, bbox, afw::image::LOCAL));
371 std::shared_ptr<MaskedImageT> binnedImage = afw::math::binImage(*subImage, binX, binY, afw::math::MEAN);
372 binnedImage->setXY0(subImage->getXY0());
373 // image to smooth into, a deep copy.
374 MaskedImageT smoothedImage = MaskedImageT(*binnedImage, true);
375 if(smoothedImage.getWidth() / 2 != kWidth / 2 + 2 || // assumed by the code that uses smoothedImage
376 smoothedImage.getHeight() / 2 != kHeight / 2 + 2) {
377 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError, "invalid image dimensions");
378 }
379
380 afw::math::convolve(smoothedImage, *binnedImage, *kernel, afw::math::ConvolutionControl());
381 *smoothedImage.getVariance() *= binX * binY * nEffective; // We want the per-pixel variance, so undo the
382 // effects of binning and smoothing
383
384 return std::make_tuple(smoothedImage, smoothingSigma, 0);
385}
386
387} // end anonymous namespace
388
391 : _ctrl(ctrl),
392 _centroidKey(CentroidResultKey::addFields(schema, name, "centroid from Sdss Centroid algorithm",
393 SIGMA_ONLY)),
394 _flagHandler(FlagHandler::addFields(schema, name, getFlagDefinitions())),
395 _centroidExtractor(schema, name, true),
396 _centroidChecker(schema, name, ctrl.doFootprintCheck, ctrl.maxDistToPeak) {}
398 afw::image::Exposure<float> const &exposure) const {
399 // get our current best guess about the centroid: either a centroider measurement or peak.
400 geom::Point2D center = _centroidExtractor(measRecord, _flagHandler);
402 result.x = center.getX();
403 result.y = center.getY();
404 measRecord.set(_centroidKey, result); // better than NaN
405
407 typedef MaskedImageT::Image ImageT;
408 typedef MaskedImageT::Variance VarianceT;
409 bool negative = false;
410 try {
411 negative = measRecord.get(measRecord.getSchema().find<afw::table::Flag>("flags_negative").key);
412 } catch (pexExcept::Exception &e) {
413 }
414
415 MaskedImageT const &mimage = exposure.getMaskedImage();
416 ImageT const &image = *mimage.getImage();
418
419 int const x = image.positionToIndex(center.getX(), afw::image::X).first;
420 int const y = image.positionToIndex(center.getY(), afw::image::Y).first;
421
422 if (!image.getBBox().contains(geom::Extent2I(x, y) + image.getXY0())) {
423 _flagHandler.setValue(measRecord, EDGE.number, true);
424 _flagHandler.setValue(measRecord, SdssCentroidAlgorithm::FAILURE.number, true);
425 return;
426 }
427
428 // Algorithm uses a least-squares fit (implemented via a convolution) to a symmetrized PSF model.
429 // If you don't have a Psf, you need to use another centroider, such as GaussianCentroider.
430 if (!psf) {
431 throw LSST_EXCEPT(FatalAlgorithmError, "SdssCentroid algorithm requires a Psf with every exposure");
432 }
433
434 int binX = 1;
435 int binY = 1;
436 double xc = 0., yc = 0., dxc = 0., dyc = 0.; // estimated centre and error therein
437 for (int binsize = 1; binsize <= _ctrl.binmax; binsize *= 2) {
439 smoothAndBinImage(psf, x, y, mimage, binX, binY, _flagHandler);
440 int errorFlag = std::get<2>(smoothResult);
441 if (errorFlag > 0) {
442 _flagHandler.setValue(measRecord, errorFlag, true);
443 _flagHandler.setValue(measRecord, SdssCentroidAlgorithm::FAILURE.number, true);
444 return;
445 }
446 MaskedImageT const smoothedImage = std::get<0>(smoothResult);
447 double const smoothingSigma = std::get<1>(smoothResult);
448
449 MaskedImageT::xy_locator mim =
450 smoothedImage.xy_at(smoothedImage.getWidth() / 2, smoothedImage.getHeight() / 2);
451
452 double sizeX2, sizeY2; // object widths^2 in x and y directions
453 double peakVal; // peak intensity in image
454
455 errorFlag = doMeasureCentroidImpl(&xc, &dxc, &yc, &dyc, &sizeX2, &sizeY2, &peakVal, mim, smoothingSigma, negative,
456 _flagHandler);
457 if (errorFlag > 0) {
458 _flagHandler.setValue(measRecord, errorFlag, true);
459 _flagHandler.setValue(measRecord, SdssCentroidAlgorithm::FAILURE.number, true);
460 return;
461 }
462
463 if (binsize > 1) {
464 // dilate from the lower left corner of central pixel
465 xc = (xc + 0.5) * binX - 0.5;
466 dxc *= binX;
467 sizeX2 *= binX * binX;
468
469 yc = (yc + 0.5) * binY - 0.5;
470 dyc *= binY;
471 sizeY2 *= binY * binY;
472 }
473
474 xc += x; // xc, yc are measured relative to pixel (x, y)
475 yc += y;
476
477 double const fac = _ctrl.wfac * (1 + smoothingSigma * smoothingSigma);
478 double const facX2 = fac * binX * binX;
479 double const facY2 = fac * binY * binY;
480
481 if (sizeX2 < facX2 && ::pow(xc - x, 2) < facX2 && sizeY2 < facY2 && ::pow(yc - y, 2) < facY2) {
482 if (binsize > 1 || _ctrl.peakMin < 0.0 || peakVal > _ctrl.peakMin) {
483 break;
484 }
485 }
486
487 if (sizeX2 >= facX2 || ::pow(xc - x, 2) >= facX2) {
488 binX *= 2;
489 }
490 if (sizeY2 >= facY2 || ::pow(yc - y, 2) >= facY2) {
491 binY *= 2;
492 }
493 }
494 result.x = afw::image::indexToPosition(xc + image.getX0());
495 result.y = afw::image::indexToPosition(yc + image.getY0());
496
497 result.xErr = sqrt(dxc * dxc);
498 result.yErr = sqrt(dyc * dyc);
499 measRecord.set(_centroidKey, result);
500 _centroidChecker(measRecord);
501}
502
504 _flagHandler.handleFailure(measRecord, error);
505}
506
512 if (flag == SdssCentroidAlgorithm::FAILURE) continue;
513 if (mapper.getInputSchema().getNames().count(mapper.getInputSchema().join(name, flag.name)) == 0)
514 continue;
516 mapper.getInputSchema().find<afw::table::Flag>(name + "_" + flag.name).key;
517 mapper.addMapping(key);
518 }
519}
520
521} // namespace base
522} // namespace meas
523} // namespace lsst
py::object result
Definition: _schema.cc:429
table::Key< std::string > name
Definition: Amplifier.cc:116
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
double x
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
table::Key< double > sigma2
afw::table::Key< double > sigma
Definition: GaussianPsf.cc:49
#define M_PI
Definition: ListMatch.cc:31
SchemaMapper * mapper
Definition: SchemaMapper.cc:71
This implements the SdssCentroid algorithm within the meas_base measurement framework.
int y
Definition: SpanSet.cc:48
table::Schema schema
Definition: python.h:134
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
MaskedImageT getMaskedImage()
Return the MaskedImage.
Definition: Exposure.h:228
std::shared_ptr< lsst::afw::detection::Psf const > getPsf() const
Return the Exposure's Psf object.
Definition: Exposure.h:319
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:73
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Definition: BaseRecord.h:151
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
Definition: BaseRecord.h:80
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
Definition: BaseRecord.h:164
Defines the fields and offsets for a table.
Definition: Schema.h:51
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
Definition: Schema.cc:467
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:21
Record class that contains measurements made on a single exposure.
Definition: Source.h:78
An integer coordinate rectangle.
Definition: Box.h:55
A FunctorKey for CentroidResult.
Base for centroid measurement transformations.
Exception to be thrown when a measurement algorithm experiences a fatal error.
Definition: exceptions.h:76
vector-type utility class to build a collection of FlagDefinitions
Definition: FlagHandler.h:60
std::size_t size() const
return the current size (number of defined elements) of the collection
Definition: FlagHandler.h:125
Utility class for handling flag fields that indicate the failure modes of an algorithm.
Definition: FlagHandler.h:148
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Definition: exceptions.h:48
static FlagDefinition const NOT_AT_MAXIMUM
Definition: SdssCentroid.h:77
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.
SdssCentroidAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
static FlagDefinition const NO_SECOND_DERIVATIVE
Definition: SdssCentroid.h:75
static FlagDefinition const FAILURE
Definition: SdssCentroid.h:73
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
static FlagDefinitionList const & getFlagDefinitions()
Definition: SdssCentroid.cc:52
static FlagDefinition const ALMOST_NO_SECOND_DERIVATIVE
Definition: SdssCentroid.h:76
static FlagDefinition const EDGE
Definition: SdssCentroid.h:74
A C++ control class to handle SdssCentroidAlgorithm's configuration.
Definition: SdssCentroid.h:48
double wfac
"fiddle factor for adjusting the binning" ;
Definition: SdssCentroid.h:52
int binmax
"maximum allowed binning" ;
Definition: SdssCentroid.h:50
double peakMin
"if the peak's less than this insist on binning at least once" ;
Definition: SdssCentroid.h:51
SdssCentroidTransform(Control const &ctrl, std::string const &name, afw::table::SchemaMapper &mapper)
Provides consistent interface for LSST exceptions.
Definition: Exception.h:107
Reports attempts to exceed implementation-defined length limits for some classes.
Definition: Runtime.h:76
T exp(T... args)
T fabs(T... args)
T make_tuple(T... args)
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image.
@ MEAN
estimate sample mean
Definition: Statistics.h:66
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binX, int const binY, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)
Definition: binImage.cc:44
constexpr double PI
The ratio of a circle's circumference to diameter.
Definition: Angle.h:40
@ SIGMA_ONLY
Only the diagonal elements of the covariance matrix are provided.
Definition: constants.h:45
A base class for image defects.
T pow(T... args)
T reset(T... args)
T sqrt(T... args)
A reusable struct for centroid measurements.
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...
Definition: FlagHandler.h:40
Key< int > psf
Definition: Exposure.cc:65