17 #include "boost/timer.hpp" 20 #include "Eigen/Cholesky" 23 #include "Eigen/Eigenvalues" 37 #include "ndarray/eigen.h" 39 #define DEBUG_MATRIX 0 40 #define DEBUG_MATRIX2 0 65 _fitForBackground(fitForBackground)
98 switch (conditionType) {
101 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
102 Eigen::VectorXd eValues = eVecValues.eigenvalues();
103 double eMax = eValues.maxCoeff();
104 double eMin = eValues.minCoeff();
105 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
106 "EIGENVALUE eMax / eMin = %.3e", eMax / eMin);
107 return (eMax / eMin);
112 Eigen::VectorXd sValues = mMat.jacobiSvd().singularValues();
113 double sMax = sValues.maxCoeff();
114 double sMin = sValues.minCoeff();
115 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.getConditionNumber",
116 "SVD eMax / eMin = %.3e", sMax / sMin);
117 return (sMax / sMin);
123 "Undefined ConditionNumberType : only EIGENVALUE, SVD allowed.");
130 Eigen::VectorXd
const& bVec) {
139 Eigen::VectorXd aVec = Eigen::VectorXd::Zero(bVec.size());
144 LOGL_DEBUG(
"TRACE2.ip.diffim.KernelSolution.solve",
145 "Solving for kernel");
147 Eigen::FullPivLU<Eigen::MatrixXd> lu(mMat);
148 if (lu.isInvertible()) {
149 aVec = lu.solve(bVec);
151 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
152 "Unable to determine kernel via LU");
157 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
158 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
159 Eigen::VectorXd eValues = eVecValues.eigenvalues();
161 for (
int i = 0; i != eValues.rows(); ++i) {
162 if (eValues(i) != 0.0) {
163 eValues(i) = 1.0/eValues(i);
167 aVec = rMat * eValues.asDiagonal() * rMat.transpose() * bVec;
171 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
172 "Unable to determine kernel via eigen-values");
178 double time = t.elapsed();
179 LOGL_DEBUG(
"TRACE3.ip.diffim.KernelSolution.solve",
180 "Compute time for matrix math : %.2f s", time);
192 template <
typename InputT>
195 bool fitForBackground
212 template <
typename InputT>
220 template <
typename InputT>
228 (void)
_kernel->computeImage(*image,
false);
232 template <
typename InputT>
240 template <
typename InputT>
248 template <
typename InputT>
258 template <
typename InputT>
266 if (varStats.
getValue(afwMath::MIN) < 0.0) {
268 "Error: variance less than 0.0");
270 if (varStats.
getValue(afwMath::MIN) == 0.0) {
272 "Error: variance equals 0.0, cannot inverse variance weight");
278 unsigned int const nKernelParameters = basisList.
size();
280 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
316 afwGeom::Box2I goodBBox = (*kiter)->shrinkBBox(templateImage.
getBBox(afwImage::LOCAL));
317 unsigned int const startCol = goodBBox.getMinX();
318 unsigned int const startRow = goodBBox.getMinY();
320 unsigned int endCol = goodBBox.getMaxX() + 1;
321 unsigned int endRow = goodBBox.getMaxY() + 1;
336 startRow, startCol, endRow-startRow, endCol-startCol
337 ).array().inverse().matrix();
340 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
341 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
342 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
353 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
354 afwMath::convolve(cimage, templateImage, **kiter,
false);
360 cMat.resize(cMat.size(), 1);
365 double time = t.elapsed();
366 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
367 "Total compute time to do basis convolutions : %.2f s", time);
374 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
377 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
378 cMat.col(kidxj) = eiterj->col(0);
382 cMat.col(nParameters-1).fill(1.);
385 _ivVec = eigeniVariance.col(0);
386 _iVec = eigenScience.col(0);
393 template <
typename InputT>
395 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.solve",
396 "mMat is %d x %d; bVec is %d; cMat is %d x %d; vVec is %d; iVec is %d",
419 template <
typename InputT>
425 unsigned int const nParameters =
_aVec.size();
427 unsigned int const nKernelParameters =
429 if (nParameters != (nKernelParameters + nBackgroundParameters))
434 for (
unsigned int idx = 0; idx < nKernelParameters; idx++) {
437 str(boost::format(
"Unable to determine kernel solution %d (nan)") % idx));
439 kValues[idx] =
_aVec(idx);
441 _kernel->setKernelParameters(kValues);
451 str(boost::format(
"Unable to determine background solution %d (nan)") %
459 template <
typename InputT>
489 template <
typename InputT>
492 bool fitForBackground
497 template <
typename InputT>
506 if (varStats.
getValue(afwMath::MIN) < 0.0) {
508 "Error: variance less than 0.0");
510 if (varStats.
getValue(afwMath::MIN) == 0.0) {
512 "Error: variance equals 0.0, cannot inverse variance weight");
535 int growPix = (*kiter)->getCtr().getX();
539 for (
typename afwDet::FootprintSet::FootprintList::iterator
545 afwDet::setMaskFromFootprint(finalMask,
552 for (
auto const & foot : *(maskedFpSetGrown.
getFootprints())) {
556 finalMask.writeFits(
"finalmask.fits");
559 ndarray::Array<int, 1, 1> maskArray =
560 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
561 fullFp->getSpans()->flatten(maskArray, finalMask.getArray(), templateImage.
getXY0());
562 auto maskEigen = maskArray.asEigen();
564 ndarray::Array<InputT, 1, 1> arrayTemplate =
565 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
566 fullFp->getSpans()->flatten(arrayTemplate, templateImage.
getArray(), templateImage.
getXY0());
567 auto eigenTemplate0 = arrayTemplate.asEigen();
569 ndarray::Array<InputT, 1, 1> arrayScience =
570 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
571 fullFp->getSpans()->flatten(arrayScience, scienceImage.
getArray(), scienceImage.
getXY0());
572 auto eigenScience0 = arrayScience.asEigen();
574 ndarray::Array<afwImage::VariancePixel, 1, 1> arrayVariance =
575 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
576 fullFp->getSpans()->flatten(arrayVariance, varianceEstimate.
getArray(), varianceEstimate.
getXY0());
577 auto eigenVariance0 = arrayVariance.asEigen();
580 for (
int i = 0; i < maskEigen.size(); i++) {
581 if (maskEigen(i) == 0.0)
585 Eigen::VectorXd eigenTemplate(nGood);
586 Eigen::VectorXd eigenScience(nGood);
587 Eigen::VectorXd eigenVariance(nGood);
589 for (
int i = 0; i < maskEigen.size(); i++) {
590 if (maskEigen(i) == 0.0) {
591 eigenTemplate(nUsed) = eigenTemplate0(i);
592 eigenScience(nUsed) = eigenScience0(i);
593 eigenVariance(nUsed) = eigenVariance0(i);
602 unsigned int const nKernelParameters = basisList.size();
604 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
616 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
617 afwMath::convolve(cimage, templateImage, **kiter,
false);
619 ndarray::Array<InputT, 1, 1> arrayC =
620 ndarray::allocate(ndarray::makeVector(fullFp->getArea()));
621 fullFp->getSpans()->flatten(arrayC, cimage.getArray(), cimage.getXY0());
622 auto eigenC0 = arrayC.asEigen();
624 Eigen::VectorXd eigenC(nGood);
626 for (
int i = 0; i < maskEigen.size(); i++) {
627 if (maskEigen(i) == 0.0) {
628 eigenC(nUsed) = eigenC0(i);
635 double time = t.elapsed();
636 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.buildWithMask",
637 "Total compute time to do basis convolutions : %.2f s", time);
641 Eigen::MatrixXd cMat(eigenTemplate.size(), nParameters);
644 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
645 cMat.block(0, kidxj, eigenTemplate.size(), 1) =
646 Eigen::MatrixXd(*eiterj).block(0, 0, eigenTemplate.size(), 1);
650 cMat.col(nParameters-1).fill(1.);
653 this->
_ivVec = eigenVariance.array().inverse().matrix();
654 this->
_iVec = eigenScience;
662 template <
typename InputT>
671 if (varStats.
getValue(afwMath::MIN) < 0.0) {
673 "Error: variance less than 0.0");
675 if (varStats.
getValue(afwMath::MIN) == 0.0) {
677 "Error: variance equals 0.0, cannot inverse variance weight");
693 unsigned int const nKernelParameters = basisList.
size();
695 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
702 afwGeom::Box2I shrunkLocalBBox = (*kiter)->shrinkBBox(templateImage.
getBBox(afwImage::LOCAL));
703 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
704 "Limits of good pixels after convolution: %d,%d -> %d,%d (local)",
705 shrunkLocalBBox.getMinX(), shrunkLocalBBox.getMinY(),
706 shrunkLocalBBox.getMaxX(), shrunkLocalBBox.getMaxY());
709 unsigned int startCol = shrunkLocalBBox.getMinX();
710 unsigned int startRow = shrunkLocalBBox.getMinY();
711 unsigned int endCol = shrunkLocalBBox.getMaxX();
712 unsigned int endRow = shrunkLocalBBox.getMaxY();
735 startRow, startCol, endRow-startRow, endCol-startCol
736 ).array().inverse().matrix();
739 eMask.resize(eMask.rows()*eMask.cols(), 1);
740 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
741 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
742 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
745 Eigen::MatrixXd maskedEigenTemplate(eigenTemplate.rows(), 1);
746 Eigen::MatrixXd maskedEigenScience(eigenScience.rows(), 1);
747 Eigen::MatrixXd maskedEigeniVariance(eigeniVariance.rows(), 1);
749 for (
int i = 0; i < eMask.rows(); i++) {
750 if (eMask(i, 0) == 0) {
751 maskedEigenTemplate(nGood, 0) = eigenTemplate(i, 0);
752 maskedEigenScience(nGood, 0) = eigenScience(i, 0);
753 maskedEigeniVariance(nGood, 0) = eigeniVariance(i, 0);
758 eigenTemplate = maskedEigenTemplate.block(0, 0, nGood, 1);
759 eigenScience = maskedEigenScience.block(0, 0, nGood, 1);
760 eigeniVariance = maskedEigeniVariance.block(0, 0, nGood, 1);
772 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
773 afwMath::convolve(cimage, templateImage, **kiter,
false);
779 cMat.resize(cMat.size(), 1);
782 Eigen::MatrixXd maskedcMat(cMat.rows(), 1);
784 for (
int i = 0; i < eMask.rows(); i++) {
785 if (eMask(i, 0) == 0) {
786 maskedcMat(nGood, 0) = cMat(i, 0);
790 cMat = maskedcMat.block(0, 0, nGood, 1);
794 double time = t.elapsed();
795 LOGL_DEBUG(
"TRACE3.ip.diffim.StaticKernelSolution.build",
796 "Total compute time to do basis convolutions : %.2f s", time);
803 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
806 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
807 cMat.col(kidxj) = eiterj->col(0);
811 cMat.col(nParameters-1).fill(1.);
814 this->
_ivVec = eigeniVariance.col(0);
815 this->
_iVec = eigenScience.col(0);
825 template <
typename InputT>
830 lsst::afw::geom::Box2I maskBox
834 if (varStats.
getValue(afwMath::MIN) < 0.0) {
836 "Error: variance less than 0.0");
838 if (varStats.
getValue(afwMath::MIN) == 0.0) {
840 "Error: variance equals 0.0, cannot inverse variance weight");
846 unsigned int const nKernelParameters = basisList.
size();
848 unsigned int const nParameters = nKernelParameters + nBackgroundParameters;
876 afwGeom::Box2I shrunkBBox = (*kiter)->shrinkBBox(templateImage.
getBBox());
878 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
879 "Limits of good pixels after convolution: %d,%d -> %d,%d",
880 shrunkBBox.getMinX(), shrunkBBox.getMinY(),
881 shrunkBBox.getMaxX(), shrunkBBox.getMaxY());
883 unsigned int const startCol = shrunkBBox.getMinX();
884 unsigned int const startRow = shrunkBBox.getMinY();
885 unsigned int const endCol = shrunkBBox.getMaxX();
886 unsigned int const endRow = shrunkBBox.getMaxY();
905 int maskStartCol = maskBox.getMinX();
906 int maskStartRow = maskBox.getMinY();
907 int maskEndCol = maskBox.getMaxX();
908 int maskEndRow = maskBox.getMaxY();
929 afwGeom::Box2I tBox = afwGeom::Box2I(afwGeom::Point2I(startCol, maskEndRow + 1),
930 afwGeom::Point2I(endCol, endRow));
932 afwGeom::Box2I bBox = afwGeom::Box2I(afwGeom::Point2I(startCol, startRow),
933 afwGeom::Point2I(endCol, maskStartRow - 1));
935 afwGeom::Box2I lBox = afwGeom::Box2I(afwGeom::Point2I(startCol, maskStartRow),
936 afwGeom::Point2I(maskStartCol - 1, maskEndRow));
938 afwGeom::Box2I rBox = afwGeom::Box2I(afwGeom::Point2I(maskEndCol + 1, maskStartRow),
939 afwGeom::Point2I(endCol, maskEndRow));
941 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
942 "Upper good pixel region: %d,%d -> %d,%d",
943 tBox.getMinX(), tBox.getMinY(), tBox.getMaxX(), tBox.getMaxY());
944 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
945 "Bottom good pixel region: %d,%d -> %d,%d",
946 bBox.getMinX(), bBox.getMinY(), bBox.getMaxX(), bBox.getMaxY());
947 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
948 "Left good pixel region: %d,%d -> %d,%d",
949 lBox.getMinX(), lBox.getMinY(), lBox.getMaxX(), lBox.getMaxY());
950 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
951 "Right good pixel region: %d,%d -> %d,%d",
952 rBox.getMinX(), rBox.getMinY(), rBox.getMaxX(), rBox.getMaxY());
956 boxArray.push_back(bBox);
957 boxArray.push_back(lBox);
958 boxArray.push_back(rBox);
960 int totalSize = tBox.getWidth() * tBox.getHeight();
961 totalSize += bBox.getWidth() * bBox.getHeight();
962 totalSize += lBox.getWidth() * lBox.getHeight();
963 totalSize += rBox.getWidth() * rBox.getHeight();
965 Eigen::MatrixXd eigenTemplate(totalSize, 1);
966 Eigen::MatrixXd eigenScience(totalSize, 1);
967 Eigen::MatrixXd eigeniVariance(totalSize, 1);
968 eigenTemplate.setZero();
969 eigenScience.setZero();
970 eigeniVariance.setZero();
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);
1004 for (kiter = basisList.
begin(); kiter != basisList.
end(); ++kiter, ++eiter) {
1005 afwMath::convolve(cimage, templateImage, **kiter,
false);
1006 Eigen::MatrixXd cMat(totalSize, 1);
1011 for (; biter != boxArray.
end(); ++biter) {
1012 int area = (*biter).getWidth() * (*biter).getHeight();
1016 esubimage.resize(area, 1);
1017 cMat.block(nTerms, 0, area, 1) = esubimage.block(0, 0, area, 1);
1026 double time = t.elapsed();
1027 LOGL_DEBUG(
"TRACE3.ip.diffim.MaskedKernelSolution.build",
1028 "Total compute time to do basis convolutions : %.2f s", time);
1035 Eigen::MatrixXd cMat(eigenTemplate.col(0).size(), nParameters);
1038 for (
unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
1039 cMat.col(kidxj) = eiterj->col(0);
1043 cMat.col(nParameters-1).fill(1.);
1046 this->
_ivVec = eigeniVariance.col(0);
1047 this->
_iVec = eigenScience.col(0);
1056 template <
typename InputT>
1059 bool fitForBackground,
1060 Eigen::MatrixXd
const& hMat,
1069 template <
typename InputT>
1071 Eigen::MatrixXd vMat = this->
_cMat.jacobiSvd().matrixV();
1072 Eigen::MatrixXd vMatvMatT = vMat * vMat.transpose();
1075 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(this->
_mMat);
1076 Eigen::MatrixXd
const& rMat = eVecValues.eigenvectors();
1077 Eigen::VectorXd eValues = eVecValues.eigenvalues();
1078 double eMax = eValues.maxCoeff();
1079 for (
int i = 0; i != eValues.rows(); ++i) {
1080 if (eValues(i) == 0.0) {
1083 else if ((eMax / eValues(i)) > maxCond) {
1084 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1085 "Truncating eValue %d; %.5e / %.5e = %.5e vs. %.5e",
1086 i, eMax, eValues(i), eMax / eValues(i), maxCond);
1090 eValues(i) = 1.0 / eValues(i);
1093 Eigen::MatrixXd mInv = rMat * eValues.asDiagonal() * rMat.transpose();
1097 for (
unsigned int i = 0; i < lambdas.
size(); i++) {
1098 double l = lambdas[i];
1099 Eigen::MatrixXd mLambda = this->
_mMat + l * _hMat;
1107 Eigen::VectorXd term1 = (this->
_aVec.transpose() * vMatvMatT * this->
_aVec);
1108 if (term1.size() != 1)
1111 double term2a = (vMatvMatT * mLambda.inverse()).trace();
1113 Eigen::VectorXd term2b = (this->
_aVec.transpose() * (mInv * this->
_bVec));
1114 if (term2b.size() != 1)
1117 double risk = term1(0) + 2 * (term2a - term2b(0));
1118 LOGL_DEBUG(
"TRACE4.ip.diffim.RegularizedKernelSolution.estimateRisk",
1119 "Lambda = %.3f, Risk = %.5e",
1121 LOGL_DEBUG(
"TRACE5.ip.diffim.RegularizedKernelSolution.estimateRisk",
1122 "%.5e + 2 * (%.5e - %.5e)",
1123 term1(0), term2a, term2b(0));
1128 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.estimateRisk",
1129 "Minimum Risk = %.3e at lambda = %.3e", risks[index], lambdas[index]);
1131 return lambdas[index];
1135 template <
typename InputT>
1137 if (includeHmat ==
true) {
1138 return this->
_mMat + _lambda * _hMat;
1145 template <
typename InputT>
1148 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1149 "cMat is %d x %d; vVec is %d; iVec is %d; hMat is %d x %d",
1151 this->
_iVec.size(), _hMat.rows(), _hMat.cols());
1220 if (lambdaType ==
"absolute") {
1221 _lambda = _policy.
getDouble(
"lambdaValue");
1223 else if (lambdaType ==
"relative") {
1224 _lambda = this->
_mMat.trace() / this->_hMat.trace();
1225 _lambda *= _policy.
getDouble(
"lambdaScaling");
1227 else if (lambdaType ==
"minimizeBiasedRisk") {
1228 double tol = _policy.
getDouble(
"maxConditionNumber");
1231 else if (lambdaType ==
"minimizeUnbiasedRisk") {
1238 LOGL_DEBUG(
"TRACE3.ip.diffim.RegularizedKernelSolution.solve",
1239 "Applying kernel regularization with lambda = %.2e", _lambda);
1252 template <
typename InputT>
1257 if (lambdaStepType ==
"linear") {
1258 double lambdaLinMin = _policy.
getDouble(
"lambdaLinMin");
1259 double lambdaLinMax = _policy.
getDouble(
"lambdaLinMax");
1260 double lambdaLinStep = _policy.
getDouble(
"lambdaLinStep");
1261 for (
double l = lambdaLinMin; l <= lambdaLinMax; l += lambdaLinStep) {
1265 else if (lambdaStepType ==
"log") {
1266 double lambdaLogMin = _policy.
getDouble(
"lambdaLogMin");
1267 double lambdaLogMax = _policy.
getDouble(
"lambdaLogMax");
1268 double lambdaLogStep = _policy.
getDouble(
"lambdaLogStep");
1269 for (
double l = lambdaLogMin; l <= lambdaLogMax; l += lambdaLogStep) {
1288 _spatialKernelFunction(spatialKernelFunction),
1289 _constantFirstTerm(false),
1299 bool isAlardLupton = _policy.
getString(
"kernelBasisSet") ==
"alard-lupton";
1300 bool usePca = _policy.
getBool(
"usePcaForSpatialKernel");
1301 if (isAlardLupton || usePca) {
1302 _constantFirstTerm =
true;
1306 _nbases = basisList.
size();
1307 _nkt = _spatialKernelFunction->getParameters().size();
1310 if (_constantFirstTerm) {
1311 _nt = (_nbases - 1) * _nkt + 1 + _nbt;
1313 _nt = _nbases * _nkt + _nbt;
1316 Eigen::MatrixXd mMat(_nt, _nt);
1317 Eigen::VectorXd bVec(_nt);
1328 LOGL_DEBUG(
"TRACE3.ip.diffim.SpatialKernelSolution",
1329 "Initializing with size %d %d %d and constant first term = %s",
1331 _constantFirstTerm ?
"true" :
"false");
1336 Eigen::MatrixXd
const& qMat,
1337 Eigen::VectorXd
const& wVec) {
1339 LOGL_DEBUG(
"TRACE5.ip.diffim.SpatialKernelSolution.addConstraint",
1340 "Adding candidate at %f, %f", xCenter, yCenter);
1344 Eigen::VectorXd pK(_nkt);
1346 for (
int idx = 0; idx < _nkt; idx++) { paramsK[idx] = 0.0; }
1347 for (
int idx = 0; idx < _nkt; idx++) {
1349 _spatialKernelFunction->setParameters(paramsK);
1350 pK(idx) = (*_spatialKernelFunction)(xCenter, yCenter);
1353 Eigen::MatrixXd pKpKt = (pK * pK.transpose());
1356 Eigen::MatrixXd pBpBt;
1357 Eigen::MatrixXd pKpBt;
1359 pB = Eigen::VectorXd(_nbt);
1363 for (
int idx = 0; idx < _nbt; idx++) { paramsB[idx] = 0.0; }
1364 for (
int idx = 0; idx < _nbt; idx++) {
1366 _background->setParameters(paramsB);
1367 pB(idx) = (*_background)(xCenter, yCenter);
1370 pBpBt = (pB * pB.transpose());
1373 pKpBt = (pK * pB.transpose());
1396 int mb = _nt - _nbt;
1398 if (_constantFirstTerm) {
1402 _mMat(0, 0) += qMat(0,0);
1403 for(
int m2 = 1; m2 < _nbases; m2++) {
1404 _mMat.block(0, m2*_nkt-dm, 1, _nkt) += qMat(0,m2) * pK.transpose();
1406 _bVec(0) += wVec(0);
1409 _mMat.block(0, mb, 1, _nbt) += qMat(0,_nbases) * pB.transpose();
1414 for(
int m1 = m0; m1 < _nbases; m1++) {
1416 _mMat.block(m1*_nkt-dm, m1*_nkt-dm, _nkt, _nkt) +=
1417 (pKpKt * qMat(m1,m1)).triangularView<Eigen::Upper>();
1420 for(
int m2 = m1+1; m2 < _nbases; m2++) {
1421 _mMat.block(m1*_nkt-dm, m2*_nkt-dm, _nkt, _nkt) += qMat(m1,m2) * pKpKt;
1426 _mMat.block(m1*_nkt-dm, mb, _nkt, _nbt) += qMat(m1,_nbases) * pKpBt;
1430 _bVec.segment(m1*_nkt-dm, _nkt) += wVec(m1) * pK;
1435 _mMat.block(mb, mb, _nbt, _nbt) +=
1436 (pBpBt * qMat(_nbases,_nbases)).triangularView<Eigen::Upper>();
1437 _bVec.segment(mb, _nbt) += wVec(_nbases) * pB;
1455 (void)_kernel->computeImage(*image,
false, pos[0], pos[1]);
1461 for (
int i = 0; i < _nt; i++) {
1462 for (
int j = i+1; j < _nt; j++) {
1486 void SpatialKernelSolution::_setKernel() {
1495 for (
int i = 0; i < _nbases; i++) {
1500 "I. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % i % cNumber));
1502 kCoeffs[i] =
_aVec(i);
1507 new afwMath::LinearCombinationKernel(basisList, kCoeffs)
1515 for (
int i = 0, idx = 0; i < _nbases; i++) {
1519 if ((i == 0) && (_constantFirstTerm)) {
1524 "II. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1526 kCoeffs[i][0] =
_aVec(idx++);
1529 for (
int j = 0; j < _nkt; j++) {
1534 "III. Unable to determine spatial kernel solution %d (nan). Condition number = %.3e") % idx % cNumber));
1536 kCoeffs[i][j] =
_aVec(idx++);
1540 _kernel->setSpatialParameters(kCoeffs);
1545 _kSum = _kernel->computeImage(*image,
false);
1550 for (
int i = 0; i < _nbt; i++) {
1551 int idx = _nt - _nbt + i;
1555 "Unable to determine spatial background solution %d (nan)") % (idx)));
1557 bgCoeffs[i] =
_aVec(idx);
1563 _background->setParameters(bgCoeffs);
Eigen::MatrixXd _cMat
K_i x R.
Eigen::MatrixXi maskToEigenMatrix(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > const &mask)
virtual std::pair< std::shared_ptr< lsst::afw::math::Kernel >, double > getSolutionPair()
Eigen::VectorXd _bVec
Derived least squares B vector.
SpatialKernelSolution(lsst::afw::math::KernelList const &basisList, lsst::afw::math::Kernel::SpatialFunctionPtr spatialKernelFunction, lsst::afw::math::Kernel::SpatialFunctionPtr background, lsst::pex::policy::Policy policy)
virtual std::shared_ptr< lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > > makeKernelImage()
std::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
KernelSolvedBy _solvedBy
Type of algorithm used to make solution.
StaticKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
double _background
Derived differential background estimate.
Eigen::VectorXd _iVec
Vectorized I.
Eigen::VectorXd _ivVec
Inverse variance.
virtual double getBackground()
std::pair< std::shared_ptr< lsst::afw::math::LinearCombinationKernel >, lsst::afw::math::Kernel::SpatialFunctionPtr > getSolutionPair()
Declaration of classes to store the solution for convolution kernels.
RegularizedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground, Eigen::MatrixXd const &hMat, lsst::pex::policy::Policy policy)
bool getBool(const std::string &name) const
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.
virtual std::shared_ptr< lsst::afw::math::Kernel > getKernel()
static int _SolutionId
Unique identifier for solution.
void _setKernelUncertainty()
Not implemented.
bool _fitForBackground
Background terms included in fit.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > ImageT
virtual double getConditionNumber(ConditionNumberType conditionType)
int _id
Unique ID for object.
Eigen::MatrixXd imageToEigenMatrix(lsst::afw::image::Image< PixelT > const &img)
Turns a 2-d Image into a 2-d Eigen Matrix.
T dynamic_pointer_cast(T... args)
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)
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
const std::string getString(const std::string &name) const
std::shared_ptr< lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > > makeKernelImage(lsst::afw::geom::Point2D const &pos)
double getValue(Property const prop=NOTHING) const
Eigen::MatrixXd _mMat
Derived least squares M matrix.
double getDouble(const std::string &name) const
lsst::geom::Point2I getXY0() const
double _kSum
Derived kernel sum.
#define LSST_EXCEPT(type,...)
MaskedKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)
void addConstraint(float xCenter, float yCenter, Eigen::MatrixXd const &qMat, Eigen::VectorXd const &wVec)
#define LOGL_DEBUG(logger, message...)
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)
Eigen::MatrixXd const & getM()
double estimateRisk(double maxCond)
Eigen::VectorXd _aVec
Derived least squares solution matrix.
std::shared_ptr< lsst::afw::math::Kernel > _kernel
Derived single-object convolution kernel.
void writeFits(std::string const &fileName, std::shared_ptr< lsst::daf::base::PropertySet const > metadata=std::shared_ptr< lsst::daf::base::PropertySet >(), std::string const &mode="w") const
lsst::geom::Extent2I getDimensions() const
#define LSST_EXCEPT_ADD(e, m)
Image Subtraction helper functions.