34 #include "lsst/base.h"
35 #include "lsst/afw/geom/Point.h"
36 #include "lsst/afw/geom/Angle.h"
37 #include "lsst/afw/geom/SpanSet.h"
38 #include "lsst/afw/image/ImagePca.h"
39 #include "lsst/afw/image/Exposure.h"
40 #include "lsst/afw/math/SpatialCell.h"
41 #include "lsst/afw/detection/Psf.h"
42 #include "lsst/afw/detection/Footprint.h"
43 #include "lsst/afw/table/Source.h"
44 #include "lsst/meas/base/GaussianCentroid.h"
49 namespace afwDetection = lsst::afw::detection;
50 namespace afwGeom = lsst::afw::geom;
51 namespace afwImage = lsst::afw::image;
52 namespace afwMath = lsst::afw::math;
56 namespace algorithms {
61 CONST_PTR(lsst::afw::detection::Psf) psf,
67 _psfImage = psf->computeImage(afwGeom::PointD(iX, iY));
74 CONST_PTR(lsst::afw::detection::Psf) psf,
78 _psfImage(psf->computeImage(afwGeom::PointD(cen)))
89 template<
typename ImageT>
91 computeFirstMoment(ImageT
const& image,
92 float const xCen,
float const yCen
97 for (
int iY = 0; iY != image->getHeight(); ++iY) {
100 end = image->row_end(iY); ptr != end; ++ptr, ++iX) {
101 double const x = iX - xCen;
102 double const y = iY - yCen;
103 double const r = std::sqrt( x*x + y*y );
104 double const m = (*ptr)*r;
110 std::string errmsg(
"");
112 errmsg =
"sum(I*r) is negative. ";
115 errmsg +=
"sum(I) is <= 0.";
118 throw LSST_EXCEPT(lsst::pex::exceptions::DomainError, errmsg);
129 template<
typename ImageT>
131 computeSecondMoment(ImageT
const& image,
132 float const xCen,
float const yCen
137 for (
int iY = 0; iY != image->getHeight(); ++iY) {
140 end = image->row_end(iY); ptr != end; ++ptr, ++iX) {
141 double const x = iX - xCen;
142 double const y = iY - yCen;
143 double const r2 = x*x + y*y;
144 double const m = (*ptr)*r2;
150 std::string errmsg(
"");
152 errmsg =
"sum(I*r*r) is negative. ";
155 errmsg +=
"sum(I) is <= 0.";
158 throw LSST_EXCEPT(lsst::pex::exceptions::DomainError, errmsg);
168 template<
typename ImageT>
169 std::pair<bool, double>
170 calcmom(ImageT
const& image,
171 float const xCen,
float const yCen,
176 if (fabs(w11) > 1e6) {
177 return std::make_pair(
false, std::numeric_limits<double>::quiet_NaN());
180 double sum = 0, sumrr = 0.0;
182 for (
int i = 0; i < image.getHeight(); ++i) {
183 float const y = i - yCen;
184 float const y2 = y*y;
186 typename ImageT::x_iterator ptr = image.row_begin(i);
187 for (
int j = 0; j < image.getWidth(); ++j, ++ptr) {
188 float const x = j - xCen;
189 float const x2 = x*x;
190 float const expon = (x2 + y2)*w11;
193 float const weight = exp(-0.5*expon);
194 float const tmod = *ptr;
195 float const ymod = tmod*
weight;
197 sumrr += (x2 + y2)*ymod;
202 if (sum <= 0 || sumrr < 0) {
203 return std::make_pair(
false, std::numeric_limits<double>::quiet_NaN());
206 return std::make_pair(
true, 0.5*sumrr/sum);
217 template<
typename ImageT>
219 computeSecondMomentAdaptive(ImageT
const& image,
220 float const xCen,
float const yCen
223 int const MAXIT = 100;
224 float const TOL = 0.0001;
226 float sigma11_ow_old = 1e6;
228 bool unweighted =
false;
230 for (; iter < MAXIT; ++iter) {
231 std::pair<bool, double> moments = calcmom(*image, xCen, yCen, w11);
233 if (not moments.first) {
240 float const sigma11_ow = moments.second;
242 if (iter > 0 && fabs(sigma11_ow/sigma11_ow_old - 1.0) < TOL) {
246 sigma11_ow_old = sigma11_ow;
266 w11 = 1/sigma11_ow - w11;
278 if (iter == MAXIT || unweighted) {
280 std::pair<bool, double> moments = calcmom(*image, xCen, yCen, w11);
283 sigma11W = moments.second;
305 afwImage::MaskedImage<double> mi = afwImage::MaskedImage<double>(_psfImage);
306 typedef afwImage::Exposure<double> Exposure;
307 std::shared_ptr<Exposure> exposure = makeExposure(mi);
308 auto foot = std::make_shared<afwDetection::Footprint>(std::make_shared<afwGeom::SpanSet>(exposure->getBBox(
311 afwGeom::Point2D center(_psfImage->getX0() + _psfImage->getWidth()/2,
312 _psfImage->getY0() + _psfImage->getHeight()/2);
313 double x(center.getX());
314 double y(center.getY());
315 afwGeom::Point2D fittedCenter = base::GaussianCentroidAlgorithm::fitCentroid(*_psfImage, x, y);
316 double const xCen = fittedCenter.getX();
317 double const yCen = fittedCenter.getY();
320 return ::sqrt(0.5*computeSecondMomentAdaptive(_psfImage, xCen, yCen));
322 return ::sqrt(2.0/afwGeom::PI)*computeFirstMoment(_psfImage, xCen, yCen);
324 return ::sqrt(0.5*computeSecondMoment(_psfImage, xCen, yCen));
331 for (
int iY = 0; iY != _psfImage->getHeight(); ++iY) {
334 end = _psfImage->row_end(iY); ptr != end;
336 double const x = iX - xCen;
337 double const y = iY - yCen;
338 double const r = std::sqrt( x*x + y*y );
339 double const m = (*ptr)*r;
340 norm += (*ptr)*(*ptr);
344 return sqrt(sum/norm);
359 for (
int iY = 0; iY != _psfImage->getHeight(); ++iY) {
363 sumsqr += (*ptr)*(*ptr);
366 return sum*sum/sumsqr;
Calculate width as sqrt(n_eff/(4 pi))
PsfAttributes(boost::shared_ptr< lsst::afw::detection::Psf const > psf, int const iX, int const iY)
Constructor for PsfAttributes.
tbl::Key< double > weight
Calculate width using <r^2>
double computeEffectiveArea() const
Compute the effective area of the psf ( sum(I)^2/sum(I^2) )
Calculate width using <r>
Weight <r^2> by I^2 to avoid negative fluxes.
Calculate width using adaptive Gaussian weights.
double computeGaussianWidth(Method how=ADAPTIVE_MOMENT) const
Compute the 'sigma' value for an equivalent gaussian psf.