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"
47#include "ndarray/eigen.h"
55namespace lsst {
namespace ip {
namespace diffim {
58meas::base::FlagDefinitionList dipoleFluxFlagDefinitions;
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");
66 return dipoleFluxFlagDefinitions;
78 return dipoleCentroidFlagDefinitions;
99 ImageT
const&
image = *exposure.getMaskedImage().getImage();
101 source.set(keys.getX(), center.getX());
102 source.set(keys.getY(), center.getY());
104 int x = center.getX() -
image.getX0();
105 int y = center.getY() -
image.getY0();
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")
113 ImageT::xy_locator im =
image.xy_at(
x,
y);
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));
123 (boost::format(
"Object at (%d, %d) has no counts") %
128 -im(-1, 1) + im( 1, 1) +
129 -im(-1, 0) + im( 1, 0) +
130 -im(-1, -1) + im( 1, -1);
132 (im(-1, 1) + im( 0, 1) + im( 1, 1)) -
133 (im(-1, -1) + im( 0, -1) + im( 1, -1));
137 source.set(keys.getX(), xx);
138 source.set(keys.getY(), yy);
162 double posValue = peaks[posInd].getPeakValue(), negValue = 0;
164 posInd = peaks.
size() - 1;
165 posValue = peaks[posInd].getPeakValue();
167 naiveCentroid(source, exposure, peaks[posInd].getI(),
170 if (posValue > 0. && posInd == 0 && peaks.
size() > 1) {
171 int negInd = peaks.
size() - 1;
172 negValue = peaks[negInd].getPeakValue();
173 if (posValue > 0. && negValue < 0.) {
174 naiveCentroid(source, exposure, peaks[negInd].getI(),
184 double posValue,
double negValue)
const {
186 double pos_x, pos_y, pos_f;
187 double neg_x, neg_y, neg_f;
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));
218class NaiveDipoleFootprinter {
220 explicit NaiveDipoleFootprinter() : _sumPositive(0.0), _sumNegative(0.0), _numPositive(0),
225 _sumPositive = _sumNegative = 0.0;
226 _numPositive = _numNegative = 0;
235 _sumPositive += ival;
236 _varPositive += vval;
239 _sumNegative += ival;
240 _varPositive += vval;
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; }
273 NaiveDipoleFootprinter functor;
274 source.getFootprint()->getSpans()->applyFunctor(functor, *(exposure.getMaskedImage().getImage()),
275 *(exposure.getMaskedImage().getVariance()));
278 source.set(
getPositiveKeys().getInstFluxErr(), ::sqrt(functor.getVarPositive()));
279 source.set(_numPositiveKey, functor.getNumPositive());
282 source.set(
getNegativeKeys().getInstFluxErr(), ::sqrt(functor.getVarNegative()));
283 source.set(_numNegativeKey, functor.getNumNegative());
304 _psfDipoleFlux(psfDipoleFlux),
308 double Up()
const {
return _errorDef; }
324 if ((negFlux > 0.0) || (posFlux < 0.0)) {
329 posCenterX, posCenterY, posFlux);
330 double chi2 = fit.first;
331 int nPix = fit.second;
332 if (nPix > _maxPix) {
354 double negCenterX,
double negCenterY,
double negFlux,
355 double posCenterX,
double posCenterY,
double posFlux
374 footprint->getBBox());
390 negModelSubim += negSubim;
401 posModelSubim += posSubim;
406 residuals += posModel;
408 residuals *= residuals;
426 (boost::format(
"No footprint for source %d") % source.getId()).str());
431 if (peakCatalog.
size() == 0) {
433 (boost::format(
"No peak for source %d") % source.getId()).str());
435 else if (peakCatalog.
size() == 1) {
447 ROOT::Minuit2::MnUserParameters fitPar;
464 ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar);
469 ROOT::Minuit2::FunctionMinimum
min = migrad(_ctrl.
maxFnCalls);
471 float minChi2 =
min.Fval();
488 double evalChi2 = fit.first;
489 int nPix = fit.second;
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()));
table::Key< std::string > name
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Record class that represents a peak in a Footprint.
float getPeakValue() const
A class to contain the data, WCS, and other information needed to describe an image of the sky.
PixelT Pixel
A pixel in this ImageBase.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
A class to represent a 2-dimensional array of pixels.
A class to manipulate images, masks, and variance as a single object.
A class to evaluate image statistics.
double getValue(Property const prop=NOTHING) const
Return the value of the desired property (if specified in the constructor)
size_type size() const
Return the number of elements in the catalog.
reference back() const
Return the last record.
reference front() const
Return the first record.
Defines the fields and offsets for a table.
Record class that contains measurements made on a single exposure.
An integer coordinate rectangle.
int getMinY() const noexcept
int getMinX() const noexcept
int getMaxX() const noexcept
int getMaxY() const noexcept
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
meas::base::FlagHandler _flagHandler
static meas::base::FlagDefinition const FAILURE
Class to minimize PsfDipoleFlux; this is the object that Minuit minimizes.
void setMaxPix(int maxPix)
void setErrorDef(double def)
virtual double operator()(std::vector< double > const ¶ms) 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
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.
Reports attempts to exceed implementation-defined length limits for some classes.
Reports errors that are due to events beyond the control of the program.
afw::table::CatalogT< PeakRecord > PeakCatalog
double indexToPosition(double ind)
Convert image index to image position.
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)
@ SUM
find sum of pixels in the image
@ NPOINT
number of sample points
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...