27#include "boost/format.hpp"
48 flagDefinitions.add(
"flag_unweightedBad",
"Both weighted and unweighted moments were invalid");
50 "flag_unweighted",
"Weighted moments converged to an invalid value; using unweighted moments");
52 flagDefinitions.add(
"flag_shift",
"centroid shifted by more than the maximum allowed amount");
54 flagDefinitions.add(
"flag_maxIter",
"Too many iterations in adaptive moments");
56 flagDefinitions.add(
"flag_psf",
"Failure in measuring PSF model shape");
62typedef Eigen::Matrix<double, 4, 4, Eigen::DontAlign> Matrix4d;
80 float const sigma11W = shape.
xx;
81 float const sigma12W = shape.
xy;
82 float const sigma22W = shape.
yy;
84 double const D = sigma11W * sigma22W - sigma12W * sigma12W;
92 if (bkgd_var <= 0.0) {
94 (boost::format(
"Background variance must be positive (saw %g)") % bkgd_var).str());
96 double const F =
geom::PI * sqrt(D) / bkgd_var;
102 double fac = F * A / (4.0 * D);
104 fisher(0, 1) = fac * sigma22W;
105 fisher(1, 0) = fisher(0, 1);
106 fisher(0, 2) = fac * sigma11W;
107 fisher(2, 0) = fisher(0, 2);
108 fisher(0, 3) = -fac * 2 * sigma12W;
109 fisher(3, 0) = fisher(0, 3);
111 fac = 3.0 * F * A * A / (16.0 * D * D);
112 fisher(1, 1) = fac * sigma22W * sigma22W;
113 fisher(2, 2) = fac * sigma11W * sigma11W;
114 fisher(3, 3) = fac * 4.0 * (sigma12W * sigma12W + D / 3.0);
116 fisher(1, 2) = fisher(3, 3) / 4.0;
117 fisher(2, 1) = fisher(1, 2);
118 fisher(1, 3) = fac * (-2 * sigma22W * sigma12W);
119 fisher(3, 1) = fisher(1, 3);
120 fisher(2, 3) = fac * (-2 * sigma11W * sigma12W);
121 fisher(3, 2) = fisher(2, 3);
128template <
typename ImageT>
130 typedef ImageT Image;
132 static bool const hasVariance =
false;
134 Image
const &getImage(ImageT
const &image)
const {
return image; }
143 static bool const hasVariance =
true;
145 Image
const &getImage(afw::image::MaskedImage<T>
const &mimage)
const {
return *mimage.getImage(); }
147 double getVariance(afw::image::MaskedImage<T>
const &mimage,
int ix,
int iy) {
148 return mimage.
at(ix, iy).variance();
153std::tuple<std::pair<bool, double>, double, double,
double> getWeights(
double sigma11,
double sigma12,
159 double const det = sigma11 * sigma22 - sigma12 * sigma12;
167bool shouldInterp(
double sigma11,
double sigma22,
double det) {
168 float const xinterp = 0.25;
169 return (sigma11 < xinterp || sigma22 < xinterp || det < xinterp * xinterp);
175geom::Box2I computeAdaptiveMomentsBBox(geom::Box2I
const &bbox,
180 double maxRadius = 1000
184 geom::Box2I result(geom::Box2D(center - offset, center + offset));
193template <
typename ImageT>
194static void calcmom(ImageT
const &
image,
195 float xcen,
float ycen,
199 double w11,
double w12,
double w22,
206 double sum, sumx, sumy, sumxx, sumyy, sumxy, sums4;
208 if (w11 < 0 || w11 > 1e6 ||
fabs(w12) > 1E6 || w22 < 0 || w22 > 1e6) {
209 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
"Invalid weight parameter(s)");
212 sum = sumx = sumy = sumxx = sumxy = sumyy = sums4 = 0;
214 int const ix0 = bbox.getMinX();
215 int const ix1 = bbox.getMaxX();
216 int const iy0 = bbox.getMinY();
217 int const iy1 = bbox.getMaxY();
219 if (ix0 < 0 || ix1 >=
image.getWidth() || iy0 < 0 || iy1 >=
image.getHeight()) {
220 throw LSST_EXCEPT(pex::exceptions::LengthError,
"Invalid image dimensions");
223 for (
int i = iy0; i <= iy1; ++i) {
224 typename ImageT::x_iterator ptr =
image.x_at(ix0, i);
225 float const y = i - ycen;
226 float const y2 = y * y;
227 float const yl = y - 0.375;
228 float const yh = y + 0.375;
229 for (
int j = ix0; j <= ix1; ++j, ++ptr) {
232 float const xl = x - 0.375;
233 float const xh = x + 0.375;
235 float expon = xl * xl * w11 + yl * yl * w22 + 2.0 * xl * yl * w12;
236 tmp = xh * xh * w11 + yh * yh * w22 + 2.0 * xh * yh * w12;
237 expon = (expon > tmp) ? expon : tmp;
238 tmp = xl * xl * w11 + yh * yh * w22 + 2.0 * xl * yh * w12;
239 expon = (expon > tmp) ? expon : tmp;
240 tmp = xh * xh * w11 + yl * yl * w22 + 2.0 * xh * yl * w12;
241 expon = (expon > tmp) ? expon : tmp;
245 for (Y = yl;
Y <= yh;
Y += 0.25) {
246 double const interpY2 =
Y *
Y;
247 for (X = xl;
X <= xh;
X += 0.25) {
248 double const interpX2 =
X *
X;
249 double const interpXy =
X *
Y;
250 expon = interpX2 * w11 + 2 * interpXy * w12 + interpY2 * w22;
253 ymod = tmod * weight;
261 float expon = x2 * w11 + 2 * xy * w12 + y2 * w22;
266 ymod = tmod * weight;
277template <
typename ImageT>
278static int calcmom(ImageT
const &
image,
279 float xcen,
float ycen,
283 double w11,
double w12,
double w22,
286 double &psumx,
double &psumy,
287 double &psumxx,
double &psumxy,
double &psumyy,
289 bool negative =
false) {
294 double sum, sumx, sumy, sumxx, sumyy, sumxy, sums4;
296 if (w11 < 0 || w11 > 1e6 ||
fabs(w12) > 1E6 || w22 < 0 || w22 > 1e6) {
297 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
"Invalid weight parameter(s)");
300 sum = sumx = sumy = sumxx = sumxy = sumyy = sums4 = 0;
302 int const ix0 = bbox.getMinX();
303 int const ix1 = bbox.getMaxX();
304 int const iy0 = bbox.getMinY();
305 int const iy1 = bbox.getMaxY();
307 if (ix0 < 0 || ix1 >=
image.getWidth() || iy0 < 0 || iy1 >=
image.getHeight()) {
308 throw LSST_EXCEPT(pex::exceptions::LengthError,
"Invalid image dimensions");
311 for (
int i = iy0; i <= iy1; ++i) {
312 typename ImageT::x_iterator ptr =
image.x_at(ix0, i);
313 float const y = i - ycen;
314 float const y2 = y * y;
315 float const yl = y - 0.375;
316 float const yh = y + 0.375;
317 for (
int j = ix0; j <= ix1; ++j, ++ptr) {
320 float const xl = x - 0.375;
321 float const xh = x + 0.375;
323 float expon = xl * xl * w11 + yl * yl * w22 + 2.0 * xl * yl * w12;
324 tmp = xh * xh * w11 + yh * yh * w22 + 2.0 * xh * yh * w12;
325 expon = (expon > tmp) ? expon : tmp;
326 tmp = xl * xl * w11 + yh * yh * w22 + 2.0 * xl * yh * w12;
327 expon = (expon > tmp) ? expon : tmp;
328 tmp = xh * xh * w11 + yl * yl * w22 + 2.0 * xh * yl * w12;
329 expon = (expon > tmp) ? expon : tmp;
333 for (Y = yl;
Y <= yh;
Y += 0.25) {
334 double const interpY2 =
Y *
Y;
335 for (X = xl;
X <= xh;
X += 0.25) {
336 double const interpX2 =
X *
X;
337 double const interpXy =
X *
Y;
338 expon = interpX2 * w11 + 2 * interpXy * w12 + interpY2 * w22;
341 ymod = tmod * weight;
343 sumx += ymod * (
X + xcen);
344 sumy += ymod * (
Y + ycen);
345 sumxx += interpX2 * ymod;
346 sumxy += interpXy * ymod;
347 sumyy += interpY2 * ymod;
348 sums4 += expon * expon * ymod;
355 float expon = x2 * w11 + 2 * xy * w12 + y2 * w22;
360 ymod = tmod * weight;
367 sums4 += expon * expon * ymod;
374 std::tuple<std::pair<bool, double>, double, double,
double>
const weights = getWeights(w11, w12, w22);
375 double const detW = std::get<1>(weights) * std::get<3>(weights) -
std::pow(std::get<2>(weights), 2);
390 return (sum < 0 && sumxx < 0 && sumyy < 0) ? 0 : -1;
392 return (sum > 0 && sumxx > 0 && sumyy > 0) ? 0 : -1;
401template <
typename ImageT>
402bool getAdaptiveMoments(ImageT
const &mimage,
double bkgd,
double xcen,
double ycen,
double shiftmax,
403 SdssShapeResult *shape,
int maxIter,
float tol1,
float tol2,
bool negative) {
407 double sumxx, sumxy, sumyy;
409 float const xcen0 = xcen;
410 float const ycen0 = ycen;
412 double sigma11W = 1.5;
413 double sigma12W = 0.0;
414 double sigma22W = 1.5;
416 double w11 = -1, w12 = -1, w22 = -1;
417 float e1_old = 1e6, e2_old = 1e6;
418 float sigma11_ow_old = 1e6;
420 typename ImageAdaptor<ImageT>::Image
const &
image = ImageAdaptor<ImageT>().getImage(mimage);
428 bool interpflag =
false;
433 sigma11W, sigma12W, sigma22W);
434 std::tuple<std::pair<bool, double>, double, double,
double> weights =
435 getWeights(sigma11W, sigma12W, sigma22W);
436 if (!std::get<0>(weights).first) {
441 double const detW = std::get<0>(weights).second;
446 const double ow11 = w11;
447 const double ow12 = w12;
448 const double ow22 = w22;
450 w11 = std::get<1>(weights);
451 w12 = std::get<2>(weights);
452 w22 = std::get<3>(weights);
454 if (shouldInterp(sigma11W, sigma22W, detW)) {
458 sigma11_ow_old = 1.e6;
467 if (calcmom(
image, xcen, ycen, bbox, bkgd, interpflag, w11, w12, w22, I0, sum, sumx, sumy,
468 sumxx, sumxy, sumyy, sums4, negative) < 0) {
473 shape->x = sumx / sum;
474 shape->y = sumy / sum;
476 if (
fabs(shape->x - xcen0) > shiftmax ||
fabs(shape->y - ycen0) > shiftmax) {
482 float const sigma11_ow = sumxx / sum;
483 float const sigma22_ow = sumyy / sum;
484 float const sigma12_ow = sumxy / sum;
486 if (sigma11_ow <= 0 || sigma22_ow <= 0) {
491 float const d = sigma11_ow + sigma22_ow;
492 float const e1 = (sigma11_ow - sigma22_ow) / d;
493 float const e2 = 2.0 * sigma12_ow / d;
497 if (iter > 0 &&
fabs(e1 - e1_old) < tol1 &&
fabs(e2 - e2_old) < tol1 &&
498 fabs(sigma11_ow / sigma11_ow_old - 1.0) < tol2) {
504 sigma11_ow_old = sigma11_ow;
529 float ow11, ow12, ow22;
531 std::tuple<std::pair<bool, double>, double, double,
double> weights =
532 getWeights(sigma11_ow, sigma12_ow, sigma22_ow);
533 if (!std::get<0>(weights).first) {
538 ow11 = std::get<1>(weights);
539 ow12 = std::get<2>(weights);
540 ow22 = std::get<3>(weights);
546 weights = getWeights(n11, n12, n22);
547 if (!std::get<0>(weights).first) {
553 sigma11W = std::get<1>(weights);
554 sigma12W = std::get<2>(weights);
555 sigma22W = std::get<3>(weights);
558 if (sigma11W <= 0 || sigma22W <= 0) {
564 if (iter == maxIter) {
569 if (sumxx + sumyy == 0.0) {
578 if (calcmom(
image, xcen, ycen, bbox, bkgd, interpflag, w11, w12, w22, I0, sum, sumx, sumy,
579 sumxx, sumxy, sumyy, ignored, negative) < 0 ||
580 (!negative && sum <= 0) || (negative && sum >= 0)) {
585 shape->xx = 1 / 12.0;
587 shape->yy = 1 / 12.0;
593 sigma11W = sumxx / sum;
594 sigma12W = sumxy / sum;
595 sigma22W = sumyy / sum;
598 shape->instFlux = I0;
599 shape->xx = sigma11W;
600 shape->xy = sigma12W;
601 shape->yy = sigma22W;
603 if (shape->xx + shape->yy != 0.0) {
607 if (ix >= 0 && ix < mimage.getWidth() && iy >= 0 && iy < mimage.getHeight()) {
608 float const bkgd_var = ImageAdaptor<ImageT>().getVariance(
611 if (bkgd_var > 0.0) {
613 Matrix4d fisher = calc_fisher(*shape, bkgd_var);
614 Matrix4d cov = fisher.inverse();
616 shape->instFluxErr =
std::sqrt(cov(0, 0));
620 shape->instFlux_xx_Cov = cov(0, 1);
621 shape->instFlux_yy_Cov = cov(0, 2);
622 shape->instFlux_xy_Cov = cov(0, 3);
623 shape->xx_yy_Cov = cov(1, 2);
624 shape->xx_xy_Cov = cov(1, 3);
625 shape->yy_xy_Cov = cov(2, 3);
652 r._includePsf =
true;
654 schema, schema.
join(name,
"psf"),
"adaptive moments of the PSF model at the object position");
656 r._includePsf =
false;
661 (boost::format(
"uncertainty covariance between %s and %s") %
662 schema.
join(name,
"instFlux") % schema.
join(name,
"xx"))
667 (boost::format(
"uncertainty covariance between %s and %s") %
668 schema.
join(name,
"instFlux") % schema.
join(name,
"yy"))
673 (boost::format(
"uncertainty covariance between %s and %s") %
674 schema.
join(name,
"instFlux") % schema.
join(name,
"xy"))
692 _instFlux_xx_Cov(s[
"instFlux"][
"xx"][
"Cov"]),
693 _instFlux_yy_Cov(s[
"instFlux"][
"yy"][
"Cov"]),
694 _instFlux_xy_Cov(s[
"instFlux"][
"xy"][
"Cov"]) {
711 static_cast<FluxResult &
>(result) = record.
get(_instFluxResult);
717 result.
flags[n] = _flagHandler.getValue(record, n);
723 return record.
get(_psfShapeResult);
727 record.
set(_shapeResult, value);
728 record.
set(_centroidResult, value);
729 record.
set(_instFluxResult, value);
735 _flagHandler.setValue(record, n, value.
flags[n]);
741 record.
set(_psfShapeResult, value);
745 return _shapeResult == other._shapeResult && _centroidResult == other._centroidResult &&
746 _instFluxResult == other._instFluxResult && _psfShapeResult == other._psfShapeResult &&
747 _instFlux_xx_Cov == other._instFlux_xx_Cov && _instFlux_yy_Cov == other._instFlux_yy_Cov &&
748 _instFlux_xy_Cov == other._instFlux_xy_Cov;
753 return _shapeResult.
isValid() && _centroidResult.isValid() && _instFluxResult.isValid() &&
754 _psfShapeResult.isValid() && _instFlux_xx_Cov.isValid() && _instFlux_yy_Cov.isValid() &&
755 _instFlux_xy_Cov.isValid();
762 _resultKey(
ResultKey::addFields(schema, name, ctrl.doMeasurePsf)),
763 _centroidExtractor(schema, name) {}
765template <
typename ImageT>
767 bool negative,
Control const &control) {
768 double xcen = center.getX();
769 double ycen = center.getY();
771 xcen -=
image.getX0();
772 ycen -=
image.getY0();
777 }
else if (shiftmax > 10) {
785 control.
tol1, control.
tol2, negative);
797 double epsilon = 1.0e-6;
798 if (IxxIyy < (1.0 + epsilon) * Ixy_sq)
804 (boost::format(
"computeAdaptiveMoments IxxIxy %d < (1 + eps=%d)*(Ixy^2=%d);"
805 " implying singular moments without any flag set")
806 % IxxIyy % epsilon % Ixy_sq).str());
821 result.
x +=
image.getX0();
822 result.
y +=
image.getY0();
824 if (ImageAdaptor<ImageT>::hasVariance) {
833template <
typename ImageT>
848 if (!std::get<0>(weights).first) {
852 double const w11 = std::get<1>(weights);
853 double const w12 = std::get<2>(weights);
854 double const w22 = std::get<3>(weights);
855 bool const interp = shouldInterp(shape.
getIxx(), shape.
getIyy(), std::get<0>(weights).second);
858 calcmom(ImageAdaptor<ImageT>().getImage(
image), localCenter.getX(), localCenter.getY(), bbox,
859 0.0, interp, w11, w12, w22, sum0);
863 if (ImageAdaptor<ImageT>::hasVariance) {
864 int ix =
static_cast<int>(center.getX() -
image.getX0());
865 int iy =
static_cast<int>(center.getY() -
image.getY0());
868 (boost::format(
"Center (%d,%d) not in image (%dx%d)") % ix % iy %
872 double var = ImageAdaptor<ImageT>().getVariance(
image, ix, iy);
883 bool negative =
false;
886 negative = measRecord.
get(measRecord.
getSchema().
find<afw::table::Flag>(
"is_negative").key);
887 }
catch (pexExcept::Exception &e) {
890 exposure.
getMaskedImage(), _centroidExtractor(measRecord, _resultKey.getFlagHandler()), negative,
893 if (_ctrl.doMeasurePsf) {
906 _resultKey.setPsfShape(measRecord, psf->computeShape(
geom::Point2D(result.
x, result.
y)));
913 measRecord.
set(_resultKey, result);
917 _resultKey.getFlagHandler().handleFailure(measRecord, error);
920#define INSTANTIATE_IMAGE(IMAGE) \
921 template SdssShapeResult SdssShapeAlgorithm::computeAdaptiveMoments( \
922 IMAGE const &, geom::Point2D const &, bool, Control const &); \
923 template FluxResult SdssShapeAlgorithm::computeFixedMomentsFlux( \
924 IMAGE const &, afw::geom::ellipses::Quadrupole const &, geom::Point2D const &)
926#define INSTANTIATE_PIXEL(PIXEL) \
927 INSTANTIATE_IMAGE(afw::image::Image<PIXEL>); \
928 INSTANTIATE_IMAGE(afw::image::MaskedImage<PIXEL>);
936 :
BaseTransform{name}, _instFluxTransform{name, mapper}, _centroidTransform{name, mapper} {
955 "PSF shape in celestial moments",
956 afw::table::CoordinateType::CELESTIAL);
965 _instFluxTransform(inputCatalog, outputCatalog, wcs, photoCalib);
966 _centroidTransform(inputCatalog, outputCatalog, wcs, photoCalib);
978 for (; inSrc != inputCatalog.
end(); ++inSrc, ++outSrc) {
991 _outShapeKey.set(*outSrc, outShape);
#define LSST_EXCEPT(type,...)
#define INSTANTIATE_PIXEL(PIXEL)
lsst::geom::AffineTransform linearizePixelToSky(lsst::geom::SpherePoint const &coord, lsst::geom::AngleUnit const &skyUnit) const
Transformer transform(lsst::geom::LinearTransform const &transform)
double const getIxy() const
double getDeterminant() const
double const getIxx() const
double const getIyy() const
MaskedImageT getMaskedImage()
std::shared_ptr< lsst::afw::detection::Psf const > getPsf() const
iterator at(int x, int y) const
lsst::afw::image::Image< ImagePixelT > Image
Field< T >::Value get(Key< T > const &key) const
void set(Key< T > const &key, U const &value)
CatalogIterator< typename Internal::iterator > iterator
bool isValid() const noexcept
geom::ellipses::Quadrupole get(BaseRecord const &record) const override
static QuadrupoleKey addFields(Schema &schema, std::string const &name, std::string const &doc, CoordinateType coordType=CoordinateType::PIXEL)
std::string join(std::string const &a, std::string const &b) const
std::set< std::string > getNames(bool topOnly=false) const
Key< T > addField(Field< T > const &field, bool doReplace=false)
SchemaItem< T > find(std::string const &name) const
Key< T > addMapping(Key< T > const &inputKey, bool doReplace=false)
Schema & editOutputSchema()
Schema const getInputSchema() const
typename Base::const_iterator const_iterator
A FunctorKey for CentroidResult.
virtual CentroidResult get(afw::table::BaseRecord const &record) const
Get a CentroidResult from the given record.
static CentroidResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc, UncertaintyEnum uncertainty)
Add the appropriate fields to a Schema, and return a CentroidResultKey that manages them.
vector-type utility class to build a collection of FlagDefinitions
std::size_t size() const
return the current size (number of defined elements) of the collection
FlagHandler()
Each error should have a corresponding static FlagDefinition object.
static FlagHandler addFields(afw::table::Schema &schema, std::string const &prefix, FlagDefinitionList const &flagDefs, FlagDefinitionList const &exclDefs=FlagDefinitionList::getEmptyList())
Add Flag fields to a schema, creating a FlagHandler object to manage them.
static FluxResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc)
Add a pair of _instFlux, _instFluxErr fields to a Schema, and return a FluxResultKey that points to t...
Exception to be thrown when a measurement algorithm experiences a known failure mode.
static FlagDefinition const SHIFT
static FlagDefinitionList const & getFlagDefinitions()
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 Result computeAdaptiveMoments(ImageT const &image, geom::Point2D const &position, bool negative=false, Control const &ctrl=Control())
Compute the adaptive Gaussian-weighted moments of an image.
static FlagDefinition const FAILURE
static unsigned int const N_FLAGS
static FluxResult computeFixedMomentsFlux(ImageT const &image, afw::geom::ellipses::Quadrupole const &shape, geom::Point2D const &position)
Compute the instFlux within a fixed Gaussian aperture.
static FlagDefinition const MAXITER
static FlagDefinition const UNWEIGHTED
SdssShapeResultKey ResultKey
static FlagDefinition const PSF_SHAPE_BAD
static FlagDefinition const UNWEIGHTED_BAD
SdssShapeAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
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.
double maxShift
"Maximum centroid shift, limited to 2-10" ;
int maxIter
"Maximum number of iterations" ;
float tol2
"Convergence tolerance for FWHM" ;
float tol1
"Convergence tolerance for e1,e2" ;
double background
"Additional value to add to background" ;
Result object SdssShapeAlgorithm.
ErrElement instFlux_yy_Cov
instFlux, yy term in the uncertainty covariance matrix
SdssShapeResult()
Constructor; initializes everything to NaN.
ErrElement instFlux_xy_Cov
instFlux, xy term in the uncertainty covariance matrix
std::bitset< SdssShapeAlgorithm::N_FLAGS > flags
Status flags (see SdssShapeAlgorithm).
ErrElement instFlux_xx_Cov
instFlux, xx term in the uncertainty covariance matrix
SdssShapeResultKey()
Default constructor; instance will not be usuable unless subsequently assigned to.
virtual SdssShapeResult get(afw::table::BaseRecord const &record) const
Get an SdssShapeResult from the given record.
static SdssShapeResultKey addFields(afw::table::Schema &schema, std::string const &name, bool doMeasurePsf)
Add the appropriate fields to a Schema, and return a SdssShapeResultKey that manages them.
virtual afw::geom::ellipses::Quadrupole getPsfShape(afw::table::BaseRecord const &record) const
Get a Quadrupole for the Psf from the given record.
bool isValid() const
Return True if the key is valid.
bool operator==(SdssShapeResultKey const &other) const
Compare the FunctorKey for equality with another, using the underlying Keys.
virtual void set(afw::table::BaseRecord &record, SdssShapeResult const &value) const
Set an SdssShapeResult in the given record.
virtual void setPsfShape(afw::table::BaseRecord &record, afw::geom::ellipses::Quadrupole const &value) const
Set a Quadrupole for the Psf at the position of the given record.
A FunctorKey for ShapeResult.
static ShapeResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc, UncertaintyEnum uncertainty, afw::table::CoordinateType coordType=afw::table::CoordinateType::PIXEL)
Add the appropriate fields to a Schema, and return a ShapeResultKey that manages them.
virtual ShapeResult get(afw::table::BaseRecord const &record) const
Get a ShapeResult from the given record.
PointD offset(PointD point1, PointD point2, double offset) const
int positionToIndex(double pos)
CatalogT< BaseRecord > BaseCatalog
SortedCatalogT< SourceRecord > SourceCatalog
Extent< double, 2 > Extent2D
AngleUnit constexpr radians
Point< double, 2 > Point2D
@ SIGMA_ONLY
Only the diagonal elements of the covariance matrix are provided.
@ FULL_COVARIANCE
The full covariance matrix is provided.
@ NO_UNCERTAINTY
Algorithm provides no uncertainy information at all.
Eigen::Matrix< ShapeElement, 3, 3, Eigen::DontAlign > ShapeTrMatrix
ShapeTrMatrix makeShapeTransformMatrix(geom::LinearTransform const &xform)
Construct a matrix suitable for transforming second moments.
A reusable struct for centroid measurements.
CentroidElement y
y (row) coordinate of the measured position
Centroid const getCentroid() const
Return a Point object containing the measured x and y.
CentroidElement x
x (column) coordinate of the measured position
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...
A reusable result struct for instFlux measurements.
meas::base::Flux instFlux
Measured instFlux in DN.
meas::base::FluxErrElement instFluxErr
Standard deviation of instFlux in DN.
A reusable struct for moments-based shape measurements.
Shape const getShape() const
Return an afw::geom::ellipses object corresponding to xx, yy, xy.
ShapeCov const getShapeErr() const
Return the 3x3 symmetric covariance matrix, with rows and columns ordered (xx, yy,...
afw::geom::ellipses::Quadrupole getQuadrupole()
void setShape(Shape const &shape)
Set struct elements from the given Quadrupole object.
ShapeElement xy
image or model second moment for xy^2
ShapeElement xx
image or model second moment for x^2
void setShapeErr(ShapeCov const &matrix)
Set the struct standard deviation elements from the given matrix, with rows and columns ordered (xx,...
ShapeElement yy
image or model second moment for y^2