28 namespace lsst {
namespace meas {
namespace algorithms {
32 typedef std::pair<afw::table::KeyTuple<afw::table::Flux>,ScaledFlux::KeyTuple> ScaledFluxKeys;
36 inline typename afw::table::Field<T>::Value
get(
37 afw::table::SourceRecord
const &
record,
38 afw::table::Key<T>
const & key,
39 typename afw::table::Field<T>::Value default_ = false
41 return key.isValid() ? record.get(key) : default_;
47 explicit SetMainFlag(afw::table::SourceRecord * record_) : record(record_) {}
49 void operator()(ScaledFluxKeys
const & keys)
const {
50 if (keys.first.flag.isValid()) {
51 record->set(keys.first.flag,
true);
61 ApplyApCorr(
double apCorr_, afw::table::SourceRecord * record_) :
apCorr(apCorr_),
record(record_) {}
63 void operator()(ScaledFluxKeys
const & keys)
const {
64 (*record)[keys.first.meas] *=
apCorr;
65 if (keys.first.err.isValid()) {
66 (*record)[keys.first.err] *=
apCorr;
71 afw::table::SourceRecord *
record;
75 class CorrectFluxes :
public Algorithm {
79 CorrectFluxesControl
const & ctrl,
80 afw::table::Schema &
schema,
87 afw::table::SourceRecord & source,
88 PTR(afw::detection::Psf
const) psf,
92 template <
typename PixelT>
94 afw::table::SourceRecord & source,
95 afw::image::Exposure<PixelT>
const & exposure,
98 return this->_apply(source, exposure.getPsf(), center);
109 CorrectFluxes::CorrectFluxes(
110 CorrectFluxesControl
const & ctrl,
111 afw::table::Schema &
schema,
113 ) : Algorithm(ctrl) {
117 ctrl.name +
".apcorr",
118 (
boost::format(
"correction applied to model fluxes to match to %f-pixel aperture")
119 % ctrl.apCorrRadius).str()
122 ctrl.name +
".apcorr.flags",
123 "flag set if aperture correction failed"
127 for (AlgorithmMap::const_iterator i = others.begin(); i != others.end(); ++i) {
128 CONST_PTR(ScaledFlux) asScaledFlux = boost::dynamic_pointer_cast<ScaledFlux const>(i->second);
129 if (i->second->getControl().name == ctrl.canonicalFluxName) {
132 pex::exceptions::InvalidParameterError,
133 (
boost::format(
"Canonical flux (%s) is not an instance of ScaledFlux")
134 % ctrl.canonicalFluxName).str()
137 int fluxCount = asScaledFlux->getFluxCount();
138 if (ctrl.canonicalFluxIndex < 0 || ctrl.canonicalFluxIndex >= fluxCount) {
140 pex::exceptions::InvalidParameterError,
141 (
boost::format(
"Invalid index (%d) for canonical flux (must be between 0 and %d)")
142 % ctrl.canonicalFluxIndex % (fluxCount - 1)).str()
145 for (
int i = 0; i < fluxCount; ++i) {
146 if (i == ctrl.canonicalFluxIndex) {
149 asScaledFlux->getFluxKeys(i),
150 asScaledFlux->getFluxCorrectionKeys(i)
155 asScaledFlux->getFluxKeys(i),
156 asScaledFlux->getFluxCorrectionKeys(i)
161 }
else if (asScaledFlux) {
162 int fluxCount = asScaledFlux->getFluxCount();
163 for (
int i = 0; i < fluxCount; ++i) {
166 asScaledFlux->getFluxKeys(i),
167 asScaledFlux->getFluxCorrectionKeys(i)
174 if (ctrl.doTieScaledFluxes && !
_canonical.first.meas.isValid()) {
176 pex::exceptions::LogicError,
177 "Cannot tie scaled fluxes without a canonical flux measurement."
182 void CorrectFluxes::_apply(
183 afw::table::SourceRecord & source,
184 PTR(afw::detection::Psf
const) psf,
187 CorrectFluxesControl
const & ctrl =
static_cast<CorrectFluxesControl
const &
>(this->getControl());
191 SetMainFlag setMainFlag(&source);
193 if (!ctrl.doApCorr && !ctrl.doTieScaledFluxes)
return;
201 pex::exceptions::LogicError,
202 "Aperture correction requested but no PSF provided"
205 double canonicalPsfFactor =
get(source,
_canonical.second.psfFactor, 1.0);
206 apCorr = psf->computeApertureFlux(ctrl.apCorrRadius, center) / canonicalPsfFactor;
209 pex::exceptions::RuntimeError,
210 "Aperture correction is unexpectedly non-finite"
216 if (ctrl.doFlagApCorrFailures) {
224 ApplyApCorr applyApCorr(apCorr, &source);
229 if (ctrl.doTieScaledFluxes) {
230 bool badCanonicalFlux =
get(source,
_canonical.first.flag,
false);
231 bool badCanonicalPsfFactor =
get(source,
_canonical.second.psfFactorFlag,
false);
232 double canonicalPsfFactor =
get(source,
_canonical.second.psfFactor, 1.0);
233 if (badCanonicalFlux || badCanonicalPsfFactor) {
234 if (ctrl.doFlagTieFailures) {
238 for (std::vector<ScaledFluxKeys>::const_iterator i =
_others.begin(); i !=
_others.end(); ++i) {
240 assert(i->first.meas.isValid());
241 if (i->second.psfFactorFlag.isValid() && source.get(i->second.psfFactorFlag)) {
242 if (ctrl.doFlagTieFailures) {
246 double psfFactor =
get(source, i->second.psfFactor, 1.0);
247 double scaling = canonicalPsfFactor / psfFactor;
248 source[i->first.meas] *=
scaling;
249 if (i->first.err.isValid()) {
250 source[i->first.err] *=
scaling;
263 return boost::make_shared<CorrectFluxesControl>(*this);
267 afw::table::Schema & schema,
271 return boost::make_shared<CorrectFluxes>(*
this, boost::ref(schema), others);
afw::table::Key< afw::table::Flag > _apCorrFlagKey
#define LSST_MEAS_ALGORITHM_PRIVATE_INTERFACE(CLASS)
Declare Algorithm::_applyT virtual function overloads with the correct types.
Class for storing ordered metadata with comments.
A control object for a pluggable algorithm that scales fluxes to a common system. ...
Point< double, 2 > Point2D
ScaledFluxKeys _canonical
afw::table::Key< float > _apCorrKey
Base class for source measurement algorithms.
Base class for measurement algorithm control objects.
#define LSST_MEAS_ALGORITHM_PRIVATE_IMPLEMENTATION(CLASS)
Implement Algorithm::_applyT virtual function overloads with the correct types.
#define LSST_EXCEPT(type,...)
std::vector< ScaledFluxKeys > _others
std::map< std::string, boost::shared_ptr< Algorithm const > > AlgorithmMap
afw::table::SourceRecord * record