17#include "boost/timer.hpp"
20#include "Eigen/Cholesky"
23#include "Eigen/Eigenvalues"
38#include "ndarray/eigen.h"
41#define DEBUG_MATRIX2 0
67 _fitForBackground(fitForBackground)
78 _fitForBackground(fitForBackground)
87 _fitForBackground(true)
100 switch (conditionType) {
103 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
104 Eigen::VectorXd eValues = eVecValues.eigenvalues();
105 double eMax = eValues.maxCoeff();
106 double eMin = eValues.minCoeff();
107 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
108 "EIGENVALUE eMax / eMin = %.3e", eMax / eMin);
109 return (eMax / eMin);
114 Eigen::VectorXd sValues = mMat.jacobiSvd().singularValues();
115 double sMax = sValues.maxCoeff();
116 double sMin = sValues.minCoeff();
117 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
118 "SVD eMax / eMin = %.3e", sMax / sMin);
119 return (sMax / sMin);
125 "Undefined ConditionNumberType : only EIGENVALUE, SVD allowed.");
132 Eigen::VectorXd
const& bVec) {
141 Eigen::VectorXd aVec = Eigen::VectorXd::Zero(bVec.size());
146 LOGL_DEBUG(
"TRACE2.ip.diffim.KernelSolution.solve",
147 "Solving for kernel");
149 Eigen::FullPivLU<Eigen::MatrixXd> lu(mMat);
150 if (lu.isInvertible()) {
151 aVec = lu.solve(bVec);
153 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
154 "Unable to determine kernel via LU");
159 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
160 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
161 Eigen::VectorXd eValues = eVecValues.eigenvalues();
163 for (
int i = 0; i != eValues.rows(); ++i) {
164 if (eValues(i) != 0.0) {
165 eValues(i) = 1.0/eValues(i);
169 aVec = rMat * eValues.asDiagonal() * rMat.transpose() * bVec;
173 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
174 "Unable to determine kernel via eigen-values");
180 double time = t.elapsed();
181 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
182 "Compute time for matrix math : %.2f s", time);
194 template <
typename InputT>
197 bool fitForBackground
214 template <
typename InputT>
222 template <
typename InputT>
230 (void)_kernel->computeImage(*
image,
false);
234 template <
typename InputT>
242 template <
typename InputT>
250 template <
typename InputT>
260 template <
typename InputT>
270 "Error: variance less than 0.0");
274 "Error: variance equals 0.0, cannot inverse variance weight");
278 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(_kernel)->getKernelList();
280 unsigned int const nKernelParameters = basisList.
size();
281 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
282 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
319 unsigned int const startCol = goodBBox.
getMinX();
320 unsigned int const startRow = goodBBox.
getMinY();
322 unsigned int endCol = goodBBox.
getMaxX() + 1;
323 unsigned int endRow = goodBBox.
getMaxY() + 1;
338 startRow, startCol, endRow-startRow, endCol-startCol
339 ).array().inverse().matrix();
342 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
343 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
344 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
357 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
364 cMat.resize(cMat.size(), 1);
369 double time = t.elapsed();
370 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
371 "Total compute time to do basis convolutions : %.2f s", time);
378 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
381 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
382 cMat.col(kidxj) = eiterj->col(0);
385 if (_fitForBackground)
386 cMat.col(nParameters-1).fill(1.);
389 _ivVec = eigeniVariance.col(0);
390 _iVec = eigenScience.col(0);
393 _mMat = _cMat.transpose() * (_ivVec.asDiagonal() * _cMat);
394 _bVec = _cMat.transpose() * (_ivVec.asDiagonal() * _iVec);
397 template <
typename InputT>
399 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.solve",
400 "mMat is %d x %d; bVec is %d; cMat is %d x %d; vVec is %d; iVec is %d",
401 _mMat.rows(), _mMat.cols(), _bVec.size(),
402 _cMat.rows(), _cMat.cols(), _ivVec.size(), _iVec.size());
423 template <
typename InputT>
429 unsigned int const nParameters = _aVec.size();
430 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
431 unsigned int const nKernelParameters =
432 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(_kernel)->getKernelList().size();
433 if (nParameters != (nKernelParameters + nBackgroundParameters))
438 for (
unsigned int idx = 0; idx < nKernelParameters; idx++) {
441 str(boost::format(
"Unable to determine kernel solution %d (nan)") % idx));
443 kValues[idx] = _aVec(idx);
445 _kernel->setKernelParameters(kValues);
448 new ImageT(_kernel->getDimensions())
450 _kSum = _kernel->computeImage(*
image,
false);
452 if (_fitForBackground) {
455 str(boost::format(
"Unable to determine background solution %d (nan)") %
458 _background = _aVec(nParameters-1);
463 template <
typename InputT>
493 template <
typename InputT>
496 bool fitForBackground
501 template <
typename InputT>
512 "Error: variance less than 0.0");
516 "Error: variance equals 0.0, cannot inverse variance weight");
524 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
539 int growPix = (*kiter)->getCtr().getX();
543 for (
typename afwDet::FootprintSet::FootprintList::iterator
549 afwDet::setMaskFromFootprint(finalMask,
556 for (
auto const & foot : *(maskedFpSetGrown.
getFootprints())) {
563 ndarray::Array<int, 1, 1> maskArray =
564 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
565 fullFp->getSpans()->flatten(maskArray, finalMask.
getArray(), templateImage.
getXY0());
566 auto maskEigen = ndarray::asEigenMatrix(maskArray);
568 ndarray::Array<InputT, 1, 1> arrayTemplate =
569 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
570 fullFp->getSpans()->flatten(arrayTemplate, templateImage.
getArray(), templateImage.
getXY0());
571 auto eigenTemplate0 = ndarray::asEigenMatrix(arrayTemplate);
573 ndarray::Array<InputT, 1, 1> arrayScience =
574 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
575 fullFp->getSpans()->flatten(arrayScience, scienceImage.
getArray(), scienceImage.
getXY0());
576 auto eigenScience0 = ndarray::asEigenMatrix(arrayScience);
578 ndarray::Array<afwImage::VariancePixel, 1, 1> arrayVariance =
579 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
580 fullFp->getSpans()->flatten(arrayVariance, varianceEstimate.
getArray(), varianceEstimate.
getXY0());
581 auto eigenVariance0 = ndarray::asEigenMatrix(arrayVariance);
584 for (
int i = 0; i < maskEigen.size(); i++) {
585 if (maskEigen(i) == 0.0)
589 Eigen::VectorXd eigenTemplate(nGood);
590 Eigen::VectorXd eigenScience(nGood);
591 Eigen::VectorXd eigenVariance(nGood);
593 for (
int i = 0; i < maskEigen.size(); i++) {
594 if (maskEigen(i) == 0.0) {
595 eigenTemplate(nUsed) = eigenTemplate0(i);
596 eigenScience(nUsed) = eigenScience0(i);
597 eigenVariance(nUsed) = eigenVariance0(i);
606 unsigned int const nKernelParameters = basisList.
size();
607 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
608 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
622 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
625 ndarray::Array<InputT, 1, 1> arrayC =
626 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
627 fullFp->getSpans()->flatten(arrayC, cimage.
getArray(), cimage.
getXY0());
628 auto eigenC0 = ndarray::asEigenMatrix(arrayC);
630 Eigen::VectorXd eigenC(nGood);
632 for (
int i = 0; i < maskEigen.size(); i++) {
633 if (maskEigen(i) == 0.0) {
634 eigenC(nUsed) = eigenC0(i);
641 double time = t.elapsed();
642 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.buildWithMask",
643 "Total compute time to do basis convolutions : %.2f s", time);
647 Eigen::MatrixXd cMat(eigenTemplate.size(), nParameters);
650 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
651 cMat.block(0, kidxj, eigenTemplate.size(), 1) =
652 Eigen::MatrixXd(*eiterj).block(0, 0, eigenTemplate.size(), 1);
655 if (this->_fitForBackground)
656 cMat.col(nParameters-1).fill(1.);
659 this->_ivVec = eigenVariance.array().inverse().matrix();
660 this->_iVec = eigenScience;
663 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_cMat);
664 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_iVec);
668 template <
typename InputT>
679 "Error: variance less than 0.0");
683 "Error: variance equals 0.0, cannot inverse variance weight");
687 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
699 unsigned int const nKernelParameters = basisList.
size();
700 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
701 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
709 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
710 "Limits of good pixels after convolution: %d,%d -> %d,%d (local)",
715 unsigned int startCol = shrunkLocalBBox.
getMinX();
716 unsigned int startRow = shrunkLocalBBox.
getMinY();
717 unsigned int endCol = shrunkLocalBBox.
getMaxX();
718 unsigned int endRow = shrunkLocalBBox.
getMaxY();
741 startRow, startCol, endRow-startRow, endCol-startCol
742 ).array().inverse().matrix();
745 eMask.resize(eMask.rows()*eMask.cols(), 1);
746 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
747 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
748 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
751 Eigen::MatrixXd maskedEigenTemplate(eigenTemplate.rows(), 1);
752 Eigen::MatrixXd maskedEigenScience(eigenScience.rows(), 1);
753 Eigen::MatrixXd maskedEigeniVariance(eigeniVariance.rows(), 1);
755 for (
int i = 0; i < eMask.rows(); i++) {
756 if (eMask(i, 0) == 0) {
757 maskedEigenTemplate(nGood, 0) = eigenTemplate(i, 0);
758 maskedEigenScience(nGood, 0) = eigenScience(i, 0);
759 maskedEigeniVariance(nGood, 0) = eigeniVariance(i, 0);
764 eigenTemplate = maskedEigenTemplate.block(0, 0, nGood, 1);
765 eigenScience = maskedEigenScience.block(0, 0, nGood, 1);
766 eigeniVariance = maskedEigeniVariance.block(0, 0, nGood, 1);
780 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
787 cMat.resize(cMat.size(), 1);
790 Eigen::MatrixXd maskedcMat(cMat.rows(), 1);
792 for (
int i = 0; i < eMask.rows(); i++) {
793 if (eMask(i, 0) == 0) {
794 maskedcMat(nGood, 0) = cMat(i, 0);
798 cMat = maskedcMat.block(0, 0, nGood, 1);
802 double time = t.elapsed();
803 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
804 "Total compute time to do basis convolutions : %.2f s", time);
811 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
814 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
815 cMat.col(kidxj) = eiterj->col(0);
818 if (this->_fitForBackground)
819 cMat.col(nParameters-1).fill(1.);
822 this->_ivVec = eigeniVariance.col(0);
823 this->_iVec = eigenScience.col(0);
826 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
827 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
833 template <
typename InputT>
844 "Error: variance less than 0.0");
848 "Error: variance equals 0.0, cannot inverse variance weight");
852 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
854 unsigned int const nKernelParameters = basisList.
size();
855 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
856 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
886 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
887 "Limits of good pixels after convolution: %d,%d -> %d,%d",
891 unsigned int const startCol = shrunkBBox.
getMinX();
892 unsigned int const startRow = shrunkBBox.
getMinY();
893 unsigned int const endCol = shrunkBBox.
getMaxX();
894 unsigned int const endRow = shrunkBBox.
getMaxY();
909 int maskStartCol = maskBox.
getMinX();
910 int maskStartRow = maskBox.
getMinY();
911 int maskEndCol = maskBox.
getMaxX();
912 int maskEndRow = maskBox.
getMaxY();
945 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
946 "Upper good pixel region: %d,%d -> %d,%d",
948 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
949 "Bottom good pixel region: %d,%d -> %d,%d",
951 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
952 "Left good pixel region: %d,%d -> %d,%d",
954 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
955 "Right good pixel region: %d,%d -> %d,%d",
969 Eigen::MatrixXd eigenTemplate(totalSize, 1);
970 Eigen::MatrixXd eigenScience(totalSize, 1);
971 Eigen::MatrixXd eigeniVariance(totalSize, 1);
972 eigenTemplate.setZero();
973 eigenScience.setZero();
974 eigeniVariance.setZero();
981 for (; biter != boxArray.
end(); ++biter) {
982 int area = (*biter).getWidth() * (*biter).getHeight();
990 Eigen::MatrixXd eiVarEstimate =
imageToEigenMatrix(sVarEstimate).array().inverse().matrix();
992 eTemplate.resize(area, 1);
993 eScience.resize(area, 1);
994 eiVarEstimate.resize(area, 1);
996 eigenTemplate.block(nTerms, 0, area, 1) = eTemplate.block(0, 0, area, 1);
997 eigenScience.block(nTerms, 0, area, 1) = eScience.block(0, 0, area, 1);
998 eigeniVariance.block(nTerms, 0, area, 1) = eiVarEstimate.block(0, 0, area, 1);
1010 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
1012 Eigen::MatrixXd cMat(totalSize, 1);
1017 for (; biter != boxArray.
end(); ++biter) {
1018 int area = (*biter).getWidth() * (*biter).getHeight();
1022 esubimage.resize(area, 1);
1023 cMat.block(nTerms, 0, area, 1) = esubimage.block(0, 0, area, 1);
1032 double time = t.elapsed();
1033 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
1034 "Total compute time to do basis convolutions : %.2f s", time);
1041 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
1044 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
1045 cMat.col(kidxj) = eiterj->col(0);
1048 if (this->_fitForBackground)
1049 cMat.col(nParameters-1).fill(1.);
1052 this->_ivVec = eigeniVariance.col(0);
1053 this->_iVec = eigenScience.col(0);
1056 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
1057 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
1062 template <
typename InputT>
1065 bool fitForBackground,
1066 Eigen::MatrixXd
const& hMat,
1075 template <
typename InputT>
1077 Eigen::MatrixXd vMat = this->_cMat.jacobiSvd().matrixV();
1078 Eigen::MatrixXd vMatvMatT = vMat * vMat.transpose();
1081 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(this->_mMat);
1082 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
1083 Eigen::VectorXd eValues = eVecValues.eigenvalues();
1084 double eMax = eValues.maxCoeff();
1085 for (
int i = 0; i != eValues.rows(); ++i) {
1086 if (eValues(i) == 0.0) {
1089 else if ((eMax / eValues(i)) > maxCond) {
1090 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1091 "Truncating eValue %d; %.5e / %.5e = %.5e vs. %.5e",
1092 i, eMax, eValues(i), eMax / eValues(i), maxCond);
1096 eValues(i) = 1.0 / eValues(i);
1099 Eigen::MatrixXd mInv = rMat * eValues.asDiagonal() * rMat.transpose();
1103 for (
unsigned int i = 0; i < lambdas.
size(); i++) {
1104 double l = lambdas[i];
1105 Eigen::MatrixXd mLambda = this->_mMat + l * _hMat;
1113 Eigen::VectorXd term1 = (this->_aVec.transpose() * vMatvMatT * this->_aVec);
1114 if (term1.size() != 1)
1117 double term2a = (vMatvMatT * mLambda.inverse()).trace();
1119 Eigen::VectorXd term2b = (this->_aVec.transpose() * (mInv * this->_bVec));
1120 if (term2b.size() != 1)
1123 double risk = term1(0) + 2 * (term2a - term2b(0));
1124 LOGL_DEBUG(
"TRACE4.ip.diffim.RegularizedKernelSolution.estimateRisk",
1125 "Lambda = %.3f, Risk = %.5e",
1127 LOGL_DEBUG(
"TRACE5.ip.diffim.RegularizedKernelSolution.estimateRisk",
1128 "%.5e + 2 * (%.5e - %.5e)",
1129 term1(0), term2a, term2b(0));
1134 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1135 "Minimum Risk = %.3e at lambda = %.3e", risks[index], lambdas[index]);
1137 return lambdas[index];
1141 template <
typename InputT>
1143 if (includeHmat ==
true) {
1144 return this->_mMat + _lambda * _hMat;
1151 template <
typename InputT>
1154 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1155 "cMat is %d x %d; vVec is %d; iVec is %d; hMat is %d x %d",
1156 this->_cMat.rows(), this->_cMat.cols(), this->_ivVec.size(),
1157 this->_iVec.size(), _hMat.rows(), _hMat.cols());
1172 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
1173 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
1225 std::string lambdaType = _ps->getAsString(
"lambdaType");
1226 if (lambdaType ==
"absolute") {
1227 _lambda = _ps->getAsDouble(
"lambdaValue");
1229 else if (lambdaType ==
"relative") {
1230 _lambda = this->_mMat.trace() / this->_hMat.trace();
1231 _lambda *= _ps->getAsDouble(
"lambdaScaling");
1233 else if (lambdaType ==
"minimizeBiasedRisk") {
1234 double tol = _ps->getAsDouble(
"maxConditionNumber");
1235 _lambda = estimateRisk(tol);
1237 else if (lambdaType ==
"minimizeUnbiasedRisk") {
1244 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1245 "Applying kernel regularization with lambda = %.2e", _lambda);
1258 template <
typename InputT>
1262 std::string lambdaStepType = _ps->getAsString(
"lambdaStepType");
1263 if (lambdaStepType ==
"linear") {
1264 double lambdaLinMin = _ps->getAsDouble(
"lambdaLinMin");
1265 double lambdaLinMax = _ps->getAsDouble(
"lambdaLinMax");
1266 double lambdaLinStep = _ps->getAsDouble(
"lambdaLinStep");
1267 for (
double l = lambdaLinMin; l <= lambdaLinMax; l += lambdaLinStep) {
1271 else if (lambdaStepType ==
"log") {
1272 double lambdaLogMin = _ps->getAsDouble(
"lambdaLogMin");
1273 double lambdaLogMax = _ps->getAsDouble(
"lambdaLogMax");
1274 double lambdaLogStep = _ps->getAsDouble(
"lambdaLogStep");
1275 for (
double l = lambdaLogMin; l <= lambdaLogMax; l += lambdaLogStep) {
1294 _spatialKernelFunction(spatialKernelFunction),
1295 _constantFirstTerm(false),
1297 _background(background),
1305 bool isAlardLupton = _ps->getAsString(
"kernelBasisSet") ==
"alard-lupton";
1306 bool usePca = _ps->getAsBool(
"usePcaForSpatialKernel");
1307 if (isAlardLupton || usePca) {
1308 _constantFirstTerm =
true;
1312 _nbases = basisList.
size();
1316 if (_constantFirstTerm) {
1317 _nt = (_nbases - 1) * _nkt + 1 + _nbt;
1319 _nt = _nbases * _nkt + _nbt;
1322 Eigen::MatrixXd mMat(_nt, _nt);
1323 Eigen::VectorXd bVec(_nt);
1334 LOGL_DEBUG(
"TRACE3.ip.diffim.SpatialKernelSolution",
1335 "Initializing with size %d %d %d and constant first term = %s",
1337 _constantFirstTerm ?
"true" :
"false");
1342 Eigen::MatrixXd
const& qMat,
1343 Eigen::VectorXd
const& wVec) {
1345 LOGL_DEBUG(
"TRACE5.ip.diffim.SpatialKernelSolution.addConstraint",
1346 "Adding candidate at %f, %f", xCenter, yCenter);
1350 Eigen::VectorXd pK(_nkt);
1352 for (
int idx = 0; idx < _nkt; idx++) { paramsK[idx] = 0.0; }
1353 for (
int idx = 0; idx < _nkt; idx++) {
1356 pK(idx) = (*_spatialKernelFunction)(xCenter, yCenter);
1359 Eigen::MatrixXd pKpKt = (pK * pK.transpose());
1362 Eigen::MatrixXd pBpBt;
1363 Eigen::MatrixXd pKpBt;
1365 pB = Eigen::VectorXd(_nbt);
1369 for (
int idx = 0; idx < _nbt; idx++) { paramsB[idx] = 0.0; }
1370 for (
int idx = 0; idx < _nbt; idx++) {
1373 pB(idx) = (*_background)(xCenter, yCenter);
1376 pBpBt = (pB * pB.transpose());
1379 pKpBt = (pK * pB.transpose());
1402 int mb = _nt - _nbt;
1404 if (_constantFirstTerm) {
1408 _mMat(0, 0) += qMat(0,0);
1409 for(
int m2 = 1; m2 < _nbases; m2++) {
1410 _mMat.block(0, m2*_nkt-dm, 1, _nkt) += qMat(0,m2) * pK.transpose();
1412 _bVec(0) += wVec(0);
1415 _mMat.block(0, mb, 1, _nbt) += qMat(0,_nbases) * pB.transpose();
1420 for(
int m1 = m0; m1 < _nbases; m1++) {
1422 _mMat.block(m1*_nkt-dm, m1*_nkt-dm, _nkt, _nkt) +=
1423 (pKpKt * qMat(m1,m1)).triangularView<Eigen::Upper>();
1426 for(
int m2 = m1+1; m2 < _nbases; m2++) {
1427 _mMat.block(m1*_nkt-dm, m2*_nkt-dm, _nkt, _nkt) += qMat(m1,m2) * pKpKt;
1432 _mMat.block(m1*_nkt-dm, mb, _nkt, _nbt) += qMat(m1,_nbases) * pKpBt;
1436 _bVec.segment(m1*_nkt-dm, _nkt) += wVec(m1) * pK;
1441 _mMat.block(mb, mb, _nbt, _nbt) +=
1442 (pBpBt * qMat(_nbases,_nbases)).triangularView<Eigen::Upper>();
1443 _bVec.segment(mb, _nbt) += wVec(_nbases) * pB;
1467 for (
int i = 0; i < _nt; i++) {
1468 for (
int j = i+1; j < _nt; j++) {
1492 void SpatialKernelSolution::_setKernel() {
1501 for (
int i = 0; i < _nbases; i++) {
1506 "I. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % i % cNumber));
1508 kCoeffs[i] =
_aVec(i);
1511 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(_kernel)->getKernelList();
1521 for (
int i = 0, idx = 0; i < _nbases; i++) {
1525 if ((i == 0) && (_constantFirstTerm)) {
1530 "II. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1532 kCoeffs[i][0] =
_aVec(idx++);
1535 for (
int j = 0; j < _nkt; j++) {
1540 "III. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1542 kCoeffs[i][j] =
_aVec(idx++);
1556 for (
int i = 0; i < _nbt; i++) {
1557 int idx = _nt - _nbt + i;
1561 "Unable to determine spatial background solution %d (nan)") % (idx)));
1563 bgCoeffs[i] =
_aVec(idx);
#define LSST_EXCEPT_ADD(e, m)
#define LSST_EXCEPT(type,...)
Image Subtraction helper functions.
Declaration of classes to store the solution for convolution kernels.
#define LOGL_DEBUG(logger, message...)
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
lsst::geom::Extent2I getDimensions() const
lsst::geom::Point2I getXY0() const
void writeFits(std::string const &fileName, daf::base::PropertySet const *metadata=nullptr, std::string const &mode="w") const
void setDoNormalize(bool doNormalize)
void setParameters(std::vector< double > const ¶ms)
std::vector< double > const & getParameters() const noexcept
lsst::geom::Extent2I const getDimensions() const
void setSpatialParameters(const std::vector< std::vector< double > > params)
double computeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize, double x=0.0, double y=0.0) const
double getValue(Property const prop=NOTHING) const
int getMinY() const noexcept
int getHeight() const noexcept
int getMinX() const noexcept
int getWidth() const noexcept
int getMaxX() const noexcept
int getMaxY() const noexcept
bool _fitForBackground
Background terms included in fit.
virtual double getConditionNumber(ConditionNumberType conditionType)
Eigen::VectorXd _bVec
Derived least squares B vector.
Eigen::MatrixXd const & getM()
Eigen::VectorXd _aVec
Derived least squares solution matrix.
KernelSolvedBy _solvedBy
Type of algorithm used to make solution.
Eigen::MatrixXd _mMat
Derived least squares M matrix.
static int _SolutionId
Unique identifier for solution.
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > ImageT
virtual void buildWithMask(lsst::afw::image::Image< InputT > const &templateImage, lsst::afw::image::Image< InputT > const &scienceImage, lsst::afw::image::Image< lsst::afw::image::VariancePixel > const &varianceEstimate, lsst::afw::image::Mask< lsst::afw::image::MaskPixel > const &pixelMask)
virtual void buildSingleMaskOrig(lsst::afw::image::Image< InputT > const &templateImage, lsst::afw::image::Image< InputT > const &scienceImage, lsst::afw::image::Image< lsst::afw::image::VariancePixel > const &varianceEstimate, lsst::geom::Box2I maskBox)
MaskedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
virtual void buildOrig(lsst::afw::image::Image< InputT > const &templateImage, lsst::afw::image::Image< InputT > const &scienceImage, lsst::afw::image::Image< lsst::afw::image::VariancePixel > const &varianceEstimate, lsst::afw::image::Mask< lsst::afw::image::MaskPixel > pixelMask)
RegularizedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground, Eigen::MatrixXd const &hMat, lsst::daf::base::PropertySet const &ps)
double estimateRisk(double maxCond)
std::pair< std::shared_ptr< lsst::afw::math::LinearCombinationKernel >, lsst::afw::math::Kernel::SpatialFunctionPtr > getSolutionPair()
std::shared_ptr< lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > > makeKernelImage(lsst::geom::Point2D const &pos)
SpatialKernelSolution(lsst::afw::math::KernelList const &basisList, lsst::afw::math::Kernel::SpatialFunctionPtr spatialKernelFunction, lsst::afw::math::Kernel::SpatialFunctionPtr background, lsst::daf::base::PropertySet const &ps)
void addConstraint(float xCenter, float yCenter, Eigen::MatrixXd const &qMat, Eigen::VectorXd const &wVec)
virtual std::pair< std::shared_ptr< lsst::afw::math::Kernel >, double > getSolutionPair()
void _setKernel()
Set kernel after solution.
virtual double getBackground()
virtual std::shared_ptr< lsst::afw::math::Kernel > getKernel()
std::shared_ptr< lsst::afw::math::Kernel > _kernel
Derived single-object convolution kernel.
void _setKernelUncertainty()
Not implemented.
virtual std::shared_ptr< lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > > makeKernelImage()
StaticKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
virtual void build(lsst::afw::image::Image< InputT > const &templateImage, lsst::afw::image::Image< InputT > const &scienceImage, lsst::afw::image::Image< lsst::afw::image::VariancePixel > const &varianceEstimate)
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Eigen::MatrixXd imageToEigenMatrix(lsst::afw::image::Image< PixelT > const &img)
Turns a 2-d Image into a 2-d Eigen Matrix.
Eigen::MatrixXi maskToEigenMatrix(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > const &mask)