17 #include "boost/timer.hpp"
20 #include "Eigen/Cholesky"
23 #include "Eigen/Eigenvalues"
30 #include "lsst/afw/detection/FootprintArray.cc"
38 #include "ndarray/eigen.h"
40 #define DEBUG_MATRIX 0
41 #define DEBUG_MATRIX2 0
43 namespace afwDet = lsst::afw::detection;
44 namespace afwMath = lsst::afw::math;
45 namespace afwGeom = lsst::afw::geom;
47 namespace pexExcept = lsst::pex::exceptions;
57 std::shared_ptr<Eigen::MatrixXd> mMat,
58 std::shared_ptr<Eigen::VectorXd> bVec,
66 _fitForBackground(fitForBackground)
77 _fitForBackground(fitForBackground)
86 _fitForBackground(true)
99 switch (conditionType) {
102 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
103 Eigen::VectorXd eValues = eVecValues.eigenvalues();
104 double eMax = eValues.maxCoeff();
105 double eMin = eValues.minCoeff();
106 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
107 "EIGENVALUE eMax / eMin = %.3e", eMax / eMin);
108 return (eMax / eMin);
113 Eigen::VectorXd sValues = mMat.jacobiSvd().singularValues();
114 double sMax = sValues.maxCoeff();
115 double sMin = sValues.minCoeff();
116 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
117 "SVD eMax / eMin = %.3e", sMax / sMin);
118 return (sMax / sMin);
123 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
124 "Undefined ConditionNumberType : only EIGENVALUE, SVD allowed.");
131 Eigen::VectorXd bVec) {
134 std::cout <<
"M " << std::endl;
135 std::cout << mMat << std::endl;
136 std::cout <<
"B " << std::endl;
137 std::cout << bVec << std::endl;
140 Eigen::VectorXd aVec = Eigen::VectorXd::Zero(bVec.size());
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");
179 double time = t.elapsed();
180 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
181 "Compute time for matrix math : %.2f s", time);
184 std::cout <<
"A " << std::endl;
185 std::cout << aVec << std::endl;
188 _aVec = std::shared_ptr<Eigen::VectorXd>(
new Eigen::VectorXd(aVec));
193 template <
typename InputT>
196 bool fitForBackground
207 std::vector<double> kValues(basisList.size());
208 _kernel = std::shared_ptr<afwMath::Kernel>(
213 template <
typename InputT>
221 template <
typename InputT>
233 template <
typename InputT>
241 template <
typename InputT>
249 template <
typename InputT>
250 std::pair<std::shared_ptr<lsst::afw::math::Kernel>,
double>
256 return std::make_pair(
_kernel, _background);
259 template <
typename InputT>
269 "Error: variance less than 0.0");
273 "Error: variance equals 0.0, cannot inverse variance weight");
279 unsigned int const nKernelParameters = basisList.size();
280 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
281 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
283 std::vector<std::shared_ptr<afwMath::Kernel> >::const_iterator kiter = basisList.begin();
318 unsigned int const startCol = goodBBox.
getMinX();
319 unsigned int const startRow = goodBBox.
getMinY();
321 unsigned int endCol = goodBBox.
getMaxX() + 1;
322 unsigned int endRow = goodBBox.
getMaxY() + 1;
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);
349 std::vector<std::shared_ptr<Eigen::MatrixXd> > convolvedEigenList(nKernelParameters);
352 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiter =
353 convolvedEigenList.
begin();
355 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
358 std::shared_ptr<Eigen::MatrixXd> cMat (
364 cMat->resize(cMat->rows()*cMat->cols(), 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);
379 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterj =
380 convolvedEigenList.
begin();
381 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterE =
382 convolvedEigenList.
end();
383 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
384 cMat.col(kidxj) = (*eiterj)->col(0);
387 if (_fitForBackground)
388 cMat.col(nParameters-1).fill(1.);
390 _cMat.reset(
new Eigen::MatrixXd(cMat));
391 _ivVec.reset(
new Eigen::VectorXd(eigeniVariance.col(0)));
392 _iVec.reset(
new Eigen::VectorXd(eigenScience.col(0)));
395 _mMat.reset(
new Eigen::MatrixXd((*_cMat).transpose() * ((*_ivVec).asDiagonal() * (*_cMat))));
396 _bVec.reset(
new Eigen::VectorXd((*_cMat).transpose() * ((*_ivVec).asDiagonal() * (*_iVec))));
399 template <
typename InputT>
401 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.solve",
402 "mMat is %d x %d; bVec is %d; cMat is %d x %d; vVec is %d; iVec is %d",
403 (*_mMat).rows(), (*_mMat).cols(), (*_bVec).size(),
404 (*_cMat).rows(), (*_cMat).cols(), (*_ivVec).size(), (*_iVec).size());
413 std::cout <<
"C" << std::endl;
414 std::cout << (*_cMat) << std::endl;
415 std::cout <<
"iV" << std::endl;
416 std::cout << (*_ivVec) << std::endl;
417 std::cout <<
"I" << std::endl;
418 std::cout << (*_iVec) << std::endl;
431 template <
typename InputT>
437 unsigned int const nParameters = _aVec->size();
438 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
439 unsigned int const nKernelParameters =
441 if (nParameters != (nKernelParameters + nBackgroundParameters))
445 std::vector<double> kValues(nKernelParameters);
446 for (
unsigned int idx = 0; idx < nKernelParameters; idx++) {
447 if (std::isnan((*_aVec)(idx))) {
449 str(
boost::format(
"Unable to determine kernel solution %d (nan)") % idx));
451 kValues[idx] = (*_aVec)(idx);
460 if (_fitForBackground) {
461 if (std::isnan((*_aVec)(nParameters-1))) {
463 str(
boost::format(
"Unable to determine background solution %d (nan)") %
466 _background = (*_aVec)(nParameters-1);
471 template <
typename InputT>
501 template <
typename InputT>
504 bool fitForBackground
509 template <
typename InputT>
520 "Error: variance less than 0.0");
524 "Error: variance equals 0.0, cannot inverse variance weight");
532 std::vector<std::shared_ptr<afwMath::Kernel> >::const_iterator kiter = basisList.begin();
546 int growPix = (*kiter)->getCtr().getX();
550 for (
typename afwDet::FootprintSet::FootprintList::iterator
567 finalMask.writeFits(
"finalmask.fits");
570 ndarray::Array<int, 1, 1> maskArray =
571 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
573 maskArray, templateImage.
getXY0());
574 ndarray::EigenView<int, 1, 1> maskEigen(maskArray);
576 ndarray::Array<InputT, 1, 1> arrayTemplate =
577 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
579 arrayTemplate, templateImage.
getXY0());
580 ndarray::EigenView<InputT, 1, 1> eigenTemplate0(arrayTemplate);
582 ndarray::Array<InputT, 1, 1> arrayScience =
583 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
585 arrayScience, scienceImage.
getXY0());
586 ndarray::EigenView<InputT, 1, 1> eigenScience0(arrayScience);
588 ndarray::Array<afwImage::VariancePixel, 1, 1> arrayVariance =
589 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
591 arrayVariance, varianceEstimate.
getXY0());
592 ndarray::EigenView<afwImage::VariancePixel, 1, 1> eigenVariance0(arrayVariance);
595 for (
int i = 0; i < maskEigen.size(); i++) {
596 if (maskEigen(i) == 0.0)
600 Eigen::VectorXd eigenTemplate(nGood);
601 Eigen::VectorXd eigenScience(nGood);
602 Eigen::VectorXd eigenVariance(nGood);
604 for (
int i = 0; i < maskEigen.size(); i++) {
605 if (maskEigen(i) == 0.0) {
606 eigenTemplate(nUsed) = eigenTemplate0(i);
607 eigenScience(nUsed) = eigenScience0(i);
608 eigenVariance(nUsed) = eigenVariance0(i);
617 unsigned int const nKernelParameters = basisList.size();
618 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
619 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
625 std::vector<std::shared_ptr<Eigen::VectorXd> >
626 convolvedEigenList(nKernelParameters);
629 typename std::vector<std::shared_ptr<Eigen::VectorXd> >::iterator eiter =
630 convolvedEigenList.
begin();
633 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
636 ndarray::Array<InputT, 1, 1> arrayC =
637 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
639 arrayC, cimage.getXY0());
640 ndarray::EigenView<InputT, 1, 1> eigenC0(arrayC);
642 Eigen::VectorXd eigenC(nGood);
644 for (
int i = 0; i < maskEigen.size(); i++) {
645 if (maskEigen(i) == 0.0) {
646 eigenC(nUsed) = eigenC0(i);
651 std::shared_ptr<Eigen::VectorXd>
652 eigenCptr (
new Eigen::VectorXd(eigenC));
656 double time = t.elapsed();
657 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.buildWithMask",
658 "Total compute time to do basis convolutions : %.2f s", time);
662 Eigen::MatrixXd cMat(eigenTemplate.size(), nParameters);
663 typename std::vector<std::shared_ptr<Eigen::VectorXd> >::iterator eiterj =
664 convolvedEigenList.
begin();
665 typename std::vector<std::shared_ptr<Eigen::VectorXd> >::iterator eiterE =
666 convolvedEigenList.
end();
667 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
668 cMat.block(0, kidxj, eigenTemplate.size(), 1) =
669 Eigen::MatrixXd(**eiterj).block(0, 0, eigenTemplate.size(), 1);
672 if (this->_fitForBackground)
673 cMat.col(nParameters-1).fill(1.);
675 this->_cMat.reset(
new Eigen::MatrixXd(cMat));
678 this->_ivVec.reset(
new Eigen::VectorXd(eigenVariance.array().inverse().matrix()));
679 this->_iVec.reset(
new Eigen::VectorXd(eigenScience));
683 new Eigen::MatrixXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_cMat))
686 new Eigen::VectorXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_iVec))
691 template <
typename InputT>
702 "Error: variance less than 0.0");
706 "Error: variance equals 0.0, cannot inverse variance weight");
711 std::vector<std::shared_ptr<afwMath::Kernel> >::const_iterator kiter = basisList.begin();
722 unsigned int const nKernelParameters = basisList.size();
723 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
724 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
732 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
733 "Limits of good pixels after convolution: %d,%d -> %d,%d (local)",
738 unsigned int startCol = shrunkLocalBBox.
getMinX();
739 unsigned int startRow = shrunkLocalBBox.
getMinY();
740 unsigned int endCol = shrunkLocalBBox.
getMaxX();
741 unsigned int endRow = shrunkLocalBBox.
getMaxY();
764 startRow, startCol, endRow-startRow, endCol-startCol
765 ).array().inverse().matrix();
768 eMask.resize(eMask.rows()*eMask.cols(), 1);
769 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
770 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
771 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
774 Eigen::MatrixXd maskedEigenTemplate(eigenTemplate.rows(), 1);
775 Eigen::MatrixXd maskedEigenScience(eigenScience.rows(), 1);
776 Eigen::MatrixXd maskedEigeniVariance(eigeniVariance.rows(), 1);
778 for (
int i = 0; i < eMask.rows(); i++) {
779 if (eMask(i, 0) == 0) {
780 maskedEigenTemplate(nGood, 0) = eigenTemplate(i, 0);
781 maskedEigenScience(nGood, 0) = eigenScience(i, 0);
782 maskedEigeniVariance(nGood, 0) = eigeniVariance(i, 0);
787 eigenTemplate = maskedEigenTemplate.block(0, 0, nGood, 1);
788 eigenScience = maskedEigenScience.block(0, 0, nGood, 1);
789 eigeniVariance = maskedEigeniVariance.block(0, 0, nGood, 1);
796 std::vector<std::shared_ptr<Eigen::MatrixXd> > convolvedEigenList(nKernelParameters);
799 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiter =
800 convolvedEigenList.
begin();
802 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
809 cMat.resize(cMat.rows() * cMat.cols(), 1);
812 Eigen::MatrixXd maskedcMat(cMat.rows(), 1);
814 for (
int i = 0; i < eMask.rows(); i++) {
815 if (eMask(i, 0) == 0) {
816 maskedcMat(nGood, 0) = cMat(i, 0);
820 cMat = maskedcMat.block(0, 0, nGood, 1);
821 std::shared_ptr<Eigen::MatrixXd> cMatPtr (
new Eigen::MatrixXd(cMat));
825 double time = t.elapsed();
826 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
827 "Total compute time to do basis convolutions : %.2f s", time);
834 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
835 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterj =
836 convolvedEigenList.
begin();
837 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterE =
838 convolvedEigenList.
end();
839 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
840 cMat.col(kidxj) = (*eiterj)->col(0);
843 if (this->_fitForBackground)
844 cMat.col(nParameters-1).fill(1.);
846 this->_cMat.reset(
new Eigen::MatrixXd(cMat));
847 this->_ivVec.reset(
new Eigen::VectorXd(eigeniVariance.col(0)));
848 this->_iVec.reset(
new Eigen::VectorXd(eigenScience.col(0)));
852 new Eigen::MatrixXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_cMat))
855 new Eigen::VectorXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_iVec))
862 template <
typename InputT>
873 "Error: variance less than 0.0");
877 "Error: variance equals 0.0, cannot inverse variance weight");
883 unsigned int const nKernelParameters = basisList.size();
884 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
885 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
887 std::vector<std::shared_ptr<afwMath::Kernel> >::const_iterator kiter = basisList.begin();
915 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
916 "Limits of good pixels after convolution: %d,%d -> %d,%d",
920 unsigned int const startCol = shrunkBBox.
getMinX();
921 unsigned int const startRow = shrunkBBox.
getMinY();
922 unsigned int const endCol = shrunkBBox.
getMaxX();
923 unsigned int const endRow = shrunkBBox.
getMaxY();
942 int maskStartCol = maskBox.
getMinX();
943 int maskStartRow = maskBox.
getMinY();
944 int maskEndCol = maskBox.
getMaxX();
945 int maskEndRow = maskBox.
getMaxY();
978 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
979 "Upper good pixel region: %d,%d -> %d,%d",
981 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
982 "Bottom good pixel region: %d,%d -> %d,%d",
984 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
985 "Left good pixel region: %d,%d -> %d,%d",
987 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
988 "Right good pixel region: %d,%d -> %d,%d",
991 std::vector<afwGeom::Box2I> boxArray;
992 boxArray.push_back(tBox);
993 boxArray.push_back(bBox);
994 boxArray.push_back(lBox);
995 boxArray.push_back(rBox);
1002 Eigen::MatrixXd eigenTemplate(totalSize, 1);
1003 Eigen::MatrixXd eigenScience(totalSize, 1);
1004 Eigen::MatrixXd eigeniVariance(totalSize, 1);
1005 eigenTemplate.setZero();
1006 eigenScience.setZero();
1007 eigeniVariance.setZero();
1013 typename std::vector<afwGeom::Box2I>::iterator biter = boxArray.begin();
1014 for (; biter != boxArray.end(); ++biter) {
1015 int area = (*biter).getWidth() * (*biter).getHeight();
1023 Eigen::MatrixXd eiVarEstimate =
imageToEigenMatrix(sVarEstimate).array().inverse().matrix();
1025 eTemplate.resize(area, 1);
1026 eScience.resize(area, 1);
1027 eiVarEstimate.resize(area, 1);
1029 eigenTemplate.block(nTerms, 0, area, 1) = eTemplate.block(0, 0, area, 1);
1030 eigenScience.block(nTerms, 0, area, 1) = eScience.block(0, 0, area, 1);
1031 eigeniVariance.block(nTerms, 0, area, 1) = eiVarEstimate.block(0, 0, area, 1);
1038 std::vector<std::shared_ptr<Eigen::MatrixXd> > convolvedEigenList(nKernelParameters);
1039 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiter =
1040 convolvedEigenList.
begin();
1042 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
1044 Eigen::MatrixXd cMat(totalSize, 1);
1048 typename std::vector<afwGeom::Box2I>::iterator biter = boxArray.begin();
1049 for (; biter != boxArray.end(); ++biter) {
1050 int area = (*biter).getWidth() * (*biter).getHeight();
1054 esubimage.resize(area, 1);
1055 cMat.block(nTerms, 0, area, 1) = esubimage.block(0, 0, area, 1);
1060 std::shared_ptr<Eigen::MatrixXd> cMatPtr (
new Eigen::MatrixXd(cMat));
1065 double time = t.elapsed();
1066 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
1067 "Total compute time to do basis convolutions : %.2f s", time);
1074 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
1075 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterj =
1076 convolvedEigenList.
begin();
1077 typename std::vector<std::shared_ptr<Eigen::MatrixXd> >::iterator eiterE =
1078 convolvedEigenList.
end();
1079 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
1080 cMat.col(kidxj) = (*eiterj)->col(0);
1083 if (this->_fitForBackground)
1084 cMat.col(nParameters-1).fill(1.);
1086 this->_cMat.reset(
new Eigen::MatrixXd(cMat));
1087 this->_ivVec.reset(
new Eigen::VectorXd(eigeniVariance.col(0)));
1088 this->_iVec.reset(
new Eigen::VectorXd(eigenScience.col(0)));
1092 new Eigen::MatrixXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_cMat))
1095 new Eigen::VectorXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_iVec))
1102 template <
typename InputT>
1105 bool fitForBackground,
1106 std::shared_ptr<Eigen::MatrixXd> hMat,
1115 template <
typename InputT>
1117 Eigen::MatrixXd vMat = (this->_cMat)->jacobiSvd().matrixV();
1118 Eigen::MatrixXd vMatvMatT = vMat * vMat.transpose();
1121 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(*(this->_mMat));
1122 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
1123 Eigen::VectorXd eValues = eVecValues.eigenvalues();
1124 double eMax = eValues.maxCoeff();
1125 for (
int i = 0; i != eValues.rows(); ++i) {
1126 if (eValues(i) == 0.0) {
1129 else if ((eMax / eValues(i)) > maxCond) {
1130 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1131 "Truncating eValue %d; %.5e / %.5e = %.5e vs. %.5e",
1132 i, eMax, eValues(i), eMax / eValues(i), maxCond);
1136 eValues(i) = 1.0 / eValues(i);
1139 Eigen::MatrixXd mInv = rMat * eValues.asDiagonal() * rMat.transpose();
1141 std::vector<double> lambdas = _createLambdaSteps();
1142 std::vector<double> risks;
1143 for (
unsigned int i = 0; i < lambdas.size(); i++) {
1144 double l = lambdas[i];
1145 Eigen::MatrixXd mLambda = *(this->_mMat) + l * (*_hMat);
1153 Eigen::VectorXd term1 = (this->_aVec->transpose() * vMatvMatT * *(this->_aVec));
1154 if (term1.size() != 1)
1157 double term2a = (vMatvMatT * mLambda.inverse()).
trace();
1159 Eigen::VectorXd term2b = (this->_aVec->transpose() * (mInv * *(this->_bVec)));
1160 if (term2b.size() != 1)
1163 double risk = term1(0) + 2 * (term2a - term2b(0));
1164 LOGL_DEBUG(
"TRACE4.ip.diffim.RegularizedKernelSolution.estimateRisk",
1165 "Lambda = %.3f, Risk = %.5e",
1167 LOGL_DEBUG(
"TRACE5.ip.diffim.RegularizedKernelSolution.estimateRisk",
1168 "%.5e + 2 * (%.5e - %.5e)",
1169 term1(0), term2a, term2b(0));
1170 risks.push_back(risk);
1172 std::vector<double>::iterator it = min_element(risks.begin(), risks.end());
1173 int index = distance(risks.begin(), it);
1174 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1175 "Minimum Risk = %.3e at lambda = %.3e", risks[index], lambdas[index]);
1177 return lambdas[index];
1181 template <
typename InputT>
1183 if (includeHmat ==
true) {
1184 return (std::shared_ptr<Eigen::MatrixXd>(
1185 new Eigen::MatrixXd(*(this->_mMat) + _lambda * (*_hMat))
1193 template <
typename InputT>
1196 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1197 "cMat is %d x %d; vVec is %d; iVec is %d; hMat is %d x %d",
1198 (*this->_cMat).rows(), (*this->_cMat).cols(), (*this->_ivVec).size(),
1199 (*this->_iVec).size(), (*_hMat).rows(), (*_hMat).cols());
1202 std::cout <<
"ID: " << (this->
_id) << std::endl;
1203 std::cout <<
"C:" << std::endl;
1204 std::cout << (*this->_cMat) << std::endl;
1205 std::cout <<
"Sigma^{-1}:" << std::endl;
1206 std::cout << Eigen::MatrixXd((*this->_ivVec).asDiagonal()) << std::endl;
1207 std::cout <<
"Y:" << std::endl;
1208 std::cout << (*this->_iVec) << std::endl;
1209 std::cout <<
"H:" << std::endl;
1210 std::cout << (*_hMat) << std::endl;
1215 new Eigen::MatrixXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_cMat))
1218 new Eigen::VectorXd(this->_cMat->transpose() * this->_ivVec->asDiagonal() * *(this->_iVec))
1271 std::string lambdaType = _policy.getString(
"lambdaType");
1272 if (lambdaType ==
"absolute") {
1273 _lambda = _policy.getDouble(
"lambdaValue");
1275 else if (lambdaType ==
"relative") {
1276 _lambda = this->_mMat->trace() / this->_hMat->trace();
1277 _lambda *= _policy.getDouble(
"lambdaScaling");
1279 else if (lambdaType ==
"minimizeBiasedRisk") {
1280 double tol = _policy.getDouble(
"maxConditionNumber");
1281 _lambda = estimateRisk(tol);
1283 else if (lambdaType ==
"minimizeUnbiasedRisk") {
1284 _lambda = estimateRisk(std::numeric_limits<double>::max());
1290 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1291 "Applying kernel regularization with lambda = %.2e", _lambda);
1304 template <
typename InputT>
1306 std::vector<double> lambdas;
1308 std::string lambdaStepType = _policy.getString(
"lambdaStepType");
1309 if (lambdaStepType ==
"linear") {
1310 double lambdaLinMin = _policy.getDouble(
"lambdaLinMin");
1311 double lambdaLinMax = _policy.getDouble(
"lambdaLinMax");
1312 double lambdaLinStep = _policy.getDouble(
"lambdaLinStep");
1313 for (
double l = lambdaLinMin; l <= lambdaLinMax; l += lambdaLinStep) {
1314 lambdas.push_back(l);
1317 else if (lambdaStepType ==
"log") {
1318 double lambdaLogMin = _policy.getDouble(
"lambdaLogMin");
1319 double lambdaLogMax = _policy.getDouble(
"lambdaLogMax");
1320 double lambdaLogStep = _policy.getDouble(
"lambdaLogStep");
1321 for (
double l = lambdaLogMin; l <= lambdaLogMax; l += lambdaLogStep) {
1322 lambdas.push_back(pow(10, l));
1340 _spatialKernelFunction(spatialKernelFunction),
1341 _constantFirstTerm(false),
1343 _background(background),
1351 bool isAlardLupton =
_policy.
getString(
"kernelBasisSet") ==
"alard-lupton";
1353 if (isAlardLupton || usePca) {
1368 std::shared_ptr<Eigen::MatrixXd> mMat (
new Eigen::MatrixXd(
_nt,
_nt));
1369 std::shared_ptr<Eigen::VectorXd> bVec (
new Eigen::VectorXd(
_nt));
1380 LOGL_DEBUG(
"TRACE3.ip.diffim.SpatialKernelSolution",
1381 "Initializing with size %d %d %d and constant first term = %s",
1388 std::shared_ptr<Eigen::MatrixXd> qMat,
1389 std::shared_ptr<Eigen::VectorXd> wVec) {
1391 LOGL_DEBUG(
"TRACE5.ip.diffim.SpatialKernelSolution.addConstraint",
1392 "Adding candidate at %f, %f", xCenter, yCenter);
1396 Eigen::VectorXd pK(
_nkt);
1398 for (
int idx = 0; idx <
_nkt; idx++) { paramsK[idx] = 0.0; }
1399 for (
int idx = 0; idx <
_nkt; idx++) {
1402 pK(idx) = (*_spatialKernelFunction)(xCenter, yCenter);
1405 Eigen::MatrixXd pKpKt = (pK * pK.transpose());
1408 Eigen::MatrixXd pBpBt;
1409 Eigen::MatrixXd pKpBt;
1411 pB = Eigen::VectorXd(
_nbt);
1414 std::vector<double> paramsB =
_background->getParameters();
1415 for (
int idx = 0; idx <
_nbt; idx++) { paramsB[idx] = 0.0; }
1416 for (
int idx = 0; idx <
_nbt; idx++) {
1419 pB(idx) = (*_background)(xCenter, yCenter);
1422 pBpBt = (pB * pB.transpose());
1425 pKpBt = (pK * pB.transpose());
1429 std::cout <<
"Spatial weights" << std::endl;
1430 std::cout <<
"pKpKt " << pKpKt << std::endl;
1432 std::cout <<
"pBpBt " << pBpBt << std::endl;
1433 std::cout <<
"pKpBt " << pKpBt << std::endl;
1438 std::cout <<
"Spatial matrix inputs" << std::endl;
1439 std::cout <<
"M " << (*qMat) << std::endl;
1440 std::cout <<
"B " << (*wVec) << std::endl;
1454 (*_mMat)(0, 0) += (*qMat)(0,0);
1455 for(
int m2 = 1; m2 <
_nbases; m2++) {
1456 (*_mMat).block(0, m2*_nkt-dm, 1, _nkt) += (*qMat)(0,m2) * pK.transpose();
1458 (*_bVec)(0) += (*wVec)(0);
1461 (*_mMat).block(0, mb, 1, _nbt) += (*qMat)(0,
_nbases) * pB.transpose();
1466 for(
int m1 = m0; m1 <
_nbases; m1++) {
1468 (*_mMat).block(m1*_nkt-dm, m1*_nkt-dm, _nkt, _nkt) +=
1469 (pKpKt * (*qMat)(m1,m1)).triangularView<Eigen::Upper>();
1472 for(
int m2 = m1+1; m2 <
_nbases; m2++) {
1473 (*_mMat).block(m1*_nkt-dm, m2*_nkt-dm, _nkt, _nkt) += (*qMat)(m1,m2) * pKpKt;
1478 (*_mMat).block(m1*_nkt-dm, mb, _nkt, _nbt) += (*qMat)(m1,
_nbases) * pKpBt;
1482 (*_bVec).segment(m1*_nkt-dm, _nkt) += (*wVec)(m1) * pK;
1487 (*_mMat).block(mb, mb, _nbt, _nbt) +=
1488 (pBpBt * (*qMat)(
_nbases,
_nbases)).triangularView<Eigen::Upper>();
1489 (*_bVec).segment(mb, _nbt) += (*wVec)(
_nbases) * pB;
1493 std::cout <<
"Spatial matrix outputs" << std::endl;
1494 std::cout <<
"mMat " << (*_mMat) << std::endl;
1495 std::cout <<
"bVec " << (*_bVec) << std::endl;
1507 (void)
_kernel->computeImage(*image,
false, pos[0], pos[1]);
1513 for (
int i = 0; i <
_nt; i++) {
1514 for (
int j = i+1; j <
_nt; j++) {
1515 (*_mMat)(j,i) = (*
_mMat)(i,j);
1546 std::vector<double> kCoeffs(
_nbases);
1547 for (
int i = 0; i <
_nbases; i++) {
1548 if (std::isnan((*
_aVec)(i))) {
1552 "I. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % i % cNumber));
1554 kCoeffs[i] = (*_aVec)(i);
1559 new afwMath::LinearCombinationKernel(basisList, kCoeffs)
1565 std::vector<std::vector<double> > kCoeffs;
1567 for (
int i = 0, idx = 0; i <
_nbases; i++) {
1568 kCoeffs.push_back(std::vector<double>(
_nkt));
1572 if (std::isnan((*
_aVec)(idx))) {
1576 "II. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1578 kCoeffs[i][0] = (*_aVec)(idx++);
1581 for (
int j = 0; j <
_nkt; j++) {
1582 if (std::isnan((*
_aVec)(idx))) {
1586 "III. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1588 kCoeffs[i][j] = (*_aVec)(idx++);
1592 _kernel->setSpatialParameters(kCoeffs);
1602 for (
int i = 0; i <
_nbt; i++) {
1603 int idx =
_nt - _nbt + i;
1604 if (std::isnan((*
_aVec)(idx))) {
1607 "Unable to determine spatial background solution %d (nan)") % (idx)));
1609 bgCoeffs[i] = (*_aVec)(idx);
An include file to include the public header files for lsst::afw::math.
void _setKernel()
Set kernel after solution.
iterator end() const
Return an STL compliant iterator to the end of the image.
void flattenArray(Footprint const &fp, ndarray::Array< T, N, C > const &src, ndarray::Array< U, N-1, D > const &dest, lsst::afw::geom::Point2I const &xy0=lsst::afw::geom::Point2I())
Flatten the first two dimensions of an array.
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
An include file to include the header files for lsst::afw::geom.
std::shared_ptr< Eigen::MatrixXd > getM()
geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
Eigen::MatrixXi maskToEigenMatrix(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > const &mask)
void writeFits(std::string const &fileName, boost::shared_ptr< lsst::daf::base::PropertySet const > metadata=boost::shared_ptr< lsst::daf::base::PropertySet >(), std::string const &mode="w") const
Write a mask to a regular FITS file.
virtual lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel >::Ptr makeKernelImage()
bool getBool(const std::string &name) const
return a boolean value associated with the given name.
a container for holding hierarchical configuration data in memory.
void setKernelParameters(std::vector< double > const ¶ms)
Set the kernel parameters of a spatially invariant kernel.
virtual std::pair< std::shared_ptr< lsst::afw::math::Kernel >, double > getSolutionPair()
const std::string getString(const std::string &name) const
return a string value associated with the given name .
SpatialKernelSolution(lsst::afw::math::KernelList const &basisList, lsst::afw::math::Kernel::SpatialFunctionPtr spatialKernelFunction, lsst::afw::math::Kernel::SpatialFunctionPtr background, lsst::pex::policy::Policy policy)
RegularizedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground, std::shared_ptr< Eigen::MatrixXd > hMat, lsst::pex::policy::Policy policy)
void addConstraint(float xCenter, float yCenter, std::shared_ptr< Eigen::MatrixXd > qMat, std::shared_ptr< Eigen::VectorXd > wVec)
boost::shared_ptr< LinearCombinationKernel > Ptr
lsst::afw::math::Kernel::Ptr _kernel
Derived single-object convolution kernel.
Use (pixels & (given mask))
A Threshold is used to pass a threshold value to detection algorithms.
virtual lsst::afw::math::Kernel::Ptr getKernel()
geom::Box2I getBBox(ImageOrigin origin=PARENT) const
KernelSolvedBy _solvedBy
Type of algorithm used to make solution.
StaticKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
A class to evaluate image statistics.
virtual double getBackground()
An integer coordinate rectangle.
Declaration of classes to store the solution for convolution kernels.
table::Key< table::Array< Kernel::Pixel > > image
LSST DM logging module built on log4cxx.
double getValue(Property const prop=NOTHING) const
Return the value of the desired property (if specified in the constructor)
An include file to include the header files for lsst::afw::image.
geom::Point2I getXY0() const
Return the image's origin.
boost::shared_ptr< Kernel > Ptr
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)
void _setKernel()
Set kernel after solution.
double _kSum
Derived kernel sum.
static int _SolutionId
Unique identifier for solution.
void _setKernelUncertainty()
Not implemented.
bool _fitForBackground
Background terms included in fit.
geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
An include file to include the header files for lsst::afw::detection.
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > ImageT
afwMath::LinearCombinationKernel const & _kernel
virtual double getConditionNumber(ConditionNumberType conditionType)
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel >::Ptr makeKernelImage(lsst::afw::geom::Point2D const &pos)
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.
std::shared_ptr< Image< PixelT > > Ptr
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)
lsst::afw::math::Kernel::SpatialFunctionPtr _spatialKernelFunction
Spatial function for Kernel.
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
int _nbt
Number of background terms.
bool _constantFirstTerm
Is the first term constant.
lsst::pex::policy::Policy _policy
Policy to control processing.
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
lsst::afw::math::LinearCombinationKernel::Ptr _kernel
Spatial convolution kernel.
MaskedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
lsst::afw::math::Kernel::SpatialFunctionPtr _background
Spatial background model.
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...
int _nkt
Number of kernel terms.
std::pair< lsst::afw::math::LinearCombinationKernel::Ptr, lsst::afw::math::Kernel::SpatialFunctionPtr > getSolutionPair()
MaskT setMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
OR bitmask into all the Mask's pixels that are in the Footprint.
int _nbases
Number of basis functions.
std::shared_ptr< Eigen::VectorXd > _aVec
Derived least squares solution matrix.
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
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::afw::geom::Box2I maskBox)
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)
double estimateRisk(double maxCond)
iterator begin() const
Return an STL compliant iterator to the start of the image.
std::shared_ptr< Eigen::VectorXd > _bVec
Derived least squares B vector.
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it...
A class to represent a 2-dimensional array of pixels.
std::vector< double > _createLambdaSteps()
Image Subtraction helper functions.
std::shared_ptr< Eigen::MatrixXd > _mMat
Derived least squares M matrix.
MaskT setMaskFromFootprintList(lsst::afw::image::Mask< MaskT > *mask, std::vector< boost::shared_ptr< Footprint >> const &footprints, MaskT const bitmask)
OR bitmask into all the Mask's pixels which are in the set of Footprints.
Eigen::MatrixXd imageToEigenMatrix(lsst::afw::image::Image< PixelT > const &img)
Turns Image into a 2-D Eigen Matrix.
std::vector< boost::shared_ptr< Kernel > > KernelList
int _nt
Total number of terms.