26 #include "boost/algorithm/string/replace.hpp"
28 #include "ndarray/eigen.h"
30 #include "lsst/afw/math/offsetImage.h"
31 #include "lsst/afw/geom/ellipses/PixelRegion.h"
32 #include "lsst/afw/table/Source.h"
36 namespace lsst {
namespace meas {
namespace base {
38 FlagDefinitionList flagDefinitions;
46 return flagDefinitions;
52 static std::array<double,10> defaultRadii = {{
53 3.0, 4.5, 6.0, 9.0, 12.0, 17.0, 25.0, 35.0, 50.0, 70.0
55 std::copy(defaultRadii.begin(), defaultRadii.end(),
radii.begin());
60 std::string prefix = (boost::format(
"%s_%.1f") % name % radius).str();
61 return boost::replace_all_copy(prefix,
".",
"_");
64 ApertureFluxAlgorithm::Keys::Keys(
65 afw::table::Schema & schema, std::string
const & prefix, std::string
const & doc,
bool isSinc
80 std::string
const & name,
81 afw::table::Schema & schema,
82 daf::base::PropertySet & metadata
87 _keys.reserve(ctrl.radii.size());
88 for (std::size_t i = 0; i < ctrl.radii.size(); ++i) {
89 metadata.add(name +
"_radii", ctrl.radii[i]);
91 std::string doc = (boost::format(
"flux within %f-pixel aperture") % ctrl.radii[i]).str();
92 _keys.push_back(Keys(schema, prefix, doc, ctrl.radii[i] <= ctrl.maxSincRadius));
100 for (std::size_t i = 0; i <
_ctrl.
radii.size(); ++i) {
101 _keys[i].flags.handleFailure(measRecord, error);
107 afw::table::SourceRecord & record,
110 record.set(_keys[index].fluxKey, result);
126 template <
typename T>
127 CONST_PTR(afw::image::Image<T>) getSincCoeffs(
128 afw::geom::Box2I const & bbox,
129 afw::geom::ellipses::Ellipse const & ellipse,
133 CONST_PTR(afw::image::Image<T>) cImage =
SincCoeffs<T>::get(ellipse.getCore(), 0.0);
134 cImage = afw::math::offsetImage(
136 ellipse.getCenter().getX(),
137 ellipse.getCenter().getY(),
140 if (!bbox.contains(cImage->getBBox())) {
146 afw::geom::Box2I overlap = cImage->getBBox();
148 if (!overlap.contains(afw::geom::Box2I(ellipse.computeBBox()))) {
154 cImage = std::make_shared< afw::image::Image<T> >(*cImage, overlap);
161 template <
typename T>
163 afw::image::Image<T>
const & image,
164 afw::geom::ellipses::Ellipse
const & ellipse,
168 CONST_PTR(afw::image::Image<T>) cImage = getSincCoeffs<T>(image.getBBox(), ellipse, result, ctrl);
170 afw::image::Image<T> subImage(image, cImage->getBBox());
171 result.
flux = (subImage.getArray().template asEigen<Eigen::ArrayXpr>()
172 * cImage->getArray().template asEigen<Eigen::ArrayXpr>()).sum();
176 template <
typename T>
178 afw::image::MaskedImage<T>
const & image,
179 afw::geom::ellipses::Ellipse
const & ellipse,
183 CONST_PTR(afw::image::Image<T>) cImage = getSincCoeffs<T>(image.getBBox(), ellipse, result, ctrl);
185 afw::image::MaskedImage<T> subImage(image, cImage->getBBox(afw::image::PARENT), afw::image::PARENT);
186 result.
flux = (subImage.getImage()->getArray().template asEigen<Eigen::ArrayXpr>()
187 * cImage->getArray().template asEigen<Eigen::ArrayXpr>()).sum();
188 result.fluxSigma = std::sqrt(
189 (subImage.getVariance()->getArray().template asEigen<Eigen::ArrayXpr>().
template cast<T>()
190 * cImage->getArray().template asEigen<Eigen::ArrayXpr>().square()).sum()
195 template <
typename T>
197 afw::image::Image<T>
const & image,
198 afw::geom::ellipses::Ellipse
const & ellipse,
202 afw::geom::ellipses::PixelRegion region(ellipse);
203 if (!image.getBBox().contains(region.getBBox())) {
210 afw::geom::ellipses::PixelRegion::Iterator spanIter = region.begin(), spanEnd = region.end();
214 typename afw::image::Image<T>::x_iterator pixIter = image.x_at(
215 spanIter->getBeginX() - image.getX0(),
216 spanIter->getY() - image.getY0()
218 result.
flux += std::accumulate(pixIter, pixIter + spanIter->getWidth(), 0.0);
223 template <
typename T>
225 afw::image::MaskedImage<T>
const & image,
226 afw::geom::ellipses::Ellipse
const & ellipse,
230 afw::geom::ellipses::PixelRegion region(ellipse);
231 if (!image.getBBox().contains(region.getBBox())) {
239 afw::geom::ellipses::PixelRegion::Iterator spanIter = region.begin(), spanEnd = region.end();
243 typename afw::image::MaskedImage<T>::Image::x_iterator pixIter = image.getImage()->x_at(
244 spanIter->getBeginX() - image.getX0(),
245 spanIter->getY() - image.getY0()
247 typename afw::image::MaskedImage<T>::Variance::x_iterator varIter = image.getVariance()->x_at(
248 spanIter->getBeginX() - image.getX0(),
249 spanIter->getY() - image.getY0()
251 result.
flux += std::accumulate(pixIter, pixIter + spanIter->getWidth(), 0.0);
253 result.
fluxSigma += std::accumulate(varIter, varIter + spanIter->getWidth(), 0.0);
259 template <
typename T>
261 afw::image::Image<T>
const & image,
262 afw::geom::ellipses::Ellipse
const & ellipse,
265 return (afw::geom::ellipses::Axes(ellipse.getCore()).getB() <= ctrl.
maxSincRadius)
270 template <
typename T>
272 afw::image::MaskedImage<T>
const & image,
273 afw::geom::ellipses::Ellipse
const & ellipse,
276 return (afw::geom::ellipses::Axes(ellipse.getCore()).getB() <= ctrl.
maxSincRadius)
280 #define INSTANTIATE(T) \
282 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeFlux( \
283 afw::image::Image<T> const &, \
284 afw::geom::ellipses::Ellipse const &, \
288 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeFlux( \
289 afw::image::MaskedImage<T> const &, \
290 afw::geom::ellipses::Ellipse const &, \
294 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeSincFlux( \
295 afw::image::Image<T> const &, \
296 afw::geom::ellipses::Ellipse const &, \
300 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeSincFlux( \
301 afw::image::MaskedImage<T> const &, \
302 afw::geom::ellipses::Ellipse const &, \
306 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeNaiveFlux( \
307 afw::image::Image<T> const &, \
308 afw::geom::ellipses::Ellipse const &, \
312 ApertureFluxAlgorithm::Result ApertureFluxAlgorithm::computeNaiveFlux( \
313 afw::image::MaskedImage<T> const &, \
314 afw::geom::ellipses::Ellipse const &, \
323 std::string
const & name,
324 afw::table::SchemaMapper & mapper
329 for (std::size_t i = 0; i < _ctrl.
radii.size(); ++i) {
335 mapper.addMapping(mapper.getInputSchema().find<afw::table::Flag>((boost::format(
"%s_%s") %
337 flag.
name).str()).key);
345 afw::table::SourceCatalog
const & inputCatalog,
346 afw::table::BaseCatalog & outputCatalog,
347 afw::image::Wcs
const & wcs,
348 afw::image::Calib
const & calib
351 std::vector<FluxResultKey> fluxKeys;
352 for (std::size_t i = 0; i < _ctrl.
radii.size(); ++i) {
356 afw::table::SourceCatalog::const_iterator inSrc = inputCatalog.begin();
357 afw::table::BaseCatalog::iterator outSrc = outputCatalog.begin();
362 for (; inSrc != inputCatalog.end() && outSrc != outputCatalog.end(); ++inSrc, ++outSrc) {
363 for (std::size_t i = 0; i < _ctrl.
radii.size(); ++i) {
364 FluxResult fluxResult = fluxKeys[i].get(*inSrc);
365 _magKeys[i].set(*outSrc, calib.getMagnitude(fluxResult.
flux, fluxResult.
fluxSigma));
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...
void setFlag(unsigned int index, bool value=true)
Set the flag value associated with the given bit.
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...
Temporarily replace negative fluxes with NaNs.
static FlagDefinitionList const & getFlagDefinitions()
ApertureFluxAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema, daf::base::PropertySet &metadata)
Construct the algorithm and add its fields to the given Schema.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
A singleton to calculate and cache the coefficients for sinc photometry.
void copyResultToRecord(Result const &result, afw::table::SourceRecord &record, int index) const
Return the flag definitions which apply to aperture flux measurements.
Configuration object for multiple-aperture flux algorithms.
Utility class for handling flag fields that indicate the failure modes of an algorithm.
static FlagDefinition const FAILURE
static FlagDefinition const APERTURE_TRUNCATED
Base class for multiple-aperture photometry algorithms.
static Result computeFlux(afw::image::Image< T > const &image, afw::geom::ellipses::Ellipse const &ellipse, Control const &ctrl=Control())
Compute the flux (and optionally, uncertanties) within an aperture using the algorithm determined by ...
double maxSincRadius
"Maximum radius (in pixels) for which the sinc algorithm should be used instead of the " "faster naiv...
static std::string makeFieldPrefix(std::string const &name, double radius)
Construct an appropriate prefix for table fields.
static FlagDefinition const SINC_COEFFS_TRUNCATED
static Result computeNaiveFlux(afw::image::Image< T > const &image, afw::geom::ellipses::Ellipse const &ellipse, Control const &ctrl=Control())
Compute the flux (and optionally, uncertanties) within an aperture using naive photometry.
_centroidExtractor(schema, name)
Flux flux
Measured flux in DN.
A FunctorKey for FluxResult.
static MagResultKey addFields(afw::table::Schema &schema, std::string const &name)
Add a pair of _mag, _magErr fields to a Schema, and return a MagResultKey that points to them...
bool getFlag(unsigned int index) const
Return the flag value associated with the given bit.
static Result computeSincFlux(afw::image::Image< T > const &image, afw::geom::ellipses::Ellipse const &ellipse, Control const &ctrl=Control())
Compute the flux (and optionally, uncertanties) within an aperture using Sinc photometry.
std::vector< double > radii
"Radius (in pixels) of apertures." ;
vector-type utility class to build a collection of FlagDefinitions
FluxErrElement fluxSigma
1-Sigma error (sqrt of variance) on flux in DN.
std::size_t size() const
return the current size (number of defined elements) of the collection
A reusable result struct for flux measurements.
A Result struct for running an aperture flux algorithm with a single radius.