def testTwoDisplays(self): """Test that we can do things with two frames""" exp = afwImage.ExposureF(300, 350) for frame in (0, 1): ds9.setMaskTransparency(50, frame=frame) if frame == 1: ds9.setMaskPlaneColor("CROSSTALK", "ignore", frame=frame) ds9.mtv(exp, title="parent", frame=frame) ds9.erase(frame=frame) ds9.dot('o', 205, 180, size=6, ctype=ds9.RED, frame=frame)
def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground): """!Provide visualization of the inputs and ouputs to the Psf-matching code @param kernelCellSet: the SpatialCellSet used in determining the matching kernel and background @param spatialKernel: spatially varying Psf-matching kernel @param spatialBackground: spatially varying background-matching function """ import lsstDebug displayCandidates = lsstDebug.Info(__name__).displayCandidates displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic plotKernelSpatialModel = lsstDebug.Info(__name__).plotKernelSpatialModel showBadCandidates = lsstDebug.Info(__name__).showBadCandidates maskTransparency = lsstDebug.Info(__name__).maskTransparency if not maskTransparency: maskTransparency = 0 ds9.setMaskTransparency(maskTransparency) if displayCandidates: diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground, frame=lsstDebug.frame, showBadCandidates=showBadCandidates) lsstDebug.frame += 1 diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground, frame=lsstDebug.frame, showBadCandidates=showBadCandidates, kernels=True) lsstDebug.frame += 1 diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground, frame=lsstDebug.frame, showBadCandidates=showBadCandidates, resids=True) lsstDebug.frame += 1 if displayKernelBasis: diUtils.showKernelBasis(spatialKernel, frame=lsstDebug.frame) lsstDebug.frame += 1 if displayKernelMosaic: diUtils.showKernelMosaic(kernelCellSet.getBBox(), spatialKernel, frame=lsstDebug.frame) lsstDebug.frame += 1 if plotKernelSpatialModel: diUtils.plotKernelSpatialModel(spatialKernel, kernelCellSet, showBadCandidates=showBadCandidates)
def displayDipoles(self, exposure, sources): """!Display debugging information on the detected dipoles @param exposure Image the dipoles were measured on @param sources The set of diaSources that were measured""" import lsstDebug display = lsstDebug.Info(__name__).display displayDiaSources = lsstDebug.Info(__name__).displayDiaSources maskTransparency = lsstDebug.Info(__name__).maskTransparency if not maskTransparency: maskTransparency = 90 ds9.setMaskTransparency(maskTransparency) ds9.mtv(exposure, frame=lsstDebug.frame) if display and displayDiaSources: with ds9.Buffering(): for source in sources: cenX, cenY = source.get("ipdiffim_DipolePsfFlux_centroid") if np.isinf(cenX) or np.isinf(cenY): cenX, cenY = source.getCentroid() isdipole = source.get("classification.dipole") if isdipole and np.isfinite(isdipole): # Dipole ctype= "green" else: # Not dipole ctype = "red" ds9.dot("o", cenX, cenY, size=2, ctype=ctype, frame=lsstDebug.frame) negCenX = source.get("ip_diffim_PsfDipoleFlux_neg_centroid_x") negCenY = source.get("ip_diffim_PsfDipoleFlux_neg_centroid_y") posCenX = source.get("ip_diffim_PsfDipoleFlux_pos_centroid_x") posCenY = source.get("ip_diffim_PsfDipoleFlux_pos_centroid_y") if (np.isinf(negCenX) or np.isinf(negCenY) or np.isinf(posCenX) or np.isinf(posCenY)): continue ds9.line([(negCenX, negCenY), (posCenX, posCenY)], ctype="yellow", frame=lsstDebug.frame) lsstDebug.frame += 1
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 Raise a RuntimeError if the reference Psf model and science Psf model have different dimensions """ scienceBBox = exposure.getBBox() sciencePsfModel = exposure.getPsf() # The Psf base class does not support getKernel() in general, as there are some Psf # classes for which this is not meaningful. # Many Psfs we use in practice are KernelPsfs, and this algorithm will work fine for them, # but someday it should probably be modified to support arbitrary Psfs. referencePsfModel = measAlg.KernelPsf.swigConvert(referencePsfModel) sciencePsfModel = measAlg.KernelPsf.swigConvert(sciencePsfModel) if referencePsfModel is None or sciencePsfModel is None: raise RuntimeError("ERROR: Psf matching is only implemented for KernelPsfs") if (referencePsfModel.getKernel().getDimensions() != sciencePsfModel.getKernel().getDimensions()): pexLog.Trace(self.log.getName(), 1, "ERROR: Dimensions of reference Psf and science Psf different; exiting") raise RuntimeError, "ERROR: Dimensions of reference Psf and science Psf different; exiting" psfWidth, psfHeight = referencePsfModel.getKernel().getDimensions() maxKernelSize = min(psfWidth, psfHeight) - 1 if maxKernelSize % 2 == 0: maxKernelSize -= 1 if self.kConfig.kernelSize > maxKernelSize: raise ValueError, "Kernel size (%d) too big to match Psfs of size %d; reduce to at least %d" % ( self.kConfig.kernelSize, psfWidth, maxKernelSize) # Infer spatial order of Psf model! # # Infer from the number of spatial parameters. # (O + 1) * (O + 2) / 2 = N # O^2 + 3 * O + 2 * (1 - N) = 0 # # Roots are [-3 +/- sqrt(9 - 8 * (1 - N))] / 2 # nParameters = sciencePsfModel.getKernel().getNSpatialParameters() root = num.sqrt(9 - 8 * (1 - nParameters)) if (root != root // 1): # We know its an integer solution pexLog.Trace(self.log.getName(), 3, "Problem inferring spatial order of image's Psf") else: order = (root - 3) / 2 if (order != order // 1): pexLog.Trace(self.log.getName(), 3, "Problem inferring spatial order of image's Psf") else: pexLog.Trace(self.log.getName(), 2, "Spatial order of Psf = %d; matching kernel order = %d" % ( order, self.kConfig.spatialKernelOrder)) 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 dimenR = referencePsfModel.getKernel().getDimensions() dimenS = sciencePsfModel.getKernel().getDimensions() 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 pexLog.Trace(self.log.getName(), 5, "Creating Psf candidate at %.1f %.1f" % (posX, posY)) # reference kernel image, at location of science subimage kernelImageR = referencePsfModel.computeImage(afwGeom.Point2D(posX, posY)).convertF() kernelMaskR = afwImage.MaskU(dimenR) kernelMaskR.set(0) kernelVarR = afwImage.ImageF(dimenR) kernelVarR.set(1.0) referenceMI = afwImage.MaskedImageF(kernelImageR, kernelMaskR, kernelVarR) # kernel image we are going to convolve kernelImageS = sciencePsfModel.computeImage(afwGeom.Point2D(posX, posY)).convertF() kernelMaskS = afwImage.MaskU(dimenS) kernelMaskS.set(0) kernelVarS = afwImage.ImageF(dimenS) kernelVarS.set(1.0) scienceMI = afwImage.MaskedImageF(kernelImageS, kernelMaskS, kernelVarS) # 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 kernelCellSet
def runDebug(self, exposure, subtractRes, selectSources, kernelSources, diaSources): """@todo Test and update for current debug display and slot names """ import lsstDebug display = lsstDebug.Info(__name__).display showSubtracted = lsstDebug.Info(__name__).showSubtracted showPixelResiduals = lsstDebug.Info(__name__).showPixelResiduals showDiaSources = lsstDebug.Info(__name__).showDiaSources showDipoles = lsstDebug.Info(__name__).showDipoles maskTransparency = lsstDebug.Info(__name__).maskTransparency if display: import lsst.afw.display.ds9 as ds9 if not maskTransparency: maskTransparency = 0 ds9.setMaskTransparency(maskTransparency) if display and showSubtracted: ds9.mtv(subtractRes.subtractedExposure, frame=lsstDebug.frame, title="Subtracted image") mi = subtractRes.subtractedExposure.getMaskedImage() x0, y0 = mi.getX0(), mi.getY0() with ds9.Buffering(): for s in diaSources: x, y = s.getX() - x0, s.getY() - y0 ctype = "red" if s.get("flags.negative") else "yellow" if (s.get("flags.pixel.interpolated.center") or s.get("flags.pixel.saturated.center") or s.get("flags.pixel.cr.center")): ptype = "x" elif (s.get("flags.pixel.interpolated.any") or s.get("flags.pixel.saturated.any") or s.get("flags.pixel.cr.any")): ptype = "+" else: ptype = "o" ds9.dot(ptype, x, y, size=4, frame=lsstDebug.frame, ctype=ctype) lsstDebug.frame += 1 if display and showPixelResiduals and selectSources: nonKernelSources = [] for source in selectSources: if not source in kernelSources: nonKernelSources.append(source) diUtils.plotPixelResiduals(exposure, subtractRes.warpedExposure, subtractRes.subtractedExposure, subtractRes.kernelCellSet, subtractRes.psfMatchingKernel, subtractRes.backgroundModel, nonKernelSources, self.subtract.config.kernel.active.detectionConfig, origVariance=False) diUtils.plotPixelResiduals(exposure, subtractRes.warpedExposure, subtractRes.subtractedExposure, subtractRes.kernelCellSet, subtractRes.psfMatchingKernel, subtractRes.backgroundModel, nonKernelSources, self.subtract.config.kernel.active.detectionConfig, origVariance=True) if display and showDiaSources: flagChecker = SourceFlagChecker(diaSources) isFlagged = [flagChecker(x) for x in diaSources] isDipole = [x.get("classification.dipole") for x in diaSources] diUtils.showDiaSources(diaSources, subtractRes.subtractedExposure, isFlagged, isDipole, frame=lsstDebug.frame) lsstDebug.frame += 1 if display and showDipoles: DipoleAnalysis().displayDipoles(subtractRes.subtractedExposure, diaSources, frame=lsstDebug.frame) lsstDebug.frame += 1
def testMaskPlanes(self): """Test basic image display""" ds9.setMaskTransparency(50) ds9.setMaskPlaneColor("CROSSTALK", "orange")
def runDebug(self, exposure, subtractRes, selectSources, kernelSources, diaSources): """@todo Test and update for current debug display and slot names """ import lsstDebug display = lsstDebug.Info(__name__).display showSubtracted = lsstDebug.Info(__name__).showSubtracted showPixelResiduals = lsstDebug.Info(__name__).showPixelResiduals showDiaSources = lsstDebug.Info(__name__).showDiaSources showDipoles = lsstDebug.Info(__name__).showDipoles maskTransparency = lsstDebug.Info(__name__).maskTransparency if display: import lsst.afw.display.ds9 as ds9 if not maskTransparency: maskTransparency = 0 ds9.setMaskTransparency(maskTransparency) if display and showSubtracted: ds9.mtv(subtractRes.subtractedExposure, frame=lsstDebug.frame, title="Subtracted image") mi = subtractRes.subtractedExposure.getMaskedImage() x0, y0 = mi.getX0(), mi.getY0() with ds9.Buffering(): for s in diaSources: x, y = s.getX() - x0, s.getY() - y0 ctype = "red" if s.get("flags.negative") else "yellow" if (s.get("flags.pixel.interpolated.center") or s.get("flags.pixel.saturated.center") or s.get("flags.pixel.cr.center")): ptype = "x" elif (s.get("flags.pixel.interpolated.any") or s.get("flags.pixel.saturated.any") or s.get("flags.pixel.cr.any")): ptype = "+" else: ptype = "o" ds9.dot(ptype, x, y, size=4, frame=lsstDebug.frame, ctype=ctype) lsstDebug.frame += 1 if display and showPixelResiduals and selectSources: nonKernelSources = [] for source in selectSources: if not source in kernelSources: nonKernelSources.append(source) diUtils.plotPixelResiduals( exposure, subtractRes.warpedExposure, subtractRes.subtractedExposure, subtractRes.kernelCellSet, subtractRes.psfMatchingKernel, subtractRes.backgroundModel, nonKernelSources, self.subtract.config.kernel.active.detectionConfig, origVariance=False) diUtils.plotPixelResiduals( exposure, subtractRes.warpedExposure, subtractRes.subtractedExposure, subtractRes.kernelCellSet, subtractRes.psfMatchingKernel, subtractRes.backgroundModel, nonKernelSources, self.subtract.config.kernel.active.detectionConfig, origVariance=True) if display and showDiaSources: flagChecker = SourceFlagChecker(diaSources) isFlagged = [flagChecker(x) for x in diaSources] isDipole = [x.get("classification.dipole") for x in diaSources] diUtils.showDiaSources(diaSources, subtractRes.subtractedExposure, isFlagged, isDipole, frame=lsstDebug.frame) lsstDebug.frame += 1 if display and showDipoles: DipoleAnalysis().displayDipoles(subtractRes.subtractedExposure, diaSources, frame=lsstDebug.frame) lsstDebug.frame += 1
def subtractExposures(self, templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None, doWarping=True, convolveTemplate=True): """!Register, Psf-match and subtract two Exposures Do the following, in order: - Warp templateExposure to match scienceExposure, if their WCSs do not already match - Determine a PSF matching kernel and differential background model that matches templateExposure to scienceExposure - PSF-match templateExposure to scienceExposure - Compute subtracted exposure (see return values for equation). @param templateExposure: exposure to PSF-match to scienceExposure @param scienceExposure: reference Exposure @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve) @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image @param candidateList: a list of footprints/maskedImages for kernel candidates; if None then source detection is run. - Currently supported: list of Footprints or measAlg.PsfCandidateF @param doWarping: what to do if templateExposure's and scienceExposure's WCSs do not match: - if True then warp templateExposure to match scienceExposure - if False then raise an Exception @param convolveTemplate: convolve the template image or the science image - if True, templateExposure is warped if doWarping, templateExposure is convolved - if False, templateExposure is warped if doWarping, scienceExposure is convolved @return a pipeBase.Struct containing these fields: - subtractedExposure: subtracted Exposure = scienceExposure - (matchedImage + backgroundModel) - matchedImage: templateExposure after warping to match templateExposure (if doWarping true), and convolving with psfMatchingKernel - psfMatchingKernel: PSF matching kernel - backgroundModel: differential background model - kernelCellSet: SpatialCellSet used to determine PSF matching kernel """ results = self.matchExposures(templateExposure=templateExposure, scienceExposure=scienceExposure, templateFwhmPix=templateFwhmPix, scienceFwhmPix=scienceFwhmPix, candidateList=candidateList, doWarping=doWarping, convolveTemplate=convolveTemplate) subtractedExposure = afwImage.ExposureF(scienceExposure, True) if convolveTemplate: subtractedMaskedImage = subtractedExposure.getMaskedImage() subtractedMaskedImage -= results.matchedExposure.getMaskedImage() subtractedMaskedImage -= results.backgroundModel else: subtractedExposure.setMaskedImage( results.warpedExposure.getMaskedImage()) subtractedMaskedImage = subtractedExposure.getMaskedImage() subtractedMaskedImage -= results.matchedExposure.getMaskedImage() subtractedMaskedImage -= results.backgroundModel # Preserve polarity of differences subtractedMaskedImage *= -1 # Place back on native photometric scale subtractedMaskedImage /= results.psfMatchingKernel.computeImage( afwImage.ImageD(results.psfMatchingKernel.getDimensions()), False) import lsstDebug display = lsstDebug.Info(__name__).display displayDiffIm = lsstDebug.Info(__name__).displayDiffIm maskTransparency = lsstDebug.Info(__name__).maskTransparency if not maskTransparency: maskTransparency = 0 if display: ds9.setMaskTransparency(maskTransparency) if display and displayDiffIm: ds9.mtv(templateExposure, frame=lsstDebug.frame, title="Template") lsstDebug.frame += 1 ds9.mtv(results.matchedExposure, frame=lsstDebug.frame, title="Matched template") lsstDebug.frame += 1 ds9.mtv(scienceExposure, frame=lsstDebug.frame, title="Science Image") lsstDebug.frame += 1 ds9.mtv(subtractedExposure, frame=lsstDebug.frame, title="Difference Image") lsstDebug.frame += 1 results.subtractedExposure = subtractedExposure return results
def matchMaskedImages(self, templateMaskedImage, scienceMaskedImage, candidateList, templateFwhmPix=None, scienceFwhmPix=None): """!PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage) Do the following, in order: - Determine a PSF matching kernel and differential background model that matches templateMaskedImage to scienceMaskedImage - Convolve templateMaskedImage by the PSF matching kernel @param templateMaskedImage: masked image to PSF-match to the reference masked image; must be warped to match the reference masked image @param scienceMaskedImage: maskedImage whose PSF is to be matched to @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve) @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image @param candidateList: a list of footprints/maskedImages for kernel candidates; if None then source detection is run. - Currently supported: list of Footprints or measAlg.PsfCandidateF @return a pipeBase.Struct containing these fields: - psfMatchedMaskedImage: the PSF-matched masked image = templateMaskedImage convolved with psfMatchingKernel. This has the same xy0, dimensions and wcs as scienceMaskedImage. - psfMatchingKernel: the PSF matching kernel - backgroundModel: differential background model - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel Raise a RuntimeError if input images have different dimensions """ import lsstDebug display = lsstDebug.Info(__name__).display displayTemplate = lsstDebug.Info(__name__).displayTemplate displaySciIm = lsstDebug.Info(__name__).displaySciIm displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells maskTransparency = lsstDebug.Info(__name__).maskTransparency if not maskTransparency: maskTransparency = 0 if display: ds9.setMaskTransparency(maskTransparency) if not candidateList: raise RuntimeError( "Candidate list must be populated by makeCandidateList") if not self._validateSize(templateMaskedImage, scienceMaskedImage): self.log.error("ERROR: Input images different size") raise RuntimeError("Input images different size") if display and displayTemplate: ds9.mtv(templateMaskedImage, frame=lsstDebug.frame, title="Image to convolve") lsstDebug.frame += 1 if display and displaySciIm: ds9.mtv(scienceMaskedImage, frame=lsstDebug.frame, title="Image to not convolve") lsstDebug.frame += 1 kernelCellSet = self._buildCellSet(templateMaskedImage, scienceMaskedImage, candidateList) if display and displaySpatialCells: diUtils.showKernelSpatialCells(scienceMaskedImage, kernelCellSet, symb="o", ctype=ds9.CYAN, ctypeUnused=ds9.YELLOW, ctypeBad=ds9.RED, size=4, frame=lsstDebug.frame, title="Image to not convolve") lsstDebug.frame += 1 if templateFwhmPix and scienceFwhmPix: self.log.info("Matching Psf FWHM %.2f -> %.2f pix", templateFwhmPix, scienceFwhmPix) if self.kConfig.useBicForKernelBasis: tmpKernelCellSet = self._buildCellSet(templateMaskedImage, scienceMaskedImage, candidateList) nbe = diffimTools.NbasisEvaluator(self.kConfig, templateFwhmPix, scienceFwhmPix) bicDegrees = nbe(tmpKernelCellSet, self.log) basisList = makeKernelBasisList(self.kConfig, templateFwhmPix, scienceFwhmPix, alardDegGauss=bicDegrees[0], metadata=self.metadata) del tmpKernelCellSet else: basisList = makeKernelBasisList(self.kConfig, templateFwhmPix, scienceFwhmPix, metadata=self.metadata) spatialSolution, psfMatchingKernel, backgroundModel = self._solve( kernelCellSet, basisList) psfMatchedMaskedImage = afwImage.MaskedImageF( templateMaskedImage.getBBox()) doNormalize = False afwMath.convolve(psfMatchedMaskedImage, templateMaskedImage, psfMatchingKernel, doNormalize) return pipeBase.Struct( matchedImage=psfMatchedMaskedImage, psfMatchingKernel=psfMatchingKernel, backgroundModel=backgroundModel, kernelCellSet=kernelCellSet, )
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 Raise a RuntimeError if the reference Psf model and science Psf model have different dimensions """ scienceBBox = exposure.getBBox() sciencePsfModel = exposure.getPsf() # The Psf base class does not support getKernel() in general, as there are some Psf # classes for which this is not meaningful. # Many Psfs we use in practice are KernelPsfs, and this algorithm will work fine for them, # but someday it should probably be modified to support arbitrary Psfs. referencePsfModel = measAlg.KernelPsf.swigConvert(referencePsfModel) sciencePsfModel = measAlg.KernelPsf.swigConvert(sciencePsfModel) if referencePsfModel is None or sciencePsfModel is None: raise RuntimeError( "ERROR: Psf matching is only implemented for KernelPsfs") if (referencePsfModel.getKernel().getDimensions() != sciencePsfModel.getKernel().getDimensions()): pexLog.Trace( self.log.getName(), 1, "ERROR: Dimensions of reference Psf and science Psf different; exiting" ) raise RuntimeError, "ERROR: Dimensions of reference Psf and science Psf different; exiting" psfWidth, psfHeight = referencePsfModel.getKernel().getDimensions() maxKernelSize = min(psfWidth, psfHeight) - 1 if maxKernelSize % 2 == 0: maxKernelSize -= 1 if self.kConfig.kernelSize > maxKernelSize: raise ValueError, "Kernel size (%d) too big to match Psfs of size %d; reduce to at least %d" % ( self.kConfig.kernelSize, psfWidth, maxKernelSize) # Infer spatial order of Psf model! # # Infer from the number of spatial parameters. # (O + 1) * (O + 2) / 2 = N # O^2 + 3 * O + 2 * (1 - N) = 0 # # Roots are [-3 +/- sqrt(9 - 8 * (1 - N))] / 2 # nParameters = sciencePsfModel.getKernel().getNSpatialParameters() root = num.sqrt(9 - 8 * (1 - nParameters)) if (root != root // 1): # We know its an integer solution pexLog.Trace(self.log.getName(), 3, "Problem inferring spatial order of image's Psf") else: order = (root - 3) / 2 if (order != order // 1): pexLog.Trace(self.log.getName(), 3, "Problem inferring spatial order of image's Psf") else: pexLog.Trace( self.log.getName(), 2, "Spatial order of Psf = %d; matching kernel order = %d" % (order, self.kConfig.spatialKernelOrder)) 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 dimenR = referencePsfModel.getKernel().getDimensions() dimenS = sciencePsfModel.getKernel().getDimensions() 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 pexLog.Trace( self.log.getName(), 5, "Creating Psf candidate at %.1f %.1f" % (posX, posY)) # reference kernel image, at location of science subimage kernelImageR = referencePsfModel.computeImage( afwGeom.Point2D(posX, posY)).convertF() kernelMaskR = afwImage.MaskU(dimenR) kernelMaskR.set(0) kernelVarR = afwImage.ImageF(dimenR) kernelVarR.set(1.0) referenceMI = afwImage.MaskedImageF(kernelImageR, kernelMaskR, kernelVarR) # kernel image we are going to convolve kernelImageS = sciencePsfModel.computeImage( afwGeom.Point2D(posX, posY)).convertF() kernelMaskS = afwImage.MaskU(dimenS) kernelMaskS.set(0) kernelVarS = afwImage.ImageF(dimenS) kernelVarS.set(1.0) scienceMI = afwImage.MaskedImageF(kernelImageS, kernelMaskS, kernelVarS) # 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 kernelCellSet