LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Static Private Attributes | List of all members
lsst.ip.diffim.psfMatch.PsfMatchTask Class Reference

Base class for Psf Matching; should not be called directly. More...

Inheritance diagram for lsst.ip.diffim.psfMatch.PsfMatchTask:

Public Member Functions

def __init__
 Create the psf-matching Task. More...
 

Public Attributes

 kConfig
 
 useRegularization
 
 hMat
 

Static Public Attributes

 ConfigClass = PsfMatchConfig
 

Private Member Functions

def _diagnostic
 Provide logging diagnostics on quality of spatial kernel fit. More...
 
def _displayDebug
 Provide visualization of the inputs and ouputs to the Psf-matching code. More...
 
def _createPcaBasis
 Create Principal Component basis. More...
 
def _buildCellSet
 Fill a SpatialCellSet with KernelCandidates for the Psf-matching process; override in derived classes. More...
 
def _solve
 Solve for the PSF matching kernel. More...
 

Static Private Attributes

string _DefaultName = "psfMatch"
 

Detailed Description

Base class for Psf Matching; should not be called directly.

Contents

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Description

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 an lsst.afw.math.KernelList 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.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Task initialization

Create the psf-matching Task.

Parameters
*argsarguments to be passed to lsst.pipe.base.task.Task.__init__
**kwargskeyword arguments to be passed to lsst.pipe.base.task.Task.__init__

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.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

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.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Configuration parameters

See PsfMatchConfig, PsfMatchConfigAL, PsfMatchConfigDF, and DetectionConfig.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Quantities set in Metadata

spatialConditionNum
Condition number of the spatial kernel fit; via PsfMatchTask._diagnostic
spatialKernelSum

Kernel sum (10^{-0.4 * Δ zeropoint}) of the spatial Psf-matching kernel; via PsfMatchTask._diagnostic

ALBasisNGauss
If using sum-of-Gaussian basis, the number of gaussians used; via generateAlardLuptonBasisList
ALBasisDegGauss
If using sum-of-Gaussian basis, the degree of spatial variation of the Gaussians; via generateAlardLuptonBasisList
ALBasisSigGauss
If using sum-of-Gaussian basis, the widths (sigma) of the Gaussians; via generateAlardLuptonBasisList
ALKernelSize

If using sum-of-Gaussian basis, the kernel size; via generateAlardLuptonBasisList

NFalsePositivesTotal
Total number of diaSources; via KernelCandidateQa.aggregate
NFalsePositivesRefAssociated
Number of diaSources that associate with the reference catalog; via KernelCandidateQa.aggregate
NFalsePositivesRefAssociated
Number of diaSources that associate with the source catalog; via KernelCandidateQa.aggregate
NFalsePositivesUnassociated
Number of diaSources that are orphans; via KernelCandidateQa.aggregate
metric_MEAN
Mean value of substamp diffim quality metrics across all KernelCandidates, for both the per-candidate (LOCAL) and SPATIAL residuals; via KernelCandidateQa.aggregate
metric_MEDIAN
Median value of substamp diffim quality metrics across all KernelCandidates, for both the per-candidate (LOCAL) and SPATIAL residuals; via KernelCandidateQa.aggregate
metric_STDEV
Standard deviation of substamp diffim quality metrics across all KernelCandidates, for both the per-candidate (LOCAL) and SPATIAL residuals; via KernelCandidateQa.aggregate

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Debug variables

The command line task interface supports a flag -d/–debug to import debug.py from your PYTHONPATH. The relevant contents of debug.py for this Task include:

1 import sys
2 import lsstDebug
3 def DebugInfo(name):
4  di = lsstDebug.getInfo(name)
5  if name == "lsst.ip.diffim.psfMatch":
6  di.display = True # enable debug output
7  di.maskTransparency = 80 # ds9 mask transparency
8  di.displayCandidates = True # show all the candidates and residuals
9  di.displayKernelBasis = False # show kernel basis functions
10  di.displayKernelMosaic = True # show kernel realized across the image
11  di.plotKernelSpatialModel = False # show coefficients of spatial model
12  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
13  return di
14 lsstDebug.Info = DebugInfo
15 lsstDebug.frame = 1

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

1 import lsst.pex.logging as pexLog
2 pexLog.Trace_setVerbosity('lsst.ip.diffim', 5)

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Example code

As a base class, there is no example code for PsfMatchTask. However, see ImagePsfMatchTask, SnapPsfMatchTask, and ModelPsfMatchTask.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Definition at line 525 of file psfMatch.py.

Constructor & Destructor Documentation

def lsst.ip.diffim.psfMatch.PsfMatchTask.__init__ (   self,
  args,
  kwargs 
)

Create the psf-matching Task.

Parameters
*argsarguments to be passed to lsst.pipe.base.task.Task.__init__
**kwargskeyword arguments to be passed to lsst.pipe.base.task.Task.__init__

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.

Definition at line 676 of file psfMatch.py.

677  def __init__(self, *args, **kwargs):
678  """!Create the psf-matching Task
679 
680  \param *args arguments to be passed to lsst.pipe.base.task.Task.__init__
681  \param **kwargs keyword arguments to be passed to lsst.pipe.base.task.Task.__init__
682 
683  The initialization sets the Psf-matching kernel configuration using the value of
684  self.config.kernel.active. If the kernel is requested with regularization to moderate
685  the bias/variance tradeoff, currently only used when a delta function kernel basis
686  is provided, it creates a regularization matrix stored as member variable
687  self.hMat.
688  """
689  pipeBase.Task.__init__(self, *args, **kwargs)
690  self.kConfig = self.config.kernel.active
691 
692  #
693  if 'useRegularization' in self.kConfig.keys():
694  self.useRegularization = self.kConfig.useRegularization
695  else:
696  self.useRegularization = False
697 
699  self.hMat = diffimLib.makeRegularizationMatrix(pexConfig.makePolicy(self.kConfig))
def __init__
Create the psf-matching Task.
Definition: psfMatch.py:676

Member Function Documentation

def lsst.ip.diffim.psfMatch.PsfMatchTask._buildCellSet (   self,
  args 
)
private

Fill a SpatialCellSet with KernelCandidates for the Psf-matching process; override in derived classes.

Definition at line 888 of file psfMatch.py.

889  def _buildCellSet(self, *args):
890  """!Fill a SpatialCellSet with KernelCandidates for the Psf-matching process;
891  override in derived classes"""
892  return
def _buildCellSet
Fill a SpatialCellSet with KernelCandidates for the Psf-matching process; override in derived classes...
Definition: psfMatch.py:888
def lsst.ip.diffim.psfMatch.PsfMatchTask._createPcaBasis (   self,
  kernelCellSet,
  nStarPerCell,
  policy 
)
private

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:a SpatialCellSet containing KernelCandidates, from which components are derived
nStarPerCell:the number of stars per cell to visit when doing the PCA
policy:input policy controlling the single kernel visitor
Returns
  • nRejectedPca: number of KernelCandidates rejected during PCA loop
  • spatialBasisList: basis list containing the principal shapes as Kernels

Definition at line 833 of file psfMatch.py.

834  def _createPcaBasis(self, kernelCellSet, nStarPerCell, policy):
835  """!Create Principal Component basis
836 
837  If a principal component analysis is requested, typically when using a delta function basis,
838  perform the PCA here and return a new basis list containing the new principal components.
839 
840  @param kernelCellSet: a SpatialCellSet containing KernelCandidates, from which components are derived
841  @param nStarPerCell: the number of stars per cell to visit when doing the PCA
842  @param policy: input policy controlling the single kernel visitor
843 
844  @return
845  - nRejectedPca: number of KernelCandidates rejected during PCA loop
846  - spatialBasisList: basis list containing the principal shapes as Kernels
847 
848  """
849  nComponents = self.kConfig.numPrincipalComponents
850  imagePca = diffimLib.KernelPcaD()
851  importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca)
852  kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell)
853  if self.kConfig.subtractMeanForPca:
854  importStarVisitor.subtractMean()
855  imagePca.analyze()
856 
857  eigenValues = imagePca.getEigenValues()
858  pcaBasisList = importStarVisitor.getEigenKernels()
859 
860  eSum = num.sum(eigenValues)
861  if eSum == 0.0:
862  raise RuntimeError("Eigenvalues sum to zero")
863  for j in range(len(eigenValues)):
864  pexLog.Trace(self.log.getName()+"._solve", 6,
865  "Eigenvalue %d : %f (%f)" % (j, eigenValues[j], eigenValues[j]/eSum))
866 
867  nToUse = min(nComponents, len(eigenValues))
868  trimBasisList = afwMath.KernelList()
869  for j in range(nToUse):
870  # Check for NaNs?
871  kimage = afwImage.ImageD(pcaBasisList[j].getDimensions())
872  pcaBasisList[j].computeImage(kimage, False)
873  if not (True in num.isnan(kimage.getArray())):
874  trimBasisList.push_back(pcaBasisList[j])
875 
876  # Put all the power in the first kernel, which will not vary spatially
877  spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList)
878 
879  # New Kernel visitor for this new basis list (no regularization explicitly)
880  singlekvPca = diffimLib.BuildSingleKernelVisitorF(spatialBasisList, policy)
881  singlekvPca.setSkipBuilt(False)
882  kernelCellSet.visitCandidates(singlekvPca, nStarPerCell)
883  singlekvPca.setSkipBuilt(True)
884  nRejectedPca = singlekvPca.getNRejected()
885 
886  return nRejectedPca, spatialBasisList
887 
limited backward compatibility to the DC2 run-time trace facilities
Definition: Trace.h:93
def _createPcaBasis
Create Principal Component basis.
Definition: psfMatch.py:833
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
def lsst.ip.diffim.psfMatch.PsfMatchTask._diagnostic (   self,
  kernelCellSet,
  spatialSolution,
  spatialKernel,
  spatialBg 
)
private

Provide logging diagnostics on quality of spatial kernel fit.

Parameters
kernelCellSet:Cellset that contains the KernelCandidates used in the fitting
spatialSolution:KernelSolution of best-fit
spatialKernel:Best-fit spatial Kernel model
spatialBg:Best-fit spatial background model

Definition at line 700 of file psfMatch.py.

701  def _diagnostic(self, kernelCellSet, spatialSolution, spatialKernel, spatialBg):
702  """!Provide logging diagnostics on quality of spatial kernel fit
703 
704  @param kernelCellSet: Cellset that contains the KernelCandidates used in the fitting
705  @param spatialSolution: KernelSolution of best-fit
706  @param spatialKernel: Best-fit spatial Kernel model
707  @param spatialBg: Best-fit spatial background model
708 
709  """
710  # What is the final kernel sum
711  kImage = afwImage.ImageD(spatialKernel.getDimensions())
712  kSum = spatialKernel.computeImage(kImage, False)
713  self.log.info("Final spatial kernel sum %.3f" % (kSum))
714 
715  # Look at how well conditioned the matrix is
716  conditionNum = spatialSolution.getConditionNumber(
717  getattr(diffimLib.KernelSolution, self.kConfig.conditionNumberType))
718  self.log.info("Spatial model condition number %.3e" % (conditionNum))
719 
720  if conditionNum < 0.0:
721  self.log.warn("Condition number is negative (%.3e)" % (conditionNum))
722  if conditionNum > self.kConfig.maxSpatialConditionNumber:
723  self.log.warn("Spatial solution exceeds max condition number (%.3e > %.3e)" % (
724  conditionNum, self.kConfig.maxSpatialConditionNumber))
725 
726  self.metadata.set("spatialConditionNum", conditionNum)
727  self.metadata.set("spatialKernelSum", kSum)
728 
729  # Look at how well the solution is constrained
730  nBasisKernels = spatialKernel.getNBasisKernels()
731  nKernelTerms = spatialKernel.getNSpatialParameters()
732  if nKernelTerms == 0: # order 0
733  nKernelTerms = 1
734 
735  # Not fit for
736  nBgTerms = spatialBg.getNParameters()
737  if nBgTerms == 1:
738  if spatialBg.getParameters()[0] == 0.0:
739  nBgTerms = 0
740 
741  nGood = 0
742  nBad = 0
743  nTot = 0
744  for cell in kernelCellSet.getCellList():
745  for cand in cell.begin(False): # False = include bad candidates
746  cand = diffimLib.cast_KernelCandidateF(cand)
747  nTot += 1
748  if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
749  nGood += 1
750  if cand.getStatus() == afwMath.SpatialCellCandidate.BAD:
751  nBad += 1
752 
753  self.log.info("Doing stats of kernel candidates used in the spatial fit.")
754 
755  # Counting statistics
756  if nBad > 2*nGood:
757  self.log.warn("Many more candidates rejected than accepted; %d total, %d rejected, %d used" % (
758  nTot, nBad, nGood) )
759  else:
760  self.log.info("%d candidates total, %d rejected, %d used" % (nTot, nBad, nGood))
761 
762  # Some judgements on the quality of the spatial models
763  if nGood < nKernelTerms:
764  self.log.warn("Spatial kernel model underconstrained; %d candidates, %d terms, %d bases" % (
765  nGood, nKernelTerms, nBasisKernels))
766  self.log.warn("Consider lowering the spatial order")
767  elif nGood <= 2*nKernelTerms:
768  self.log.warn("Spatial kernel model poorly constrained; %d candidates, %d terms, %d bases" % (
769  nGood, nKernelTerms, nBasisKernels))
770  self.log.warn("Consider lowering the spatial order")
771  else:
772  self.log.info("Spatial kernel model well constrained; %d candidates, %d terms, %d bases" % (
773  nGood, nKernelTerms, nBasisKernels))
774 
775  if nGood < nBgTerms:
776  self.log.warn("Spatial background model underconstrained; %d candidates, %d terms" % (
777  nGood, nBgTerms))
778  self.log.warn("Consider lowering the spatial order")
779  elif nGood <= 2*nBgTerms:
780  self.log.warn("Spatial background model poorly constrained; %d candidates, %d terms" % (
781  nGood, nBgTerms))
782  self.log.warn("Consider lowering the spatial order")
783  else:
784  self.log.info("Spatial background model appears well constrained; %d candidates, %d terms" % (
785  nGood, nBgTerms))
def _diagnostic
Provide logging diagnostics on quality of spatial kernel fit.
Definition: psfMatch.py:700
def lsst.ip.diffim.psfMatch.PsfMatchTask._displayDebug (   self,
  kernelCellSet,
  spatialKernel,
  spatialBackground 
)
private

Provide visualization of the inputs and ouputs to the Psf-matching code.

Parameters
kernelCellSet:the SpatialCellSet used in determining the matching kernel and background
spatialKernel:spatially varying Psf-matching kernel
spatialBackground:spatially varying background-matching function

Definition at line 786 of file psfMatch.py.

787  def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground):
788  """!Provide visualization of the inputs and ouputs to the Psf-matching code
789 
790  @param kernelCellSet: the SpatialCellSet used in determining the matching kernel and background
791  @param spatialKernel: spatially varying Psf-matching kernel
792  @param spatialBackground: spatially varying background-matching function
793 
794  """
795  import lsstDebug
796  displayCandidates = lsstDebug.Info(__name__).displayCandidates
797  displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis
798  displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic
799  plotKernelSpatialModel = lsstDebug.Info(__name__).plotKernelSpatialModel
800  showBadCandidates = lsstDebug.Info(__name__).showBadCandidates
801  maskTransparency = lsstDebug.Info(__name__).maskTransparency
802  if not maskTransparency:
803  maskTransparency = 0
804  ds9.setMaskTransparency(maskTransparency)
805 
806  if displayCandidates:
807  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
808  frame=lsstDebug.frame,
809  showBadCandidates=showBadCandidates)
810  lsstDebug.frame += 1
811  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
812  frame=lsstDebug.frame,
813  showBadCandidates=showBadCandidates,
814  kernels=True)
815  lsstDebug.frame += 1
816  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
817  frame=lsstDebug.frame,
818  showBadCandidates=showBadCandidates,
819  resids=True)
820  lsstDebug.frame += 1
821 
822  if displayKernelBasis:
823  diUtils.showKernelBasis(spatialKernel, frame=lsstDebug.frame)
824  lsstDebug.frame += 1
825 
826  if displayKernelMosaic:
827  diUtils.showKernelMosaic(kernelCellSet.getBBox(), spatialKernel, frame=lsstDebug.frame)
828  lsstDebug.frame += 1
829 
830  if plotKernelSpatialModel:
831  diUtils.plotKernelSpatialModel(spatialKernel, kernelCellSet, showBadCandidates=showBadCandidates)
832 
def _displayDebug
Provide visualization of the inputs and ouputs to the Psf-matching code.
Definition: psfMatch.py:786
def lsst.ip.diffim.psfMatch.PsfMatchTask._solve (   self,
  kernelCellSet,
  basisList,
  returnOnExcept = False 
)
private

Solve for the PSF matching kernel.

Parameters
kernelCellSet:a SpatialCellSet to use in determining the matching kernel (typically as provided by _buildCellSet)
basisList:list of Kernels to be used in the decomposition of the spatially varying kernel (typically as provided by makeKernelBasisList)
returnOnExcept:if True then return (None, None) if an error occurs, else raise the exception
Returns
  • psfMatchingKernel: PSF matching kernel
  • backgroundModel: differential background model

Raise Exception if unable to determine PSF matching kernel and returnOnExcept False

Definition at line 894 of file psfMatch.py.

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

Member Data Documentation

string lsst.ip.diffim.psfMatch.PsfMatchTask._DefaultName = "psfMatch"
staticprivate

Definition at line 674 of file psfMatch.py.

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

Definition at line 673 of file psfMatch.py.

lsst.ip.diffim.psfMatch.PsfMatchTask.hMat

Definition at line 698 of file psfMatch.py.

lsst.ip.diffim.psfMatch.PsfMatchTask.kConfig

Definition at line 689 of file psfMatch.py.

lsst.ip.diffim.psfMatch.PsfMatchTask.useRegularization

Definition at line 693 of file psfMatch.py.


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