27 #include "boost/math/constants/constants.hpp" 47 namespace extensions {
48 namespace photometryKron {
51 base::FlagDefinitionList flagDefinitions;
54 base::FlagDefinition
const KronFluxAlgorithm::FAILURE = flagDefinitions.addFailureFlag(
"general failure flag, set if anything went wrong");
55 base::FlagDefinition
const KronFluxAlgorithm::EDGE = flagDefinitions.add(
"flag_edge",
"bad measurement due to image edge");
62 base::FlagDefinition
const KronFluxAlgorithm::SMALL_RADIUS = flagDefinitions.add(
"flag_small_radius",
"measured Kron radius was smaller than that of the PSF");
63 base::FlagDefinition
const KronFluxAlgorithm::BAD_SHAPE = flagDefinitions.add(
"flag_bad_shape",
"shape for measuring Kron radius is bad; used PSF shape");
66 return flagDefinitions;
74 template <
typename MaskedImageT>
77 explicit FootprintFlux() : _sum(0.0), _sumVar(0.0) {}
94 double getSum()
const {
return _sum; }
97 double getSumVar()
const {
return _sumVar; }
115 template <
typename MaskedImageT,
typename WeightImageT>
116 class FootprintFindMoment {
118 FootprintFindMoment(MaskedImageT
const& mimage,
122 ) : _xcen(center.getX()), _ycen(center.getY()),
124 _cosTheta(::
cos(theta)),
125 _sinTheta(::
sin(theta)),
126 _sum(0.0), _sumR(0.0),
128 _sumVar(0.0), _sumRVar(0.0),
130 _imageX0(mimage.getX0()), _imageY0(mimage.getY0())
138 _sumVar = _sumRVar = 0.0;
141 MaskedImageT
const& mimage = this->getImage();
143 int const x0 =
bbox.getMinX(), y0 =
bbox.getMinY(), x1 =
bbox.getMaxX(), y1 =
bbox.getMaxY();
145 if (x0 < _imageX0 || y0 < _imageY0 ||
146 x1 >= _imageX0 + mimage.getWidth() || y1 >= _imageY0 + mimage.getHeight()) {
148 (
boost::format(
"Footprint %d,%d--%d,%d doesn't fit in image %d,%d--%d,%d")
150 % _imageX0 % _imageY0
151 % (_imageX0 + mimage.getWidth() - 1) % (_imageY0 + mimage.getHeight() - 1)
158 double x =
static_cast<double>(pos.getX());
159 double y =
static_cast<double>(pos.getY());
160 double const dx = x - _xcen;
161 double const dy = y - _ycen;
162 double const du = dx*_cosTheta + dy*_sinTheta;
163 double const dv = -dx*_sinTheta + dy*_cosTheta;
165 double r = ::hypot(du, dv*_ab);
167 if (::hypot(dx, dy) < 0.5) {
179 double const eR = 0.38259771140356325;
189 _sumRVar += r*r*vval;
194 double getIr()
const {
return _sumR/_sum; }
199 double getIrVar()
const {
return _sumRVar/(_sum*_sum) + _sumVar*_sumR*_sumR/::pow(_sum, 4); }
203 bool getGood()
const {
return _sum > 0 && _sumR > 0; }
209 double const _cosTheta, _sinTheta;
216 int const _imageX0, _imageY0;
232 template<
typename ImageT>
244 bool const smoothImage = sigma > 0;
245 int kSize = smoothImage ? 2*
int(2*sigma) + 1 : 1;
248 bool const doNormalize =
true, doCopyEdge =
false;
264 bbox.
clip(image.getBBox());
272 FootprintFindMoment<ImageT, afw::detection::Psf::Image> iRFunctor(
278 iRFunctor, *(subImage.getImage()));
286 if (!iRFunctor.getGood()) {
290 radius = iRFunctor.getIr()*sqrt(axes.
getB()/axes.
getA());
291 if (radius <= radius0) {
300 return std::make_shared<KronAperture>(center, axes, radiusForRadius);
304 template<
typename ImageT>
308 double const maxSincRadius
312 if (axes.
getB() > maxSincRadius) {
313 FootprintFlux<ImageT> fluxFunctor;
316 fluxFunctor, *(image.getImage()), *(image.getVariance()));
317 return std::make_pair(fluxFunctor.getSum(), ::sqrt(fluxFunctor.getSumVar()));
324 " aperture radius %g,%g theta %g")
335 double smoothingSigma=0.0
344 template<
typename ImageT>
347 double const nRadiusForFlux,
348 double const maxSincRadius
352 axes.
scale(nRadiusForFlux);
355 return photometer(image, ellip, maxSincRadius);
373 meas::
base::FluxResultKey::addFields(schema, name,
"flux from Kron Flux algorithm")
375 _radiusKey(schema.addField<
float>(name +
"_radius",
"Kron radius (sqrt(a*b))")),
376 _radiusForRadiusKey(schema.addField<
float>(name +
"_radius_for_radius",
377 "radius used to estimate <radius> (sqrt(a*b))")),
378 _psfRadiusKey(schema.addField<
float>(name +
"_psf_radius",
"Radius of PSF")),
379 _centroidExtractor(schema, name, true)
392 void KronFluxAlgorithm::_applyAperture(
429 source.
set(_fluxResultKey, fluxResult);
436 void KronFluxAlgorithm::_applyForced(
445 KronAperture const aperture(reference, refToMeas, radius);
446 _applyAperture(source, exposure, aperture);
484 axes = exposure.
getPsf()->computeShape();
491 footprintAxes.
scale(::sqrt(2));
493 double radius0 = axes.getDeterminantRadius();
494 double const footRadius = footprintAxes.getDeterminantRadius();
498 axes.scale(radius0/axes.getDeterminantRadius());
517 aperture = _fallbackRadius(source, R_K_psf, e);
520 aperture = _fallbackRadius(source, R_K_psf, e);
532 double newRadius = rad;
538 }
else if (!exposure.
getPsf()) {
544 }
else if (rad < R_K_psf) {
548 if (newRadius != rad) {
554 _applyAperture(source, exposure, *aperture);
556 source.
set(_psfRadiusKey, R_K_psf);
568 _applyForced(measRecord, exposure, center, refRecord,
583 }
else if (R_K_psf > 0) {
599 #define INSTANTIATE(TYPE) \ 600 template PTR(KronAperture) KronAperture::determineRadius<afw::image::MaskedImage<TYPE> >( \ 601 afw::image::MaskedImage<TYPE> const&, \ 602 afw::geom::ellipses::Axes, \ 603 afw::geom::Point2D const&, \ 604 KronFluxControl const& \ 606 template std::pair<double, double> KronAperture::measureFlux<afw::image::MaskedImage<TYPE> >( \ 607 afw::image::MaskedImage<TYPE> const&, \ Defines the fields and offsets for a table.
double const getB() const
static meas::base::FlagDefinition const SMALL_RADIUS
lsst::geom::Point2D const & getCenter() const
Return the center point.
static meas::base::FlagDefinition const NO_MINIMUM_RADIUS
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
lsst::geom::AffineTransform linearizeTransform(TransformPoint2ToPoint2 const &original, lsst::geom::Point2D const &inPoint)
Approximate a Transform by its local linearization.
C++ control object for Kron flux.
float Pixel
Typedefs to be used for pixel values.
virtual void measureForced(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure, afw::table::SourceRecord const &refRecord, afw::geom::SkyWcs const &refWcs) const
Called to measure a single child source in an image.
ShapeSlotDefinition::MeasValue getShape() const
Get the value of the Shape slot measurement.
std::pair< double, double > photometer(ImageT const &image, afw::geom::ellipses::Ellipse const &aperture, double const maxSincRadius)
double smoothingSigma
"Smooth image with N(0, smoothingSigma^2) Gaussian while estimating R_K" ;
double const getA() const
Parameters to control convolution.
constexpr double radToDeg(double x) noexcept
double calculatePsfKronRadius(boost::shared_ptr< afw::detection::Psf const > const &psf, afw::geom::Point2D const ¢er, double smoothingSigma=0.0)
Reports attempts to exceed implementation-defined length limits for some classes. ...
double minimumRadius
"Minimum Kron radius (if == 0.0 use PSF's Kron radius) if enforceMinimumRadius. " "Also functions as ...
bool getShapeFlag() const
Return true if the measurement in the Shape slot failed.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
std::shared_ptr< Footprint > getFootprint() const
BaseCore const & getCore() const
Return the ellipse core.
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, lsst::geom::Point2I offset=lsst::geom::Point2I())
Factory function for creating SpanSets from a Stencil.
Provides consistent interface for LSST exceptions.
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.
bool fixed
"if true, use existing shape and centroid measurements instead of fitting" ;
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
Set the flag field corresponding to the given flag index.
double sin(Angle const &a)
meas::base::FluxErrElement instFluxErr
Standard deviation of instFlux in DN.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
static boost::shared_ptr< KronAperture > determineRadius(ImageT const &image, afw::geom::ellipses::Axes axes, afw::geom::Point2D const ¢er, KronFluxControl const &ctrl)
Determine the Kron Aperture from an image.
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
double cos(Angle const &a)
static meas::base::FlagDefinition const USED_MINIMUM_RADIUS
static meas::base::FlagDefinition const USED_PSF_RADIUS
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
A base class for image defects.
MaskedImageT getMaskedImage()
Return the MaskedImage.
lsst::geom::Box2I growBBox(lsst::geom::Box2I const &bbox) const
Given a bounding box for pixels one wishes to compute by convolving an image with this kernel...
static afw::geom::ellipses::Axes getKronAxes(afw::geom::ellipses::Axes const &shape, afw::geom::LinearTransform const &transformation, double const radius)
Determine Kron axes from a reference image.
static meas::base::FlagDefinition const NO_FALLBACK_RADIUS
static meas::base::FlagDefinition const BAD_SHAPE_NO_PSF
An ellipse defined by an arbitrary BaseCore and a center point.
double nSigmaForRadius
"Multiplier of rms size for aperture used to initially estimate the Kron radius" ; ...
bool enforceMinimumRadius
"If true check that the Kron radius exceeds some minimum" ;
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
A class to manipulate images, masks, and variance as a single object.
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
std::pair< double, double > measureFlux(ImageT const &image, double const nRadiusForFlux, double const maxSincRadius) const
Photometer within the Kron Aperture on an image.
void scale(double factor)
Scale the size of the ellipse core by the given factor.
afw::table::Key< double > sigma
const char * source()
Source function that allows astChannel to source from a Stream.
#define CONST_PTR(...)
A shared pointer to a const object.
std::string refRadiusName
"Name of field specifying reference Kron radius for forced measurement" ;
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image...
float getRadiusForRadius() const
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.
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
A Transform obtained by putting two SkyWcs objects "back to back".
static meas::base::FlagDefinition const FAILURE
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Reports attempts to access elements outside a valid range of indices.
An ellipse core for the semimajor/semiminor axis and position angle parametrization (a...
double maxSincRadius
"Largest aperture for which to use the slow, accurate, sinc aperture code" ;
static meas::base::FlagDefinition const BAD_RADIUS
Transformer transform(lsst::geom::LinearTransform const &transform)
std::shared_ptr< lsst::afw::detection::Psf > getPsf()
Return the Exposure's Psf object.
int nIterForRadius
"Number of times to iterate when setting the Kron radius" ;
Class for storing generic metadata.
void clip(Box2I const &other) noexcept
Shrink this to ensure that other.contains(*this).
bool useFootprintRadius
"Use the Footprint size as part of initial estimate of Kron radius" ;
static meas::base::FlagDefinition const EDGE
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
static meas::base::FlagDefinitionList const & getFlagDefinitions()
std::shared_ptr< geom::SkyWcs const > getWcs() const
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
virtual 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...
Record class that contains measurements made on a single exposure.
meas::base::Flux instFlux
Measured instFlux in DN.
double getDeterminantRadius() const
Return the radius defined as the 4th root of the determinant of the quadrupole matrix.
double const getTheta() const
vector-type utility class to build a collection of FlagDefinitions
void add(std::string const &name, T const &value)
Append a single value to the vector of values for a property name (possibly hierarchical).
A polymorphic base class for representing an image's Point Spread Function.
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
#define LSST_EXCEPTION_TYPE(t, b, c)
Macro used to define new types of exceptions without additional data.
afw::geom::ellipses::Axes & getAxes()
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it...
An integer coordinate rectangle.
A reusable result struct for instFlux measurements.
double constexpr PI
The ratio of a circle's circumference to diameter.
CentroidSlotDefinition::MeasValue getCentroid() const
Get the value of the Centroid slot measurement.
Reports errors that are due to events beyond the control of the program.
double nRadiusForFlux
"Number of Kron radii for Kron flux" ;
A Result struct for running an aperture flux algorithm with a single radius.
#define INSTANTIATE(TYPE)
static meas::base::FlagDefinition const BAD_SHAPE
geom::ellipses::Quadrupole computeShape(lsst::geom::Point2D position=makeNullPoint(), image::Color color=image::Color()) const
Compute the ellipse corresponding to the second moments of the Psf.