17#include "boost/timer/timer.hpp"
20#include "Eigen/Cholesky"
23#include "Eigen/Eigenvalues"
38#include "ndarray/eigen.h"
41#define DEBUG_MATRIX2 0
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);
124 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
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;
169 }
catch (pexExcept::Exception& e) {
172 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
173 "Unable to determine kernel via eigen-values");
175 throw LSST_EXCEPT(pexExcept::Exception,
"Unable to determine kernel solution");
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>
217 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return solution");
222 template <
typename InputT>
225 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return image");
234 template <
typename InputT>
237 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return background");
242 template <
typename InputT>
245 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return ksum");
250 template <
typename InputT>
254 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return solution");
260 template <
typename InputT>
270 "Error: variance less than 0.0");
274 "Error: variance equals 0.0, cannot inverse variance weight");
280 unsigned int const nKernelParameters = basisList.
size();
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);
385 cMat.col(nParameters-1).fill(1.);
388 _ivVec = eigeniVariance.col(0);
389 _iVec = eigenScience.col(0);
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",
414 }
catch (pexExcept::Exception &e) {
422 template <
typename InputT>
425 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot make solution");
428 unsigned int const nParameters =
_aVec.size();
430 unsigned int const nKernelParameters =
432 if (nParameters != (nKernelParameters + nBackgroundParameters))
433 throw LSST_EXCEPT(pexExcept::Exception,
"Mismatched sizes in kernel solution");
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);
454 str(boost::format(
"Unable to determine background solution %d (nan)") %
462 template <
typename InputT>
464 throw LSST_EXCEPT(pexExcept::Exception,
"Uncertainty calculation not supported");
114 Eigen::VectorXd sValues = mMat.jacobiSvd().singularValues(); {
…}
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");
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();
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);
654 cMat.col(nParameters-1).fill(1.);
657 this->
_ivVec = eigenVariance.array().inverse().matrix();
658 this->
_iVec = eigenScience;
666 template <
typename InputT>
677 "Error: variance less than 0.0");
681 "Error: variance equals 0.0, cannot inverse variance weight");
697 unsigned int const nKernelParameters = basisList.
size();
699 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
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);
816 cMat.col(nParameters-1).fill(1.);
819 this->
_ivVec = eigeniVariance.col(0);
820 this->
_iVec = eigenScience.col(0);
830 template <
typename InputT>
841 "Error: variance less than 0.0");
845 "Error: variance equals 0.0, cannot inverse variance weight");
851 unsigned int const nKernelParameters = basisList.
size();
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);
1045 cMat.col(nParameters-1).fill(1.);
1048 this->
_ivVec = eigeniVariance.col(0);
1049 this->
_iVec = eigenScience.col(0);
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;
1105 }
catch (pexExcept::Exception &e) {
1109 Eigen::VectorXd term1 = (this->
_aVec.transpose() * vMatvMatT * this->
_aVec);
1110 if (term1.size() != 1)
1111 throw LSST_EXCEPT(pexExcept::Exception,
"Matrix size mismatch");
1113 double term2a = (vMatvMatT * mLambda.inverse()).trace();
1115 Eigen::VectorXd term2b = (this->_aVec.transpose() * (mInv * this->
_bVec));
1116 if (term2b.size() != 1)
1117 throw LSST_EXCEPT(pexExcept::Exception,
"Matrix size mismatch");
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());
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");
1233 else if (lambdaType ==
"minimizeUnbiasedRisk") {
1237 throw LSST_EXCEPT(pexExcept::Exception,
"lambdaType in PropertySet not recognized");
1240 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1241 "Applying kernel regularization with lambda = %.2e", _lambda);
1246 }
catch (pexExcept::Exception &e) {
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) {
1276 throw LSST_EXCEPT(pexExcept::Exception,
"lambdaStepType in PropertySet not recognized");
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();
1309 _nkt = _spatialKernelFunction->getParameters().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++) {
1351 _spatialKernelFunction->setParameters(paramsK);
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++) {
1368 _background->setParameters(paramsB);
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;
1452 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return image");
1457 (void)_kernel->computeImage(*
image,
false, pos[0], pos[1]);
1463 for (
int i = 0; i < _nt; i++) {
1464 for (
int j = i+1; j < _nt; j++) {
1471 }
catch (pexExcept::Exception &e) {
1482 throw LSST_EXCEPT(pexExcept::Exception,
"Kernel not solved; cannot return solution");
1488 void SpatialKernelSolution::_setKernel() {
1497 for (
int i = 0; i < _nbases; i++) {
1500 pexExcept::Exception,
1502 "I. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % i % cNumber));
1504 kCoeffs[i] =
_aVec(i);
1517 for (
int i = 0, idx = 0; i < _nbases; i++) {
1521 if ((i == 0) && (_constantFirstTerm)) {
1524 pexExcept::Exception,
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++) {
1534 pexExcept::Exception,
1536 "III. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1538 kCoeffs[i][j] =
_aVec(idx++);
1542 _kernel->setSpatialParameters(kCoeffs);
1546 std::shared_ptr<ImageT>
image (
new ImageT(_kernel->getDimensions()));
1547 _kSum = _kernel->computeImage(*image,
false);
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);
1565 _background->setParameters(bgCoeffs);
100 switch (conditionType) {
…}
58 Eigen::MatrixXd mMat, {
…}
#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.
@ BITMASK
Use (pixels & (given mask))
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)
std::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
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
virtual double getConditionNumber(ConditionNumberType conditionType)
Eigen::MatrixXd const & getM()
KernelSolution(Eigen::MatrixXd mMat, Eigen::VectorXd bVec, bool fitForBackground)
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)
double _background
Derived differential background estimate.
double _kSum
Derived kernel sum.
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()
Eigen::VectorXd _iVec
Vectorized I.
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()
Eigen::VectorXd _ivVec
Inverse variance.
Eigen::MatrixXd _cMat
K_i x R.
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)
std::int32_t MaskPixel
default type for Masks and MaskedImage Masks
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
std::vector< std::shared_ptr< Kernel > > KernelList
Point< double, 2 > Point2D
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)
T dynamic_pointer_cast(T... args)