LSST Applications g042eb84c57+730a74494b,g04e9c324dd+8c5ae1fdc5,g134cb467dc+1f1e3e7524,g199a45376c+0ba108daf9,g1fd858c14a+fa7d31856b,g210f2d0738+f66ac109ec,g262e1987ae+83a3acc0e5,g29ae962dfc+d856a2cb1f,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+a1e0c9f713,g47891489e3+0d594cb711,g4d44eb3520+c57ec8f3ed,g4d7b6aa1c5+f66ac109ec,g53246c7159+8c5ae1fdc5,g56a1a4eaf3+fd7ad03fde,g64539dfbff+f66ac109ec,g67b6fd64d1+0d594cb711,g67fd3c3899+f66ac109ec,g6985122a63+0d594cb711,g74acd417e5+3098891321,g786e29fd12+668abc6043,g81db2e9a8d+98e2ab9f28,g87389fa792+8856018cbb,g89139ef638+0d594cb711,g8d7436a09f+80fda9ce03,g8ea07a8fe4+760ca7c3fc,g90f42f885a+033b1d468d,g97be763408+a8a29bda4b,g99822b682c+e3ec3c61f9,g9d5c6a246b+0d5dac0c3d,ga41d0fce20+9243b26dd2,gbf99507273+8c5ae1fdc5,gd7ef33dd92+0d594cb711,gdab6d2f7ff+3098891321,ge410e46f29+0d594cb711,geaed405ab2+c4bbc419c6,gf9a733ac38+8c5ae1fdc5,w.2025.38
LSST Data Management Base Package
Loading...
Searching...
No Matches
KronPhotometry.cc
Go to the documentation of this file.
1// -*- LSST-C++ -*-
2/*
3 * LSST Data Management System
4 * Copyright 2008-2015 LSST Corporation.
5 *
6 * This product includes software developed by the
7 * LSST Project (http://www.lsst.org/).
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the LSST License Statement and
20 * the GNU General Public License along with this program. If not,
21 * see <http://www.lsstcorp.org/LegalNotices/>.
22 */
23
24#include <numeric>
25#include <cmath>
26#include <functional>
27#include "boost/algorithm/string.hpp"
28#include "boost/math/constants/constants.hpp"
29#include "lsst/pex/exceptions.h"
30#include "lsst/geom/Point.h"
31#include "lsst/geom/Box.h"
41#include "lsst/meas/base.h"
43
45
46namespace lsst {
47namespace meas {
48namespace extensions {
49namespace photometryKron {
50
51namespace {
52base::FlagDefinitionList flagDefinitions;
53} // end anonymous
54
55base::FlagDefinition const KronFluxAlgorithm::FAILURE = flagDefinitions.addFailureFlag( "general failure flag, set if anything went wrong");
56base::FlagDefinition const KronFluxAlgorithm::EDGE = flagDefinitions.add("flag_edge", "bad measurement due to image edge");
57base::FlagDefinition const KronFluxAlgorithm::BAD_SHAPE_NO_PSF = flagDefinitions.add("flag_bad_shape_no_psf", "bad shape and no PSF");
58base::FlagDefinition const KronFluxAlgorithm::NO_MINIMUM_RADIUS = flagDefinitions.add("flag_no_minimum_radius", "minimum radius could not enforced: no minimum value or PSF");
59base::FlagDefinition const KronFluxAlgorithm::NO_FALLBACK_RADIUS = flagDefinitions.add("flag_no_fallback_radius", "no minimum radius and no PSF provided");
60base::FlagDefinition const KronFluxAlgorithm::BAD_RADIUS = flagDefinitions.add("flag_bad_radius", "bad Kron radius");
61base::FlagDefinition const KronFluxAlgorithm::USED_MINIMUM_RADIUS = flagDefinitions.add("flag_used_minimum_radius", "used the minimum radius for the Kron aperture");
62base::FlagDefinition const KronFluxAlgorithm::USED_PSF_RADIUS = flagDefinitions.add("flag_used_psf_radius", "used the PSF Kron radius for the Kron aperture");
63base::FlagDefinition const KronFluxAlgorithm::SMALL_RADIUS = flagDefinitions.add("flag_small_radius", "measured Kron radius was smaller than that of the PSF");
64base::FlagDefinition const KronFluxAlgorithm::BAD_SHAPE = flagDefinitions.add("flag_bad_shape", "shape for measuring Kron radius is bad; used PSF shape");
65
67 return flagDefinitions;
68}
69
72
73namespace {
74
75template <typename MaskedImageT>
76 class FootprintFlux {
77public:
78 explicit FootprintFlux() : _sum(0.0), _sumVar(0.0) {}
79
81 void reset() {
82 _sum = _sumVar = 0.0;
83 }
84 void reset(afw::detection::Footprint const&) {}
85
87 void operator()(geom::Point2I const & pos,
88 typename MaskedImageT::Image::Pixel const & ival,
89 typename MaskedImageT::Variance::Pixel const & vval) {
90 _sum += ival;
91 _sumVar += vval;
92 }
93
95 double getSum() const { return _sum; }
96
98 double getSumVar() const { return _sumVar; }
99
100private:
101 double _sum;
102 double _sumVar;
103};
104
105/************************************************************************************************************/
116template <typename MaskedImageT, typename WeightImageT>
117class FootprintFindMoment {
118public:
119 FootprintFindMoment(MaskedImageT const& mimage,
120 geom::Point2D const& center, // center of the object
121 double const ab, // axis ratio
122 double const theta // rotation of ellipse +ve from x axis
123 ) : _xcen(center.getX()), _ycen(center.getY()),
124 _ab(ab),
125 _cosTheta(::cos(theta)),
126 _sinTheta(::sin(theta)),
127 _sum(0.0), _sumR(0.0),
128#if 0
129 _sumVar(0.0), _sumRVar(0.0),
130#endif
131 _imageX0(mimage.getX0()), _imageY0(mimage.getY0()),
132 _imageWidth(mimage.getWidth()), _imageHeight(mimage.getHeight())
133 {}
134
136 void reset() {}
137 void reset(afw::detection::Footprint const& foot) {
138 _sum = _sumR = 0.0;
139#if 0
140 _sumVar = _sumRVar = 0.0;
141#endif
142
143 geom::Box2I const& bbox(foot.getBBox());
144 int const x0 = bbox.getMinX(), y0 = bbox.getMinY(), x1 = bbox.getMaxX(), y1 = bbox.getMaxY();
145
146 if (x0 < _imageX0 || y0 < _imageY0 ||
147 x1 >= _imageX0 + _imageWidth || y1 >= _imageY0 + _imageHeight) {
148 throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeError,
149 (boost::format("Footprint %d,%d--%d,%d doesn't fit in image %d,%d--%d,%d")
150 % x0 % y0 % x1 % y1
151 % _imageX0 % _imageY0
152 % (_imageX0 + _imageWidth - 1) % (_imageY0 + _imageHeight - 1)
153 ).str());
154 }
155 }
156
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;
165
166 double r = ::hypot(du, dv*_ab); // ellipsoidal radius
167#if 1
168 if (::hypot(dx, dy) < 0.5) { // within a pixel of the centre
169 /*
170 * We gain significant precision for flattened Gaussians by treating the central pixel specially
171 *
172 * If the object's centered in the pixel (and has constant surface brightness) we have <r> == eR;
173 * if it's at the corner <r> = 2*eR; we interpolate between these exact results linearily in the
174 * displacement. And then add in quadrature which is also a bit dubious
175 *
176 * We could avoid all these issues by estimating <r> using the same trick as we use for
177 * the sinc fluxes; it's not clear that it's worth it.
178 */
179
180 double const eR = 0.38259771140356325; // <r> for a single square pixel, about the centre
181 r = ::hypot(r, eR*(1 + ::hypot(dx, dy)/geom::ROOT2));
182 }
183#endif
184
185 _sum += ival;
186 _sumR += r*ival;
187#if 0
188 typename MaskedImageT::Variance::Pixel vval = iloc.variance(0, 0);
189 _sumVar += vval;
190 _sumRVar += r*r*vval;
191#endif
192 }
193
195 double getIr() const { return _sumR/_sum; }
196
197#if 0
199// double getIrVar() const { return _sumRVar/_sum - getIr()*getIr(); } // Wrong?
200 double getIrVar() const { return _sumRVar/(_sum*_sum) + _sumVar*_sumR*_sumR/::pow(_sum, 4); }
201#endif
202
204 bool getGood() const { return _sum > 0 && _sumR > 0; }
205
206private:
207 double const _xcen; // center of object
208 double const _ycen; // center of object
209 double const _ab; // axis ratio
210 double const _cosTheta, _sinTheta; // {cos,sin}(angle from x-axis)
211 double _sum; // sum of I
212 double _sumR; // sum of R*I
213#if 0
214 double _sumVar; // sum of Var(I)
215 double _sumRVar; // sum of R*R*Var(I)
216#endif
217 int const _imageX0, _imageY0; // origin of image we're measuring
218 int const _imageWidth, _imageHeight; // size of image we're measuring
219
220};
221} // end anonymous namespace
222
224 afw::geom::ellipses::Axes const& shape,
225 geom::LinearTransform const& transformation,
226 double const radius
227 )
228{
229 afw::geom::ellipses::Axes axes(shape);
230 axes.scale(radius/axes.getDeterminantRadius());
231 return axes.transform(transformation);
232}
233
234template<typename ImageT>
236 ImageT const& image,
238 geom::Point2D const& center,
239 KronFluxControl const& ctrl
240 )
241{
242 //
243 // We might smooth the image because this is what SExtractor and Pan-STARRS do. But I don't see much gain
244 //
245 double const sigma = ctrl.smoothingSigma; // Gaussian width of smoothing sigma to apply
246 bool const smoothImage = sigma > 0;
247 int kSize = smoothImage ? 2*int(2*sigma) + 1 : 1;
248 afw::math::GaussianFunction1<afw::math::Kernel::Pixel> gaussFunc(smoothImage ? sigma : 100);
249 afw::math::SeparableKernel kernel(kSize, kSize, gaussFunc, gaussFunc);
250 bool const doNormalize = true, doCopyEdge = false;
251 afw::math::ConvolutionControl convCtrl(doNormalize, doCopyEdge);
252 double radius0 = axes.getDeterminantRadius();
254 float radiusForRadius = std::nanf("");
255 for (int i = 0; i < ctrl.nIterForRadius; ++i) {
256 axes.scale(ctrl.nSigmaForRadius);
257 radiusForRadius = axes.getDeterminantRadius(); // radius we used to estimate R_K
258 //
259 // Build an elliptical Footprint of the proper size
260 //
262 afw::geom::ellipses::Ellipse(axes, center)));
263 geom::Box2I bbox = !smoothImage ?
264 foot.getBBox() :
265 kernel.growBBox(foot.getBBox()); // the smallest bbox needed to convolve with Kernel
266 bbox.clip(image.getBBox());
267 ImageT subImage(image, bbox, afw::image::PARENT, smoothImage);
268 if (smoothImage) {
269 afw::math::convolve(subImage, ImageT(image, bbox, afw::image::PARENT, false), kernel, convCtrl);
270 }
271 //
272 // Find the desired first moment of the elliptical radius, which corresponds to the major axis.
273 //
274 FootprintFindMoment<ImageT, afw::detection::Psf::Image> iRFunctor(
275 subImage, center, axes.getA()/axes.getB(), axes.getTheta()
276 );
277
278 try {
279 foot.getSpans()->applyFunctor(
280 iRFunctor, *(subImage.getImage()));
282 if (i == 0) {
283 LSST_EXCEPT_ADD(e, "Determining Kron aperture");
284 }
285 break; // use the radius we have
286 }
287
288 if (!iRFunctor.getGood()) {
289 throw LSST_EXCEPT(BadKronException, "Bad integral defining Kron radius");
290 }
291
292 radius = iRFunctor.getIr()*sqrt(axes.getB()/axes.getA());
293 if (radius <= radius0) {
294 break;
295 }
296 radius0 = radius;
297
298 axes.scale(radius/axes.getDeterminantRadius()); // set axes to our current estimate of R_K
299
300 if (radius > ctrl.maxRadius) {
301 throw LSST_EXCEPT(BadKronException, "Kron radius too large");
302 }
303
304 iRFunctor.reset();
305 }
306
307 return std::make_shared<KronAperture>(center, axes, radiusForRadius);
308}
309
310// Photometer an image with a particular aperture
311template<typename ImageT>
313 ImageT const& image, // Image to measure
314 afw::geom::ellipses::Ellipse const& aperture, // Aperture in which to measure
315 double const maxSincRadius // largest radius that we use sinc apertures to measure
316 )
317{
318 afw::geom::ellipses::Axes const& axes = aperture.getCore();
319 if (axes.getB() > maxSincRadius) {
320 FootprintFlux<ImageT> fluxFunctor;
321 auto spans = afw::geom::SpanSet::fromShape(aperture);
322 spans->applyFunctor(
323 fluxFunctor, *(image.getImage()), *(image.getVariance()));
324 return std::make_pair(fluxFunctor.getSum(), ::sqrt(fluxFunctor.getSumVar()));
325 }
326 try {
328 return std::make_pair(fluxResult.instFlux, fluxResult.instFluxErr);
329 } catch(pex::exceptions::LengthError &e) {
330 LSST_EXCEPT_ADD(e, (boost::format("Measuring Kron flux for object at (%.3f, %.3f);"
331 " aperture radius %g,%g theta %g")
332 % aperture.getCenter().getX() % aperture.getCenter().getY()
333 % axes.getA() % axes.getB() % geom::radToDeg(axes.getTheta())).str());
334 throw e;
335 }
336}
337
338
340 std::shared_ptr<afw::detection::Psf const> const& psf, // PSF to measure
341 geom::Point2D const& center, // Centroid of source on parent image
342 double smoothingSigma=0.0 // Gaussian sigma of smoothing applied
343 )
344{
345 assert(psf);
346 double const radius = psf->computeShape(center).getDeterminantRadius();
347 // For a Gaussian N(0, sigma^2), the Kron radius is sqrt(pi/2)*sigma
348 return ::sqrt(geom::PI/2)*::hypot(radius, std::max(0.0, smoothingSigma));
349}
350
351template<typename ImageT>
353 ImageT const& image,
354 double const nRadiusForFlux,
355 double const maxSincRadius
356 ) const
357{
358 afw::geom::ellipses::Axes axes(getAxes()); // Copy of ellipse core, so we can scale
359 axes.scale(nRadiusForFlux);
360 afw::geom::ellipses::Ellipse const ellip(axes, getCenter());
361
362 return photometer(image, ellip, maxSincRadius);
363}
364
365/************************************************************************************************************/
366
373 KronFluxControl const & ctrl,
374 std::string const & name,
375 afw::table::Schema & schema,
376 daf::base::PropertySet & metadata
377) : _name(name),
378 _ctrl(ctrl),
379 _fluxResultKey(
380 meas::base::FluxResultKey::addFields(schema, name, "flux from Kron Flux algorithm")
381 ),
382 _radiusKey(schema.addField<float>(name + "_radius", "Kron radius (sqrt(a*b))")),
383 _radiusForRadiusKey(schema.addField<float>(name + "_radius_for_radius",
384 "radius used to estimate <radius> (sqrt(a*b))")),
385 _psfRadiusKey(schema.addField<float>(name + "_psf_radius", "Radius of PSF")),
386 _centroidExtractor(schema, name, true)
387{
389 auto metadataName = name + "_nRadiusForflux";
390 boost::to_upper(metadataName);
391 metadata.add(metadataName, ctrl.nRadiusForFlux);
392}
393
395 afw::table::SourceRecord & measRecord,
397) const {
398 _flagHandler.handleFailure(measRecord, error);
399}
400
401void KronFluxAlgorithm::_applyAperture(
403 afw::image::Exposure<float> const& exposure,
404 KronAperture const& aperture
405 ) const
406{
407 double const rad = aperture.getAxes().getDeterminantRadius();
409 throw LSST_EXCEPT(
413 );
414 }
415
417 try {
418 result = aperture.measureFlux(exposure.getMaskedImage(), _ctrl.nRadiusForFlux, _ctrl.maxSincRadius);
419 } catch (pex::exceptions::LengthError const& e) {
420 // We hit the edge of the image; there's no reasonable fallback or recovery
421 throw LSST_EXCEPT(
423 EDGE.doc,
425 );
427 throw LSST_EXCEPT(
429 EDGE.doc,
431 );
432 }
433
434 // set the results in the source object
435 meas::base::FluxResult fluxResult;
436 fluxResult.instFlux = result.first;
437 fluxResult.instFluxErr = result.second;
438 source.set(_fluxResultKey, fluxResult);
439 source.set(_radiusKey, aperture.getAxes().getDeterminantRadius());
440 //
441 // REMINDER: In the old code, the psfFactor is calculated using getPsfFactor,
442 // and the values set for _fluxCorrectionKeys. See old meas_algorithms version.
443}
444
445void KronFluxAlgorithm::_applyForced(
446 afw::table::SourceRecord & source,
447 afw::image::Exposure<float> const & exposure,
448 geom::Point2D const & center,
449 afw::table::SourceRecord const & reference,
450 geom::AffineTransform const & refToMeas
451 ) const
452{
453 float const radius = reference.get(reference.getSchema().find<float>(_ctrl.refRadiusName).key);
454 KronAperture const aperture(reference, refToMeas, radius);
455 _applyAperture(source, exposure, aperture);
456 if (exposure.getPsf()) {
457 source.set(_psfRadiusKey, calculatePsfKronRadius(exposure.getPsf(), center, _ctrl.smoothingSigma));
458 }
459}
460
463 afw::image::Exposure<float> const& exposure
464 ) const {
465 geom::Point2D center = _centroidExtractor(source, _flagHandler);
466
467 // Did we hit a condition that fundamentally prevented measuring the Kron flux?
468 // Such conditions include hitting the edge of the image and bad input shape, but not low signal-to-noise.
469 bool bad = false;
470
471 afw::image::MaskedImage<float> const& mimage = exposure.getMaskedImage();
472
473 double R_K_psf = -1;
474 if (exposure.getPsf()) {
475 R_K_psf = calculatePsfKronRadius(exposure.getPsf(), center, _ctrl.smoothingSigma);
476 }
477
478 //
479 // Get the shape of the desired aperture
480 //
482 if (!source.getShapeFlag()) {
483 axes = source.getShape();
484 } else {
485 bad = true;
486 if (!exposure.getPsf()) {
487 throw LSST_EXCEPT(
490 BAD_SHAPE_NO_PSF.number
491 );
492 }
493 axes = exposure.getPsf()->computeShape(exposure.getPsf()->getAveragePosition());
494 _flagHandler.setValue(source, BAD_SHAPE.number, true);
495 }
496 if (_ctrl.useFootprintRadius) {
497 afw::geom::ellipses::Axes footprintAxes(source.getFootprint()->getShape());
498 // if the Footprint's a disk of radius R we want footRadius == R.
499 // As <r^2> = R^2/2 for a disk, we need to scale up by sqrt(2)
500 footprintAxes.scale(::sqrt(2));
501
502 double radius0 = axes.getDeterminantRadius();
503 double const footRadius = footprintAxes.getDeterminantRadius();
504
505 if (footRadius > radius0*_ctrl.nSigmaForRadius) {
506 radius0 = footRadius/_ctrl.nSigmaForRadius; // we'll scale it up by nSigmaForRadius
507 axes.scale(radius0/axes.getDeterminantRadius());
508 }
509 }
510
512 if (_ctrl.fixed) {
513 aperture.reset(new KronAperture(source));
514 } else {
515 try {
516 aperture = KronAperture::determineRadius(mimage, axes, center, _ctrl);
518 // We hit the edge of the image: no reasonable fallback or recovery possible
519 throw LSST_EXCEPT(
521 EDGE.doc,
522 EDGE.number
523 );
524 } catch (BadKronException& e) {
525 // Not setting bad=true because we only failed due to low S/N
526 aperture = _fallbackRadius(source, R_K_psf, e);
527 } catch(pex::exceptions::Exception& e) {
528 bad = true; // There's something fundamental keeping us from measuring the Kron aperture
529 aperture = _fallbackRadius(source, R_K_psf, e);
530 }
531 }
532
533 /*
534 * Estimate the minimum acceptable Kron radius as the Kron radius of the PSF or the
535 * provided minimum radius
536 */
537
538 // Enforce constraints on minimum radius
539 double rad = aperture->getAxes().getDeterminantRadius();
540 if (_ctrl.enforceMinimumRadius) {
541 double newRadius = rad;
542 if (_ctrl.minimumRadius > 0.0) {
543 if (rad < _ctrl.minimumRadius) {
544 newRadius = _ctrl.minimumRadius;
545 _flagHandler.setValue(source, USED_MINIMUM_RADIUS.number, true);
546 }
547 } else if (!exposure.getPsf()) {
548 throw LSST_EXCEPT(
551 NO_MINIMUM_RADIUS.number
552 );
553 } else if (rad < R_K_psf) {
554 newRadius = R_K_psf;
555 _flagHandler.setValue(source, USED_PSF_RADIUS.number, true);
556 }
557 if (newRadius != rad) {
558 aperture->getAxes().scale(newRadius/rad);
559 _flagHandler.setValue(source, SMALL_RADIUS.number, true); // guilty after all
560 }
561 }
562
563 _applyAperture(source, exposure, *aperture);
564 source.set(_radiusForRadiusKey, aperture->getRadiusForRadius());
565 source.set(_psfRadiusKey, R_K_psf);
566 if (bad) _flagHandler.setValue(source, FAILURE.number, true);
567}
568
570 afw::table::SourceRecord & measRecord,
571 afw::image::Exposure<float> const & exposure,
572 afw::table::SourceRecord const & refRecord,
573 afw::geom::SkyWcs const & refWcs
574 ) const {
575 geom::Point2D center = _centroidExtractor(measRecord, _flagHandler);
576 auto xytransform = afw::geom::makeWcsPairTransform(refWcs, *exposure.getWcs());
577 _applyForced(measRecord, exposure, center, refRecord,
578 linearizeTransform(*xytransform, refRecord.getCentroid())
579 );
580
581}
582
583
584std::shared_ptr<KronAperture> KronFluxAlgorithm::_fallbackRadius(afw::table::SourceRecord& source, double const R_K_psf,
586{
587 _flagHandler.setValue(source, BAD_RADIUS.number, true);
588 double newRadius;
589 if (_ctrl.minimumRadius > 0) {
590 newRadius = _ctrl.minimumRadius;
591 _flagHandler.setValue(source, USED_MINIMUM_RADIUS.number, true);
592 } else if (R_K_psf > 0) {
593 newRadius = R_K_psf;
594 _flagHandler.setValue(source, USED_PSF_RADIUS.number, true);
595 } else {
596 throw LSST_EXCEPT(
600 );
601 }
602 std::shared_ptr<KronAperture> aperture(new KronAperture(source));
603 aperture->getAxes().scale(newRadius/aperture->getAxes().getDeterminantRadius());
604 return aperture;
605}
606
607
608#define INSTANTIATE(TYPE) \
609template std::shared_ptr<KronAperture> KronAperture::determineRadius<afw::image::MaskedImage<TYPE> >( \
610 afw::image::MaskedImage<TYPE> const&, \
611 afw::geom::ellipses::Axes, \
612 geom::Point2D const&, \
613 KronFluxControl const& \
614 ); \
615template std::pair<double, double> KronAperture::measureFlux<afw::image::MaskedImage<TYPE> >( \
616 afw::image::MaskedImage<TYPE> const&, \
617 double const, \
618 double const \
619 ) const;
620
622
623}}}} // namespace lsst::meas::extensions::photometryKron
#define INSTANTIATE(FROMSYS, TOSYS)
Definition Detector.cc:509
#define LSST_EXCEPTION_TYPE(t, b, c)
Macro used to define new types of exceptions without additional data.
Definition Exception.h:69
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it.
Definition Exception.h:54
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
Class to describe the properties of a detected object from an image.
Definition Footprint.h:63
lsst::geom::Box2I getBBox() const
Return the Footprint's bounding box.
Definition Footprint.h:208
std::shared_ptr< geom::SpanSet > getSpans() const
Return a shared pointer to the SpanSet.
Definition Footprint.h:115
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition SkyWcs.h:118
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.
Definition SpanSet.cc:688
An ellipse core for the semimajor/semiminor axis and position angle parametrization (a,...
Definition Axes.h:47
double const getTheta() const
Definition Axes.h:57
double const getA() const
Definition Axes.h:51
double const getB() const
Definition Axes.h:54
void scale(double factor)
Scale the size of the ellipse core by the given factor.
Definition BaseCore.cc:103
double getDeterminantRadius() const
Return the radius defined as the 4th root of the determinant of the quadrupole matrix.
Definition BaseCore.cc:117
Transformer transform(lsst::geom::LinearTransform const &transform)
Return the transform that maps the ellipse to the unit circle.
An ellipse defined by an arbitrary BaseCore and a center point.
Definition Ellipse.h:51
lsst::geom::Point2D const & getCenter() const
Return the center point.
Definition Ellipse.h:62
BaseCore const & getCore() const
Return the ellipse core.
Definition Ellipse.h:71
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition Exposure.h:72
A class to manipulate images, masks, and variance as a single object.
Definition MaskedImage.h:74
Parameters to control convolution.
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,...
Definition Kernel.cc:167
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
Definition Kernel.h:860
Defines the fields and offsets for a table.
Definition Schema.h:51
Record class that contains measurements made on a single exposure.
Definition Source.h:78
CentroidSlotDefinition::MeasValue getCentroid() const
Get the value of the Centroid slot measurement.
Definition Source.h:569
Class for storing generic metadata.
Definition PropertySet.h:67
void add(std::string const &name, T const &value)
Append a single value to the vector of values for a property name (possibly hierarchical).
An integer coordinate rectangle.
Definition Box.h:55
A 2D linear coordinate transformation.
static Result computeSincFlux(afw::image::Image< T > const &image, afw::geom::ellipses::Ellipse const &ellipse, Control const &ctrl=Control())
Compute the instFlux (and optionally, uncertanties) within an aperture using Sinc photometry.
vector-type utility class to build a collection of FlagDefinitions
Definition FlagHandler.h:60
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.
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
Set the flag field corresponding to the given flag index.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Definition exceptions.h:48
std::pair< double, double > measureFlux(ImageT const &image, double const nRadiusForFlux, double const maxSincRadius) const
Photometer within the Kron Aperture on an image.
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.
static std::shared_ptr< KronAperture > determineRadius(ImageT const &image, afw::geom::ellipses::Axes axes, geom::Point2D const &center, KronFluxControl const &ctrl)
Determine the Kron Aperture from an image.
static meas::base::FlagDefinition const BAD_RADIUS
static meas::base::FlagDefinition const USED_MINIMUM_RADIUS
static meas::base::FlagDefinition const FAILURE
static meas::base::FlagDefinition const SMALL_RADIUS
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.
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 meas::base::FlagDefinition const BAD_SHAPE
static meas::base::FlagDefinitionList const & getFlagDefinitions()
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.
static meas::base::FlagDefinition const EDGE
static meas::base::FlagDefinition const NO_MINIMUM_RADIUS
static meas::base::FlagDefinition const NO_FALLBACK_RADIUS
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.
static meas::base::FlagDefinition const BAD_SHAPE_NO_PSF
static meas::base::FlagDefinition const USED_PSF_RADIUS
double smoothingSigma
"Smooth image with N(0, smoothingSigma^2) Gaussian while estimating R_K" ;
int nIterForRadius
"Number of times to iterate when setting the Kron radius" ;
double maxRadius
"Maximum aperture radius in pixels; used to avoid excess memory consumption for faint objects" ;
double minimumRadius
"Minimum Kron radius (if == 0.0 use PSF's Kron radius) if enforceMinimumRadius. " "Also functions as ...
double maxSincRadius
"Largest aperture for which to use the slow, accurate, sinc aperture code" ;
double nRadiusForFlux
"Number of Kron radii for Kron flux" ;
double nSigmaForRadius
"Multiplier of rms size for aperture used to initially estimate the Kron radius" ;
Provides consistent interface for LSST exceptions.
Definition Exception.h:107
Reports attempts to exceed implementation-defined length limits for some classes.
Definition Runtime.h:76
Reports attempts to access elements outside a valid range of indices.
Definition Runtime.h:89
Reports errors that are due to events beyond the control of the program.
Definition Runtime.h:104
T cos(T... args)
T epsilon(T... args)
T make_pair(T... args)
T make_shared(T... args)
T max(T... args)
const char * source()
Source function that allows astChannel to source from a Stream.
Definition Stream.h:224
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
A Transform obtained by putting two SkyWcs objects "back to back".
Definition SkyWcs.cc:161
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.
double constexpr ROOT2
Definition Angle.h:47
constexpr double radToDeg(double x) noexcept
Definition Angle.h:53
Point< double, 2 > Point2D
Definition Point.h:324
double constexpr PI
The ratio of a circle's circumference to diameter.
Definition Angle.h:40
Point< int, 2 > Point2I
Definition Point.h:321
std::pair< double, double > photometer(ImageT const &image, afw::geom::ellipses::Ellipse const &aperture, double const maxSincRadius)
double calculatePsfKronRadius(std::shared_ptr< afw::detection::Psf const > const &psf, geom::Point2D const &center, double smoothingSigma=0.0)
T nanf(T... args)
T quiet_NaN(T... args)
T reset(T... args)
T sin(T... args)
A Result struct for running an aperture flux algorithm with a single radius.
meas::base::Flux instFlux
Measured instFlux in DN.
meas::base::FluxErrElement instFluxErr
Standard deviation of instFlux in DN.