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
923
924 maxSpatialIterations = self.kConfig.maxSpatialIterations
925 nStarPerCell = self.kConfig.nStarPerCell
926 usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel
927
928
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
936 ksv = diffimLib.KernelSumVisitorF(ps)
937
938
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
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
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
971 if nRejectedKsum > 0:
972 totalIterations += 1
973 continue
974
975
976
977
978
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
990
991
992
993
994
995
996
997
998 if (nRejectedPca > 0):
999 totalIterations += 1
1000 continue
1001 else:
1002 spatialBasisList = basisList
1003
1004
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
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
1024 if nGoodSpatial == 0 and nRejectedSpatial == 0:
1025 raise RuntimeError("No kernel candidates for spatial fit")
1026
1027 if nRejectedSpatial == 0:
1028
1029 break
1030
1031
1032 thisIteration += 1
1033
1034
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