lsst.meas.extensions.photometryKron
20.0.0-4-g66bcc37+f1010e24e6
|
Go to the documentation of this file.
27 #include "boost/algorithm/string.hpp"
28 #include "boost/math/constants/constants.hpp"
48 namespace extensions {
49 namespace photometryKron {
52 base::FlagDefinitionList flagDefinitions;
55 base::FlagDefinition
const KronFluxAlgorithm::FAILURE = flagDefinitions.addFailureFlag(
"general failure flag, set if anything went wrong");
56 base::FlagDefinition
const KronFluxAlgorithm::EDGE = flagDefinitions.add(
"flag_edge",
"bad measurement due to image edge");
63 base::FlagDefinition
const KronFluxAlgorithm::SMALL_RADIUS = flagDefinitions.add(
"flag_small_radius",
"measured Kron radius was smaller than that of the PSF");
64 base::FlagDefinition
const KronFluxAlgorithm::BAD_SHAPE = flagDefinitions.add(
"flag_bad_shape",
"shape for measuring Kron radius is bad; used PSF shape");
67 return flagDefinitions;
75 template <
typename MaskedImageT>
78 explicit FootprintFlux() : _sum(0.0), _sumVar(0.0) {}
88 typename MaskedImageT::Image::Pixel
const & ival,
89 typename MaskedImageT::Variance::Pixel
const & vval) {
95 double getSum()
const {
return _sum; }
98 double getSumVar()
const {
return _sumVar; }
116 template <
typename MaskedImageT,
typename WeightImageT>
117 class FootprintFindMoment {
119 FootprintFindMoment(MaskedImageT
const& mimage,
123 ) : _xcen(center.getX()), _ycen(center.getY()),
125 _cosTheta(::
cos(theta)),
126 _sinTheta(::
sin(theta)),
127 _sum(0.0), _sumR(0.0),
129 _sumVar(0.0), _sumRVar(0.0),
131 _imageX0(mimage.getX0()), _imageY0(mimage.getY0())
136 void reset(afw::detection::Footprint
const& foot) {
139 _sumVar = _sumRVar = 0.0;
142 MaskedImageT
const& mimage = this->getImage();
143 geom::Box2I
const&
bbox(foot.getBBox());
144 int const x0 =
bbox.getMinX(), y0 =
bbox.getMinY(), x1 =
bbox.getMaxX(), y1 =
bbox.getMaxY();
146 if (x0 < _imageX0 || y0 < _imageY0 ||
147 x1 >= _imageX0 + mimage.getWidth() || y1 >= _imageY0 + mimage.getHeight()) {
149 (boost::format(
"Footprint %d,%d--%d,%d doesn't fit in image %d,%d--%d,%d")
151 % _imageX0 % _imageY0
152 % (_imageX0 + mimage.getWidth() - 1) % (_imageY0 + mimage.getHeight() - 1)
158 void operator()(
geom::Point2I const & pos,
typename MaskedImageT::Image::Pixel
const & ival) {
159 double x =
static_cast<double>(pos.getX());
160 double y =
static_cast<double>(pos.getY());
161 double const dx =
x - _xcen;
162 double const dy =
y - _ycen;
163 double const du = dx*_cosTheta + dy*_sinTheta;
164 double const dv = -dx*_sinTheta + dy*_cosTheta;
166 double r = ::hypot(du, dv*_ab);
168 if (::
hypot(dx, dy) < 0.5) {
180 double const eR = 0.38259771140356325;
188 typename MaskedImageT::Variance::Pixel vval = iloc.variance(0, 0);
190 _sumRVar += r*r*vval;
195 double getIr()
const {
return _sumR/_sum; }
200 double getIrVar()
const {
return _sumRVar/(_sum*_sum) + _sumVar*_sumR*_sumR/::
pow(_sum, 4); }
204 bool getGood()
const {
return _sum > 0 && _sumR > 0; }
210 double const _cosTheta, _sinTheta;
217 int const _imageX0, _imageY0;
233 template<
typename ImageT>
245 bool const smoothImage =
sigma > 0;
246 int kSize = smoothImage ? 2*int(2*
sigma) + 1 : 1;
249 bool const doNormalize =
true, doCopyEdge =
false;
273 FootprintFindMoment<ImageT, afw::detection::Psf::Image> iRFunctor(
279 iRFunctor, *(subImage.getImage()));
287 if (!iRFunctor.getGood()) {
291 radius = iRFunctor.getIr()*sqrt(axes.
getB()/axes.
getA());
292 if (radius <= radius0) {
301 return std::make_shared<KronAperture>(center, axes, radiusForRadius);
305 template<
typename ImageT>
309 double const maxSincRadius
313 if (axes.
getB() > maxSincRadius) {
314 FootprintFlux<ImageT> fluxFunctor;
317 fluxFunctor, *(
image.getImage()), *(
image.getVariance()));
318 return std::make_pair(fluxFunctor.getSum(), ::sqrt(fluxFunctor.getSumVar()));
324 LSST_EXCEPT_ADD(e, (boost::format(
"Measuring Kron flux for object at (%.3f, %.3f);"
325 " aperture radius %g,%g theta %g")
336 double smoothingSigma=0.0
340 double const radius =
psf->computeShape(center).getDeterminantRadius();
345 template<
typename ImageT>
348 double const nRadiusForFlux,
349 double const maxSincRadius
353 axes.
scale(nRadiusForFlux);
374 meas::base::FluxResultKey::addFields(
schema,
name,
"flux from Kron Flux algorithm")
376 _radiusKey(
schema.addField<float>(
name +
"_radius",
"Kron radius (sqrt(a*b))")),
377 _radiusForRadiusKey(
schema.addField<float>(
name +
"_radius_for_radius",
378 "radius used to estimate <radius> (sqrt(a*b))")),
379 _psfRadiusKey(
schema.addField<float>(
name +
"_psf_radius",
"Radius of PSF")),
383 auto metadataName =
name +
"_nRadiusForflux";
384 boost::to_upper(metadataName);
395 void KronFluxAlgorithm::_applyAperture(
429 meas::base::FluxResult fluxResult;
430 fluxResult.instFlux =
result.first;
431 fluxResult.instFluxErr =
result.second;
432 source.set(_fluxResultKey, fluxResult);
439 void KronFluxAlgorithm::_applyForced(
440 afw::table::SourceRecord & source,
441 afw::image::Exposure<float>
const & exposure,
443 afw::table::SourceRecord
const & reference,
444 geom::AffineTransform
const & refToMeas
447 float const radius = reference.get(reference.getSchema().find<
float>(_ctrl.
refRadiusName).key);
448 KronAperture
const aperture(reference, refToMeas, radius);
449 _applyAperture(source, exposure, aperture);
450 if (exposure.getPsf()) {
476 if (!
source.getShapeFlag()) {
487 axes = exposure.
getPsf()->computeShape();
494 footprintAxes.
scale(::sqrt(2));
520 aperture = _fallbackRadius(
source, R_K_psf, e);
523 aperture = _fallbackRadius(
source, R_K_psf, e);
535 double newRadius = rad;
541 }
else if (!exposure.
getPsf()) {
547 }
else if (rad < R_K_psf) {
551 if (newRadius != rad) {
557 _applyAperture(
source, exposure, *aperture);
559 source.set(_psfRadiusKey, R_K_psf);
569 geom::Point2D center = _centroidExtractor(measRecord, _flagHandler);
571 _applyForced(measRecord, exposure, center, refRecord,
586 }
else if (R_K_psf > 0) {
596 PTR(KronAperture) aperture(
new KronAperture(source));
602 #define INSTANTIATE(TYPE) \
603 template PTR(KronAperture) KronAperture::determineRadius<afw::image::MaskedImage<TYPE> >( \
604 afw::image::MaskedImage<TYPE> const&, \
605 afw::geom::ellipses::Axes, \
606 geom::Point2D const&, \
607 KronFluxControl const& \
609 template std::pair<double, double> KronAperture::measureFlux<afw::image::MaskedImage<TYPE> >( \
610 afw::image::MaskedImage<TYPE> const&, \
constexpr double radToDeg(double x) noexcept
std::shared_ptr< lsst::afw::detection::Psf const > getPsf() const
double minimumRadius
"Minimum Kron radius (if == 0.0 use PSF's Kron radius) if enforceMinimumRadius. " "Also functions as ...
static meas::base::FlagDefinition const NO_FALLBACK_RADIUS
meas::base::Flux instFlux
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
CentroidSlotDefinition::MeasValue getCentroid() const
double const getB() const
bool fixed
"if true, use existing shape and centroid measurements instead of fitting" ;
void add(std::string const &name, T const &value)
#define LSST_EXCEPT_ADD(e, m)
KronFluxAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema, daf::base::PropertySet &metadata)
A class that knows how to calculate fluxes using the KRON photometry algorithm.
afw::table::Key< double > sigma
float getRadiusForRadius() const
double const getTheta() const
lsst::geom::AffineTransform linearizeTransform(TransformPoint2ToPoint2 const &original, lsst::geom::Point2D const &inPoint)
C++ control object for Kron flux.
double nSigmaForRadius
"Multiplier of rms size for aperture used to initially estimate the Kron radius" ;
lsst::geom::Box2I growBBox(lsst::geom::Box2I const &bbox) const
Point< double, 2 > Point2D
double getDeterminantRadius() const
MaskedImageT getMaskedImage()
static meas::base::FlagDefinition const USED_PSF_RADIUS
double const getA() const
meas::base::FluxErrElement instFluxErr
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
std::unique_ptr< SchemaItem< U > > result
static afw::geom::ellipses::Axes getKronAxes(afw::geom::ellipses::Axes const &shape, geom::LinearTransform const &transformation, double const radius)
Determine Kron axes from a reference image.
#define INSTANTIATE(TYPE)
double nRadiusForFlux
"Number of Kron radii for Kron flux" ;
lsst::geom::Point2D const & getCenter() const
static meas::base::FlagDefinition const EDGE
bool useFootprintRadius
"Use the Footprint size as part of initial estimate of Kron radius" ;
std::pair< double, double > measureFlux(ImageT const &image, double const nRadiusForFlux, double const maxSincRadius) const
Photometer within the Kron Aperture on an image.
double calculatePsfKronRadius(boost::shared_ptr< afw::detection::Psf const > const &psf, geom::Point2D const ¢er, double smoothingSigma=0.0)
static meas::base::FlagDefinition const BAD_SHAPE
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
static meas::base::FlagDefinition const SMALL_RADIUS
static meas::base::FlagDefinition const BAD_SHAPE_NO_PSF
#define LSST_EXCEPT(type,...)
bool enforceMinimumRadius
"If true check that the Kron radius exceeds some minimum" ;
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
std::pair< double, double > photometer(ImageT const &image, afw::geom::ellipses::Ellipse const &aperture, double const maxSincRadius)
static meas::base::FlagDefinition const FAILURE
static meas::base::FlagDefinition const BAD_RADIUS
std::string refRadiusName
"Name of field specifying reference Kron radius for forced measurement" ;
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, lsst::geom::Point2I offset=lsst::geom::Point2I())
geom::Point2D const & getCenter() const
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
static boost::shared_ptr< KronAperture > determineRadius(ImageT const &image, afw::geom::ellipses::Axes axes, geom::Point2D const ¢er, KronFluxControl const &ctrl)
Determine the Kron Aperture from an image.
double maxSincRadius
"Largest aperture for which to use the slow, accurate, sinc aperture code" ;
Transformer transform(lsst::geom::LinearTransform const &transform)
static meas::base::FlagDefinitionList const & getFlagDefinitions()
BaseCore const & getCore() const
int nIterForRadius
"Number of times to iterate when setting the Kron radius" ;
virtual void fail(afw::table::SourceRecord &measRecord, meas::base::MeasurementError *error=NULL) const
static meas::base::FlagDefinition const NO_MINIMUM_RADIUS
std::shared_ptr< geom::SkyWcs const > getWcs() const
#define LSST_EXCEPTION_TYPE(t, b, c)
afw::geom::ellipses::Axes & getAxes()
virtual void measureForced(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure, afw::table::SourceRecord const &refRecord, afw::geom::SkyWcs const &refWcs) const
void scale(double factor)
static FlagHandler addFields(afw::table::Schema &schema, std::string const &prefix, FlagDefinitionList const &flagDefs, FlagDefinitionList const &exclDefs=FlagDefinitionList::getEmptyList())
static meas::base::FlagDefinition const USED_MINIMUM_RADIUS
double smoothingSigma
"Smooth image with N(0, smoothingSigma^2) Gaussian while estimating R_K" ;