LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
DipoleAlgorithms.cc
Go to the documentation of this file.
1/*
2 * LSST Data Management System
3 * Copyright 2008-2015 AURA/LSST
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
26#include <iostream> // std::cout
27#include <algorithm> // std::sort
28#include <limits> // std::numeric_limits
29#include <cmath> // std::sqrt
30
31#if !defined(DOXYGEN)
32# include "Minuit2/FCNBase.h"
33# include "Minuit2/FunctionMinimum.h"
34# include "Minuit2/MnMigrad.h"
35# include "Minuit2/MnMinos.h"
36# include "Minuit2/MnPrint.h"
37#endif
38
39#include <memory>
40#include "lsst/pex/exceptions.h"
41#include "lsst/afw/image.h"
42#include "lsst/afw/detection.h"
43#include "lsst/afw/table.h"
44#include "lsst/afw/math.h"
45#include "lsst/geom.h"
47#include "ndarray/eigen.h"
48
51namespace afwImage = lsst::afw::image;
52namespace afwMath = lsst::afw::math;
53namespace geom = lsst::geom;
54
55namespace lsst { namespace ip { namespace diffim {
56
57namespace {
58meas::base::FlagDefinitionList dipoleFluxFlagDefinitions;
59}
60
61meas::base::FlagDefinition const DipoleFluxAlgorithm::FAILURE = dipoleFluxFlagDefinitions.addFailureFlag("general failure flag, set if anything went wrong");
62meas::base::FlagDefinition const DipoleFluxAlgorithm::POS_FLAG = dipoleFluxFlagDefinitions.add("pos_flag", "failure flag for positive, set if anything went wrong");
63meas::base::FlagDefinition const DipoleFluxAlgorithm::NEG_FLAG = dipoleFluxFlagDefinitions.add("neg_flag", "failure flag for negative, set if anything went wrong");
64
66 return dipoleFluxFlagDefinitions;
67}
68
69namespace {
70meas::base::FlagDefinitionList dipoleCentroidFlagDefinitions;
71}
72
73meas::base::FlagDefinition const DipoleCentroidAlgorithm::FAILURE = dipoleCentroidFlagDefinitions.addFailureFlag("general failure flag, set if anything went wrong");
74meas::base::FlagDefinition const DipoleCentroidAlgorithm::POS_FLAG = dipoleCentroidFlagDefinitions.add("pos_flag", "failure flag for positive, set if anything went wrong");
75meas::base::FlagDefinition const DipoleCentroidAlgorithm::NEG_FLAG = dipoleCentroidFlagDefinitions.add("neg_flag", "failure flag for negative, set if anything went wrong");
76
78 return dipoleCentroidFlagDefinitions;
79}
80
81 int const NEGCENTXPAR(0); // Parameter for the x-component of the negative lobe centroid
82 int const NEGCENTYPAR(1); // Parameter for the y-component of the negative lobe centroid
83 int const NEGFLUXPAR(2); // Parameter for the flux of the negative lobe
84 int const POSCENTXPAR(3); // Parameter for the x-component of the positive lobe centroid
85 int const POSCENTYPAR(4); // Parameter for the y-component of the positive lobe centroid
86 int const POSFLUXPAR(5); // Parameter for the flux of the positive lobe
87
88
89namespace {
90
91void naiveCentroid(
93 afw::image::Exposure<float> const& exposure,
94 geom::Point2I const & center,
96 )
97{
98 typedef afw::image::Image<float> ImageT;
99 ImageT const& image = *exposure.getMaskedImage().getImage();
100 // set to the input centroid, just in case all else fails
101 source.set(keys.getX(), center.getX());
102 source.set(keys.getY(), center.getY());
103
104 int x = center.getX() - image.getX0();
105 int y = center.getY() - image.getY0();
106
107 if (x < 1 || x >= image.getWidth() - 1 || y < 1 || y >= image.getHeight() - 1) {
109 (boost::format("Object at (%d, %d) is too close to the edge")
110 % x % y).str());
111 }
112
113 ImageT::xy_locator im = image.xy_at(x, y);
114
115 double const sum =
116 (im(-1, 1) + im( 0, 1) + im( 1, 1) +
117 im(-1, 0) + im( 0, 0) + im( 1, 0) +
118 im(-1, -1) + im( 0, -1) + im( 1, -1));
119
120
121 if (sum == 0.0) {
123 (boost::format("Object at (%d, %d) has no counts") %
124 x % y).str());
125 }
126
127 double const sum_x =
128 -im(-1, 1) + im( 1, 1) +
129 -im(-1, 0) + im( 1, 0) +
130 -im(-1, -1) + im( 1, -1);
131 double const sum_y =
132 (im(-1, 1) + im( 0, 1) + im( 1, 1)) -
133 (im(-1, -1) + im( 0, -1) + im( 1, -1));
134
135 float xx = afw::image::indexToPosition(x + image.getX0()) + sum_x / sum;
136 float yy = afw::image::indexToPosition(y + image.getY0()) + sum_y / sum;
137 source.set(keys.getX(), xx);
138 source.set(keys.getY(), yy);
139}
140
141} // anonymous namespace
142
143
145 Control const & ctrl,
146 std::string const & name,
148) : DipoleCentroidAlgorithm(ctrl, name, schema, "unweighted first moment centroid"),
149 _ctrl(ctrl)
150{ }
151
157 afw::image::Exposure<float> const & exposure
158) const {
159 afw::detection::PeakCatalog const& peaks = source.getFootprint()->getPeaks();
160
161 int posInd = 0;
162 double posValue = peaks[posInd].getPeakValue(), negValue = 0;
163 if (posValue < 0.) { /* All peaks are negative so use the *most* negative value */
164 posInd = peaks.size() - 1;
165 posValue = peaks[posInd].getPeakValue();
166 }
167 naiveCentroid(source, exposure, peaks[posInd].getI(),
168 (posValue >= 0 ? getPositiveKeys() : getNegativeKeys()));
169
170 if (posValue > 0. && posInd == 0 && peaks.size() > 1) { /* See if there's also a negative peak */
171 int negInd = peaks.size() - 1;
172 negValue = peaks[negInd].getPeakValue();
173 if (posValue > 0. && negValue < 0.) {
174 naiveCentroid(source, exposure, peaks[negInd].getI(),
175 (negValue >= 0 ? getPositiveKeys() : getNegativeKeys()));
176 }
177 }
178
179 mergeCentroids(source, posValue, negValue);
180
181}
182
184 double posValue, double negValue) const {
185
186 double pos_x, pos_y, pos_f;
187 double neg_x, neg_y, neg_f;
188
189 pos_x = source.get(getPositiveKeys().getX());
190 pos_y = source.get(getPositiveKeys().getY());
191 pos_f = posValue;
192
193 neg_x = source.get(getNegativeKeys().getX());
194 neg_y = source.get(getNegativeKeys().getY());
195 neg_f = -negValue;
196
197 if(std::isfinite(pos_x) && std::isfinite(pos_y) &&
198 std::isfinite(neg_x) && std::isfinite(neg_y)) {
199 source.set(getCenterKeys().getX(), (pos_x * pos_f + neg_x * neg_f) / (pos_f + neg_f));
200 source.set(getCenterKeys().getY(), (pos_y * pos_f + neg_y * neg_f) / (pos_f + neg_f));
201 } else if (std::isfinite(pos_x) && std::isfinite(pos_y)) {
202 source.set(getCenterKeys().getX(), pos_x);
203 source.set(getCenterKeys().getY(), pos_y);
204 } else {
205 source.set(getCenterKeys().getX(), neg_x);
206 source.set(getCenterKeys().getY(), neg_y);
207 }
208}
209
211 meas::base::MeasurementError * error) const {
212 _flagHandler.handleFailure(measRecord, error);
213}
214
215
216namespace {
217
218class NaiveDipoleFootprinter {
219public:
220 explicit NaiveDipoleFootprinter() : _sumPositive(0.0), _sumNegative(0.0), _numPositive(0),
221 _numNegative(0) {}
222
224 void reset() {
225 _sumPositive = _sumNegative = 0.0;
226 _numPositive = _numNegative = 0;
227 }
228 void reset(afwDet::Footprint const&) {}
229
231 void operator() (geom::Point2I const & pos,
234 if (ival >= 0.0) {
235 _sumPositive += ival;
236 _varPositive += vval;
237 ++_numPositive;
238 } else {
239 _sumNegative += ival;
240 _varPositive += vval;
241 ++_numNegative;
242 }
243 }
244
245 double getSumPositive() const { return _sumPositive; }
246 double getSumNegative() const { return _sumNegative; }
247 double getVarPositive() const { return _sumPositive; }
248 double getVarNegative() const { return _sumNegative; }
249 int getNumPositive() const { return _numPositive; }
250 int getNumNegative() const { return _numNegative; }
251
252private:
253 double _sumPositive;
254 double _sumNegative;
255 double _varPositive;
256 double _varNegative;
257 int _numPositive;
258 int _numNegative;
259};
260
261} // anonymous namespace
262
263
269 afw::image::Exposure<float> const & exposure
270) const {
272
273 NaiveDipoleFootprinter functor;
274 source.getFootprint()->getSpans()->applyFunctor(functor, *(exposure.getMaskedImage().getImage()),
275 *(exposure.getMaskedImage().getVariance()));
276
277 source.set(getPositiveKeys().getInstFlux(), functor.getSumPositive());
278 source.set(getPositiveKeys().getInstFluxErr(), ::sqrt(functor.getVarPositive()));
279 source.set(_numPositiveKey, functor.getNumPositive());
280
281 source.set(getNegativeKeys().getInstFlux(), functor.getSumNegative());
282 source.set(getNegativeKeys().getInstFluxErr(), ::sqrt(functor.getVarNegative()));
283 source.set(_numNegativeKey, functor.getNumNegative());
284 functor.reset();
285}
286
288 _flagHandler.handleFailure(measRecord, error);
289}
290
291
295class MinimizeDipoleChi2 : public ROOT::Minuit2::FCNBase {
296public:
297 explicit MinimizeDipoleChi2(PsfDipoleFlux const& psfDipoleFlux,
299 afw::image::Exposure<float> const& exposure
300 ) : _errorDef(1.0),
301 _nPar(6),
302 _maxPix(1e4),
303 _bigChi2(1e10),
304 _psfDipoleFlux(psfDipoleFlux),
305 _source(source),
306 _exposure(exposure)
307 {}
308 double Up() const { return _errorDef; }
309 void setErrorDef(double def) { _errorDef = def; }
310 int getNpar() const { return _nPar; }
311 int getMaxPix() const { return _maxPix; }
312 void setMaxPix(int maxPix) { _maxPix = maxPix; }
313
314 // Evaluate our cost function (in this case chi^2)
315 virtual double operator()(std::vector<double> const & params) const {
316 double negCenterX = params[NEGCENTXPAR];
317 double negCenterY = params[NEGCENTYPAR];
318 double negFlux = params[NEGFLUXPAR];
319 double posCenterX = params[POSCENTXPAR];
320 double posCenterY = params[POSCENTYPAR];
321 double posFlux = params[POSFLUXPAR];
322
323 /* Restrict negative dipole to be negative; positive to be positive */
324 if ((negFlux > 0.0) || (posFlux < 0.0)) {
325 return _bigChi2;
326 }
327
328 std::pair<double,int> fit = _psfDipoleFlux.chi2(_source, _exposure, negCenterX, negCenterY, negFlux,
329 posCenterX, posCenterY, posFlux);
330 double chi2 = fit.first;
331 int nPix = fit.second;
332 if (nPix > _maxPix) {
333 return _bigChi2;
334 }
335
336 return chi2;
337 }
338
339private:
340 double _errorDef; // how much cost function has changed at the +- 1 error points
341 int _nPar; // number of parameters in the fit; hard coded for MinimizeDipoleChi2
342 int _maxPix; // maximum number of pixels that shoud be in the footprint;
343 // prevents too much centroid wander
344 double _bigChi2; // large value to tell fitter when it has gone into bad region of parameter space
345
346 PsfDipoleFlux const& _psfDipoleFlux;
347 afw::table::SourceRecord & _source;
348 afw::image::Exposure<float> const& _exposure;
349};
350
353 afw::image::Exposure<float> const& exposure,
354 double negCenterX, double negCenterY, double negFlux,
355 double posCenterX, double posCenterY, double posFlux
356) const {
357
358 geom::Point2D negCenter(negCenterX, negCenterY);
359 geom::Point2D posCenter(posCenterX, posCenterY);
360
361 std::shared_ptr<afw::detection::Footprint const> footprint = source.getFootprint();
362
363 /*
364 * Fit for the superposition of Psfs at the two centroids.
365 */
366 std::shared_ptr<afwDet::Psf const> psf = exposure.getPsf();
367 std::shared_ptr<afwImage::Image<afwMath::Kernel::Pixel>> negPsf = psf->computeImage(negCenter);
368 std::shared_ptr<afwImage::Image<afwMath::Kernel::Pixel>> posPsf = psf->computeImage(posCenter);
369
370 afwImage::Image<double> negModel(footprint->getBBox());
371 afwImage::Image<double> posModel(footprint->getBBox());
372 afwImage::Image<float> data(*(exposure.getMaskedImage().getImage()),footprint->getBBox());
373 afwImage::Image<afwImage::VariancePixel> var(*(exposure.getMaskedImage().getVariance()),
374 footprint->getBBox());
375
376 geom::Box2I negPsfBBox = negPsf->getBBox();
377 geom::Box2I posPsfBBox = posPsf->getBBox();
378 geom::Box2I negModelBBox = negModel.getBBox();
379 geom::Box2I posModelBBox = posModel.getBBox();
380
381 // Portion of the negative Psf that overlaps the model
382 int negXmin = std::max(negPsfBBox.getMinX(), negModelBBox.getMinX());
383 int negYmin = std::max(negPsfBBox.getMinY(), negModelBBox.getMinY());
384 int negXmax = std::min(negPsfBBox.getMaxX(), negModelBBox.getMaxX());
385 int negYmax = std::min(negPsfBBox.getMaxY(), negModelBBox.getMaxY());
386 geom::Box2I negBBox = geom::Box2I(geom::Point2I(negXmin, negYmin),
387 geom::Point2I(negXmax, negYmax));
388 afwImage::Image<afwMath::Kernel::Pixel> negSubim(*negPsf, negBBox);
389 afwImage::Image<double> negModelSubim(negModel, negBBox);
390 negModelSubim += negSubim;
391
392 // Portion of the positive Psf that overlaps the model
393 int posXmin = std::max(posPsfBBox.getMinX(), posModelBBox.getMinX());
394 int posYmin = std::max(posPsfBBox.getMinY(), posModelBBox.getMinY());
395 int posXmax = std::min(posPsfBBox.getMaxX(), posModelBBox.getMaxX());
396 int posYmax = std::min(posPsfBBox.getMaxY(), posModelBBox.getMaxY());
397 geom::Box2I posBBox = geom::Box2I(geom::Point2I(posXmin, posYmin),
398 geom::Point2I(posXmax, posYmax));
399 afwImage::Image<afwMath::Kernel::Pixel> posSubim(*posPsf, posBBox);
400 afwImage::Image<double> posModelSubim(posModel, posBBox);
401 posModelSubim += posSubim;
402
403 negModel *= negFlux; // scale negative model to image
404 posModel *= posFlux; // scale positive model to image
405 afwImage::Image<double> residuals(negModel, true); // full model contains negative lobe...
406 residuals += posModel; // plus positive lobe...
407 residuals -= data; // minus the data...
408 residuals *= residuals; // squared...
409 residuals /= var; // divided by the variance : [(model-data)/sigma]**2
411 double chi2 = stats.getValue(afwMath::SUM);
412 int nPix = stats.getValue(afwMath::NPOINT);
413 return std::pair<double,int>(chi2, nPix);
414}
415
418 afw::image::Exposure<float> const & exposure
419) const {
420
422
423 std::shared_ptr<afw::detection::Footprint const> footprint = source.getFootprint();
424 if (!footprint) {
426 (boost::format("No footprint for source %d") % source.getId()).str());
427 }
428
429 afw::detection::PeakCatalog peakCatalog = afw::detection::PeakCatalog(footprint->getPeaks());
430
431 if (peakCatalog.size() == 0) {
433 (boost::format("No peak for source %d") % source.getId()).str());
434 }
435 else if (peakCatalog.size() == 1) {
436 // No deblending to do
437 return;
438 }
439
440 // For N>=2, just measure the brightest-positive and brightest-negative
441 // peaks. peakCatalog is automatically ordered by peak flux, with the most
442 // positive one (brightest) being first
443 afw::detection::PeakRecord const& positivePeak = peakCatalog.front();
444 afw::detection::PeakRecord const& negativePeak = peakCatalog.back();
445
446 // Set up fit parameters and param names
447 ROOT::Minuit2::MnUserParameters fitPar;
448
449 fitPar.Add((boost::format("P%d")%NEGCENTXPAR).str(), negativePeak.getFx(), _ctrl.stepSizeCoord);
450 fitPar.Add((boost::format("P%d")%NEGCENTYPAR).str(), negativePeak.getFy(), _ctrl.stepSizeCoord);
451 fitPar.Add((boost::format("P%d")%NEGFLUXPAR).str(), negativePeak.getPeakValue(), _ctrl.stepSizeFlux);
452 fitPar.Add((boost::format("P%d")%POSCENTXPAR).str(), positivePeak.getFx(), _ctrl.stepSizeCoord);
453 fitPar.Add((boost::format("P%d")%POSCENTYPAR).str(), positivePeak.getFy(), _ctrl.stepSizeCoord);
454 fitPar.Add((boost::format("P%d")%POSFLUXPAR).str(), positivePeak.getPeakValue(), _ctrl.stepSizeFlux);
455
456 // Create the minuit object that knows how to minimise our functor
457 //
458 MinimizeDipoleChi2 minimizerFunc(*this, source, exposure);
459 minimizerFunc.setErrorDef(_ctrl.errorDef);
460
461 //
462 // tell minuit about it
463 //
464 ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar);
465
466 //
467 // And let it loose
468 //
469 ROOT::Minuit2::FunctionMinimum min = migrad(_ctrl.maxFnCalls);
470
471 float minChi2 = min.Fval();
472 bool const isValid = min.IsValid() && std::isfinite(minChi2);
473
474 if (true || isValid) { // calculate coeffs even in minuit is unhappy
475
476 /* I need to call chi2 one more time to grab nPix to calculate chi2/dof.
477 Turns out that the Minuit operator method has to be const, and the
478 measurement _apply method has to be const, so I can't store nPix as a
479 private member variable anywhere. Consted into a corner.
480 */
481 std::pair<double,int> fit = chi2(source, exposure,
482 min.UserState().Value(NEGCENTXPAR),
483 min.UserState().Value(NEGCENTYPAR),
484 min.UserState().Value(NEGFLUXPAR),
485 min.UserState().Value(POSCENTXPAR),
486 min.UserState().Value(POSCENTYPAR),
487 min.UserState().Value(POSFLUXPAR));
488 double evalChi2 = fit.first;
489 int nPix = fit.second;
490
491 std::shared_ptr<geom::Point2D> minNegCentroid(new geom::Point2D(min.UserState().Value(NEGCENTXPAR),
492 min.UserState().Value(NEGCENTYPAR)));
493 source.set(getNegativeKeys().getInstFlux(), min.UserState().Value(NEGFLUXPAR));
494 source.set(getNegativeKeys().getInstFluxErr(), min.UserState().Error(NEGFLUXPAR));
495
496 std::shared_ptr<geom::Point2D> minPosCentroid(new geom::Point2D(min.UserState().Value(POSCENTXPAR),
497 min.UserState().Value(POSCENTYPAR)));
498 source.set(getPositiveKeys().getInstFlux(), min.UserState().Value(POSFLUXPAR));
499 source.set(getPositiveKeys().getInstFluxErr(), min.UserState().Error(POSFLUXPAR));
500
501 source.set(_chi2dofKey, evalChi2 / (nPix - minimizerFunc.getNpar()));
502 source.set(_negCentroid.getX(), minNegCentroid->getX());
503 source.set(_negCentroid.getY(), minNegCentroid->getY());
504 source.set(_posCentroid.getX(), minPosCentroid->getX());
505 source.set(_posCentroid.getY(), minPosCentroid->getY());
506 source.set(_avgCentroid.getX(), 0.5*(minNegCentroid->getX() + minPosCentroid->getX()));
507 source.set(_avgCentroid.getY(), 0.5*(minNegCentroid->getY() + minPosCentroid->getY()));
508
509 }
510}
511
513 _flagHandler.handleFailure(measRecord, error);
514}
515}}} // namespace lsst::ip::diffim
char * data
Definition BaseRecord.cc:61
int min
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
int y
Definition SpanSet.cc:48
table::Schema schema
Definition python.h:134
Class to describe the properties of a detected object from an image.
Definition Footprint.h:63
Record class that represents a peak in a Footprint.
Definition Peak.h:42
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition Exposure.h:72
PixelT Pixel
A pixel in this ImageBase.
Definition ImageBase.h:115
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition ImageBase.h:445
A class to represent a 2-dimensional array of pixels.
Definition Image.h:51
A class to manipulate images, masks, and variance as a single object.
Definition MaskedImage.h:74
A class to evaluate image statistics.
Definition Statistics.h:222
size_type size() const
Return the number of elements in the catalog.
Definition Catalog.h:412
reference back() const
Return the last record.
Definition Catalog.h:460
reference front() const
Return the first record.
Definition Catalog.h:457
T Value
The data type for get and set.
Definition FunctorKey.h:77
Defines the fields and offsets for a table.
Definition Schema.h:51
Record class that contains measurements made on a single exposure.
Definition Source.h:78
An integer coordinate rectangle.
Definition Box.h:55
int getMinY() const noexcept
Definition Box.h:158
int getMinX() const noexcept
Definition Box.h:157
int getMaxX() const noexcept
Definition Box.h:161
int getMaxY() const noexcept
Definition Box.h:162
Intermediate base class for algorithms that compute a centroid.
static meas::base::FlagDefinition const FAILURE
static meas::base::FlagDefinition const POS_FLAG
static meas::base::FlagDefinition const NEG_FLAG
static meas::base::FlagDefinitionList const & getFlagDefinitions()
static meas::base::FlagDefinitionList const & getFlagDefinitions()
ResultKey const & getPositiveKeys() const
Return the standard flux keys registered by this algorithm.
static meas::base::FlagDefinition const POS_FLAG
static meas::base::FlagDefinition const NEG_FLAG
ResultKey const & getNegativeKeys() const
static meas::base::FlagDefinition const FAILURE
Class to minimize PsfDipoleFlux; this is the object that Minuit minimizes.
virtual double operator()(std::vector< double > const &params) const
MinimizeDipoleChi2(PsfDipoleFlux const &psfDipoleFlux, afw::table::SourceRecord &source, afw::image::Exposure< float > const &exposure)
ResultKey const & getPositiveKeys() const
ResultKey const & getNegativeKeys() const
NaiveDipoleCentroid(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Given an image and a pixel position, return a Centroid using a naive 3x3 weighted moment.
void mergeCentroids(afw::table::SourceRecord &source, double posValue, double negValue) const
void fail(afw::table::SourceRecord &measRecord, meas::base::MeasurementError *error=NULL) const
Handle an exception thrown by the current algorithm by setting flags in the given record.
ResultKey const & getCenterKeys() const
Return the standard centroid keys registered by this algorithm.
void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Given an image and a pixel position, return a Centroid using a naive 3x3 weighted moment.
void fail(afw::table::SourceRecord &measRecord, meas::base::MeasurementError *error=NULL) const
Handle an exception thrown by the current algorithm by setting flags in the given record.
float stepSizeCoord
"Default initial step size for coordinates in non-linear fitter" ;
double errorDef
"How many sigma the error bars of the non-linear fitter represent" ;
float stepSizeFlux
"Default initial step size for flux in non-linear fitter" ;
int maxFnCalls
"Maximum function calls for non-linear fitter; 0 = unlimited" ;
Implementation of Psf dipole flux.
std::pair< double, int > chi2(afw::table::SourceRecord &source, afw::image::Exposure< float > const &exposure, double negCenterX, double negCenterY, double negFlux, double posCenterX, double poCenterY, double posFlux) const
void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
void fail(afw::table::SourceRecord &measRecord, meas::base::MeasurementError *error=NULL) const
Handle an exception thrown by the current algorithm by setting flags in the given record.
A FunctorKey for CentroidResult.
afw::table::Key< CentroidElement > getX() const
Return a Key for the x coordinate.
afw::table::Key< CentroidElement > getY() const
Return a Key for the y coordinate.
vector-type utility class to build a collection of FlagDefinitions
Definition FlagHandler.h:60
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Definition exceptions.h:48
Reports attempts to exceed implementation-defined length limits for some classes.
Definition Runtime.h:76
Reports errors that are due to events beyond the control of the program.
Definition Runtime.h:104
bool isValid
Definition fits.cc:404
T isfinite(T... args)
T max(T... args)
T min(T... args)
Definition __init__.py:1
afw::table::CatalogT< PeakRecord > PeakCatalog
Definition Peak.h:244
double indexToPosition(double ind)
Convert image index to image position.
Definition ImageUtils.h:55
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
Definition Statistics.h:361
@ SUM
find sum of pixels in the image
Definition Statistics.h:68
@ NPOINT
number of sample points
Definition Statistics.h:56
int const NEGFLUXPAR(2)
int const NEGCENTXPAR(0)
int const NEGCENTYPAR(1)
int const POSFLUXPAR(5)
int const POSCENTXPAR(3)
int const POSCENTYPAR(4)
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