def logPairs(obj, pairs, logLevel=Log.DEBUG): """Log ``(name, value)`` pairs to ``obj.metadata`` and ``obj.log`` Parameters ---------- obj : `lsst.pipe.base.Task`-type A `~lsst.pipe.base.Task` or any other object with these two attributes: - ``metadata`` an instance of `lsst.daf.base.PropertyList`` (or other object with ``add(name, value)`` method). - ``log`` an instance of `lsst.log.Log`. pairs : sequence A sequence of ``(name, value)`` pairs, with value typically numeric. logLevel : optional Log level (an `lsst.log` level constant, such as `lsst.log.Log.DEBUG`). """ strList = [] for name, value in pairs: try: # Use LongLong explicitly here in case an early value in the sequence is int-sized obj.metadata.addLongLong(name, value) except TypeError: obj.metadata.add(name, value) strList.append("%s=%s" % (name, value)) log(obj.log.getName(), logLevel, "; ".join(strList))
def testRedir(self): """ Test redirection to stream. """ with TestRedir.StdoutCapture(self.outputFilename): log.configure() dest = io.StringIO() log_utils.enable_notebook_logging(dest) log.log(log.getDefaultLogger().getName(), log.INFO, "This is INFO") log.info(u"This is unicode INFO") log.trace("This is TRACE") log.debug("This is DEBUG") log.warn("This is WARN") log.error("This is ERROR") log.fatal("This is FATAL") log_utils.disable_notebook_logging() log.warn("Format %d %g %s", 3, 2.71828, "foo") self.assertEqual( dest.getvalue(), """root INFO: This is INFO root INFO: This is unicode INFO root WARN: This is WARN root ERROR: This is ERROR root FATAL: This is FATAL """, ) self.check( """ root WARN: Format 3 2.71828 foo """ )
def _createPcaBasis(self, kernelCellSet, nStarPerCell, policy): """!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. @param kernelCellSet: a SpatialCellSet containing KernelCandidates, from which components are derived @param nStarPerCell: the number of stars per cell to visit when doing the PCA @param policy: input policy controlling the single kernel visitor @return - nRejectedPca: number of KernelCandidates rejected during PCA loop - spatialBasisList: basis list containing the principal shapes as Kernels """ nComponents = self.kConfig.numPrincipalComponents imagePca = diffimLib.KernelPcaD() importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca) kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell) if self.kConfig.subtractMeanForPca: importStarVisitor.subtractMean() imagePca.analyze() eigenValues = imagePca.getEigenValues() pcaBasisList = importStarVisitor.getEigenKernels() eSum = np.sum(eigenValues) if eSum == 0.0: raise RuntimeError("Eigenvalues sum to zero") for j in range(len(eigenValues)): log.log("TRACE5." + self.log.getName() + "._solve", log.DEBUG, "Eigenvalue %d : %f (%f)", j, eigenValues[j], eigenValues[j] / eSum) nToUse = min(nComponents, len(eigenValues)) trimBasisList = [] for j in range(nToUse): # Check for NaNs? kimage = afwImage.ImageD(pcaBasisList[j].getDimensions()) pcaBasisList[j].computeImage(kimage, False) if not (True in np.isnan(kimage.getArray())): trimBasisList.append(pcaBasisList[j]) # Put all the power in the first kernel, which will not vary spatially spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList) # New Kernel visitor for this new basis list (no regularization explicitly) singlekvPca = diffimLib.BuildSingleKernelVisitorF( spatialBasisList, policy) singlekvPca.setSkipBuilt(False) kernelCellSet.visitCandidates(singlekvPca, nStarPerCell) singlekvPca.setSkipBuilt(True) nRejectedPca = singlekvPca.getNRejected() return nRejectedPca, spatialBasisList
def logPairs(obj, pairs, logLevel=Log.DEBUG): """!Log (name, value) pairs to obj.metadata and obj.log @param obj a \ref task.Task "Task", or any other object with these two attributes: * metadata an instance of lsst.daf.base.PropertyList (or other object with add(name, value) method) * log an instance of lsst.log.Log @param pairs a collection of (name, value) pairs @param logLevel log level (an lsst.log level constant, such as lsst.log.Log.DEBUG) """ strList = [] for name, value in pairs: try: obj.metadata.add(name, value) except Exception as e: obj.log.fatal( "%s.metadata.add(name=%r, value=%r) failed with error=%s", type(obj).__name__, name, value, e) strList.append("%s=%s" % (name, value)) log(obj.log.getName(), logLevel, "; ".join(strList))
def testBasic(self): """ Test basic log output with default configuration. Since the default threshold is INFO, the DEBUG or TRACE message is not emitted. """ with TestLog.StdoutCapture(self.outputFilename): log.configure() log.log(log.getDefaultLoggerName(), log.INFO, "This is INFO") log.info(u"This is unicode INFO") log.trace("This is TRACE") log.debug("This is DEBUG") log.warn("This is WARN") log.error("This is ERROR") log.fatal("This is FATAL") log.warn("Format %d %g %s", 3, 2.71828, "foo") self.check(""" root INFO: This is INFO root INFO: This is unicode INFO root WARN: This is WARN root ERROR: This is ERROR root FATAL: This is FATAL root WARN: Format 3 2.71828 foo """)
# See the COPYRIGHT file at the top-level directory of this distribution # for details of code ownership. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # from .version import * # generated by sconsUtils unless you tell it not to try: from .runEotestTask import * except ImportError: import lsst.log as log log.log("cp.pipe __init__", log.WARN, "eotest module not found; runEotestTask not available") from .makeBrighterFatterKernel import * from .defects import * from .ptc import * from .cpCombine import * from .measureCrosstalk import * from .linearity import *
def _buildCellSet(self, exposure, referencePsfModel): """!Build a SpatialCellSet for use with the solve method @param exposure: The science exposure that will be convolved; must contain a Psf @param referencePsfModel: Psf model to match to @return -kernelCellSet: a SpatialCellSet to be used by self._solve -referencePsfModel: Validated and/or modified reference model used to populate the SpatialCellSet If the reference Psf model and science Psf model have different dimensions, adjust the referencePsfModel (the model to which the exposure PSF will be matched) to match that of the science Psf. If the science Psf dimensions vary across the image, as is common with a WarpedPsf, either pad or clip (depending on config.padPsf) the dimensions to be constant. """ scienceBBox = exposure.getBBox() sciencePsfModel = exposure.getPsf() dimenR = referencePsfModel.getLocalKernel().getDimensions() psfWidth, psfHeight = dimenR regionSizeX, regionSizeY = scienceBBox.getDimensions() scienceX0, scienceY0 = scienceBBox.getMin() sizeCellX = self.kConfig.sizeCellX sizeCellY = self.kConfig.sizeCellY kernelCellSet = afwMath.SpatialCellSet( afwGeom.Box2I(afwGeom.Point2I(scienceX0, scienceY0), afwGeom.Extent2I(regionSizeX, regionSizeY)), sizeCellX, sizeCellY ) nCellX = regionSizeX//sizeCellX nCellY = regionSizeY//sizeCellY if nCellX == 0 or nCellY == 0: raise ValueError("Exposure dimensions=%s and sizeCell=(%s, %s). Insufficient area to match" % (scienceBBox.getDimensions(), sizeCellX, sizeCellY)) # Survey the PSF dimensions of the Spatial Cell Set # to identify the minimum enclosed or maximum bounding square BBox. widthList = [] heightList = [] for row in range(nCellY): posY = sizeCellY*row + sizeCellY//2 + scienceY0 for col in range(nCellX): posX = sizeCellX*col + sizeCellX//2 + scienceX0 widthS, heightS = sciencePsfModel.computeBBox(afwGeom.Point2D(posX, posY)).getDimensions() widthList.append(widthS) heightList.append(heightS) psfSize = max(max(heightList), max(widthList)) if self.config.doAutoPadPsf: minPsfSize = nextOddInteger(self.kConfig.kernelSize*self.config.autoPadPsfTo) paddingPix = max(0, minPsfSize - psfSize) else: if self.config.padPsfBy % 2 != 0: raise ValueError("Config padPsfBy (%i pixels) must be even number." % self.config.padPsfBy) paddingPix = self.config.padPsfBy if paddingPix > 0: self.log.info("Padding Science PSF from (%s, %s) to (%s, %s) pixels" % (psfSize, psfSize, paddingPix + psfSize, paddingPix + psfSize)) psfSize += paddingPix # Check that PSF is larger than the matching kernel maxKernelSize = psfSize - 1 if maxKernelSize % 2 == 0: maxKernelSize -= 1 if self.kConfig.kernelSize > maxKernelSize: message = """ Kernel size (%d) too big to match Psfs of size %d. Please reconfigure by setting one of the following: 1) kernel size to <= %d 2) doAutoPadPsf=True 3) padPsfBy to >= %s """ % (self.kConfig.kernelSize, psfSize, maxKernelSize, self.kConfig.kernelSize - maxKernelSize) raise ValueError(message) dimenS = afwGeom.Extent2I(psfSize, psfSize) if (dimenR != dimenS): try: referencePsfModel = referencePsfModel.resized(psfSize, psfSize) self.log.info("Adjusted dimensions of reference PSF model from %s to %s" % (dimenR, dimenS)) except Exception as e: self.log.warn("Zero padding or clipping the reference PSF model of type %s and dimensions %s" " to the science Psf dimensions %s because: %s", referencePsfModel.__class__.__name__, dimenR, dimenS, e) dimenR = dimenS policy = pexConfig.makePolicy(self.kConfig) for row in range(nCellY): # place at center of cell posY = sizeCellY * row + sizeCellY//2 + scienceY0 for col in range(nCellX): # place at center of cell posX = sizeCellX * col + sizeCellX//2 + scienceX0 log.log("TRACE4." + self.log.getName(), log.DEBUG, "Creating Psf candidate at %.1f %.1f", posX, posY) # reference kernel image, at location of science subimage referenceMI = self._makePsfMaskedImage(referencePsfModel, posX, posY, dimensions=dimenR) # kernel image we are going to convolve scienceMI = self._makePsfMaskedImage(sciencePsfModel, posX, posY, dimensions=dimenR) # The image to convolve is the science image, to the reference Psf. kc = diffimLib.makeKernelCandidate(posX, posY, scienceMI, referenceMI, policy) kernelCellSet.insertCandidate(kc) import lsstDebug display = lsstDebug.Info(__name__).display displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells maskTransparency = lsstDebug.Info(__name__).maskTransparency if not maskTransparency: maskTransparency = 0 if display: ds9.setMaskTransparency(maskTransparency) if display and displaySpatialCells: diUtils.showKernelSpatialCells(exposure.getMaskedImage(), kernelCellSet, symb="o", ctype=ds9.CYAN, ctypeUnused=ds9.YELLOW, ctypeBad=ds9.RED, size=4, frame=lsstDebug.frame, title="Image to be convolved") lsstDebug.frame += 1 return pipeBase.Struct(kernelCellSet=kernelCellSet, referencePsfModel=referencePsfModel, )
def _solve(self, kernelCellSet, basisList, returnOnExcept=False): """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``. """ import lsstDebug display = lsstDebug.Info(__name__).display maxSpatialIterations = self.kConfig.maxSpatialIterations nStarPerCell = self.kConfig.nStarPerCell usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel # Visitor for the single kernel fit policy = pexConfig.makePolicy(self.kConfig) if self.useRegularization: singlekv = diffimLib.BuildSingleKernelVisitorF( basisList, policy, self.hMat) else: singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy) # Visitor for the kernel sum rejection ksv = diffimLib.KernelSumVisitorF(policy) # Main loop t0 = time.time() try: totalIterations = 0 thisIteration = 0 while (thisIteration < maxSpatialIterations): # Make sure there are no uninitialized candidates as active occupants of Cell nRejectedSkf = -1 while (nRejectedSkf != 0): log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Building single kernels...") kernelCellSet.visitCandidates(singlekv, nStarPerCell) nRejectedSkf = singlekv.getNRejected() log.log( "TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to initial kernel fit", thisIteration, nRejectedSkf) # Reject outliers in kernel sum ksv.resetKernelSum() ksv.setMode(diffimLib.KernelSumVisitorF.AGGREGATE) kernelCellSet.visitCandidates(ksv, nStarPerCell) ksv.processKsumDistribution() ksv.setMode(diffimLib.KernelSumVisitorF.REJECT) kernelCellSet.visitCandidates(ksv, nStarPerCell) nRejectedKsum = ksv.getNRejected() log.log( "TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to kernel sum", thisIteration, nRejectedKsum) # Do we jump back to the top without incrementing thisIteration? if nRejectedKsum > 0: totalIterations += 1 continue # At this stage we can either apply the spatial fit to # the kernels, or we run a PCA, use these as a *new* # basis set with lower dimensionality, and then apply # the spatial fit to these kernels if (usePcaForSpatialKernel): log.log("TRACE0." + self.log.getName() + "._solve", log.DEBUG, "Building Pca basis") nRejectedPca, spatialBasisList = self._createPcaBasis( kernelCellSet, nStarPerCell, policy) log.log( "TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to Pca kernel fit", thisIteration, nRejectedPca) # We don't want to continue on (yet) with the # spatial modeling, because we have bad objects # contributing to the Pca basis. We basically # need to restart from the beginning of this loop, # since the cell-mates of those objects that were # rejected need their original Kernels built by # singleKernelFitter. # Don't count against thisIteration if (nRejectedPca > 0): totalIterations += 1 continue else: spatialBasisList = basisList # We have gotten on to the spatial modeling part regionBBox = kernelCellSet.getBBox() spatialkv = diffimLib.BuildSpatialKernelVisitorF( spatialBasisList, regionBBox, policy) kernelCellSet.visitCandidates(spatialkv, nStarPerCell) spatialkv.solveLinearEquation() log.log("TRACE2." + self.log.getName() + "._solve", log.DEBUG, "Spatial kernel built with %d candidates", spatialkv.getNCandidates()) spatialKernel, spatialBackground = spatialkv.getSolutionPair() # Check the quality of the spatial fit (look at residuals) assesskv = diffimLib.AssessSpatialKernelVisitorF( spatialKernel, spatialBackground, policy) kernelCellSet.visitCandidates(assesskv, nStarPerCell) nRejectedSpatial = assesskv.getNRejected() nGoodSpatial = assesskv.getNGood() log.log( "TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to spatial kernel fit", thisIteration, nRejectedSpatial) log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "%d candidates used in fit", nGoodSpatial) # If only nGoodSpatial == 0, might be other candidates in the cells if nGoodSpatial == 0 and nRejectedSpatial == 0: raise RuntimeError("No kernel candidates for spatial fit") if nRejectedSpatial == 0: # Nothing rejected, finished with spatial fit break # Otherwise, iterate on... thisIteration += 1 # Final fit if above did not converge if (nRejectedSpatial > 0) and (thisIteration == maxSpatialIterations): log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Final spatial fit") if (usePcaForSpatialKernel): nRejectedPca, spatialBasisList = self._createPcaBasis( kernelCellSet, nStarPerCell, policy) regionBBox = kernelCellSet.getBBox() spatialkv = diffimLib.BuildSpatialKernelVisitorF( spatialBasisList, regionBBox, policy) kernelCellSet.visitCandidates(spatialkv, nStarPerCell) spatialkv.solveLinearEquation() log.log("TRACE2." + self.log.getName() + "._solve", log.DEBUG, "Spatial kernel built with %d candidates", spatialkv.getNCandidates()) spatialKernel, spatialBackground = spatialkv.getSolutionPair() spatialSolution = spatialkv.getKernelSolution() except Exception as e: self.log.error("ERROR: Unable to calculate psf matching kernel") log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, str(e)) raise e t1 = time.time() log.log("TRACE0." + self.log.getName() + "._solve", log.DEBUG, "Total time to compute the spatial kernel : %.2f s", (t1 - t0)) if display: self._displayDebug(kernelCellSet, spatialKernel, spatialBackground) self._diagnostic(kernelCellSet, spatialSolution, spatialKernel, spatialBackground) return spatialSolution, spatialKernel, spatialBackground
def _solve(self, kernelCellSet, basisList, returnOnExcept=False): """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``. """ import lsstDebug display = lsstDebug.Info(__name__).display maxSpatialIterations = self.kConfig.maxSpatialIterations nStarPerCell = self.kConfig.nStarPerCell usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel # Visitor for the single kernel fit policy = pexConfig.makePolicy(self.kConfig) if self.useRegularization: singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy, self.hMat) else: singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy) # Visitor for the kernel sum rejection ksv = diffimLib.KernelSumVisitorF(policy) # Main loop t0 = time.time() try: totalIterations = 0 thisIteration = 0 while (thisIteration < maxSpatialIterations): # Make sure there are no uninitialized candidates as active occupants of Cell nRejectedSkf = -1 while (nRejectedSkf != 0): log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Building single kernels...") kernelCellSet.visitCandidates(singlekv, nStarPerCell) nRejectedSkf = singlekv.getNRejected() log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to initial kernel fit", thisIteration, nRejectedSkf) # Reject outliers in kernel sum ksv.resetKernelSum() ksv.setMode(diffimLib.KernelSumVisitorF.AGGREGATE) kernelCellSet.visitCandidates(ksv, nStarPerCell) ksv.processKsumDistribution() ksv.setMode(diffimLib.KernelSumVisitorF.REJECT) kernelCellSet.visitCandidates(ksv, nStarPerCell) nRejectedKsum = ksv.getNRejected() log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to kernel sum", thisIteration, nRejectedKsum) # Do we jump back to the top without incrementing thisIteration? if nRejectedKsum > 0: totalIterations += 1 continue # At this stage we can either apply the spatial fit to # the kernels, or we run a PCA, use these as a *new* # basis set with lower dimensionality, and then apply # the spatial fit to these kernels if (usePcaForSpatialKernel): log.log("TRACE0." + self.log.getName() + "._solve", log.DEBUG, "Building Pca basis") nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, policy) log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to Pca kernel fit", thisIteration, nRejectedPca) # We don't want to continue on (yet) with the # spatial modeling, because we have bad objects # contributing to the Pca basis. We basically # need to restart from the beginning of this loop, # since the cell-mates of those objects that were # rejected need their original Kernels built by # singleKernelFitter. # Don't count against thisIteration if (nRejectedPca > 0): totalIterations += 1 continue else: spatialBasisList = basisList # We have gotten on to the spatial modeling part regionBBox = kernelCellSet.getBBox() spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, policy) kernelCellSet.visitCandidates(spatialkv, nStarPerCell) spatialkv.solveLinearEquation() log.log("TRACE2." + self.log.getName() + "._solve", log.DEBUG, "Spatial kernel built with %d candidates", spatialkv.getNCandidates()) spatialKernel, spatialBackground = spatialkv.getSolutionPair() # Check the quality of the spatial fit (look at residuals) assesskv = diffimLib.AssessSpatialKernelVisitorF(spatialKernel, spatialBackground, policy) kernelCellSet.visitCandidates(assesskv, nStarPerCell) nRejectedSpatial = assesskv.getNRejected() nGoodSpatial = assesskv.getNGood() log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Iteration %d, rejected %d candidates due to spatial kernel fit", thisIteration, nRejectedSpatial) log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "%d candidates used in fit", nGoodSpatial) # If only nGoodSpatial == 0, might be other candidates in the cells if nGoodSpatial == 0 and nRejectedSpatial == 0: raise RuntimeError("No kernel candidates for spatial fit") if nRejectedSpatial == 0: # Nothing rejected, finished with spatial fit break # Otherwise, iterate on... thisIteration += 1 # Final fit if above did not converge if (nRejectedSpatial > 0) and (thisIteration == maxSpatialIterations): log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, "Final spatial fit") if (usePcaForSpatialKernel): nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, policy) regionBBox = kernelCellSet.getBBox() spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, policy) kernelCellSet.visitCandidates(spatialkv, nStarPerCell) spatialkv.solveLinearEquation() log.log("TRACE2." + self.log.getName() + "._solve", log.DEBUG, "Spatial kernel built with %d candidates", spatialkv.getNCandidates()) spatialKernel, spatialBackground = spatialkv.getSolutionPair() spatialSolution = spatialkv.getKernelSolution() except Exception as e: self.log.error("ERROR: Unable to calculate psf matching kernel") log.log("TRACE1." + self.log.getName() + "._solve", log.DEBUG, str(e)) raise e t1 = time.time() log.log("TRACE0." + self.log.getName() + "._solve", log.DEBUG, "Total time to compute the spatial kernel : %.2f s", (t1 - t0)) if display: self._displayDebug(kernelCellSet, spatialKernel, spatialBackground) self._diagnostic(kernelCellSet, spatialSolution, spatialKernel, spatialBackground) return spatialSolution, spatialKernel, spatialBackground
def _createPcaBasis(self, kernelCellSet, nStarPerCell, policy): """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 policy : `lsst.pex.policy.Policy` input policy 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. """ nComponents = self.kConfig.numPrincipalComponents imagePca = diffimLib.KernelPcaD() importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca) kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell) if self.kConfig.subtractMeanForPca: importStarVisitor.subtractMean() imagePca.analyze() eigenValues = imagePca.getEigenValues() pcaBasisList = importStarVisitor.getEigenKernels() eSum = np.sum(eigenValues) if eSum == 0.0: raise RuntimeError("Eigenvalues sum to zero") for j in range(len(eigenValues)): log.log("TRACE5." + self.log.getName() + "._solve", log.DEBUG, "Eigenvalue %d : %f (%f)", j, eigenValues[j], eigenValues[j]/eSum) nToUse = min(nComponents, len(eigenValues)) trimBasisList = [] for j in range(nToUse): # Check for NaNs? kimage = afwImage.ImageD(pcaBasisList[j].getDimensions()) pcaBasisList[j].computeImage(kimage, False) if not (True in np.isnan(kimage.getArray())): trimBasisList.append(pcaBasisList[j]) # Put all the power in the first kernel, which will not vary spatially spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList) # New Kernel visitor for this new basis list (no regularization explicitly) singlekvPca = diffimLib.BuildSingleKernelVisitorF(spatialBasisList, policy) singlekvPca.setSkipBuilt(False) kernelCellSet.visitCandidates(singlekvPca, nStarPerCell) singlekvPca.setSkipBuilt(True) nRejectedPca = singlekvPca.getNRejected() return nRejectedPca, spatialBasisList