33 # include "Minuit2/FCNBase.h"
34 # include "Minuit2/FunctionMinimum.h"
35 # include "Minuit2/MnMigrad.h"
36 # include "Minuit2/MnMinos.h"
37 # include "Minuit2/MnPrint.h"
48 #include "ndarray/eigen.h"
56 namespace lsst {
namespace ip {
namespace diffim {
59 meas::base::FlagDefinitionList dipoleFluxFlagDefinitions;
62 meas::base::FlagDefinition
const DipoleFluxAlgorithm::FAILURE = dipoleFluxFlagDefinitions.addFailureFlag(
"general failure flag, set if anything went wrong");
63 meas::base::FlagDefinition
const DipoleFluxAlgorithm::POS_FLAG = dipoleFluxFlagDefinitions.add(
"pos_flag",
"failure flag for positive, set if anything went wrong");
64 meas::base::FlagDefinition
const DipoleFluxAlgorithm::NEG_FLAG = dipoleFluxFlagDefinitions.add(
"neg_flag",
"failure flag for negative, set if anything went wrong");
67 return dipoleFluxFlagDefinitions;
79 return dipoleCentroidFlagDefinitions;
105 int x = center.getX() -
image.getX0();
106 int y = center.getY() -
image.getY0();
108 if (x < 1 || x >=
image.getWidth() - 1 || y < 1 || y >=
image.getHeight() - 1) {
110 (boost::format(
"Object at (%d, %d) is too close to the edge")
114 ImageT::xy_locator im =
image.xy_at(x, y);
117 (im(-1, 1) + im( 0, 1) + im( 1, 1) +
118 im(-1, 0) + im( 0, 0) + im( 1, 0) +
119 im(-1, -1) + im( 0, -1) + im( 1, -1));
124 (boost::format(
"Object at (%d, %d) has no counts") %
129 -im(-1, 1) + im( 1, 1) +
130 -im(-1, 0) + im( 1, 0) +
131 -im(-1, -1) + im( 1, -1);
133 (im(-1, 1) + im( 0, 1) + im( 1, 1)) -
134 (im(-1, -1) + im( 0, -1) + im( 1, -1));
163 double posValue = peaks[posInd].getPeakValue(), negValue = 0;
165 posInd = peaks.
size() - 1;
166 posValue = peaks[posInd].getPeakValue();
168 naiveCentroid(
source, exposure, peaks[posInd].getI(),
171 if (posValue > 0. && posInd == 0 && peaks.
size() > 1) {
172 int negInd = peaks.
size() - 1;
173 negValue = peaks[negInd].getPeakValue();
174 if (posValue > 0. && negValue < 0.) {
175 naiveCentroid(
source, exposure, peaks[negInd].getI(),
185 double posValue,
double negValue)
const {
187 double pos_x, pos_y, pos_f;
188 double neg_x, neg_y, neg_f;
219 class NaiveDipoleFootprinter {
221 explicit NaiveDipoleFootprinter() : _sumPositive(0.0), _sumNegative(0.0), _numPositive(0),
226 _sumPositive = _sumNegative = 0.0;
227 _numPositive = _numNegative = 0;
236 _sumPositive += ival;
237 _varPositive += vval;
240 _sumNegative += ival;
241 _varPositive += vval;
246 double getSumPositive()
const {
return _sumPositive; }
247 double getSumNegative()
const {
return _sumNegative; }
248 double getVarPositive()
const {
return _sumPositive; }
249 double getVarNegative()
const {
return _sumNegative; }
250 int getNumPositive()
const {
return _numPositive; }
251 int getNumNegative()
const {
return _numNegative; }
274 NaiveDipoleFootprinter functor;
280 source.set(_numPositiveKey, functor.getNumPositive());
284 source.set(_numNegativeKey, functor.getNumNegative());
305 _psfDipoleFlux(psfDipoleFlux),
309 double Up()
const {
return _errorDef; }
325 if ((negFlux > 0.0) || (posFlux < 0.0)) {
330 posCenterX, posCenterY, posFlux);
331 double chi2 = fit.first;
332 int nPix = fit.second;
333 if (nPix > _maxPix) {
355 double negCenterX,
double negCenterY,
double negFlux,
356 double posCenterX,
double posCenterY,
double posFlux
375 footprint->getBBox());
391 negModelSubim += negSubim;
402 posModelSubim += posSubim;
407 residuals += posModel;
409 residuals *= residuals;
411 afwMath::Statistics stats = afwMath::makeStatistics(residuals, afwMath::SUM | afwMath::NPOINT);
413 int nPix = stats.
getValue(afwMath::NPOINT);
427 (boost::format(
"No footprint for source %d") %
source.getId()).str());
432 if (peakCatalog.
size() == 0) {
434 (boost::format(
"No peak for source %d") %
source.getId()).str());
436 else if (peakCatalog.
size() == 1) {
448 ROOT::Minuit2::MnUserParameters fitPar;
465 ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar);
470 ROOT::Minuit2::FunctionMinimum
min = migrad(_ctrl.
maxFnCalls);
472 float minChi2 =
min.Fval();
489 double evalChi2 = fit.first;
490 int nPix = fit.second;
502 source.set(_chi2dofKey, evalChi2 / (nPix - minimizerFunc.
getNpar()));
503 source.set(_negCentroid.
getX(), minNegCentroid->getX());
504 source.set(_negCentroid.
getY(), minNegCentroid->getY());
505 source.set(_posCentroid.
getX(), minPosCentroid->getX());
506 source.set(_posCentroid.
getY(), minPosCentroid->getY());
507 source.set(_avgCentroid.
getX(), 0.5*(minNegCentroid->getX() + minPosCentroid->getX()));
508 source.set(_avgCentroid.
getY(), 0.5*(minNegCentroid->getY() + minPosCentroid->getY()));