35 # include "Minuit2/FCNBase.h"
36 # include "Minuit2/FunctionMinimum.h"
37 # include "Minuit2/MnMigrad.h"
38 # include "Minuit2/MnMinos.h"
39 # include "Minuit2/MnPrint.h"
43 #include "Eigen/Cholesky"
55 namespace afwDetection = lsst::afw::detection;
56 namespace afwGeom = lsst::afw::geom;
58 namespace afwMath = lsst::afw::math;
62 namespace algorithms {
66 int const WARP_BUFFER(1);
67 std::string
const WARP_ALGORITHM(
"lanczos5");
71 template<
typename PixelT>
77 explicit SetPcaImageVisitor(
78 PsfImagePca<MaskedImageT> *imagePca,
79 unsigned int const mask=0
x0
81 afwMath::CandidateVisitor(),
89 PsfCandidate<PixelT> *imCandidate =
dynamic_cast<PsfCandidate<PixelT> *
>(candidate);
90 if (imCandidate == NULL) {
91 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
92 "Failed to cast SpatialCellCandidate to PsfCandidate");
109 throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
111 % imCandidate->getXCenter() % imCandidate->getYCenter()));
116 throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
117 str(
boost::format(
"Variance of Image at %d, %d contains NaN")
118 % imCandidate->getXCenter() % imCandidate->getYCenter()));
121 _imagePca->addImage(im, imCandidate->getSource()->getPsfFlux());
122 }
catch(lsst::pex::exceptions::LengthError &) {
132 template<
typename PixelT>
145 PsfCandidate<PixelT> *imCandidate =
dynamic_cast<PsfCandidate<PixelT> *
>(candidate);
146 if (imCandidate == NULL) {
147 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
148 "Failed to cast SpatialCellCandidate to PsfCandidate");
152 imCandidate->getMaskedImage();
153 }
catch(lsst::pex::exceptions::LengthError &) {
161 double getN()
const {
return _n; }
172 template<
typename ImageT>
173 std::vector<typename ImageT::Ptr> offsetKernel(
179 unsigned int const nKernel = kernels.size();
180 std::vector<typename ImageT::Ptr> kernelImages(nKernel);
182 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
183 "Kernel has no components");
187 for (
unsigned int i = 0; i != nKernel; ++i) {
188 kernels[i]->computeImage(scratch,
false);
205 template<
typename PixelT>
210 int const nEigenComponents,
211 int const spatialOrder,
213 int const nStarPerCell,
214 bool const constantWeight,
236 SetPcaImageVisitor<PixelT> importStarVisitor(&imagePca);
237 bool const ignoreExceptions =
true;
238 psfCells.
visitCandidates(&importStarVisitor, nStarPerCell, ignoreExceptions);
247 double deltaLim = 10.0;
252 for (
int i = 0; i != niter; ++i) {
253 int const ncomp = (i == 0) ? 0 :
254 ((nEigenComponents == 0) ? imagePca.
getEigenImages().size() : nEigenComponents);
256 if (i > 0 && delta < deltaLim) {
263 std::vector<typename MaskedImageT::Ptr> eigenImages = imagePca.
getEigenImages();
265 int const nEigen =
static_cast<int>(eigenValues.size());
267 int const ncomp = (nEigenComponents <= 0 || nEigen < nEigenComponents) ? nEigen : nEigenComponents;
273 for (
int k = 0; k != ncomp; ++k) {
274 ImageT
const& im = *eigenImages[k]->getImage();
277 if (bkg_border > im.getWidth()) {
278 bkg_border = im.getWidth() / 2;
280 if (bkg_border > im.getHeight()) {
281 bkg_border = im.getHeight() / 2;
286 for (
int i = 0; i != bkg_border; ++i) {
287 typename ImageT::const_x_iterator
288 ptrB = im.row_begin(i), ptrT = im.row_begin(im.getHeight() - i - 1);
289 for (
int j = 0; j != im.getWidth(); ++j, ++ptrB, ++ptrT) {
290 sum += *ptrB + *ptrT;
293 for (
int i = bkg_border; i < im.getHeight() - bkg_border; ++i) {
295 typename ImageT::const_x_iterator
296 ptrL = im.row_begin(i), ptrR = im.row_begin(i) + im.getWidth() - bkg_border;
297 for (
int j = 0; j != bkg_border; ++j, ++ptrL, ++ptrR) {
298 sum += *ptrL + *ptrR;
301 sum /= 2*(bkg_border*im.getWidth() + bkg_border*(im.getHeight() - 2*bkg_border));
303 *eigenImages[k] -= sum;
310 std::vector<afwMath::Kernel::SpatialFunctionPtr> spatialFunctionList;
313 for (
int i = 0; i != ncomp; ++i) {
318 ImageT&
image = *eigenImages[i]->getImage();
319 double sum = std::accumulate(image.begin(
true), image.end(
true), 0.0);
323 for (
typename ImageT::fast_iterator ptr0 = eigenImages[0]->getImage()->begin(
true),
324 ptr1 = image.begin(
true), end = image.end(
true); ptr1 != end; ++ptr0, ++ptr1) {
325 *ptr1 = *ptr1 / sum - *ptr0;
337 spatialFunction->setParameter(0, 1.0);
338 spatialFunctionList.push_back(spatialFunction);
344 return std::make_pair(psf, eigenValues);
351 template<
typename PixelT>
353 int const nStarPerCell)
355 countVisitor<PixelT> counter;
358 return counter.getN();
368 template<
typename ModelImageT,
typename DataImageT>
369 std::pair<double, double>
370 fitKernel(ModelImageT
const& mImage,
371 DataImageT
const& data,
373 bool detected =
true,
376 assert(data.getDimensions() == mImage.getDimensions());
381 double sumMM = 0.0, sumMD = 0.0, sumDD = 0.0;
383 for (
int y = 0;
y != data.getHeight(); ++
y) {
384 typename ModelImageT::x_iterator mptr = mImage.row_begin(
y);
385 for (
typename DataImageT::x_iterator ptr = data.row_begin(
y), end = data.row_end(
y);
386 ptr != end; ++ptr, ++mptr) {
387 double const m = (*mptr)[0];
388 double const d = ptr.image();
389 double const var = ptr.variance() + lambda*d;
390 if (detected && !(ptr.mask() & DETECTED)) {
393 if (ptr.mask() & BAD) {
397 double const iVar = 1.0/var;
407 throw LSST_EXCEPT(lsst::pex::exceptions::RangeError,
"No good pixels");
410 throw LSST_EXCEPT(lsst::pex::exceptions::RangeError,
"sum(data*data)/var == 0");
413 double const amp = sumMD/sumMM;
414 double const chi2 = (sumDD - 2*amp*sumMD + amp*amp*sumMM)/(npix - 1);
421 int y = data.getHeight()/2;
422 int x = data.getWidth()/2;
425 for (
int ii = -hsize; ii <= hsize; ++ii) {
426 for (
int jj = -hsize; jj <= hsize; ++jj) {
427 printf(
"%7.1f ", data.at(x + jj, y - ii).image());
430 for (
int jj = -hsize; jj <= hsize; ++jj) {
431 printf(
"%7.1f ", amp*(*(mImage.at(x + jj, y - ii)))[0]);
435 printf(
"%g %.1f\n", amp, chi2);
439 return std::make_pair(chi2, amp);
448 template<
typename PixelT>
471 if (imCandidate == NULL) {
472 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
473 "Failed to cast SpatialCellCandidate to PsfCandidate");
476 double const xcen = imCandidate->
getSource()->getX();
477 double const ycen = imCandidate->
getSource()->getY();
483 }
catch(lsst::pex::exceptions::LengthError &) {
488 std::pair<double, double> result = fitKernel(*
_kImage, *data,
_lambda,
false,
491 double dchi2 = result.first;
492 double const amp = result.second;
498 }
catch(lsst::pex::exceptions::RangeError &e) {
500 imCandidate->
setChi2(std::numeric_limits<double>::quiet_NaN());
501 imCandidate->
setAmplitude(std::numeric_limits<double>::quiet_NaN());
521 std::vector<double>
const& coeffs
527 assert (nComponents*nSpatialParams == static_cast<long>(coeffs.size()));
529 std::vector<std::vector<double> > kCoeffs;
530 kCoeffs.reserve(nComponents);
531 for (
int i = 0; i != nComponents; ++i) {
532 kCoeffs.push_back(std::vector<double>(nSpatialParams));
533 std::copy(coeffs.begin() + i*nSpatialParams,
534 coeffs.begin() + (i + 1)*nSpatialParams, kCoeffs[i].begin());
545 Eigen::VectorXd
const& vec
551 assert (nComponents*nSpatialParams == vec.size());
553 std::vector<std::vector<double> > kCoeffs;
554 kCoeffs.reserve(nComponents);
555 for (
int i = 0; i != nComponents; ++i) {
556 std::vector<double> spatialCoeffs(nSpatialParams);
557 for (
int j = 0; j != nSpatialParams; ++j) {
558 spatialCoeffs[j] = vec[i*nSpatialParams + j];
560 kCoeffs.push_back(spatialCoeffs);
569 template<
typename PixelT>
619 template<
typename PixelT>
620 std::pair<bool, double>
624 int const nStarPerCell,
625 double const tolerance,
639 std::vector<double> coeffs;
640 coeffs.assign(nComponents*nSpatialParams, 0.0);
642 std::vector<double> stepSize;
643 stepSize.assign(nComponents*nSpatialParams, 100);
647 ROOT::Minuit2::MnUserParameters fitPar;
648 std::vector<std::string> paramNames;
649 paramNames.reserve(nComponents*nSpatialParams);
651 for (
int i = 0, c = 0; c != nComponents; ++c) {
653 for (
int s = 0; s != nSpatialParams; ++s, ++i) {
654 paramNames.push_back((
boost::format(
"C%d:%d") % c % s).str());
655 fitPar.Add(paramNames[i].c_str(), coeffs[i], stepSize[i]);
662 MinimizeChi2<PixelT> minimizerFunc(getChi2, kernel, psfCells, nStarPerCell, nComponents, nSpatialParams);
664 double const errorDef = 1.0;
669 ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar);
674 ROOT::Minuit2::FunctionMinimum min =
675 migrad(maxFnCalls, tolerance/(1e-4*errorDef));
677 float minChi2 = min.Fval();
678 bool const isValid = min.IsValid() && std::isfinite(minChi2);
680 if (
true || isValid) {
681 for (
int i = 0; i != nComponents*nSpatialParams; ++i) {
682 coeffs[i] = min.UserState().Value(i);
688 #if 0 // Estimate errors; we don't really need this
689 ROOT::Minuit2::MnMinos minos(minimizerFunc, min);
690 for (
int i = 0, c = 0; c != nComponents; ++c) {
691 for (
int s = 0; s != nSpatialParams; ++s, ++i) {
692 char const *
name = paramNames[i].c_str();
693 printf(
"%s %g", name, min.UserState().Value(name));
694 if (isValid && !fitPar.Parameter(fitPar.Index(name)).IsFixed()) {
695 printf(
" (%g+%g)\n", minos(i).first, minos(i).second);
707 return std::make_pair(isValid, minChi2);
751 template<
typename PixelT>
762 afwMath::CandidateVisitor(),
782 kernels[i]->computeImage(*
_basisImgs[i],
false);
792 PsfCandidate<PixelT>::getBorderWidth());
801 PsfCandidate<PixelT> *imCandidate =
dynamic_cast<PsfCandidate<PixelT> *
>(candidate);
802 if (imCandidate == NULL) {
803 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
804 "Failed to cast SpatialCellCandidate to PsfCandidate");
810 }
catch(lsst::pex::exceptions::LengthError &) {
813 double const xcen = imCandidate->getXCenter();
814 double const ycen = imCandidate->getYCenter();
819 double const amp = imCandidate->getAmplitude();
830 std::pair<afwMath::Kernel::Ptr, std::pair<double, double> > ret =
832 double const amp = ret.second.first;
835 double const var = imCandidate->getVar();
836 double const ivar = 1/(var +
_tau2);
844 std::vector<typename KImage::Ptr> basisImages = offsetKernel<KImage>(
_kernel, dx, dy);
848 typename Image::Ptr dataImage(
new Image(*data->getImage(),
true));
851 dPtr != end; ++dPtr, ++bPtr) {
852 *dPtr = *dPtr / amp - *bPtr;
857 PsfCandidate<PixelT>::getBorderWidth());
859 _b(i) += ivar*params[ic][is]*basisDotData;
871 Eigen::MatrixXd
const& getA()
const {
return _A; }
872 Eigen::VectorXd
const& getB()
const {
return _b; }
887 template<
typename PixelT>
894 PsfCandidate<PixelT> *imCandidate =
dynamic_cast<PsfCandidate<PixelT> *
>(candidate);
895 if (imCandidate == NULL) {
896 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
897 "Failed to cast SpatialCellCandidate to PsfCandidate");
907 template<
typename PixelT>
908 std::pair<bool, double>
912 bool const doNonLinearFit,
913 int const nStarPerCell,
914 double const tolerance,
918 if (doNonLinearFit) {
919 return fitSpatialKernelFromPsfCandidates<PixelT>(kernel, psfCells, nStarPerCell, tolerance);
922 double const tau = 0;
927 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
928 "Failed to cast Kernel to LinearCombinationKernel while building spatial PSF model");
934 setAmplitudeVisitor<PixelT> setAmplitude;
940 FillABVisitor<PixelT> getAB(*lcKernel, tau);
948 Eigen::MatrixXd
const& A = getAB.getA();
949 Eigen::VectorXd
const&
b = getAB.getB();
950 Eigen::VectorXd
x0(b.size());
956 x0(0) =
b(0)/A(0, 0);
959 x0 = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
963 std::cout <<
"A " << A << std::endl;
964 std::cout <<
"b " << b.transpose() << std::endl;
965 std::cout <<
"x " << x.transpose() << std::endl;
968 for (
int j = 0; j < b.size(); ++j) {
969 for (
int i = 0; i < b.size(); ++i) {
973 img.writeFits(
"a.fits");
976 for (
int i = 0; i != 6; ++i) {
977 double xcen = 25;
double ycen = 35 + 35*i;
978 std::cout <<
"x, y " << xcen <<
" , " << ycen <<
" b "
979 << (x[3] + xcen*x[4] + ycen*x[5])/(x[0] + xcen*x[1] + ycen*x[2]) << std::endl;
1001 return std::make_pair(
true, getChi2.
getValue());
1008 template<
typename MaskedImageT>
1016 if (std::isnan(x + y)) {
1017 return std::numeric_limits<double>::quiet_NaN();
1030 typename MaskedImageT::Ptr subData(
new MaskedImageT(*data, bbox,
afwImage::PARENT,
false));
1034 double lambda = 0.0;
1039 if (std::isnan(psfFlux)) {
1040 std::pair<double, double> result = fitKernel(*kImage, *subData, lambda,
true);
1041 chi2 = result.first;
1042 amp = result.second;
1044 chi2 = std::numeric_limits<double>::quiet_NaN();
1050 typename MaskedImageT::Image::Ptr
1051 kImageF(
new typename MaskedImageT::Image(*kImage,
true));
1054 *subData->getImage() -= *kImageF;
1057 }
catch(lsst::pex::exceptions::RangeError &e) {
1069 template<
typename Image>
1080 int const nKernel = kernels.size();
1083 throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
1084 "Your kernel must have at least one component");
1091 std::vector<KernelT::Ptr> kernelImages = offsetKernel<KernelT>(kernel, pos[0], pos[1]);
1099 Eigen::MatrixXd A(nKernel, nKernel);
1100 Eigen::VectorXd
b(nKernel);
1102 for (
int i = 0; i != nKernel; ++i) {
1105 for (
int j = i; j != nKernel; ++j) {
1109 Eigen::VectorXd
x(nKernel);
1112 x(0) =
b(0)/A(0, 0);
1114 x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
1118 int const x0 = kernelImages[0]->getX0(),
y0 = kernelImages[0]->getY0();
1121 std::vector<double> params(nKernel);
1122 for (
int i = 0; i != nKernel; ++i) {
1124 newKernel->setCtrX(x0 + static_cast<int>(newKernel->getWidth()/2));
1125 newKernel->setCtrY(
y0 + static_cast<int>(newKernel->getHeight()/2));
1128 newKernels[i] = newKernel;
1131 return std::make_pair(params, newKernels);
1141 template<
typename Image>
1142 std::pair<afwMath::Kernel::Ptr, std::pair<double, double> >
1151 std::vector<double> params = fit.first;
1153 int const nKernel = params.size();
1154 assert(kernels.size() ==
static_cast<unsigned int>(nKernel));
1157 for (
int i = 0; i != nKernel; ++i) {
1160 amp += params[i] * k->getSum();
1165 outputKernel->setCtrX(kernels[0]->getCtrX());
1166 outputKernel->setCtrY(kernels[0]->getCtrY());
1168 return std::make_pair(outputKernel, std::make_pair(amp, chisq));
1177 typedef float Pixel;
1180 std::pair<afwMath::LinearCombinationKernel::Ptr, std::vector<double> >
1183 int const,
bool const,
int const);
1188 std::pair<bool, double>
1190 int const,
double const,
double const);
1192 std::pair<bool, double>
1194 int const,
double const,
double const);
1205 std::pair<afwMath::Kernel::Ptr, std::pair<double, double> >
afwImage::MaskedImage< PixelT > MaskedImage
2-dimensional weighted sum of Chebyshev polynomials of the first kind.
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Class used by SpatialCell for spatial PSF fittig.
void setStatus(Status status)
Set the candidate's status.
Class for doing PCA on PSF stars.
A coordinate class intended to represent absolute positions.
void setAmplitude(double amplitude)
Set the best-fit amplitude.
geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
ImageT::Ptr offsetImage(ImageT const &inImage, float dx, float dy, std::string const &algorithmName, unsigned int buffer)
Return an image offset by (dx, dy) using the specified algorithm.
std::vector< double > const & getEigenValues() const
Return Eigen values.
afwImage::Exposure< PixelT > Exposure
table::Key< std::string > name
void setErrorDef(double def)
afwImage::Image< afwMath::Kernel::Pixel > KImage
int positionToIndex(double pos)
Convert image position to nearest integer index.
std::vector< typename KImage::Ptr > _basisImgs
void processCandidate(afwMath::SpatialCellCandidate *candidate)
int countPsfCandidates(lsst::afw::math::SpatialCellSet const &psfCells, int const nStarPerCell=-1)
boost::shared_ptr< afw::table::SourceRecord > getSource() const
Return the original Source.
A class to contain the data, WCS, and other information needed to describe an image of the sky...
A coordinate class intended to represent offsets and dimensions.
double subtractPsf(lsst::afw::detection::Psf const &psf, ImageT *data, double x, double y, double psfFlux=std::numeric_limits< double >::quiet_NaN())
MinimizeChi2(evalChi2Visitor< PixelT > &chi2Visitor, afwMath::Kernel *kernel, afwMath::SpatialCellSet const &psfCells, int nStarPerCell, int nComponents, int nSpatialParams)
boost::shared_ptr< Image > computeImage(geom::Point2D position=makeNullPoint(), image::Color color=image::Color(), ImageOwnerEnum owner=COPY) const
Return an Image of the PSF, in a form that can be compared directly with star images.
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
boost::shared_ptr< LinearCombinationKernel > Ptr
Define a collection of useful Functions.
evalChi2Visitor(afwMath::Kernel const &kernel, double lambda)
afwImage::Image< PixelT > Image
std::pair< std::vector< double >, lsst::afw::math::KernelList > fitKernelParamsToImage(lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
afwMath::Kernel const & _kernel
An integer coordinate rectangle.
int getHeight() const
Return the Kernel's height.
table::Key< table::Array< Kernel::Pixel > > image
int const _nSpatialParams
double innerProduct(Image1T const &lhs, Image2T const &rhs, int border)
int getWidth() const
Return the Kernel's width.
double getValue(Property const prop=NOTHING) const
Return the value of the desired property (if specified in the constructor)
Eigen::MatrixXd _basisDotBasis
boost::shared_ptr< Kernel > Ptr
A collection of SpatialCells covering an entire image.
ImageList const & getEigenImages() const
Return Eigen images.
Pass parameters to a Statistics objectA class to pass parameters which control how the stats are calc...
A class to pass around to all our PsfCandidates to evaluate the PSF fit's X^2.
Class used by SpatialCell for spatial PSF fittig.
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
afwMath::LinearCombinationKernel const & _kernel
virtual KernelList const & getKernelList() const
Get the fixed basis kernels.
double computeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize, double x=0.0, double y=0.0) const
Compute an image (pixellized representation of the kernel) in place.
A kernel that is a linear combination of fixed basis kernels.
A class to manipulate images, masks, and variance as a single object.
evalChi2Visitor< PixelT > & _chi2Visitor
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
std::shared_ptr< Image< PixelT > > Ptr
void setSpatialParameters(const std::vector< std::vector< double > > params)
Set the parameters of all spatial functions.
void setSpatialParameters(afwMath::Kernel *kernel, std::vector< double > const &coeffs)
std::shared_ptr< const MaskedImage > ConstPtr
std::shared_ptr< MaskedImage > Ptr
shared pointer to a MaskedImage
#define LSST_EXCEPT(type,...)
void setNanSafe(bool isNanSafe)
SpatialFunctionPtr getSpatialFunction(unsigned int index) const
Return a clone of the specified spatial function (one component of the spatial model) ...
boost::shared_ptr< FixedKernel > Ptr
static void setWidth(int width)
Set the width of the image that getImage should return.
afwMath::Kernel * _kernel
afwMath::SpatialCellSet const & _psfCells
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Class to ensure constraints for spatial modeling.
afw::table::Key< double > b
std::pair< lsst::afw::math::Kernel::Ptr, std::pair< double, double > > fitKernelToImage(lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
static void setHeight(int height)
Set the height of the image that getImage should return.
void visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions=false)
double operator()(const std::vector< double > &coeffs) const
boost::shared_ptr< afw::image::MaskedImage< PixelT > > getOffsetImage(std::string const algorithm, unsigned int buffer) const
Return an offset version of the image of the source. The returned image has been offset to put the ce...
void setChi2(double chi2)
Set the candidate's chi^2.
find sum of pixels in the image
A floating-point coordinate rectangle geometry.
A polymorphic base class for representing an image's Point Spread Function.
std::pair< lsst::afw::math::LinearCombinationKernel::Ptr, std::vector< double > > createKernelFromPsfCandidates(lsst::afw::math::SpatialCellSet const &psfCells, lsst::afw::geom::Extent2I const &dims, lsst::afw::geom::Point2I const &xy0, int const nEigenComponents, int const spatialOrder, int const ksize, int const nStarPerCell=-1, bool const constantWeight=true, int const border=3)
#define LSST_EXCEPT_ADD(e, m)
Kernels are used for convolution with MaskedImages and (eventually) Images.
void visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell=-1, bool const ignoreExceptions=false)
Class stored in SpatialCells for spatial Psf fitting.
virtual double updateBadPixels(unsigned long mask, int const ncomp)
PsfImagePca< MaskedImageT > * _imagePca
std::pair< bool, double > fitSpatialKernelFromPsfCandidates(lsst::afw::math::Kernel *kernel, lsst::afw::math::SpatialCellSet const &psfCells, int const nStarPerCell=-1, double const tolerance=1e-5, double const lambda=0.0)
A kernel created from an Image.
std::vector< boost::shared_ptr< Kernel > > KernelList