Loading [MathJax]/extensions/tex2jax.js
LSST Applications g04a91732dc+9666464c73,g0fba68d861+079660c10e,g1fd858c14a+94f68680cf,g208c678f98+627fe8cd4e,g271391ec13+ac98094cfc,g2c84ff76c0+12036dbf49,g2c9e612ef2+a92a2e6025,g35bb328faa+fcb1d3bbc8,g4d2262a081+bcdfaf528c,g4e0f332c67+c58e4b632d,g53246c7159+fcb1d3bbc8,g60b5630c4e+a92a2e6025,g67b6fd64d1+9d1b2ab50a,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g7b71ed6315+fcb1d3bbc8,g8852436030+506db7da85,g89139ef638+9d1b2ab50a,g8d6b6b353c+a92a2e6025,g9125e01d80+fcb1d3bbc8,g989de1cb63+9d1b2ab50a,g9f33ca652e+d1749da127,ga2b97cdc51+a92a2e6025,gabe3b4be73+1e0a283bba,gb1101e3267+6ecbd0580e,gb58c049af0+f03b321e39,gb89ab40317+9d1b2ab50a,gb90eeb9370+384e1fc23b,gcf25f946ba+506db7da85,gd315a588df+382ef11c06,gd6cbbdb0b4+75aa4b1db4,gd9a9a58781+fcb1d3bbc8,gde0f65d7ad+a095917f21,ge278dab8ac+c61fbefdff,ge410e46f29+9d1b2ab50a,ge82c20c137+e12a08b75a,gf67bdafdda+9d1b2ab50a,gfd5510ef7b+df344d16e5,v29.0.0.rc2
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
lsst::ip::diffim::MaskedKernelSolution< InputT > Class Template Reference

#include <KernelSolution.h>

Inheritance diagram for lsst::ip::diffim::MaskedKernelSolution< InputT >:
lsst::ip::diffim::StaticKernelSolution< InputT > lsst::ip::diffim::KernelSolution

Public Types

typedef std::shared_ptr< MaskedKernelSolution< InputT > > Ptr
 
enum  KernelSolvedBy {
  NONE = 0 , CHOLESKY_LDLT = 1 , CHOLESKY_LLT = 2 , LU = 3 ,
  EIGENVECTOR = 4
}
 
enum  ConditionNumberType { EIGENVALUE = 0 , SVD = 1 }
 
typedef lsst::afw::math::Kernel::Pixel PixelT
 
typedef lsst::afw::image::Image< lsst::afw::math::Kernel::PixelImageT
 

Public Member Functions

 MaskedKernelSolution (lsst::afw::math::KernelList const &basisList, bool fitForBackground)
 
virtual ~MaskedKernelSolution ()
 
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)
 
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)
 
void solve ()
 
virtual void solve (Eigen::MatrixXd const &mMat, Eigen::VectorXd const &bVec)
 
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)
 
virtual std::shared_ptr< lsst::afw::math::KernelgetKernel ()
 
virtual std::shared_ptr< lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > > makeKernelImage ()
 
virtual double getBackground ()
 
virtual double getKsum ()
 
virtual std::pair< std::shared_ptr< lsst::afw::math::Kernel >, double > getSolutionPair ()
 
KernelSolvedBy getSolvedBy ()
 
virtual double getConditionNumber (ConditionNumberType conditionType)
 
virtual double getConditionNumber (Eigen::MatrixXd const &mMat, ConditionNumberType conditionType)
 
Eigen::MatrixXd const & getM ()
 
Eigen::VectorXd const & getB ()
 
void printM ()
 
void printB ()
 
void printA ()
 
int getId () const
 

Protected Member Functions

void _setKernel ()
 Set kernel after solution.
 
void _setKernelUncertainty ()
 Not implemented.
 

Protected Attributes

Eigen::MatrixXd _cMat
 K_i x R.
 
Eigen::VectorXd _iVec
 Vectorized I.
 
Eigen::VectorXd _ivVec
 Inverse variance.
 
std::shared_ptr< lsst::afw::math::Kernel_kernel
 Derived single-object convolution kernel.
 
double _background
 Derived differential background estimate.
 
double _kSum
 Derived kernel sum.
 
int _id
 Unique ID for object.
 
Eigen::MatrixXd _mMat
 Derived least squares M matrix.
 
Eigen::VectorXd _bVec
 Derived least squares B vector.
 
Eigen::VectorXd _aVec
 Derived least squares solution matrix.
 
KernelSolvedBy _solvedBy
 Type of algorithm used to make solution.
 
bool _fitForBackground
 Background terms included in fit.
 

Static Protected Attributes

static int _SolutionId = 0
 Unique identifier for solution.
 

Detailed Description

template<typename InputT>
class lsst::ip::diffim::MaskedKernelSolution< InputT >

Definition at line 119 of file KernelSolution.h.

Member Typedef Documentation

◆ ImageT

◆ PixelT

◆ Ptr

Definition at line 121 of file KernelSolution.h.

Member Enumeration Documentation

◆ ConditionNumberType

Enumerator
EIGENVALUE 
SVD 

Definition at line 45 of file KernelSolution.h.

◆ KernelSolvedBy

Enumerator
NONE 
CHOLESKY_LDLT 
CHOLESKY_LLT 
LU 
EIGENVECTOR 

Definition at line 37 of file KernelSolution.h.

Constructor & Destructor Documentation

◆ MaskedKernelSolution()

template<typename InputT>
lsst::ip::diffim::MaskedKernelSolution< InputT >::MaskedKernelSolution ( lsst::afw::math::KernelList const & basisList,
bool fitForBackground )

Definition at line 493 of file KernelSolution.cc.

496 :
498 {};
StaticKernelSolution(lsst::afw::math::KernelList const &basisList, bool fitForBackground)

◆ ~MaskedKernelSolution()

template<typename InputT>
virtual lsst::ip::diffim::MaskedKernelSolution< InputT >::~MaskedKernelSolution ( )
inlinevirtual

Definition at line 125 of file KernelSolution.h.

125{};

Member Function Documentation

◆ _setKernel()

template<typename InputT>
void lsst::ip::diffim::StaticKernelSolution< InputT >::_setKernel ( )
protectedinherited

Set kernel after solution.

Definition at line 423 of file KernelSolution.cc.

423 {
425 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot make solution");
426 }
427
428 unsigned int const nParameters = _aVec.size();
429 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
430 unsigned int const nKernelParameters =
433 throw LSST_EXCEPT(pexExcept::Exception, "Mismatched sizes in kernel solution");
434
435 /* Fill in the kernel results */
437 for (unsigned int idx = 0; idx < nKernelParameters; idx++) {
438 if (std::isnan(_aVec(idx))) {
440 str(boost::format("Unable to determine kernel solution %d (nan)") % idx));
441 }
442 kValues[idx] = _aVec(idx);
443 }
444 _kernel->setKernelParameters(kValues);
445
447 new ImageT(_kernel->getDimensions())
448 );
449 _kSum = _kernel->computeImage(*image, false);
450
451 if (_fitForBackground) {
452 if (std::isnan(_aVec(nParameters-1))) {
454 str(boost::format("Unable to determine background solution %d (nan)") %
455 (nParameters-1)));
456 }
458 }
459 }
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
bool _fitForBackground
Background terms included in fit.
Eigen::VectorXd _aVec
Derived least squares solution matrix.
KernelSolvedBy _solvedBy
Type of algorithm used to make solution.
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > ImageT
double _background
Derived differential background estimate.
std::shared_ptr< lsst::afw::math::Kernel > _kernel
Derived single-object convolution kernel.
T dynamic_pointer_cast(T... args)

◆ _setKernelUncertainty()

template<typename InputT>
void lsst::ip::diffim::StaticKernelSolution< InputT >::_setKernelUncertainty ( )
protectedinherited

Not implemented.

Definition at line 463 of file KernelSolution.cc.

463 {
464 throw LSST_EXCEPT(pexExcept::Exception, "Uncertainty calculation not supported");
465
466 /* Estimate of parameter uncertainties comes from the inverse of the
467 * covariance matrix (noise spectrum).
468 * N.R. 15.4.8 to 15.4.15
469 *
470 * Since this is a linear problem no need to use Fisher matrix
471 * N.R. 15.5.8
472 *
473 * Although I might be able to take advantage of the solution above.
474 * Since this now works and is not the rate limiting step, keep as-is for DC3a.
475 *
476 * Use Cholesky decomposition again.
477 * Cholkesy:
478 * Cov = L L^t
479 * Cov^(-1) = (L L^t)^(-1)
480 * = (L^T)^-1 L^(-1)
481 *
482 * Code would be:
483 *
484 * Eigen::MatrixXd cov = _mMat.transpose() * _mMat;
485 * Eigen::LLT<Eigen::MatrixXd> llt = cov.llt();
486 * Eigen::MatrixXd error2 = llt.matrixL().transpose().inverse()*llt.matrixL().inverse();
487 */
488 }

◆ build()

template<typename InputT>
void lsst::ip::diffim::StaticKernelSolution< InputT >::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 )
virtualinherited

Definition at line 261 of file KernelSolution.cc.

265 {
266
268 if (varStats.getValue(afwMath::MIN) < 0.0) {
270 "Error: variance less than 0.0");
271 }
272 if (varStats.getValue(afwMath::MIN) == 0.0) {
274 "Error: variance equals 0.0, cannot inverse variance weight");
275 }
276
279
280 unsigned int const nKernelParameters = basisList.size();
281 unsigned int const nBackgroundParameters = _fitForBackground ? 1 : 0;
283
285
286 /* Ignore buffers around edge of convolved images :
287 *
288 * If the kernel has width 5, it has center pixel 2. The first good pixel
289 * is the (5-2)=3rd pixel, which is array index 2, and ends up being the
290 * index of the central pixel.
291 *
292 * You also have a buffer of unusable pixels on the other side, numbered
293 * width-center-1. The last good usable pixel is N-width+center+1.
294 *
295 * Example : the kernel is width = 5, center = 2
296 *
297 * ---|---|-c-|---|---|
298 *
299 * the image is width = N
300 * convolve this with the kernel, and you get
301 *
302 * |-x-|-x-|-g-|---|---| ... |---|---|-g-|-x-|-x-|
303 *
304 * g = first/last good pixel
305 * x = bad
306 *
307 * the first good pixel is the array index that has the value "center", 2
308 * the last good pixel has array index N-(5-2)+1
309 * eg. if N = 100, you want to use up to index 97
310 * 100-3+1 = 98, and the loops use i < 98, meaning the last
311 * index you address is 97.
312 */
313
314 /* NOTE - we are accessing particular elements of Eigen arrays using
315 these coordinates, therefore they need to be in LOCAL coordinates.
316 This was written before ndarray unification.
317 */
318 geom::Box2I goodBBox = (*kiter)->shrinkBBox(templateImage.getBBox(afwImage::LOCAL));
319 unsigned int const startCol = goodBBox.getMinX();
320 unsigned int const startRow = goodBBox.getMinY();
321 // endCol/Row is one past the index of the last good col/row
322 unsigned int endCol = goodBBox.getMaxX() + 1;
323 unsigned int endRow = goodBBox.getMaxY() + 1;
324
326
327 /* Eigen representation of input images; only the pixels that are unconvolved in cimage below */
329 startCol,
333 startCol,
338 ).array().inverse().matrix();
339
340 /* Resize into 1-D for later usage */
341 eigenTemplate.resize(eigenTemplate.rows()*eigenTemplate.cols(), 1);
342 eigenScience.resize(eigenScience.rows()*eigenScience.cols(), 1);
343 eigeniVariance.resize(eigeniVariance.rows()*eigeniVariance.cols(), 1);
344
345 /* Holds image convolved with basis function */
347
348 /* Holds eigen representation of image convolved with all basis functions */
350
351 /* Iterators over convolved image list and basis list */
353 /* Create C_i in the formalism of Alard & Lupton */
355 convolutionControl.setDoNormalize(false);
356 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
357 afwMath::convolve(cimage, templateImage, **kiter, convolutionControl); /* cimage stores convolved image */
358
360 startCol,
363 cMat.resize(cMat.size(), 1);
364 *eiter = cMat;
365
366 }
367
368 t.stop();
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);
372
373 /*
374 Load matrix with all values from convolvedEigenList : all images
375 (eigeniVariance, convolvedEigenList) must be the same size
376 */
380 for (unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
381 cMat.col(kidxj) = eiterj->col(0);
382 }
383 /* Treat the last "image" as all 1's to do the background calculation. */
385 cMat.col(nParameters-1).fill(1.);
386
387 _cMat = cMat;
388 _ivVec = eigeniVariance.col(0);
389 _iVec = eigenScience.col(0);
390
391 /* Make these outside of solve() so I can check condition number */
392 _mMat = _cMat.transpose() * (_ivVec.asDiagonal() * _cMat);
393 _bVec = _cMat.transpose() * (_ivVec.asDiagonal() * _iVec);
394 }
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition Log.h:515
Eigen::VectorXd _bVec
Derived least squares B vector.
Eigen::MatrixXd _mMat
Derived least squares M matrix.
Eigen::VectorXd _iVec
Vectorized I.
Eigen::VectorXd _ivVec
Inverse variance.
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)
Definition Statistics.h:361
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.
Eigen::MatrixXd imageToEigenMatrix(lsst::afw::image::Image< PixelT > const &img)
Turns a 2-d Image into a 2-d Eigen Matrix.

◆ buildOrig()

template<typename InputT>
void lsst::ip::diffim::MaskedKernelSolution< InputT >::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 )
virtual

Definition at line 667 of file KernelSolution.cc.

672 {
673
675 if (varStats.getValue(afwMath::MIN) < 0.0) {
677 "Error: variance less than 0.0");
678 }
679 if (varStats.getValue(afwMath::MIN) == 0.0) {
681 "Error: variance equals 0.0, cannot inverse variance weight");
682 }
683
687
688 /* Only BAD pixels marked in this mask */
694 sMask &= bitMask;
695 /* TBD: Need to figure out a way to spread this; currently done in Python */
696
697 unsigned int const nKernelParameters = basisList.size();
698 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
700
701 /* NOTE - we are accessing particular elements of Eigen arrays using
702 these coordinates, therefore they need to be in LOCAL coordinates.
703 This was written before ndarray unification.
704 */
705 /* Ignore known EDGE pixels for speed */
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)",
709 shrunkLocalBBox.getMinX(), shrunkLocalBBox.getMinY(),
710 shrunkLocalBBox.getMaxX(), shrunkLocalBBox.getMaxY());
711
712 /* Subimages are addressed in raw pixel coordinates */
713 unsigned int startCol = shrunkLocalBBox.getMinX();
714 unsigned int startRow = shrunkLocalBBox.getMinY();
715 unsigned int endCol = shrunkLocalBBox.getMaxX();
716 unsigned int endRow = shrunkLocalBBox.getMaxY();
717 /* Needed for Eigen block slicing operation */
718 endCol += 1;
719 endRow += 1;
720
722
723 /* Eigen representation of input images; only the pixels that are unconvolved in cimage below */
725 startCol,
728
730 startCol,
734 startCol,
739 ).array().inverse().matrix();
740
741 /* Resize into 1-D for later usage */
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);
746
747 /* Do the masking, slowly for now... */
751 int nGood = 0;
752 for (int i = 0; i < eMask.rows(); i++) {
753 if (eMask(i, 0) == 0) {
757 nGood += 1;
758 }
759 }
760 /* Can't resize() since all values are lost; use blocks */
761 eigenTemplate = maskedEigenTemplate.block(0, 0, nGood, 1);
762 eigenScience = maskedEigenScience.block(0, 0, nGood, 1);
763 eigeniVariance = maskedEigeniVariance.block(0, 0, nGood, 1);
764
765
766 /* Holds image convolved with basis function */
768
769 /* Holds eigen representation of image convolved with all basis functions */
771
772 /* Iterators over convolved image list and basis list */
774 /* Create C_i in the formalism of Alard & Lupton */
776 convolutionControl.setDoNormalize(false);
777 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
778 afwMath::convolve(cimage, templateImage, **kiter, convolutionControl); /* cimage stores convolved image */
779
781 startCol,
784 cMat.resize(cMat.size(), 1);
785
786 /* Do masking */
788 int nGood = 0;
789 for (int i = 0; i < eMask.rows(); i++) {
790 if (eMask(i, 0) == 0) {
791 maskedcMat(nGood, 0) = cMat(i, 0);
792 nGood += 1;
793 }
794 }
795 cMat = maskedcMat.block(0, 0, nGood, 1);
796 *eiter = cMat;
797 }
798
799 t.stop();
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);
803
804 /*
805 Load matrix with all values from convolvedEigenList : all images
806 (eigeniVariance, convolvedEigenList) must be the same size
807 */
811 for (unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
812 cMat.col(kidxj) = eiterj->col(0);
813 }
814 /* Treat the last "image" as all 1's to do the background calculation. */
815 if (this->_fitForBackground)
816 cMat.col(nParameters-1).fill(1.);
817
818 this->_cMat = cMat;
819 this->_ivVec = eigeniVariance.col(0);
820 this->_iVec = eigenScience.col(0);
821
822 /* Make these outside of solve() so I can check condition number */
823 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
824 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
825
826 }
Eigen::MatrixXi maskToEigenMatrix(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > const &mask)

◆ buildSingleMaskOrig()

template<typename InputT>
void lsst::ip::diffim::MaskedKernelSolution< InputT >::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 )
virtual

Definition at line 831 of file KernelSolution.cc.

836 {
837
839 if (varStats.getValue(afwMath::MIN) < 0.0) {
841 "Error: variance less than 0.0");
842 }
843 if (varStats.getValue(afwMath::MIN) == 0.0) {
845 "Error: variance equals 0.0, cannot inverse variance weight");
846 }
847
850
851 unsigned int const nKernelParameters = basisList.size();
852 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
854
856
857 /*
858 NOTE : If we are using these views in Afw's Image space, we need to
859 make sure and compensate for the XY0 of the image:
860
861 geom::Box2I fullBBox = templateImage.getBBox();
862 int maskStartCol = maskBox.getMinX();
863 int maskStartRow = maskBox.getMinY();
864 int maskEndCol = maskBox.getMaxX();
865 int maskEndRow = maskBox.getMaxY();
866
867
868 If we are going to be doing the slicing in Eigen matrices derived from
869 the images, ignore the XY0.
870
871 geom::Box2I fullBBox = templateImage.getBBox(afwImage::LOCAL);
872
873 int maskStartCol = maskBox.getMinX() - templateImage.getX0();
874 int maskStartRow = maskBox.getMinY() - templateImage.getY0();
875 int maskEndCol = maskBox.getMaxX() - templateImage.getX0();
876 int maskEndRow = maskBox.getMaxY() - templateImage.getY0();
877
878 */
879
880
881 geom::Box2I shrunkBBox = (*kiter)->shrinkBBox(templateImage.getBBox());
882
883 LOGL_DEBUG("TRACE3.ip.diffim.MaskedKernelSolution.build",
884 "Limits of good pixels after convolution: %d,%d -> %d,%d",
885 shrunkBBox.getMinX(), shrunkBBox.getMinY(),
886 shrunkBBox.getMaxX(), shrunkBBox.getMaxY());
887
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();
892
893 /* NOTE: no endCol/endRow += 1 for block slicing, since we are doing the
894 slicing using Afw, not Eigen
895
896 Eigen arrays have index 0,0 in the upper right, while LSST images
897 have 0,0 in the lower left. The y-axis is flipped. When translating
898 Images to Eigen matrices in ipDiffim::imageToEigenMatrix this is
899 accounted for. However, we still need to be aware of this fact if
900 addressing subregions of an Eigen matrix. This is why the slicing is
901 done in Afw, its cleaner.
902 */
903
904
905 /* Inner limits; of mask box */
906 int maskStartCol = maskBox.getMinX();
907 int maskStartRow = maskBox.getMinY();
908 int maskEndCol = maskBox.getMaxX();
909 int maskEndRow = maskBox.getMaxY();
910
911 /*
912
913 |---------------------------|
914 | Kernel Boundary |
915 | |---------------------| |
916 | | Top | |
917 | |......_________......| |
918 | | | | | |
919 | | L | Box | R | |
920 | | | | | |
921 | |......---------......| |
922 | | Bottom | |
923 | |---------------------| |
924 | |
925 |---------------------------|
926
927 4 regions we want to extract from the pixels: top bottom left right
928
929 */
932
935
938
941
942 LOGL_DEBUG("TRACE3.ip.diffim.MaskedKernelSolution.build",
943 "Upper good pixel region: %d,%d -> %d,%d",
944 tBox.getMinX(), tBox.getMinY(), tBox.getMaxX(), tBox.getMaxY());
945 LOGL_DEBUG("TRACE3.ip.diffim.MaskedKernelSolution.build",
946 "Bottom good pixel region: %d,%d -> %d,%d",
947 bBox.getMinX(), bBox.getMinY(), bBox.getMaxX(), bBox.getMaxY());
948 LOGL_DEBUG("TRACE3.ip.diffim.MaskedKernelSolution.build",
949 "Left good pixel region: %d,%d -> %d,%d",
950 lBox.getMinX(), lBox.getMinY(), lBox.getMaxX(), lBox.getMaxY());
951 LOGL_DEBUG("TRACE3.ip.diffim.MaskedKernelSolution.build",
952 "Right good pixel region: %d,%d -> %d,%d",
953 rBox.getMinX(), rBox.getMinY(), rBox.getMaxX(), rBox.getMaxY());
954
956 boxArray.push_back(tBox);
957 boxArray.push_back(bBox);
958 boxArray.push_back(lBox);
959 boxArray.push_back(rBox);
960
961 int totalSize = tBox.getWidth() * tBox.getHeight();
962 totalSize += bBox.getWidth() * bBox.getHeight();
963 totalSize += lBox.getWidth() * lBox.getHeight();
964 totalSize += rBox.getWidth() * rBox.getHeight();
965
969 eigenTemplate.setZero();
970 eigenScience.setZero();
971 eigeniVariance.setZero();
972
974
975 int nTerms = 0;
977 for (; biter != boxArray.end(); ++biter) {
978 int area = (*biter).getWidth() * (*biter).getHeight();
979
983
986 Eigen::MatrixXd eiVarEstimate = imageToEigenMatrix(sVarEstimate).array().inverse().matrix();
987
988 eTemplate.resize(area, 1);
989 eScience.resize(area, 1);
990 eiVarEstimate.resize(area, 1);
991
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);
995
996 nTerms += area;
997 }
998
1000
1003 /* Create C_i in the formalism of Alard & Lupton */
1005 convolutionControl.setDoNormalize(false);
1006 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
1007 afwMath::convolve(cimage, templateImage, **kiter, convolutionControl); /* cimage stores convolved image */
1009 cMat.setZero();
1010
1011 int nTerms = 0;
1013 for (; biter != boxArray.end(); ++biter) {
1014 int area = (*biter).getWidth() * (*biter).getHeight();
1015
1018 esubimage.resize(area, 1);
1019 cMat.block(nTerms, 0, area, 1) = esubimage.block(0, 0, area, 1);
1020
1021 nTerms += area;
1022 }
1023
1024 *eiter = cMat;
1025
1026 }
1027
1028 t.stop();
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);
1032
1033 /*
1034 Load matrix with all values from convolvedEigenList : all images
1035 (eigeniVariance, convolvedEigenList) must be the same size
1036 */
1040 for (unsigned int kidxj = 0; eiterj != eiterE; eiterj++, kidxj++) {
1041 cMat.col(kidxj) = eiterj->col(0);
1042 }
1043 /* Treat the last "image" as all 1's to do the background calculation. */
1044 if (this->_fitForBackground)
1045 cMat.col(nParameters-1).fill(1.);
1046
1047 this->_cMat = cMat;
1048 this->_ivVec = eigeniVariance.col(0);
1049 this->_iVec = eigenScience.col(0);
1050
1051 /* Make these outside of solve() so I can check condition number */
1052 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_cMat;
1053 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * this->_iVec;
1054 }

◆ buildWithMask()

template<typename InputT>
void lsst::ip::diffim::MaskedKernelSolution< InputT >::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

Definition at line 501 of file KernelSolution.cc.

506 {
507
509 if (varStats.getValue(afwMath::MIN) < 0.0) {
511 "Error: variance less than 0.0");
512 }
513 if (varStats.getValue(afwMath::MIN) == 0.0) {
515 "Error: variance equals 0.0, cannot inverse variance weight");
516 }
517
518 /* Full footprint of all input images */
521
525
526 /* Only BAD pixels marked in this mask */
532
533 /* Create a Footprint that contains all the masked pixels set above */
536
537 /* And spread it by the kernel half width */
538 int growPix = (*kiter)->getCtr().getX();
540
541#if 0
543 ptr = maskedFpSetGrown.getFootprints()->begin(),
544 end = maskedFpSetGrown.getFootprints()->end();
545 ptr != end;
546 ++ptr) {
547
549 (**ptr),
551 }
552#endif
553
555 for (auto const & foot : *(maskedFpSetGrown.getFootprints())) {
557 }
558 pixelMask.writeFits("pixelmask.fits");
559 finalMask.writeFits("finalmask.fits");
560
561
564 fullFp->getSpans()->flatten(maskArray, finalMask.getArray(), templateImage.getXY0());
566
569 fullFp->getSpans()->flatten(arrayTemplate, templateImage.getArray(), templateImage.getXY0());
571
574 fullFp->getSpans()->flatten(arrayScience, scienceImage.getArray(), scienceImage.getXY0());
576
579 fullFp->getSpans()->flatten(arrayVariance, varianceEstimate.getArray(), varianceEstimate.getXY0());
581
582 int nGood = 0;
583 for (int i = 0; i < maskEigen.size(); i++) {
584 if (maskEigen(i) == 0.0)
585 nGood += 1;
586 }
587
591 int nUsed = 0;
592 for (int i = 0; i < maskEigen.size(); i++) {
593 if (maskEigen(i) == 0.0) {
597 nUsed += 1;
598 }
599 }
600
601
603
604 unsigned int const nKernelParameters = basisList.size();
605 unsigned int const nBackgroundParameters = this->_fitForBackground ? 1 : 0;
607
608 /* Holds image convolved with basis function */
610
611 /* Holds eigen representation of image convolved with all basis functions */
613
614 /* Iterators over convolved image list and basis list */
616
617 /* Create C_i in the formalism of Alard & Lupton */
619 convolutionControl.setDoNormalize(false);
620 for (kiter = basisList.begin(); kiter != basisList.end(); ++kiter, ++eiter) {
621 afwMath::convolve(cimage, templateImage, **kiter, convolutionControl); /* cimage stores convolved image */
622
625 fullFp->getSpans()->flatten(arrayC, cimage.getArray(), cimage.getXY0());
627
629 int nUsed = 0;
630 for (int i = 0; i < maskEigen.size(); i++) {
631 if (maskEigen(i) == 0.0) {
632 eigenC(nUsed) = eigenC0(i);
633 nUsed += 1;
634 }
635 }
636
637 *eiter = eigenC;
638 }
639 t.stop();
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);
643
644 /* Load matrix with all convolved images */
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);
651 }
652 /* Treat the last "image" as all 1's to do the background calculation. */
653 if (this->_fitForBackground)
654 cMat.col(nParameters-1).fill(1.);
655
656 this->_cMat = cMat;
657 this->_ivVec = eigenVariance.array().inverse().matrix();
658 this->_iVec = eigenScience;
659
660 /* Make these outside of solve() so I can check condition number */
661 this->_mMat = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_cMat);
662 this->_bVec = this->_cMat.transpose() * this->_ivVec.asDiagonal() * (this->_iVec);
663 }

◆ getB()

Eigen::VectorXd const & lsst::ip::diffim::KernelSolution::getB ( )
inlineinherited

Definition at line 65 of file KernelSolution.h.

65{return _bVec;}

◆ getBackground()

template<typename InputT>
double lsst::ip::diffim::StaticKernelSolution< InputT >::getBackground ( )
virtualinherited

Definition at line 235 of file KernelSolution.cc.

235 {
237 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot return background");
238 }
239 return _background;
240 }

◆ getConditionNumber() [1/2]

double lsst::ip::diffim::KernelSolution::getConditionNumber ( ConditionNumberType conditionType)
virtualinherited

Definition at line 94 of file KernelSolution.cc.

94 {
95 return getConditionNumber(_mMat, conditionType);
96 }
virtual double getConditionNumber(ConditionNumberType conditionType)

◆ getConditionNumber() [2/2]

double lsst::ip::diffim::KernelSolution::getConditionNumber ( Eigen::MatrixXd const & mMat,
ConditionNumberType conditionType )
virtualinherited

Definition at line 98 of file KernelSolution.cc.

99 {
100 switch (conditionType) {
101 case EIGENVALUE:
102 {
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);
110 break;
111 }
112 case SVD:
113 {
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);
120 break;
121 }
122 default:
123 {
124 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
125 "Undefined ConditionNumberType : only EIGENVALUE, SVD allowed.");
126 break;
127 }
128 }
129 }

◆ getId()

int lsst::ip::diffim::KernelSolution::getId ( ) const
inlineinherited

Definition at line 69 of file KernelSolution.h.

69{ return _id; }
int _id
Unique ID for object.

◆ getKernel()

template<typename InputT>
std::shared_ptr< lsst::afw::math::Kernel > lsst::ip::diffim::StaticKernelSolution< InputT >::getKernel ( )
virtualinherited

Definition at line 215 of file KernelSolution.cc.

215 {
217 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot return solution");
218 }
219 return _kernel;
220 }

◆ getKsum()

template<typename InputT>
double lsst::ip::diffim::StaticKernelSolution< InputT >::getKsum ( )
virtualinherited

Definition at line 243 of file KernelSolution.cc.

243 {
245 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot return ksum");
246 }
247 return _kSum;
248 }

◆ getM()

Eigen::MatrixXd const & lsst::ip::diffim::KernelSolution::getM ( )
inlineinherited

Definition at line 64 of file KernelSolution.h.

64{return _mMat;}

◆ getSolutionPair()

template<typename InputT>
std::pair< std::shared_ptr< lsst::afw::math::Kernel >, double > lsst::ip::diffim::StaticKernelSolution< InputT >::getSolutionPair ( )
virtualinherited

Definition at line 252 of file KernelSolution.cc.

252 {
254 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot return solution");
255 }
256
258 }
T make_pair(T... args)

◆ getSolvedBy()

KernelSolvedBy lsst::ip::diffim::KernelSolution::getSolvedBy ( )
inlineinherited

Definition at line 60 of file KernelSolution.h.

60{return _solvedBy;}

◆ makeKernelImage()

Definition at line 223 of file KernelSolution.cc.

223 {
225 throw LSST_EXCEPT(pexExcept::Exception, "Kernel not solved; cannot return image");
226 }
229 );
230 (void)_kernel->computeImage(*image, false);
231 return image;
232 }

◆ printA()

void lsst::ip::diffim::KernelSolution::printA ( )
inlineinherited

Definition at line 68 of file KernelSolution.h.

68{std::cout << _aVec << std::endl;}
T endl(T... args)

◆ printB()

void lsst::ip::diffim::KernelSolution::printB ( )
inlineinherited

Definition at line 67 of file KernelSolution.h.

67{std::cout << _bVec << std::endl;}

◆ printM()

void lsst::ip::diffim::KernelSolution::printM ( )
inlineinherited

Definition at line 66 of file KernelSolution.h.

66{std::cout << _mMat << std::endl;}

◆ solve() [1/2]

void lsst::ip::diffim::KernelSolution::solve ( Eigen::MatrixXd const & mMat,
Eigen::VectorXd const & bVec )
virtualinherited

Definition at line 131 of file KernelSolution.cc.

132 {
133
134 if (DEBUG_MATRIX) {
135 std::cout << "M " << std::endl;
136 std::cout << mMat << std::endl;
137 std::cout << "B " << std::endl;
138 std::cout << bVec << std::endl;
139 }
140
141 Eigen::VectorXd aVec = Eigen::VectorXd::Zero(bVec.size());
142
143 boost::timer::cpu_timer t;
144
145 LOGL_DEBUG("TRACE2.ip.diffim.KernelSolution.solve",
146 "Solving for kernel");
147 _solvedBy = LU;
148 Eigen::FullPivLU<Eigen::MatrixXd> lu(mMat);
149 if (lu.isInvertible()) {
150 aVec = lu.solve(bVec);
151 } else {
152 LOGL_DEBUG("TRACE3.ip.diffim.KernelSolution.solve",
153 "Unable to determine kernel via LU");
154 /* LAST RESORT */
155 try {
156
158 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eVecValues(mMat);
159 Eigen::MatrixXd const& rMat = eVecValues.eigenvectors();
160 Eigen::VectorXd eValues = eVecValues.eigenvalues();
161
162 for (int i = 0; i != eValues.rows(); ++i) {
163 if (eValues(i) != 0.0) {
164 eValues(i) = 1.0/eValues(i);
165 }
166 }
167
168 aVec = rMat * eValues.asDiagonal() * rMat.transpose() * bVec;
169 } catch (pexExcept::Exception& e) {
170
171 _solvedBy = NONE;
172 LOGL_DEBUG("TRACE3.ip.diffim.KernelSolution.solve",
173 "Unable to determine kernel via eigen-values");
174
175 throw LSST_EXCEPT(pexExcept::Exception, "Unable to determine kernel solution");
176 }
177 }
178
179 t.stop();
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);
183
184 if (DEBUG_MATRIX) {
185 std::cout << "A " << std::endl;
186 std::cout << aVec << std::endl;
187 }
188
189 _aVec = aVec;
190 }
#define DEBUG_MATRIX
T time(T... args)

◆ solve() [2/2]

template<typename InputT>
void lsst::ip::diffim::StaticKernelSolution< InputT >::solve ( )
virtualinherited

Reimplemented from lsst::ip::diffim::KernelSolution.

Definition at line 397 of file KernelSolution.cc.

397 {
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());
402
403 if (DEBUG_MATRIX) {
404 std::cout << "C" << std::endl;
406 std::cout << "iV" << std::endl;
408 std::cout << "I" << std::endl;
410 }
411
412 try {
414 } catch (pexExcept::Exception &e) {
415 LSST_EXCEPT_ADD(e, "Unable to solve static kernel matrix");
416 throw e;
417 }
418 /* Turn matrices into _kernel and _background */
419 _setKernel();
420 }
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it.
Definition Exception.h:54
void _setKernel()
Set kernel after solution.

Member Data Documentation

◆ _aVec

Eigen::VectorXd lsst::ip::diffim::KernelSolution::_aVec
protectedinherited

Derived least squares solution matrix.

Definition at line 75 of file KernelSolution.h.

◆ _background

template<typename InputT>
double lsst::ip::diffim::StaticKernelSolution< InputT >::_background
protectedinherited

Derived differential background estimate.

Definition at line 110 of file KernelSolution.h.

◆ _bVec

Eigen::VectorXd lsst::ip::diffim::KernelSolution::_bVec
protectedinherited

Derived least squares B vector.

Definition at line 74 of file KernelSolution.h.

◆ _cMat

template<typename InputT>
Eigen::MatrixXd lsst::ip::diffim::StaticKernelSolution< InputT >::_cMat
protectedinherited

K_i x R.

Definition at line 105 of file KernelSolution.h.

◆ _fitForBackground

bool lsst::ip::diffim::KernelSolution::_fitForBackground
protectedinherited

Background terms included in fit.

Definition at line 77 of file KernelSolution.h.

◆ _id

int lsst::ip::diffim::KernelSolution::_id
protectedinherited

Unique ID for object.

Definition at line 72 of file KernelSolution.h.

◆ _iVec

template<typename InputT>
Eigen::VectorXd lsst::ip::diffim::StaticKernelSolution< InputT >::_iVec
protectedinherited

Vectorized I.

Definition at line 106 of file KernelSolution.h.

◆ _ivVec

template<typename InputT>
Eigen::VectorXd lsst::ip::diffim::StaticKernelSolution< InputT >::_ivVec
protectedinherited

Inverse variance.

Definition at line 107 of file KernelSolution.h.

◆ _kernel

Derived single-object convolution kernel.

Definition at line 109 of file KernelSolution.h.

◆ _kSum

template<typename InputT>
double lsst::ip::diffim::StaticKernelSolution< InputT >::_kSum
protectedinherited

Derived kernel sum.

Definition at line 111 of file KernelSolution.h.

◆ _mMat

Eigen::MatrixXd lsst::ip::diffim::KernelSolution::_mMat
protectedinherited

Derived least squares M matrix.

Definition at line 73 of file KernelSolution.h.

◆ _SolutionId

int lsst::ip::diffim::KernelSolution::_SolutionId = 0
staticprotectedinherited

Unique identifier for solution.

Definition at line 78 of file KernelSolution.h.

◆ _solvedBy

KernelSolvedBy lsst::ip::diffim::KernelSolution::_solvedBy
protectedinherited

Type of algorithm used to make solution.

Definition at line 76 of file KernelSolution.h.


The documentation for this class was generated from the following files: