LSST Applications g02d81e74bb+86cf3d8bc9,g180d380827+7a4e862ed4,g2079a07aa2+86d27d4dc4,g2305ad1205+e1ca1c66fa,g29320951ab+012e1474a1,g295015adf3+341ea1ce94,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g33d1c0ed96+0e5473021a,g3a166c0a6a+0e5473021a,g3ddfee87b4+c429d67c83,g48712c4677+f88676dd22,g487adcacf7+27e1e21933,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+b41db86c35,g5a732f18d5+53520f316c,g64a986408d+86cf3d8bc9,g858d7b2824+86cf3d8bc9,g8a8a8dda67+585e252eca,g99cad8db69+84912a7fdc,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,ga8c6da7877+a2b54eae19,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+6681f309db,gc120e1dc64+f0fcc2f6d8,gc28159a63d+0e5473021a,gcf0d15dbbd+c429d67c83,gdaeeff99f8+f9a426f77a,ge6526c86ff+0433e6603d,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gff1a9f87cc+86cf3d8bc9,w.2024.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Static Protected Attributes | List of all members
lsst.ip.diffim.psfMatch.PsfMatchTask Class Reference
Inheritance diagram for lsst.ip.diffim.psfMatch.PsfMatchTask:
lsst.ip.diffim.makeKernel.MakeKernelTask lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask

Public Member Functions

 __init__ (self, *args, **kwargs)
 

Public Attributes

 kConfig
 
 useRegularization
 
 hMat
 

Static Public Attributes

 ConfigClass = PsfMatchConfig
 

Protected Member Functions

 _diagnostic (self, kernelCellSet, spatialSolution, spatialKernel, spatialBg)
 
 _displayDebug (self, kernelCellSet, spatialKernel, spatialBackground)
 
 _createPcaBasis (self, kernelCellSet, nStarPerCell, ps)
 
 _buildCellSet (self, *args)
 
 _solve (self, kernelCellSet, basisList, returnOnExcept=False)
 

Static Protected Attributes

str _DefaultName = "psfMatch"
 

Detailed Description

Base class for Psf Matching; should not be called directly

Notes
-----
PsfMatchTask is a base class that implements the core functionality for matching the
Psfs of two images using a spatially varying Psf-matching `lsst.afw.math.LinearCombinationKernel`.
The Task requires the user to provide an instance of an `lsst.afw.math.SpatialCellSet`,
filled with `lsst.ip.diffim.KernelCandidate` instances, and a list of `lsst.afw.math.Kernels`
of basis shapes that will be used for the decomposition.  If requested, the Task
also performs background matching and returns the differential background model as an
`lsst.afw.math.Kernel.SpatialFunction`.

**Invoking the Task**

As a base class, this Task is not directly invoked.  However, ``run()`` methods that are
implemented on derived classes will make use of the core ``_solve()`` functionality,
which defines a sequence of `lsst.afw.math.CandidateVisitor` classes that iterate
through the KernelCandidates, first building up a per-candidate solution and then
building up a spatial model from the ensemble of candidates.  Sigma clipping is
performed using the mean and standard deviation of all kernel sums (to reject
variable objects), on the per-candidate substamp diffim residuals
(to indicate a bad choice of kernel basis shapes for that particular object),
and on the substamp diffim residuals using the spatial kernel fit (to indicate a bad
choice of spatial kernel order, or poor constraints on the spatial model).  The
``_diagnostic()`` method logs information on the quality of the spatial fit, and also
modifies the Task metadata.

.. list-table:: Quantities set in Metadata
   :header-rows: 1

   * - Parameter
     - Description
   * - ``spatialConditionNum``
     - Condition number of the spatial kernel fit
   * - ``spatialKernelSum``
     - Kernel sum (10^{-0.4 * ``Delta``; zeropoint}) of the spatial Psf-matching kernel
   * - ``ALBasisNGauss``
     - If using sum-of-Gaussian basis, the number of gaussians used
   * - ``ALBasisDegGauss``
     - If using sum-of-Gaussian basis, the deg of spatial variation of the Gaussians
   * - ``ALBasisSigGauss``
     - If using sum-of-Gaussian basis, the widths (sigma) of the Gaussians
   * - ``ALKernelSize``
     - If using sum-of-Gaussian basis, the kernel size
   * - ``NFalsePositivesTotal``
     - Total number of diaSources
   * - ``NFalsePositivesRefAssociated``
     - Number of diaSources that associate with the reference catalog
   * - ``NFalsePositivesRefAssociated``
     - Number of diaSources that associate with the source catalog
   * - ``NFalsePositivesUnassociated``
     - Number of diaSources that are orphans
   * - ``metric_MEAN``
     - Mean value of substamp diffim quality metrics across all KernelCandidates,
       for both the per-candidate (LOCAL) and SPATIAL residuals
   * - ``metric_MEDIAN``
     - Median value of substamp diffim quality metrics across all KernelCandidates,
       for both the per-candidate (LOCAL) and SPATIAL residuals
   * - ``metric_STDEV``
     - Standard deviation of substamp diffim quality metrics across all KernelCandidates,
       for both the per-candidate (LOCAL) and SPATIAL residuals

**Debug variables**

The ``pipetask`` command line interface supports a
flag --debug to import @b debug.py from your PYTHONPATH.  The relevant contents of debug.py
for this Task include:

.. code-block:: py

    import sys
    import lsstDebug
    def DebugInfo(name):
        di = lsstDebug.getInfo(name)
        if name == "lsst.ip.diffim.psfMatch":
            # enable debug output
            di.display = True
            # display mask transparency
            di.maskTransparency = 80
            # show all the candidates and residuals
            di.displayCandidates = True
            # show kernel basis functions
            di.displayKernelBasis = False
            # show kernel realized across the image
            di.displayKernelMosaic = True
            # show coefficients of spatial model
            di.plotKernelSpatialModel = False
            # show fixed and spatial coefficients and coefficient histograms
            di.plotKernelCoefficients = True
            # show the bad candidates (red) along with good (green)
            di.showBadCandidates = True
        return di
    lsstDebug.Info = DebugInfo
    lsstDebug.frame = 1

Note that if you want additional logging info, you may add to your scripts:

.. code-block:: py

    import lsst.utils.logging as logUtils
    logUtils.trace_set_at("lsst.ip.diffim", 4)

Definition at line 542 of file psfMatch.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.ip.diffim.psfMatch.PsfMatchTask.__init__ ( self,
* args,
** kwargs )
Create the psf-matching Task

Parameters
----------
*args
    Arguments to be passed to ``lsst.pipe.base.task.Task.__init__``
**kwargs
    Keyword arguments to be passed to ``lsst.pipe.base.task.Task.__init__``

Notes
-----
The initialization sets the Psf-matching kernel configuration using the value of
self.config.kernel.active.  If the kernel is requested with regularization to moderate
the bias/variance tradeoff, currently only used when a delta function kernel basis
is provided, it creates a regularization matrix stored as member variable
self.hMat.

Reimplemented in lsst.ip.diffim.makeKernel.MakeKernelTask, and lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask.

Definition at line 648 of file psfMatch.py.

648 def __init__(self, *args, **kwargs):
649 """Create the psf-matching Task
650
651 Parameters
652 ----------
653 *args
654 Arguments to be passed to ``lsst.pipe.base.task.Task.__init__``
655 **kwargs
656 Keyword arguments to be passed to ``lsst.pipe.base.task.Task.__init__``
657
658 Notes
659 -----
660 The initialization sets the Psf-matching kernel configuration using the value of
661 self.config.kernel.active. If the kernel is requested with regularization to moderate
662 the bias/variance tradeoff, currently only used when a delta function kernel basis
663 is provided, it creates a regularization matrix stored as member variable
664 self.hMat.
665 """
666 pipeBase.Task.__init__(self, *args, **kwargs)
667 self.kConfig = self.config.kernel.active
668
669 if 'useRegularization' in self.kConfig:
670 self.useRegularization = self.kConfig.useRegularization
671 else:
672 self.useRegularization = False
673
674 if self.useRegularization:
675 self.hMat = diffimLib.makeRegularizationMatrix(pexConfig.makePropertySet(self.kConfig))
676

Member Function Documentation

◆ _buildCellSet()

lsst.ip.diffim.psfMatch.PsfMatchTask._buildCellSet ( self,
* args )
protected
Fill a SpatialCellSet with KernelCandidates for the Psf-matching process;
override in derived classes

Reimplemented in lsst.ip.diffim.makeKernel.MakeKernelTask, and lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask.

Definition at line 888 of file psfMatch.py.

888 def _buildCellSet(self, *args):
889 """Fill a SpatialCellSet with KernelCandidates for the Psf-matching process;
890 override in derived classes"""
891 return
892

◆ _createPcaBasis()

lsst.ip.diffim.psfMatch.PsfMatchTask._createPcaBasis ( self,
kernelCellSet,
nStarPerCell,
ps )
protected
Create Principal Component basis

If a principal component analysis is requested, typically when using a delta function basis,
perform the PCA here and return a new basis list containing the new principal components.

Parameters
----------
kernelCellSet : `lsst.afw.math.SpatialCellSet`
    a SpatialCellSet containing KernelCandidates, from which components are derived
nStarPerCell : `int`
    the number of stars per cell to visit when doing the PCA
ps : `lsst.daf.base.PropertySet`
    input property set controlling the single kernel visitor

Returns
-------
nRejectedPca : `int`
    number of KernelCandidates rejected during PCA loop
spatialBasisList : `list` of `lsst.afw.math.kernel.FixedKernel`
    basis list containing the principal shapes as Kernels

Raises
------
RuntimeError
    If the Eigenvalues sum to zero.

Definition at line 821 of file psfMatch.py.

821 def _createPcaBasis(self, kernelCellSet, nStarPerCell, ps):
822 """Create Principal Component basis
823
824 If a principal component analysis is requested, typically when using a delta function basis,
825 perform the PCA here and return a new basis list containing the new principal components.
826
827 Parameters
828 ----------
829 kernelCellSet : `lsst.afw.math.SpatialCellSet`
830 a SpatialCellSet containing KernelCandidates, from which components are derived
831 nStarPerCell : `int`
832 the number of stars per cell to visit when doing the PCA
833 ps : `lsst.daf.base.PropertySet`
834 input property set controlling the single kernel visitor
835
836 Returns
837 -------
838 nRejectedPca : `int`
839 number of KernelCandidates rejected during PCA loop
840 spatialBasisList : `list` of `lsst.afw.math.kernel.FixedKernel`
841 basis list containing the principal shapes as Kernels
842
843 Raises
844 ------
845 RuntimeError
846 If the Eigenvalues sum to zero.
847 """
848 nComponents = self.kConfig.numPrincipalComponents
849 imagePca = diffimLib.KernelPcaD()
850 importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca)
851 kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell)
852 if self.kConfig.subtractMeanForPca:
853 importStarVisitor.subtractMean()
854 imagePca.analyze()
855
856 eigenValues = imagePca.getEigenValues()
857 pcaBasisList = importStarVisitor.getEigenKernels()
858
859 eSum = np.sum(eigenValues)
860 if eSum == 0.0:
861 raise RuntimeError("Eigenvalues sum to zero")
862 trace_logger = getTraceLogger(self.log.getChild("_solve"), 5)
863 for j in range(len(eigenValues)):
864 trace_logger.debug("Eigenvalue %d : %f (%f)", j, eigenValues[j], eigenValues[j]/eSum)
865
866 nToUse = min(nComponents, len(eigenValues))
867 trimBasisList = []
868 for j in range(nToUse):
869 # Check for NaNs?
870 kimage = afwImage.ImageD(pcaBasisList[j].getDimensions())
871 pcaBasisList[j].computeImage(kimage, False)
872 if not (True in np.isnan(kimage.array)):
873 trimBasisList.append(pcaBasisList[j])
874
875 # Put all the power in the first kernel, which will not vary spatially
876 spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList)
877
878 # New Kernel visitor for this new basis list (no regularization explicitly)
879 singlekvPca = diffimLib.BuildSingleKernelVisitorF(spatialBasisList, ps)
880 singlekvPca.setSkipBuilt(False)
881 kernelCellSet.visitCandidates(singlekvPca, nStarPerCell)
882 singlekvPca.setSkipBuilt(True)
883 nRejectedPca = singlekvPca.getNRejected()
884
885 return nRejectedPca, spatialBasisList
886
int min

◆ _diagnostic()

lsst.ip.diffim.psfMatch.PsfMatchTask._diagnostic ( self,
kernelCellSet,
spatialSolution,
spatialKernel,
spatialBg )
protected
Provide logging diagnostics on quality of spatial kernel fit

Parameters
----------
kernelCellSet : `lsst.afw.math.SpatialCellSet`
    Cellset that contains the KernelCandidates used in the fitting
spatialSolution : `lsst.ip.diffim.SpatialKernelSolution`
    KernelSolution of best-fit
spatialKernel : `lsst.afw.math.LinearCombinationKernel`
    Best-fit spatial Kernel model
spatialBg : `lsst.afw.math.Function2D`
    Best-fit spatial background model

Reimplemented in lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask.

Definition at line 677 of file psfMatch.py.

677 def _diagnostic(self, kernelCellSet, spatialSolution, spatialKernel, spatialBg):
678 """Provide logging diagnostics on quality of spatial kernel fit
679
680 Parameters
681 ----------
682 kernelCellSet : `lsst.afw.math.SpatialCellSet`
683 Cellset that contains the KernelCandidates used in the fitting
684 spatialSolution : `lsst.ip.diffim.SpatialKernelSolution`
685 KernelSolution of best-fit
686 spatialKernel : `lsst.afw.math.LinearCombinationKernel`
687 Best-fit spatial Kernel model
688 spatialBg : `lsst.afw.math.Function2D`
689 Best-fit spatial background model
690 """
691 # What is the final kernel sum
692 kImage = afwImage.ImageD(spatialKernel.getDimensions())
693 kSum = spatialKernel.computeImage(kImage, False)
694 self.log.info("Final spatial kernel sum %.3f", kSum)
695
696 # Look at how well conditioned the matrix is
697 conditionNum = spatialSolution.getConditionNumber(
698 getattr(diffimLib.KernelSolution, self.kConfig.conditionNumberType))
699 self.log.info("Spatial model condition number %.3e", conditionNum)
700
701 if conditionNum < 0.0:
702 self.log.warning("Condition number is negative (%.3e)", conditionNum)
703 if conditionNum > self.kConfig.maxSpatialConditionNumber:
704 self.log.warning("Spatial solution exceeds max condition number (%.3e > %.3e)",
705 conditionNum, self.kConfig.maxSpatialConditionNumber)
706
707 self.metadata["spatialConditionNum"] = conditionNum
708 self.metadata["spatialKernelSum"] = kSum
709
710 # Look at how well the solution is constrained
711 nBasisKernels = spatialKernel.getNBasisKernels()
712 nKernelTerms = spatialKernel.getNSpatialParameters()
713 if nKernelTerms == 0: # order 0
714 nKernelTerms = 1
715
716 # Not fit for
717 nBgTerms = spatialBg.getNParameters()
718 if nBgTerms == 1:
719 if spatialBg.getParameters()[0] == 0.0:
720 nBgTerms = 0
721
722 nGood = 0
723 nBad = 0
724 nTot = 0
725 for cell in kernelCellSet.getCellList():
726 for cand in cell.begin(False): # False = include bad candidates
727 nTot += 1
728 if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
729 nGood += 1
730 if cand.getStatus() == afwMath.SpatialCellCandidate.BAD:
731 nBad += 1
732
733 self.log.info("Doing stats of kernel candidates used in the spatial fit.")
734
735 # Counting statistics
736 if nBad > 2*nGood:
737 self.log.warning("Many more candidates rejected than accepted; %d total, %d rejected, %d used",
738 nTot, nBad, nGood)
739 else:
740 self.log.info("%d candidates total, %d rejected, %d used", nTot, nBad, nGood)
741
742 # Some judgements on the quality of the spatial models
743 if nGood < nKernelTerms:
744 self.log.warning("Spatial kernel model underconstrained; %d candidates, %d terms, %d bases",
745 nGood, nKernelTerms, nBasisKernels)
746 self.log.warning("Consider lowering the spatial order")
747 elif nGood <= 2*nKernelTerms:
748 self.log.warning("Spatial kernel model poorly constrained; %d candidates, %d terms, %d bases",
749 nGood, nKernelTerms, nBasisKernels)
750 self.log.warning("Consider lowering the spatial order")
751 else:
752 self.log.info("Spatial kernel model well constrained; %d candidates, %d terms, %d bases",
753 nGood, nKernelTerms, nBasisKernels)
754
755 if nGood < nBgTerms:
756 self.log.warning("Spatial background model underconstrained; %d candidates, %d terms",
757 nGood, nBgTerms)
758 self.log.warning("Consider lowering the spatial order")
759 elif nGood <= 2*nBgTerms:
760 self.log.warning("Spatial background model poorly constrained; %d candidates, %d terms",
761 nGood, nBgTerms)
762 self.log.warning("Consider lowering the spatial order")
763 else:
764 self.log.info("Spatial background model appears well constrained; %d candidates, %d terms",
765 nGood, nBgTerms)
766

◆ _displayDebug()

lsst.ip.diffim.psfMatch.PsfMatchTask._displayDebug ( self,
kernelCellSet,
spatialKernel,
spatialBackground )
protected
Provide visualization of the inputs and ouputs to the Psf-matching code

Parameters
----------
kernelCellSet : `lsst.afw.math.SpatialCellSet`
    The SpatialCellSet used in determining the matching kernel and background
spatialKernel : `lsst.afw.math.LinearCombinationKernel`
    Spatially varying Psf-matching kernel
spatialBackground : `lsst.afw.math.Function2D`
    Spatially varying background-matching function

Definition at line 767 of file psfMatch.py.

767 def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground):
768 """Provide visualization of the inputs and ouputs to the Psf-matching code
769
770 Parameters
771 ----------
772 kernelCellSet : `lsst.afw.math.SpatialCellSet`
773 The SpatialCellSet used in determining the matching kernel and background
774 spatialKernel : `lsst.afw.math.LinearCombinationKernel`
775 Spatially varying Psf-matching kernel
776 spatialBackground : `lsst.afw.math.Function2D`
777 Spatially varying background-matching function
778 """
779 import lsstDebug
780 displayCandidates = lsstDebug.Info(__name__).displayCandidates
781 displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis
782 displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic
783 plotKernelSpatialModel = lsstDebug.Info(__name__).plotKernelSpatialModel
784 plotKernelCoefficients = lsstDebug.Info(__name__).plotKernelCoefficients
785 showBadCandidates = lsstDebug.Info(__name__).showBadCandidates
786 maskTransparency = lsstDebug.Info(__name__).maskTransparency
787 if not maskTransparency:
788 maskTransparency = 0
789 afwDisplay.setDefaultMaskTransparency(maskTransparency)
790
791 if displayCandidates:
792 diutils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
793 frame=lsstDebug.frame,
794 showBadCandidates=showBadCandidates)
795 lsstDebug.frame += 1
796 diutils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
797 frame=lsstDebug.frame,
798 showBadCandidates=showBadCandidates,
799 kernels=True)
800 lsstDebug.frame += 1
801 diutils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
802 frame=lsstDebug.frame,
803 showBadCandidates=showBadCandidates,
804 resids=True)
805 lsstDebug.frame += 1
806
807 if displayKernelBasis:
808 diutils.showKernelBasis(spatialKernel, frame=lsstDebug.frame)
809 lsstDebug.frame += 1
810
811 if displayKernelMosaic:
812 diutils.showKernelMosaic(kernelCellSet.getBBox(), spatialKernel, frame=lsstDebug.frame)
813 lsstDebug.frame += 1
814
815 if plotKernelSpatialModel:
816 diutils.plotKernelSpatialModel(spatialKernel, kernelCellSet, showBadCandidates=showBadCandidates)
817
818 if plotKernelCoefficients:
819 diutils.plotKernelCoefficients(spatialKernel, kernelCellSet)
820

◆ _solve()

lsst.ip.diffim.psfMatch.PsfMatchTask._solve ( self,
kernelCellSet,
basisList,
returnOnExcept = False )
protected
Solve for the PSF matching kernel

Parameters
----------
kernelCellSet : `lsst.afw.math.SpatialCellSet`
    a SpatialCellSet to use in determining the matching kernel
     (typically as provided by _buildCellSet)
basisList : `list` of `lsst.afw.math.kernel.FixedKernel`
    list of Kernels to be used in the decomposition of the spatially varying kernel
    (typically as provided by makeKernelBasisList)
returnOnExcept : `bool`, optional
    if True then return (None, None) if an error occurs, else raise the exception

Returns
-------
psfMatchingKernel : `lsst.afw.math.LinearCombinationKernel`
    Spatially varying Psf-matching kernel
backgroundModel : `lsst.afw.math.Function2D`
    Spatially varying background-matching function

Raises
------
RuntimeError :
    If unable to determine PSF matching kernel and ``returnOnExcept==False``.

Definition at line 894 of file psfMatch.py.

894 def _solve(self, kernelCellSet, basisList, returnOnExcept=False):
895 """Solve for the PSF matching kernel
896
897 Parameters
898 ----------
899 kernelCellSet : `lsst.afw.math.SpatialCellSet`
900 a SpatialCellSet to use in determining the matching kernel
901 (typically as provided by _buildCellSet)
902 basisList : `list` of `lsst.afw.math.kernel.FixedKernel`
903 list of Kernels to be used in the decomposition of the spatially varying kernel
904 (typically as provided by makeKernelBasisList)
905 returnOnExcept : `bool`, optional
906 if True then return (None, None) if an error occurs, else raise the exception
907
908 Returns
909 -------
910 psfMatchingKernel : `lsst.afw.math.LinearCombinationKernel`
911 Spatially varying Psf-matching kernel
912 backgroundModel : `lsst.afw.math.Function2D`
913 Spatially varying background-matching function
914
915 Raises
916 ------
917 RuntimeError :
918 If unable to determine PSF matching kernel and ``returnOnExcept==False``.
919 """
920
921 import lsstDebug
922 display = lsstDebug.Info(__name__).display
923
924 maxSpatialIterations = self.kConfig.maxSpatialIterations
925 nStarPerCell = self.kConfig.nStarPerCell
926 usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel
927
928 # Visitor for the single kernel fit
929 ps = pexConfig.makePropertySet(self.kConfig)
930 if self.useRegularization:
931 singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, ps, self.hMat)
932 else:
933 singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, ps)
934
935 # Visitor for the kernel sum rejection
936 ksv = diffimLib.KernelSumVisitorF(ps)
937
938 # Main loop
939 trace_loggers = [getTraceLogger(self.log.getChild("_solve"), i) for i in range(5)]
940 t0 = time.time()
941 totalIterations = 0
942 thisIteration = 0
943 while (thisIteration < maxSpatialIterations):
944
945 # Make sure there are no uninitialized candidates as active occupants of Cell
946 nRejectedSkf = -1
947 while (nRejectedSkf != 0):
948 trace_loggers[1].debug("Building single kernels...")
949 kernelCellSet.visitCandidates(singlekv, nStarPerCell, ignoreExceptions=True)
950 nRejectedSkf = singlekv.getNRejected()
951 trace_loggers[1].debug(
952 "Iteration %d, rejected %d candidates due to initial kernel fit",
953 thisIteration, nRejectedSkf
954 )
955
956 # Reject outliers in kernel sum
957 ksv.resetKernelSum()
958 ksv.setMode(diffimLib.KernelSumVisitorF.AGGREGATE)
959 kernelCellSet.visitCandidates(ksv, nStarPerCell, ignoreExceptions=True)
960 ksv.processKsumDistribution()
961 ksv.setMode(diffimLib.KernelSumVisitorF.REJECT)
962 kernelCellSet.visitCandidates(ksv, nStarPerCell, ignoreExceptions=True)
963
964 nRejectedKsum = ksv.getNRejected()
965 trace_loggers[1].debug(
966 "Iteration %d, rejected %d candidates due to kernel sum",
967 thisIteration, nRejectedKsum
968 )
969
970 # Do we jump back to the top without incrementing thisIteration?
971 if nRejectedKsum > 0:
972 totalIterations += 1
973 continue
974
975 # At this stage we can either apply the spatial fit to
976 # the kernels, or we run a PCA, use these as a *new*
977 # basis set with lower dimensionality, and then apply
978 # the spatial fit to these kernels
979
980 if (usePcaForSpatialKernel):
981 trace_loggers[0].debug("Building Pca basis")
982
983 nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, ps)
984 trace_loggers[1].debug(
985 "Iteration %d, rejected %d candidates due to Pca kernel fit",
986 thisIteration, nRejectedPca
987 )
988
989 # We don't want to continue on (yet) with the
990 # spatial modeling, because we have bad objects
991 # contributing to the Pca basis. We basically
992 # need to restart from the beginning of this loop,
993 # since the cell-mates of those objects that were
994 # rejected need their original Kernels built by
995 # singleKernelFitter.
996
997 # Don't count against thisIteration
998 if (nRejectedPca > 0):
999 totalIterations += 1
1000 continue
1001 else:
1002 spatialBasisList = basisList
1003
1004 # We have gotten on to the spatial modeling part
1005 regionBBox = kernelCellSet.getBBox()
1006 spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, ps)
1007 kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
1008 spatialkv.solveLinearEquation()
1009 trace_loggers[2].debug("Spatial kernel built with %d candidates", spatialkv.getNCandidates())
1010 spatialKernel, spatialBackground = spatialkv.getSolutionPair()
1011
1012 # Check the quality of the spatial fit (look at residuals)
1013 assesskv = diffimLib.AssessSpatialKernelVisitorF(spatialKernel, spatialBackground, ps)
1014 kernelCellSet.visitCandidates(assesskv, nStarPerCell)
1015 nRejectedSpatial = assesskv.getNRejected()
1016 nGoodSpatial = assesskv.getNGood()
1017 trace_loggers[1].debug(
1018 "Iteration %d, rejected %d candidates due to spatial kernel fit",
1019 thisIteration, nRejectedSpatial
1020 )
1021 trace_loggers[1].debug("%d candidates used in fit", nGoodSpatial)
1022
1023 # If only nGoodSpatial == 0, might be other candidates in the cells
1024 if nGoodSpatial == 0 and nRejectedSpatial == 0:
1025 raise RuntimeError("No kernel candidates for spatial fit")
1026
1027 if nRejectedSpatial == 0:
1028 # Nothing rejected, finished with spatial fit
1029 break
1030
1031 # Otherwise, iterate on...
1032 thisIteration += 1
1033
1034 # Final fit if above did not converge
1035 if (nRejectedSpatial > 0) and (thisIteration == maxSpatialIterations):
1036 trace_loggers[1].debug("Final spatial fit")
1037 if (usePcaForSpatialKernel):
1038 nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, ps)
1039 regionBBox = kernelCellSet.getBBox()
1040 spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, ps)
1041 kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
1042 spatialkv.solveLinearEquation()
1043 trace_loggers[2].debug("Spatial kernel built with %d candidates", spatialkv.getNCandidates())
1044 spatialKernel, spatialBackground = spatialkv.getSolutionPair()
1045
1046 spatialSolution = spatialkv.getKernelSolution()
1047
1048 t1 = time.time()
1049 trace_loggers[0].debug("Total time to compute the spatial kernel : %.2f s", (t1 - t0))
1050
1051 if display:
1052 self._displayDebug(kernelCellSet, spatialKernel, spatialBackground)
1053
1054 self._diagnostic(kernelCellSet, spatialSolution, spatialKernel, spatialBackground)
1055
1056 return spatialSolution, spatialKernel, spatialBackground
1057
1058

Member Data Documentation

◆ _DefaultName

str lsst.ip.diffim.psfMatch.PsfMatchTask._DefaultName = "psfMatch"
staticprotected

Definition at line 646 of file psfMatch.py.

◆ ConfigClass

lsst.ip.diffim.psfMatch.PsfMatchTask.ConfigClass = PsfMatchConfig
static

Definition at line 645 of file psfMatch.py.

◆ hMat

lsst.ip.diffim.psfMatch.PsfMatchTask.hMat

Definition at line 675 of file psfMatch.py.

◆ kConfig

lsst.ip.diffim.psfMatch.PsfMatchTask.kConfig

Definition at line 667 of file psfMatch.py.

◆ useRegularization

lsst.ip.diffim.psfMatch.PsfMatchTask.useRegularization

Definition at line 670 of file psfMatch.py.


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