17#include "boost/timer/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());
143 boost::timer::cpu_timer t;
145 LOGL_DEBUG(
"TRACE2.ip.diffim.KernelSolution.solve",
146 "Solving for kernel");
148 Eigen::FullPivLU<Eigen::MatrixXd> lu(mMat);
149 if (lu.isInvertible()) {
150 aVec = lu.solve(bVec);
152 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
153 "Unable to determine kernel via LU");
158 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
159 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
160 Eigen::VectorXd eValues = eVecValues.eigenvalues();
162 for (
int i = 0; i != eValues.rows(); ++i) {
163 if (eValues(i) != 0.0) {
164 eValues(i) = 1.0/eValues(i);
168 aVec = rMat * eValues.asDiagonal() * rMat.transpose() * bVec;
172 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
173 "Unable to determine kernel via eigen-values");
180 double time = 1e-9 * t.elapsed().wall;
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;
325 boost::timer::cpu_timer t;
337 startRow, startCol, endRow-startRow, endCol-startCol
338 ).array().inverse().matrix();
341 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
342 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
343 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
352 typename std::vector<Eigen::MatrixXd>::iterator eiter = convolvedEigenList.
begin();
356 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
363 cMat.resize(cMat.size(), 1);
369 double time = 1e-9 * t.elapsed().wall;
370 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
371 "Total compute time to do basis convolutions : %.2f s", time);
377 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
378 typename std::vector<Eigen::MatrixXd>::iterator eiterj = convolvedEigenList.
begin();
379 typename std::vector<Eigen::MatrixXd>::iterator eiterE = convolvedEigenList.
end();
380 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
381 cMat.col(kidxj) = eiterj->col(0);
384 if (_fitForBackground)
385 cMat.col(nParameters-1).fill(1.);
388 _ivVec = eigeniVariance.col(0);
389 _iVec = eigenScience.col(0);
392 _mMat = _cMat.transpose() * (_ivVec.asDiagonal() * _cMat);
393 _bVec = _cMat.transpose() * (_ivVec.asDiagonal() * _iVec);
396 template <
typename InputT>
398 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.solve",
399 "mMat is %d x %d; bVec is %d; cMat is %d x %d; vVec is %d; iVec is %d",
400 _mMat.rows(), _mMat.cols(), _bVec.size(),
401 _cMat.rows(), _cMat.cols(), _ivVec.size(), _iVec.size());
422 template <
typename InputT>
428 unsigned int const nParameters = _aVec.size();
429 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
430 unsigned int const nKernelParameters =
431 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(_kernel)->getKernelList().size();
432 if (nParameters != (nKernelParameters + nBackgroundParameters))
437 for (
unsigned int idx = 0; idx < nKernelParameters; idx++) {
440 str(boost::format(
"Unable to determine kernel solution %d (nan)") % idx));
442 kValues[idx] = _aVec(idx);
444 _kernel->setKernelParameters(kValues);
447 new ImageT(_kernel->getDimensions())
449 _kSum = _kernel->computeImage(*
image,
false);
451 if (_fitForBackground) {
454 str(boost::format(
"Unable to determine background solution %d (nan)") %
457 _background = _aVec(nParameters-1);
462 template <
typename InputT>
492 template <
typename InputT>
495 bool fitForBackground
500 template <
typename InputT>
511 "Error: variance less than 0.0");
515 "Error: variance equals 0.0, cannot inverse variance weight");
523 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
538 int growPix = (*kiter)->getCtr().getX();
542 for (
typename afwDet::FootprintSet::FootprintList::iterator
548 afwDet::setMaskFromFootprint(finalMask,
555 for (
auto const & foot : *(maskedFpSetGrown.
getFootprints())) {
562 ndarray::Array<int, 1, 1> maskArray =
563 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
564 fullFp->getSpans()->flatten(maskArray, finalMask.
getArray(), templateImage.
getXY0());
565 auto maskEigen = ndarray::asEigenMatrix(maskArray);
567 ndarray::Array<InputT, 1, 1> arrayTemplate =
568 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
569 fullFp->getSpans()->flatten(arrayTemplate, templateImage.
getArray(), templateImage.
getXY0());
570 auto eigenTemplate0 = ndarray::asEigenMatrix(arrayTemplate);
572 ndarray::Array<InputT, 1, 1> arrayScience =
573 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
574 fullFp->getSpans()->flatten(arrayScience, scienceImage.
getArray(), scienceImage.
getXY0());
575 auto eigenScience0 = ndarray::asEigenMatrix(arrayScience);
577 ndarray::Array<afwImage::VariancePixel, 1, 1> arrayVariance =
578 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
579 fullFp->getSpans()->flatten(arrayVariance, varianceEstimate.
getArray(), varianceEstimate.
getXY0());
580 auto eigenVariance0 = ndarray::asEigenMatrix(arrayVariance);
583 for (
int i = 0; i < maskEigen.size(); i++) {
584 if (maskEigen(i) == 0.0)
588 Eigen::VectorXd eigenTemplate(nGood);
589 Eigen::VectorXd eigenScience(nGood);
590 Eigen::VectorXd eigenVariance(nGood);
592 for (
int i = 0; i < maskEigen.size(); i++) {
593 if (maskEigen(i) == 0.0) {
594 eigenTemplate(nUsed) = eigenTemplate0(i);
595 eigenScience(nUsed) = eigenScience0(i);
596 eigenVariance(nUsed) = eigenVariance0(i);
602 boost::timer::cpu_timer t;
604 unsigned int const nKernelParameters = basisList.
size();
605 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
606 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
615 typename std::vector<Eigen::VectorXd>::iterator eiter = convolvedEigenList.
begin();
620 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
623 ndarray::Array<InputT, 1, 1> arrayC =
624 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
625 fullFp->getSpans()->flatten(arrayC, cimage.
getArray(), cimage.
getXY0());
626 auto eigenC0 = ndarray::asEigenMatrix(arrayC);
628 Eigen::VectorXd eigenC(nGood);
630 for (
int i = 0; i < maskEigen.size(); i++) {
631 if (maskEigen(i) == 0.0) {
632 eigenC(nUsed) = eigenC0(i);
640 double time = 1e-9 * t.elapsed().wall;
641 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.buildWithMask",
642 "Total compute time to do basis convolutions : %.2f s", time);
645 Eigen::MatrixXd cMat(eigenTemplate.size(), nParameters);
646 typename std::vector<Eigen::VectorXd>::iterator eiterj = convolvedEigenList.
begin();
647 typename std::vector<Eigen::VectorXd>::iterator eiterE = convolvedEigenList.
end();
648 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
649 cMat.block(0, kidxj, eigenTemplate.size(), 1) =
650 Eigen::MatrixXd(*eiterj).block(0, 0, eigenTemplate.size(), 1);
653 if (this->_fitForBackground)
654 cMat.col(nParameters-1).fill(1.);
657 this->_ivVec = eigenVariance.array().inverse().matrix();
658 this->_iVec = eigenScience;
661 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_cMat);
662 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_iVec);
666 template <
typename InputT>
677 "Error: variance less than 0.0");
681 "Error: variance equals 0.0, cannot inverse variance weight");
685 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
697 unsigned int const nKernelParameters = basisList.
size();
698 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
699 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
706 geom::Box2I shrunkLocalBBox = (*kiter)->shrinkBBox(templateImage.
getBBox(afwImage::LOCAL));
707 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
708 "Limits of good pixels after convolution: %d,%d -> %d,%d (local)",
713 unsigned int startCol = shrunkLocalBBox.
getMinX();
714 unsigned int startRow = shrunkLocalBBox.
getMinY();
715 unsigned int endCol = shrunkLocalBBox.
getMaxX();
716 unsigned int endRow = shrunkLocalBBox.
getMaxY();
721 boost::timer::cpu_timer t;
738 startRow, startCol, endRow-startRow, endCol-startCol
739 ).array().inverse().matrix();
742 eMask.resize(eMask.rows()*eMask.cols(), 1);
743 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
744 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
745 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
748 Eigen::MatrixXd maskedEigenTemplate(eigenTemplate.rows(), 1);
749 Eigen::MatrixXd maskedEigenScience(eigenScience.rows(), 1);
750 Eigen::MatrixXd maskedEigeniVariance(eigeniVariance.rows(), 1);
752 for (
int i = 0; i < eMask.rows(); i++) {
753 if (eMask(i, 0) == 0) {
754 maskedEigenTemplate(nGood, 0) = eigenTemplate(i, 0);
755 maskedEigenScience(nGood, 0) = eigenScience(i, 0);
756 maskedEigeniVariance(nGood, 0) = eigeniVariance(i, 0);
761 eigenTemplate = maskedEigenTemplate.block(0, 0, nGood, 1);
762 eigenScience = maskedEigenScience.block(0, 0, nGood, 1);
763 eigeniVariance = maskedEigeniVariance.block(0, 0, nGood, 1);
773 typename std::vector<Eigen::MatrixXd>::iterator eiter = convolvedEigenList.
begin();
777 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
784 cMat.resize(cMat.size(), 1);
787 Eigen::MatrixXd maskedcMat(cMat.rows(), 1);
789 for (
int i = 0; i < eMask.rows(); i++) {
790 if (eMask(i, 0) == 0) {
791 maskedcMat(nGood, 0) = cMat(i, 0);
795 cMat = maskedcMat.block(0, 0, nGood, 1);
800 double time = 1e-9 * t.elapsed().wall;
801 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
802 "Total compute time to do basis convolutions : %.2f s", time);
808 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
809 typename std::vector<Eigen::MatrixXd>::iterator eiterj = convolvedEigenList.
begin();
810 typename std::vector<Eigen::MatrixXd>::iterator eiterE = convolvedEigenList.
end();
811 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
812 cMat.col(kidxj) = eiterj->col(0);
815 if (this->_fitForBackground)
816 cMat.col(nParameters-1).fill(1.);
819 this->_ivVec = eigeniVariance.col(0);
820 this->_iVec = eigenScience.col(0);
823 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
824 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
830 template <
typename InputT>
841 "Error: variance less than 0.0");
845 "Error: variance equals 0.0, cannot inverse variance weight");
849 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(this->_kernel)->getKernelList();
851 unsigned int const nKernelParameters = basisList.
size();
852 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
853 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
883 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
884 "Limits of good pixels after convolution: %d,%d -> %d,%d",
888 unsigned int const startCol = shrunkBBox.
getMinX();
889 unsigned int const startRow = shrunkBBox.
getMinY();
890 unsigned int const endCol = shrunkBBox.
getMaxX();
891 unsigned int const endRow = shrunkBBox.
getMaxY();
906 int maskStartCol = maskBox.
getMinX();
907 int maskStartRow = maskBox.
getMinY();
908 int maskEndCol = maskBox.
getMaxX();
909 int maskEndRow = maskBox.
getMaxY();
942 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
943 "Upper good pixel region: %d,%d -> %d,%d",
945 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
946 "Bottom good pixel region: %d,%d -> %d,%d",
948 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
949 "Left good pixel region: %d,%d -> %d,%d",
951 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
952 "Right good pixel region: %d,%d -> %d,%d",
966 Eigen::MatrixXd eigenTemplate(totalSize, 1);
967 Eigen::MatrixXd eigenScience(totalSize, 1);
968 Eigen::MatrixXd eigeniVariance(totalSize, 1);
969 eigenTemplate.setZero();
970 eigenScience.setZero();
971 eigeniVariance.setZero();
973 boost::timer::cpu_timer t;
976 typename std::vector<geom::Box2I>::iterator biter = boxArray.
begin();
977 for (; biter != boxArray.
end(); ++biter) {
978 int area = (*biter).getWidth() * (*biter).getHeight();
986 Eigen::MatrixXd eiVarEstimate =
imageToEigenMatrix(sVarEstimate).array().inverse().matrix();
988 eTemplate.resize(area, 1);
989 eScience.resize(area, 1);
990 eiVarEstimate.resize(area, 1);
992 eigenTemplate.block(nTerms, 0, area, 1) = eTemplate.block(0, 0, area, 1);
993 eigenScience.block(nTerms, 0, area, 1) = eScience.block(0, 0, area, 1);
994 eigeniVariance.block(nTerms, 0, area, 1) = eiVarEstimate.block(0, 0, area, 1);
1002 typename std::vector<Eigen::MatrixXd>::iterator eiter = convolvedEigenList.
begin();
1006 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
1008 Eigen::MatrixXd cMat(totalSize, 1);
1012 typename std::vector<geom::Box2I>::iterator biter = boxArray.
begin();
1013 for (; biter != boxArray.
end(); ++biter) {
1014 int area = (*biter).getWidth() * (*biter).getHeight();
1018 esubimage.resize(area, 1);
1019 cMat.block(nTerms, 0, area, 1) = esubimage.block(0, 0, area, 1);
1029 double time = 1e-9 * t.elapsed().wall;
1030 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
1031 "Total compute time to do basis convolutions : %.2f s", time);
1037 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
1038 typename std::vector<Eigen::MatrixXd>::iterator eiterj = convolvedEigenList.
begin();
1039 typename std::vector<Eigen::MatrixXd>::iterator eiterE = convolvedEigenList.
end();
1040 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
1041 cMat.col(kidxj) = eiterj->col(0);
1044 if (this->_fitForBackground)
1045 cMat.col(nParameters-1).fill(1.);
1048 this->_ivVec = eigeniVariance.col(0);
1049 this->_iVec = eigenScience.col(0);
1052 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
1053 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
1058 template <
typename InputT>
1061 bool fitForBackground,
1062 Eigen::MatrixXd
const& hMat,
1071 template <
typename InputT>
1073 Eigen::MatrixXd vMat = this->_cMat.jacobiSvd().matrixV();
1074 Eigen::MatrixXd vMatvMatT = vMat * vMat.transpose();
1077 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(this->_mMat);
1078 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
1079 Eigen::VectorXd eValues = eVecValues.eigenvalues();
1080 double eMax = eValues.maxCoeff();
1081 for (
int i = 0; i != eValues.rows(); ++i) {
1082 if (eValues(i) == 0.0) {
1085 else if ((eMax / eValues(i)) > maxCond) {
1086 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1087 "Truncating eValue %d; %.5e / %.5e = %.5e vs. %.5e",
1088 i, eMax, eValues(i), eMax / eValues(i), maxCond);
1092 eValues(i) = 1.0 / eValues(i);
1095 Eigen::MatrixXd mInv = rMat * eValues.asDiagonal() * rMat.transpose();
1099 for (
unsigned int i = 0; i < lambdas.
size(); i++) {
1100 double l = lambdas[i];
1101 Eigen::MatrixXd mLambda = this->_mMat + l * _hMat;
1109 Eigen::VectorXd term1 = (this->_aVec.transpose() * vMatvMatT * this->_aVec);
1110 if (term1.size() != 1)
1113 double term2a = (vMatvMatT * mLambda.inverse()).trace();
1115 Eigen::VectorXd term2b = (this->_aVec.transpose() * (mInv * this->_bVec));
1116 if (term2b.size() != 1)
1119 double risk = term1(0) + 2 * (term2a - term2b(0));
1120 LOGL_DEBUG(
"TRACE4.ip.diffim.RegularizedKernelSolution.estimateRisk",
1121 "Lambda = %.3f, Risk = %.5e",
1123 LOGL_DEBUG(
"TRACE5.ip.diffim.RegularizedKernelSolution.estimateRisk",
1124 "%.5e + 2 * (%.5e - %.5e)",
1125 term1(0), term2a, term2b(0));
1128 std::vector<double>::iterator it = min_element(risks.
begin(), risks.
end());
1129 int index = distance(risks.
begin(), it);
1130 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1131 "Minimum Risk = %.3e at lambda = %.3e", risks[index], lambdas[index]);
1133 return lambdas[index];
1137 template <
typename InputT>
1139 if (includeHmat ==
true) {
1140 return this->_mMat + _lambda * _hMat;
1147 template <
typename InputT>
1150 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1151 "cMat is %d x %d; vVec is %d; iVec is %d; hMat is %d x %d",
1152 this->_cMat.rows(), this->_cMat.cols(), this->_ivVec.size(),
1153 this->_iVec.size(), _hMat.rows(), _hMat.cols());
1168 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
1169 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
1221 std::string lambdaType = _ps->getAsString(
"lambdaType");
1222 if (lambdaType ==
"absolute") {
1223 _lambda = _ps->getAsDouble(
"lambdaValue");
1225 else if (lambdaType ==
"relative") {
1226 _lambda = this->_mMat.trace() / this->_hMat.trace();
1227 _lambda *= _ps->getAsDouble(
"lambdaScaling");
1229 else if (lambdaType ==
"minimizeBiasedRisk") {
1230 double tol = _ps->getAsDouble(
"maxConditionNumber");
1231 _lambda = estimateRisk(tol);
1233 else if (lambdaType ==
"minimizeUnbiasedRisk") {
1240 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1241 "Applying kernel regularization with lambda = %.2e", _lambda);
1254 template <
typename InputT>
1258 std::string lambdaStepType = _ps->getAsString(
"lambdaStepType");
1259 if (lambdaStepType ==
"linear") {
1260 double lambdaLinMin = _ps->getAsDouble(
"lambdaLinMin");
1261 double lambdaLinMax = _ps->getAsDouble(
"lambdaLinMax");
1262 double lambdaLinStep = _ps->getAsDouble(
"lambdaLinStep");
1263 for (
double l = lambdaLinMin; l <= lambdaLinMax; l += lambdaLinStep) {
1267 else if (lambdaStepType ==
"log") {
1268 double lambdaLogMin = _ps->getAsDouble(
"lambdaLogMin");
1269 double lambdaLogMax = _ps->getAsDouble(
"lambdaLogMax");
1270 double lambdaLogStep = _ps->getAsDouble(
"lambdaLogStep");
1271 for (
double l = lambdaLogMin; l <= lambdaLogMax; l += lambdaLogStep) {
1290 _spatialKernelFunction(spatialKernelFunction),
1291 _constantFirstTerm(false),
1293 _background(background),
1301 bool isAlardLupton = _ps->getAsString(
"kernelBasisSet") ==
"alard-lupton";
1302 bool usePca = _ps->getAsBool(
"usePcaForSpatialKernel");
1303 if (isAlardLupton || usePca) {
1304 _constantFirstTerm =
true;
1308 _nbases = basisList.
size();
1312 if (_constantFirstTerm) {
1313 _nt = (_nbases - 1) * _nkt + 1 + _nbt;
1315 _nt = _nbases * _nkt + _nbt;
1318 Eigen::MatrixXd mMat(_nt, _nt);
1319 Eigen::VectorXd bVec(_nt);
1330 LOGL_DEBUG(
"TRACE3.ip.diffim.SpatialKernelSolution",
1331 "Initializing with size %d %d %d and constant first term = %s",
1333 _constantFirstTerm ?
"true" :
"false");
1338 Eigen::MatrixXd
const& qMat,
1339 Eigen::VectorXd
const& wVec) {
1341 LOGL_DEBUG(
"TRACE5.ip.diffim.SpatialKernelSolution.addConstraint",
1342 "Adding candidate at %f, %f", xCenter, yCenter);
1346 Eigen::VectorXd pK(_nkt);
1348 for (
int idx = 0; idx < _nkt; idx++) { paramsK[idx] = 0.0; }
1349 for (
int idx = 0; idx < _nkt; idx++) {
1352 pK(idx) = (*_spatialKernelFunction)(xCenter, yCenter);
1355 Eigen::MatrixXd pKpKt = (pK * pK.transpose());
1358 Eigen::MatrixXd pBpBt;
1359 Eigen::MatrixXd pKpBt;
1361 pB = Eigen::VectorXd(_nbt);
1365 for (
int idx = 0; idx < _nbt; idx++) { paramsB[idx] = 0.0; }
1366 for (
int idx = 0; idx < _nbt; idx++) {
1369 pB(idx) = (*_background)(xCenter, yCenter);
1372 pBpBt = (pB * pB.transpose());
1375 pKpBt = (pK * pB.transpose());
1398 int mb = _nt - _nbt;
1400 if (_constantFirstTerm) {
1404 _mMat(0, 0) += qMat(0,0);
1405 for(
int m2 = 1; m2 < _nbases; m2++) {
1406 _mMat.block(0, m2*_nkt-dm, 1, _nkt) += qMat(0,m2) * pK.transpose();
1408 _bVec(0) += wVec(0);
1411 _mMat.block(0, mb, 1, _nbt) += qMat(0,_nbases) * pB.transpose();
1416 for(
int m1 = m0; m1 < _nbases; m1++) {
1418 _mMat.block(m1*_nkt-dm, m1*_nkt-dm, _nkt, _nkt) +=
1419 (pKpKt * qMat(m1,m1)).triangularView<Eigen::Upper>();
1422 for(
int m2 = m1+1; m2 < _nbases; m2++) {
1423 _mMat.block(m1*_nkt-dm, m2*_nkt-dm, _nkt, _nkt) += qMat(m1,m2) * pKpKt;
1428 _mMat.block(m1*_nkt-dm, mb, _nkt, _nbt) += qMat(m1,_nbases) * pKpBt;
1432 _bVec.segment(m1*_nkt-dm, _nkt) += wVec(m1) * pK;
1437 _mMat.block(mb, mb, _nbt, _nbt) +=
1438 (pBpBt * qMat(_nbases,_nbases)).triangularView<Eigen::Upper>();
1439 _bVec.segment(mb, _nbt) += wVec(_nbases) * pB;
1463 for (
int i = 0; i < _nt; i++) {
1464 for (
int j = i+1; j < _nt; j++) {
1488 void SpatialKernelSolution::_setKernel() {
1497 for (
int i = 0; i < _nbases; i++) {
1502 "I. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % i % cNumber));
1504 kCoeffs[i] =
_aVec(i);
1507 std::dynamic_pointer_cast<afwMath::LinearCombinationKernel>(_kernel)->getKernelList();
1517 for (
int i = 0, idx = 0; i < _nbases; i++) {
1521 if ((i == 0) && (_constantFirstTerm)) {
1526 "II. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1528 kCoeffs[i][0] =
_aVec(idx++);
1531 for (
int j = 0; j < _nkt; j++) {
1536 "III. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1538 kCoeffs[i][j] =
_aVec(idx++);
1552 for (
int i = 0; i < _nbt; i++) {
1553 int idx = _nt - _nbt + i;
1557 "Unable to determine spatial background solution %d (nan)") % (idx)));
1559 bgCoeffs[i] =
_aVec(idx);
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Image Subtraction helper functions.
Declaration of classes to store the solution for convolution kernels.
LSST DM logging module built on log4cxx.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
A Threshold is used to pass a threshold value to detection algorithms.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
lsst::geom::Point2I getXY0() const
Return the image's origin.
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
void writeFits(std::string const &fileName, daf::base::PropertySet const *metadata=nullptr, std::string const &mode="w") const
Write a mask to a regular FITS file.
Parameters to control convolution.
void setDoNormalize(bool doNormalize)
void setParameters(std::vector< double > const ¶ms)
Set all function parameters.
std::vector< double > const & getParameters() const noexcept
Return all function parameters.
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
void setSpatialParameters(const std::vector< std::vector< double > > params)
Set the parameters of all spatial functions.
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 evaluate image statistics.
double getValue(Property const prop=NOTHING) const
Return the value of the desired property (if specified in the constructor)
Class for storing generic metadata.
An integer coordinate rectangle.
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)
Provides consistent interface for LSST exceptions.
Reports invalid arguments.
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
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.
@ MIN
estimate sample minimum
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)