def makeSpatialKernel(self, order): basicGaussian1 = afwMath.GaussianFunction2D(2., 2., 0.) basicKernel1 = afwMath.AnalyticKernel(self.ksize, self.ksize, basicGaussian1) basicGaussian2 = afwMath.GaussianFunction2D(5., 3., 0.5 * num.pi) basicKernel2 = afwMath.AnalyticKernel(self.ksize, self.ksize, basicGaussian2) basisList = afwMath.KernelList() basisList.append(basicKernel1) basisList.append(basicKernel2) basisList = afwMath.KernelList( ipDiffim.renormalizeKernelList(basisList)) spatialKernelFunction = afwMath.PolynomialFunction2D(order) spatialKernel = afwMath.LinearCombinationKernel( basisList, spatialKernelFunction) kCoeffs = [ [ 0.0 for x in range(1, spatialKernelFunction.getNParameters() + 1) ], [ 0.01 * x for x in range(1, spatialKernelFunction.getNParameters() + 1) ] ] kCoeffs[0][ 0] = 1.0 # it does not vary spatially; constant across image spatialKernel.setSpatialParameters(kCoeffs) return spatialKernel
def _computeVaryingPsf(self): """Compute a varying PSF as a linear combination of PCA (== Karhunen-Loeve) basis functions We simply desire a PSF that is not constant across the image, so the precise choice of parameters (e.g., sigmas, setSpatialParameters) are not crucial. """ kernelSize = 31 sigma1 = 1.75 sigma2 = 2.0*sigma1 basisKernelList = afwMath.KernelList() for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel(kernelSize, kernelSize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5E-2, 0.2E-2]]) exactPsf = measAlg.PcaPsf(exactKernel) return exactPsf
def testLinearCombinationKernelAnalytic(self): """Test LinearCombinationKernel using analytic basis kernels. The basis kernels are mutable so that we can verify that the LinearCombinationKernel has private copies of the basis kernels. """ kWidth = 5 kHeight = 8 # create list of kernels basisImArrList = [] basisKernelList = afwMath.KernelList() for basisKernelParams in [(1.2, 0.3, 1.570796), (1.0, 0.2, 0.0)]: basisKernelFunction = afwMath.GaussianFunction2D( *basisKernelParams) basisKernel = afwMath.AnalyticKernel(kWidth, kHeight, basisKernelFunction) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray()) basisKernelList.append(basisKernel) kParams = [0.0] * len(basisKernelList) kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams) self.assertTrue(not kernel.isDeltaFunctionBasis()) self.basicTests(kernel, len(kParams)) # make sure the linear combination kernel has private copies of its basis kernels # by altering the local basis kernels and making sure the new images do NOT match modBasisImArrList = [] for basisKernel in basisKernelList: basisKernel.setKernelParameters((0.4, 0.5, 0.6)) modBasisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(modBasisImage, True) modBasisImArrList.append(modBasisImage.getArray()) for ii in range(len(basisKernelList)): kParams = [0.0] * len(basisKernelList) kParams[ii] = 1.0 kernel.setKernelParameters(kParams) kIm = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kIm, True) kImArr = kIm.getArray() if not np.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii)) if np.allclose(kImArr, modBasisImArrList[ii]): self.fail("%s = %s == %s for *modified* %s'th basis kernel" % (kernel.__class__.__name__, kImArr, modBasisImArrList[ii], ii)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False)
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 = num.sum(eigenValues) if eSum == 0.0: raise RuntimeError("Eigenvalues sum to zero") for j in range(len(eigenValues)): pexLog.Trace( self.log.getName() + "._solve", 6, "Eigenvalue %d : %f (%f)" % (j, eigenValues[j], eigenValues[j] / eSum)) nToUse = min(nComponents, len(eigenValues)) trimBasisList = afwMath.KernelList() for j in range(nToUse): # Check for NaNs? kimage = afwImage.ImageD(pcaBasisList[j].getDimensions()) pcaBasisList[j].computeImage(kimage, False) if not (True in num.isnan(kimage.getArray())): trimBasisList.push_back(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 makeDeltaFunctionKernelList(kWidth, kHeight): """Create a list of delta function kernels This is useful for constructing a LinearCombinationKernel. """ kVec = afwMath.KernelList() for activeCol in range(kWidth): for activeRow in range(kHeight): kVec.append( afwMath.DeltaFunctionKernel( kWidth, kHeight, afwGeom.Point2I(activeCol, activeRow))) return kVec
def testLinearCombinationKernel(self): """Test LinearCombinationKernel using a set of delta basis functions """ kWidth = 3 kHeight = 2 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation( os.path.join(testPath, "data", "kernel5.boost")) persistence = dafPersist.Persistence.getPersistence(pol) # create list of kernels basisImArrList = [] kVec = afwMath.KernelList() for row in range(kHeight): for col in range(kWidth): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(col, row)) basisImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray().transpose().copy()) kVec.append(kernel) kParams = [0.0] * len(kVec) k = afwMath.LinearCombinationKernel(kVec, kParams) for ii in range(len(kVec)): kParams = [0.0] * len(kVec) kParams[ii] = 1.0 k.setKernelParameters(kParams) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("LinearCombinationKernel", storageList2, additionalData) k2 = afwMath.LinearCombinationKernel.swigConvert(x) self.kernelCheck(k, k2) kIm = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kIm, True) kImArr = kIm.getArray().transpose() if not np.allclose(kImArr, basisImArrList[ii]): self.fail( "%s = %s != %s for the %s'th basis kernel" % (k2.__class__.__name__, kImArr, basisImArrList[ii], ii))
def testRejection(self): # we need to construct a candidate whose shape does not # match the underlying basis # # so lets just make a kernel list with all the power in # the center, but the candidate requires some off center # power kc1 = self.makeCandidate(1, 0.0, 0.0) kc2 = self.makeCandidate(2, 0.0, 0.0) kc3 = self.makeCandidate(3, 0.0, 0.0) bskv1 = ipDiffim.BuildSingleKernelVisitorF(self.kList, self.policy) bskv1.processCandidate(kc1) bskv1.processCandidate(kc2) bskv1.processCandidate(kc3) imagePca = ipDiffim.KernelPcaD() kpv = ipDiffim.KernelPcaVisitorF(imagePca) kpv.processCandidate(kc1) kpv.processCandidate(kc2) kpv.processCandidate(kc3) kpv.subtractMean() imagePca.analyze() eigenKernels = afwMath.KernelList() eigenKernels.push_back(kpv.getEigenKernels()[0]) self.assertEqual(len(eigenKernels), 1) # bogus candidate mi1 = afwImage.MaskedImageF(afwGeom.Extent2I(self.size, self.size)) mi1.getVariance().set(0.1) mi1.set(self.size//2, self.size//2, (1, 0x0, 1)) mi2 = afwImage.MaskedImageF(afwGeom.Extent2I(self.size, self.size)) mi2.getVariance().set(0.1) # make it high enough to make the mean resids large mi2.set(self.size//3, self.size//3, (self.size**2, 0x0, 1)) kc4 = ipDiffim.makeKernelCandidate(0, 0, mi1, mi2, self.policy) self.assertEqual(kc4.getStatus(), afwMath.SpatialCellCandidate.UNKNOWN) # process with eigenKernels bskv2 = ipDiffim.BuildSingleKernelVisitorF(eigenKernels, self.policy) bskv2.setSkipBuilt(False) bskv2.processCandidate(kc1) bskv2.processCandidate(kc2) bskv2.processCandidate(kc3) bskv2.processCandidate(kc4) self.assertEqual(bskv2.getNProcessed(), 4) self.assertEqual(bskv2.getNRejected(), 1) self.assertEqual(kc1.getStatus(), afwMath.SpatialCellCandidate.GOOD) self.assertEqual(kc2.getStatus(), afwMath.SpatialCellCandidate.GOOD) self.assertEqual(kc3.getStatus(), afwMath.SpatialCellCandidate.GOOD) self.assertEqual(kc4.getStatus(), afwMath.SpatialCellCandidate.BAD)
def makeGaussianKernelList(kWidth, kHeight, gaussParamsList): """Create a list of gaussian kernels. This is useful for constructing a LinearCombinationKernel. Inputs: - kWidth, kHeight: width and height of kernel - gaussParamsList: a list of parameters for GaussianFunction2D (each a 3-tuple of floats) """ kVec = afwMath.KernelList() for majorSigma, minorSigma, angle in gaussParamsList: kFunc = afwMath.GaussianFunction2D(majorSigma, minorSigma, angle) kVec.append(afwMath.AnalyticKernel(kWidth, kHeight, kFunc)) return kVec
def testTicket873(self): """Demonstrate ticket 873: convolution of a MaskedImage with a spatially varying LinearCombinationKernel of basis kernels with low covariance gives incorrect variance. """ # create spatial model sFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, -0.5/self.width, -0.5/self.height), (0.0, 1.0/self.width, 0.0/self.height), (0.0, 0.0/self.width, 1.0/self.height), ) # create three kernels with some non-overlapping pixels # (non-zero pixels in one kernel vs. zero pixels in other kernels); # note: the extreme example of this is delta function kernels, but this is less extreme basisKernelList = afwMath.KernelList() kImArr = numpy.zeros([5, 5], dtype=float) kImArr[1:4, 1:4] = 0.5 kImArr[2, 2] = 1.0 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kImArr[:, :] = 0.0 kImArr[0:2, 0:2] = 0.125 kImArr[3:5, 3:5] = 0.125 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kImArr[:, :] = 0.0 kImArr[0:2, 3:5] = 0.125 kImArr[3:5, 0:2] = 0.125 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 3.0e-3, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr="Spatially varying LinearCombinationKernel of basis " "kernels with low covariance, using %s" % ( methodStr,), maxInterpDist=maxInterpDist, rtol=rtol)
def getDeltaLinearCombinationKernel(kSize, imSize, spOrder): """Return a LinearCombinationKernel of delta functions @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ kernelList = afwMath.KernelList() for ctrX in range(kSize): for ctrY in range(kSize): kernelList.append(afwMath.DeltaFunctionKernel(kSize, kSize, afwGeom.Point2I(ctrX, ctrY))) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc) spParams = getSpatialParameters(len(kernelList), polyFunc) kernel.setSpatialParameters(spParams); return kernel
def testBad(self): ti = afwImage.MaskedImageF(afwGeom.Extent2I(100, 100)) ti.getVariance().set(0.1) ti.set(50, 50, (1., 0x0, 1.)) sKernel = self.makeSpatialKernel(2) si = afwImage.MaskedImageF(ti.getDimensions()) afwMath.convolve(si, ti, sKernel, True) bbox = afwGeom.Box2I(afwGeom.Point2I(25, 25), afwGeom.Point2I(75, 75)) si = afwImage.MaskedImageF(si, bbox, afwImage.LOCAL) ti = afwImage.MaskedImageF(ti, bbox, afwImage.LOCAL) kc = ipDiffim.KernelCandidateF(50., 50., ti, si, self.policy) badGaussian = afwMath.GaussianFunction2D(1., 1., 0.) badKernel = afwMath.AnalyticKernel(self.ksize, self.ksize, badGaussian) basisList = afwMath.KernelList() basisList.append(badKernel) badSpatialKernelFunction = afwMath.PolynomialFunction2D(0) badSpatialKernel = afwMath.LinearCombinationKernel( basisList, badSpatialKernelFunction) badSpatialKernel.setSpatialParameters([[ 1, ]]) sBg = afwMath.PolynomialFunction2D(1) bgCoeffs = [10., 10., 10.] sBg.setParameters(bgCoeffs) # must be initialized bskv = ipDiffim.BuildSingleKernelVisitorF(self.kList, self.policy) bskv.processCandidate(kc) self.assertEqual(kc.isInitialized(), True) askv = ipDiffim.AssessSpatialKernelVisitorF(badSpatialKernel, sBg, self.policy) askv.processCandidate(kc) self.assertEqual(askv.getNProcessed(), 1) self.assertEqual(askv.getNRejected(), 1) self.assertEqual(kc.getStatus(), afwMath.SpatialCellCandidate.BAD)
def testRenormalize(self): # inputs gauss1 = afwMath.GaussianFunction2D(2, 2) gauss2 = afwMath.GaussianFunction2D(3, 4) gauss3 = afwMath.GaussianFunction2D(0.2, 0.25) gaussKernel1 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss1) gaussKernel2 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss2) gaussKernel3 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss3) kimage1 = afwImage.ImageD(gaussKernel1.getDimensions()) ksum1 = gaussKernel1.computeImage(kimage1, False) kimage2 = afwImage.ImageD(gaussKernel2.getDimensions()) ksum2 = gaussKernel2.computeImage(kimage2, False) kimage3 = afwImage.ImageD(gaussKernel3.getDimensions()) ksum3 = gaussKernel3.computeImage(kimage3, False) self.assertTrue(ksum1 != 1.) self.assertTrue(ksum2 != 1.) self.assertTrue(ksum3 != 1.) # no constraints on first kernels norm self.assertTrue(num.sum(num.ravel(kimage2.getArray())**2 ) != 1.) self.assertTrue(num.sum(num.ravel(kimage3.getArray())**2 ) != 1.) basisListIn = afwMath.KernelList() basisListIn.push_back(gaussKernel1) basisListIn.push_back(gaussKernel2) basisListIn.push_back(gaussKernel3) # outputs basisListOut = ipDiffim.renormalizeKernelList(basisListIn) gaussKernel1 = basisListOut[0] gaussKernel2 = basisListOut[1] gaussKernel3 = basisListOut[2] ksum1 = gaussKernel1.computeImage(kimage1, False) ksum2 = gaussKernel2.computeImage(kimage2, False) ksum3 = gaussKernel3.computeImage(kimage3, False) self.assertAlmostEqual(ksum1, 1.) self.assertAlmostEqual(ksum2, 0.) self.assertAlmostEqual(ksum3, 0.) # no constraints on first kernels norm self.assertAlmostEqual(num.sum(num.ravel(kimage2.getArray())**2 ), 1.) self.assertAlmostEqual(num.sum(num.ravel(kimage3.getArray())**2 ), 1.)
def testComputeImageRaise(self): """Test Kernel.computeImage raises OverflowException iff doNormalize True and kernel sum exactly 0 """ kWidth = 4 kHeight = 3 polyFunc1 = afwMath.PolynomialFunction1D(0) polyFunc2 = afwMath.PolynomialFunction2D(0) analKernel = afwMath.AnalyticKernel(kWidth, kHeight, polyFunc2) kImage = afwImage.ImageD(analKernel.getDimensions()) for coeff in (-1, -1e-99, 0, 1e99, 1): analKernel.setKernelParameters([coeff]) analKernel.computeImage(kImage, False) fixedKernel = afwMath.FixedKernel(kImage) sepKernel = afwMath.SeparableKernel(kWidth, kHeight, polyFunc1, polyFunc1) sepKernel.setKernelParameters([coeff, coeff]) kernelList = afwMath.KernelList() kernelList.append(analKernel) lcKernel = afwMath.LinearCombinationKernel(kernelList, [1]) self.assert_(not lcKernel.isDeltaFunctionBasis()) doRaise = (coeff == 0) self.basicTestComputeImageRaise(analKernel, doRaise, "AnalyticKernel") self.basicTestComputeImageRaise(fixedKernel, doRaise, "FixedKernel") self.basicTestComputeImageRaise(sepKernel, doRaise, "SeparableKernel") self.basicTestComputeImageRaise(lcKernel, doRaise, "LinearCombinationKernel") lcKernel.setKernelParameters([0]) self.basicTestComputeImageRaise(lcKernel, True, "LinearCombinationKernel")
def getGaussianLinearCombinationKernel(kSize, imSize, spOrder): """Return a LinearCombinationKernel with 5 bases, each a Gaussian @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ kernelList = afwMath.KernelList() for fwhmX, fwhmY, angle in ( (2.0, 2.0, 0.0), (0.5, 4.0, 0.0), (0.5, 4.0, math.pi / 4.0), (0.5, 4.0, math.pi / 2.0), (4.0, 4.0, 0.0), ): gaussFunc = afwMath.GaussianFunction2D(fwhmX, fwhmY, angle) kernelList.append(afwMath.AnalyticKernel(kSize, kSize, gaussFunc)) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc) spParams = getSpatialParameters(len(kernelList), polyFunc) kernel.setSpatialParameters(spParams); return kernel
def showPsfCandidates(exposure, psfCellSet, psf=None, display=None, normalize=True, showBadCandidates=True, fitBasisComponents=False, variance=None, chi=None): """Display the PSF candidates. If psf is provided include PSF model and residuals; if normalize is true normalize the PSFs (and residuals) If chi is True, generate a plot of residuals/sqrt(variance), i.e. chi If fitBasisComponents is true, also find the best linear combination of the PSF's components (if they exist) """ if not display: display = afwDisplay.Display() if chi is None: if variance is not None: # old name for chi chi = variance # # Show us the ccandidates # mos = displayUtils.Mosaic() # candidateCenters = [] candidateCentersBad = [] candidateIndex = 0 for cell in psfCellSet.getCellList(): for cand in cell.begin(False): # include bad candidates rchi2 = cand.getChi2() if rchi2 > 1e100: rchi2 = numpy.nan if not showBadCandidates and cand.isBad(): continue if psf: im_resid = displayUtils.Mosaic(gutter=0, background=-5, mode="x") try: im = cand.getMaskedImage() # copy of this object's image xc, yc = cand.getXCenter(), cand.getYCenter() margin = 0 if True else 5 w, h = im.getDimensions() bbox = lsst.geom.BoxI(lsst.geom.PointI(margin, margin), im.getDimensions()) if margin > 0: bim = im.Factory(w + 2*margin, h + 2*margin) stdev = numpy.sqrt(afwMath.makeStatistics(im.getVariance(), afwMath.MEAN).getValue()) afwMath.randomGaussianImage(bim.getImage(), afwMath.Random()) bim.getVariance().set(stdev**2) bim.assign(im, bbox) im = bim xc += margin yc += margin im = im.Factory(im, True) im.setXY0(cand.getMaskedImage().getXY0()) except Exception: continue if not variance: im_resid.append(im.Factory(im, True)) if True: # tweak up centroids mi = im psfIm = mi.getImage() config = measBase.SingleFrameMeasurementTask.ConfigClass() config.slots.centroid = "base_SdssCentroid" schema = afwTable.SourceTable.makeMinimalSchema() measureSources = measBase.SingleFrameMeasurementTask(schema, config=config) catalog = afwTable.SourceCatalog(schema) extra = 10 # enough margin to run the sdss centroider miBig = mi.Factory(im.getWidth() + 2*extra, im.getHeight() + 2*extra) miBig[extra:-extra, extra:-extra, afwImage.LOCAL] = mi miBig.setXY0(mi.getX0() - extra, mi.getY0() - extra) mi = miBig del miBig exp = afwImage.makeExposure(mi) exp.setPsf(psf) footprintSet = afwDet.FootprintSet(mi, afwDet.Threshold(0.5*numpy.max(psfIm.getArray())), "DETECTED") footprintSet.makeSources(catalog) if len(catalog) == 0: raise RuntimeError("Failed to detect any objects") measureSources.run(catalog, exp) if len(catalog) == 1: source = catalog[0] else: # more than one source; find the once closest to (xc, yc) dmin = None # an invalid value to catch logic errors for i, s in enumerate(catalog): d = numpy.hypot(xc - s.getX(), yc - s.getY()) if i == 0 or d < dmin: source, dmin = s, d xc, yc = source.getCentroid() # residuals using spatial model try: subtractPsf(psf, im, xc, yc) except Exception: continue resid = im if variance: resid = resid.getImage() var = im.getVariance() var = var.Factory(var, True) numpy.sqrt(var.getArray(), var.getArray()) # inplace sqrt resid /= var im_resid.append(resid) # Fit the PSF components directly to the data (i.e. ignoring the spatial model) if fitBasisComponents: im = cand.getMaskedImage() im = im.Factory(im, True) im.setXY0(cand.getMaskedImage().getXY0()) try: noSpatialKernel = psf.getKernel() except Exception: noSpatialKernel = None if noSpatialKernel: candCenter = lsst.geom.PointD(cand.getXCenter(), cand.getYCenter()) fit = fitKernelParamsToImage(noSpatialKernel, im, candCenter) params = fit[0] kernels = afwMath.KernelList(fit[1]) outputKernel = afwMath.LinearCombinationKernel(kernels, params) outImage = afwImage.ImageD(outputKernel.getDimensions()) outputKernel.computeImage(outImage, False) im -= outImage.convertF() resid = im if margin > 0: bim = im.Factory(w + 2*margin, h + 2*margin) afwMath.randomGaussianImage(bim.getImage(), afwMath.Random()) bim *= stdev bim.assign(resid, bbox) resid = bim if variance: resid = resid.getImage() resid /= var im_resid.append(resid) im = im_resid.makeMosaic() else: im = cand.getMaskedImage() if normalize: im /= afwMath.makeStatistics(im, afwMath.MAX).getValue() objId = splitId(cand.getSource().getId(), True)["objId"] if psf: lab = "%d chi^2 %.1f" % (objId, rchi2) ctype = afwDisplay.RED if cand.isBad() else afwDisplay.GREEN else: lab = "%d flux %8.3g" % (objId, cand.getSource().getPsfInstFlux()) ctype = afwDisplay.GREEN mos.append(im, lab, ctype) if False and numpy.isnan(rchi2): display.mtv(cand.getMaskedImage().getImage(), title="showPsfCandidates: candidate") print("amp", cand.getAmplitude()) im = cand.getMaskedImage() center = (candidateIndex, xc - im.getX0(), yc - im.getY0()) candidateIndex += 1 if cand.isBad(): candidateCentersBad.append(center) else: candidateCenters.append(center) if variance: title = "chi(Psf fit)" else: title = "Stars & residuals" mosaicImage = mos.makeMosaic(display=display, title=title) with display.Buffering(): for centers, color in ((candidateCenters, afwDisplay.GREEN), (candidateCentersBad, afwDisplay.RED)): for cen in centers: bbox = mos.getBBox(cen[0]) display.dot("+", cen[1] + bbox.getMinX(), cen[2] + bbox.getMinY(), ctype=color) return mosaicImage
def testSVLinearCombinationKernel(self): """Test a spatially varying LinearCombinationKernel """ kWidth = 3 kHeight = 2 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel6.boost") persistence = dafPersist.Persistence.getPersistence(pol) # create image arrays for the basis kernels basisImArrList = [] imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.1 imArr[kWidth//2, :] = 0.9 basisImArrList.append(imArr) imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.2 imArr[:, kHeight//2] = 0.8 basisImArrList.append(imArr) # create a list of basis kernels from the images kVec = afwMath.KernelList() for basisImArr in basisImArrList: basisImage = afwImage.makeImageFromArray(basisImArr.transpose().copy()) kernel = afwMath.FixedKernel(basisImage) kVec.append(kernel) # create spatially varying linear combination kernel spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (0.0, 1.0, 0.0), (0.0, 0.0, 1.0), ) k = afwMath.LinearCombinationKernel(kVec, spFunc) k.setSpatialParameters(sParams) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("LinearCombinationKernel", storageList2, additionalData) k2 = afwMath.LinearCombinationKernel.swigConvert(x) self.kernelCheck(k, k2) kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for colPos, rowPos, coeff0, coeff1 in [ (0.0, 0.0, 0.0, 0.0), (1.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 0.5), ]: k2.computeImage(kImage, False, colPos, rowPos) kImArr = kImage.getArray().transpose() refKImArr = (basisImArrList[0] * coeff0) + (basisImArrList[1] * coeff1) if not numpy.allclose(kImArr, refKImArr): self.fail("%s = %s != %s at colPos=%s, rowPos=%s" % \ (k2.__class__.__name__, kImArr, refKImArr, colPos, rowPos))
def testWithThreeBases(self): kc1 = self.makeCandidate(1, 0.0, 0.0) kc2 = self.makeCandidate(2, 0.0, 0.0) kc3 = self.makeCandidate(3, 0.0, 0.0) bskv1 = ipDiffim.BuildSingleKernelVisitorF(self.kList, self.policy) bskv1.processCandidate(kc1) bskv1.processCandidate(kc2) bskv1.processCandidate(kc3) self.assertEqual(bskv1.getNProcessed(), 3) # make sure orig solution is the current one soln1_1 = kc1.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId() soln2_1 = kc2.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId() soln3_1 = kc3.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId() self.assertEqual(soln1_1, kc1.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln2_1, kc2.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln3_1, kc3.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) # do pca basis; visit manually since visitCandidates is still broken imagePca = ipDiffim.KernelPcaD() kpv = ipDiffim.KernelPcaVisitorF(imagePca) kpv.processCandidate(kc1) kpv.processCandidate(kc2) kpv.processCandidate(kc3) kpv.subtractMean() imagePca.analyze() eigenKernels = afwMath.KernelList() eigenKernels.push_back(kpv.getEigenKernels()[0]) self.assertEqual(len(eigenKernels), 1) # the other eKernels are 0.0 and you can't get their coeffs! # do twice to mimic a Pca loop bskv2 = ipDiffim.BuildSingleKernelVisitorF(eigenKernels, self.policy) bskv2.setSkipBuilt(False) bskv2.processCandidate(kc1) bskv2.processCandidate(kc2) bskv2.processCandidate(kc3) self.assertEqual(bskv2.getNProcessed(), 3) soln1_2 = kc1.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() soln2_2 = kc2.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() soln3_2 = kc3.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() # pca is recent self.assertEqual(soln1_2, kc1.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln2_2, kc2.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln3_2, kc3.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) # orig is still orig self.assertEqual(soln1_1, kc1.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId()) self.assertEqual(soln2_1, kc2.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId()) self.assertEqual(soln3_1, kc3.getKernelSolution(ipDiffim.KernelCandidateF.ORIG).getId()) # pca is not orig self.assertNotEqual(soln1_2, soln1_1) self.assertNotEqual(soln2_2, soln2_1) self.assertNotEqual(soln3_2, soln3_1) # do twice to mimic a Pca loop bskv3 = ipDiffim.BuildSingleKernelVisitorF(eigenKernels, self.policy) bskv3.setSkipBuilt(False) bskv3.processCandidate(kc1) bskv3.processCandidate(kc2) bskv3.processCandidate(kc3) self.assertEqual(bskv3.getNProcessed(), 3) soln1_3 = kc1.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() soln2_3 = kc2.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() soln3_3 = kc3.getKernelSolution(ipDiffim.KernelCandidateF.PCA).getId() # pca is recent self.assertEqual(soln1_3, kc1.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln2_3, kc2.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) self.assertEqual(soln3_3, kc3.getKernelSolution(ipDiffim.KernelCandidateF.RECENT).getId()) # pca is not previous pca self.assertNotEqual(soln1_2, soln1_3) self.assertNotEqual(soln2_2, soln2_3) self.assertNotEqual(soln3_2, soln3_3)
def testAutoCorrelation(orderMake, orderFit, inMi=None, display=False): config = ipDiffim.ImagePsfMatchTask.ConfigClass() config.kernel.name = "AL" subconfig = config.kernel.active subconfig.fitForBackground = True stride = 100 if inMi == None: width = 512 height = 2048 inMi = afwImage.MaskedImageF(afwGeom.Extent2I(width, height)) for j in num.arange(stride // 2, height, stride): j = int(j) for i in num.arange(stride // 2, width, stride): i = int(i) inMi.set(i - 1, j - 1, (100., 0x0, 1.)) inMi.set(i - 1, j + 0, (100., 0x0, 1.)) inMi.set(i - 1, j + 1, (100., 0x0, 1.)) inMi.set(i + 0, j - 1, (100., 0x0, 1.)) inMi.set(i + 0, j + 0, (100., 0x0, 1.)) inMi.set(i + 0, j + 1, (100., 0x0, 1.)) inMi.set(i + 1, j - 1, (100., 0x0, 1.)) inMi.set(i + 1, j + 0, (100., 0x0, 1.)) inMi.set(i + 1, j + 1, (100., 0x0, 1.)) addNoise(inMi) kSize = subconfig.kernelSize basicGaussian1 = afwMath.GaussianFunction2D(2., 2., 0.) basicKernel1 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian1) basicGaussian2 = afwMath.GaussianFunction2D(5., 3., 0.5 * num.pi) basicKernel2 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian2) basisList = afwMath.KernelList() basisList.append(basicKernel1) basisList.append(basicKernel2) spatialKernelFunction = afwMath.PolynomialFunction2D(orderMake) spatialKernel = afwMath.LinearCombinationKernel(basisList, spatialKernelFunction) kCoeffs = [[ 1.0 for x in range(1, spatialKernelFunction.getNParameters() + 1) ], [ 0.01 * x for x in range(1, spatialKernelFunction.getNParameters() + 1) ]] spatialKernel.setSpatialParameters(kCoeffs) cMi = afwImage.MaskedImageF(inMi.getDimensions()) afwMath.convolve(cMi, inMi, spatialKernel, True) if display: ds9.mtv(inMi.getImage(), frame=1) ds9.mtv(inMi.getVariance(), frame=2) ds9.mtv(cMi.getImage(), frame=3) ds9.mtv(cMi.getVariance(), frame=4) subconfig.spatialKernelOrder = orderFit subconfig.sizeCellX = stride subconfig.sizeCellY = stride psfmatch = ipDiffim.ImagePsfMatchTask(config=config) result = psfmatch.run(inMi, cMi, "subtractMaskedImages") differenceMaskedImage = result.subtractedImage spatialKernel = result.psfMatchingKernel spatialBg = result.backgroundModel kernelCellSet = result.kernelCellSet makeAutoCorrelation(kernelCellSet, spatialKernel, makePlot=True)
def showPsfCandidates(exposure, psfCellSet, psf=None, frame=None, normalize=True, showBadCandidates=True, variance=None, chi=None): """Display the PSF candidates. If psf is provided include PSF model and residuals; if normalize is true normalize the PSFs (and residuals) If chi is True, generate a plot of residuals/sqrt(variance), i.e. chi """ if chi is None: if variance is not None: # old name for chi chi = variance # # Show us the ccandidates # mos = displayUtils.Mosaic() # candidateCenters = [] candidateCentersBad = [] candidateIndex = 0 for cell in psfCellSet.getCellList(): for cand in cell.begin(False): # include bad candidates cand = algorithmsLib.cast_PsfCandidateF(cand) rchi2 = cand.getChi2() if rchi2 > 1e100: rchi2 = numpy.nan if not showBadCandidates and cand.isBad(): continue if psf: im_resid = displayUtils.Mosaic(gutter=0, background=-5, mode="x") try: im = cand.getMaskedImage() # copy of this object's image xc, yc = cand.getXCenter(), cand.getYCenter() margin = 0 if True else 5 w, h = im.getDimensions() bbox = afwGeom.BoxI(afwGeom.PointI(margin, margin), im.getDimensions()) if margin > 0: bim = im.Factory(w + 2*margin, h + 2*margin) stdev = numpy.sqrt(afwMath.makeStatistics(im.getVariance(), afwMath.MEAN).getValue()) afwMath.randomGaussianImage(bim.getImage(), afwMath.Random()) bim *= stdev var = bim.getVariance(); var.set(stdev**2); del var sbim = im.Factory(bim, bbox) sbim <<= im del sbim im = bim xc += margin; yc += margin im = im.Factory(im, True) im.setXY0(cand.getMaskedImage().getXY0()) except: continue if not variance: im_resid.append(im.Factory(im, True)) # residuals using spatial model chi2 = algorithmsLib.subtractPsf(psf, im, xc, yc) resid = im if variance: resid = resid.getImage() var = im.getVariance() var = var.Factory(var, True) numpy.sqrt(var.getArray(), var.getArray()) # inplace sqrt resid /= var im_resid.append(resid) # Fit the PSF components directly to the data (i.e. ignoring the spatial model) im = cand.getMaskedImage() im = im.Factory(im, True) im.setXY0(cand.getMaskedImage().getXY0()) noSpatialKernel = afwMath.cast_LinearCombinationKernel(psf.getKernel()) candCenter = afwGeom.PointD(cand.getXCenter(), cand.getYCenter()) fit = algorithmsLib.fitKernelParamsToImage(noSpatialKernel, im, candCenter) params = fit[0] kernels = afwMath.KernelList(fit[1]) outputKernel = afwMath.LinearCombinationKernel(kernels, params) outImage = afwImage.ImageD(outputKernel.getDimensions()) outputKernel.computeImage(outImage, False) im -= outImage.convertF() resid = im if margin > 0: bim = im.Factory(w + 2*margin, h + 2*margin) afwMath.randomGaussianImage(bim.getImage(), afwMath.Random()) bim *= stdev sbim = im.Factory(bim, bbox) sbim <<= resid del sbim resid = bim if variance: resid = resid.getImage() resid /= var im_resid.append(resid) im = im_resid.makeMosaic() else: im = cand.getMaskedImage() if normalize: im /= afwMath.makeStatistics(im, afwMath.MAX).getValue() objId = splitId(cand.getSource().getId(), True)["objId"] if psf: lab = "%d chi^2 %.1f" % (objId, rchi2) ctype = ds9.RED if cand.isBad() else ds9.GREEN else: lab = "%d flux %8.3g" % (objId, cand.getSource().getPsfFlux()) ctype = ds9.GREEN mos.append(im, lab, ctype) if False and numpy.isnan(rchi2): ds9.mtv(cand.getMaskedImage().getImage(), title="candidate", frame=1) print "amp", cand.getAmplitude() im = cand.getMaskedImage() center = (candidateIndex, xc - im.getX0(), yc - im.getY0()) candidateIndex += 1 if cand.isBad(): candidateCentersBad.append(center) else: candidateCenters.append(center) if variance: title = "chi(Psf fit)" else: title = "Stars & residuals" mosaicImage = mos.makeMosaic(frame=frame, title=title) with ds9.Buffering(): for centers, color in ((candidateCenters, ds9.GREEN), (candidateCentersBad, ds9.RED)): for cen in centers: bbox = mos.getBBox(cen[0]) ds9.dot("+", cen[1] + bbox.getMinX(), cen[2] + bbox.getMinY(), frame=frame, ctype=color) return mosaicImage
def setUp(self): width, height = 110, 301 self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height)) self.mi.set(0) sd = 3 # standard deviation of image self.mi.getVariance().set(sd*sd) self.mi.getMask().addMaskPlane("DETECTED") self.FWHM = 5 self.ksize = 31 # size of desired kernel sigma1 = 1.75 sigma2 = 2*sigma1 self.exposure = afwImage.makeExposure(self.mi) self.exposure.setPsf(measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5*sigma1, 1, 0.1)) crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0*afwGeom.degrees, 0.0*afwGeom.degrees) wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0) self.exposure.setWcs(wcs) ccd = cameraGeom.Ccd(cameraGeom.Id(1)) ccd.addAmp(cameraGeom.Amp(cameraGeom.Id(0), afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()), afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(0,0)), afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()), cameraGeom.ElectronicParams(1.0, 100.0, 65535))) self.exposure.setDetector(ccd) self.exposure.getDetector().setDistortion(None) # # Make a kernel with the exactly correct basis functions. Useful for debugging # basisKernelList = afwMath.KernelList() for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel(self.ksize, self.ksize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 # 1 => up to linear spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5*1e-2, 0.2e-2]]) rand = afwMath.Random() # make these tests repeatable by setting seed addNoise = True if addNoise: im = self.mi.getImage() afwMath.randomGaussianImage(im, rand) # N(0, 1) im *= sd # N(0, sd^2) del im xarr, yarr = [], [] for x, y in [(20, 20), (60, 20), (30, 35), (50, 50), (20, 90), (70, 160), (25, 265), (75, 275), (85, 30), (50, 120), (70, 80), (60, 210), (20, 210), ]: xarr.append(x) yarr.append(y) for x, y in zip(xarr, yarr): dx = rand.uniform() - 0.5 # random (centered) offsets dy = rand.uniform() - 0.5 k = exactKernel.getSpatialFunction(1)(x, y) # functional variation of Kernel ... b = (k*sigma1**2/((1 - k)*sigma2**2)) # ... converted double Gaussian's "b" #flux = 80000 - 20*x - 10*(y/float(height))**2 flux = 80000*(1 + 0.1*(rand.uniform() - 0.5)) I0 = flux*(1 + b)/(2*np.pi*(sigma1**2 + b*sigma2**2)) for iy in range(y - self.ksize//2, y + self.ksize//2 + 1): if iy < 0 or iy >= self.mi.getHeight(): continue for ix in range(x - self.ksize//2, x + self.ksize//2 + 1): if ix < 0 or ix >= self.mi.getWidth(): continue I = I0*psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b) Isample = rand.poisson(I) if addNoise else I self.mi.getImage().set(ix, iy, self.mi.getImage().get(ix, iy) + Isample) self.mi.getVariance().set(ix, iy, self.mi.getVariance().get(ix, iy) + I) # bbox = afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(width, height)) self.cellSet = afwMath.SpatialCellSet(bbox, 100) self.footprintSet = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100), "DETECTED") self.catalog = SpatialModelPsfTestCase.measure(self.footprintSet, self.exposure) for source in self.catalog: try: cand = measAlg.makePsfCandidate(source, self.exposure) self.cellSet.insertCandidate(cand) except Exception, e: print e continue
def testSVLinearCombinationKernelFixed(self): """Test a spatially varying LinearCombinationKernel """ kWidth = 3 kHeight = 2 # create image arrays for the basis kernels basisImArrList = [] imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.1 imArr[kWidth // 2, :] = 0.9 basisImArrList.append(imArr) imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.2 imArr[:, kHeight // 2] = 0.8 basisImArrList.append(imArr) # create a list of basis kernels from the images basisKernelList = afwMath.KernelList() for basisImArr in basisImArrList: basisImage = afwImage.makeImageFromArray( basisImArr.transpose().copy()) kernel = afwMath.FixedKernel(basisImage) basisKernelList.append(kernel) # create spatially varying linear combination kernel spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (0.0, 1.0, 0.0), (0.0, 0.0, 1.0), ) kernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) self.assert_(not kernel.isDeltaFunctionBasis()) self.basicTests(kernel, 2, 3) kernel.setSpatialParameters(sParams) kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for colPos, rowPos, coeff0, coeff1 in [ (0.0, 0.0, 0.0, 0.0), (1.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 0.5), ]: kernel.computeImage(kImage, False, colPos, rowPos) kImArr = kImage.getArray().transpose() refKImArr = (basisImArrList[0] * coeff0) + (basisImArrList[1] * coeff1) if not numpy.allclose(kImArr, refKImArr): self.fail("%s = %s != %s at colPos=%s, rowPos=%s" % \ (kernel.__class__.__name__, kImArr, refKImArr, colPos, rowPos)) sParams = ( (0.1, 1.0, 0.0), (0.1, 0.0, 1.0), ) kernel.setSpatialParameters(sParams) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) newSParams = ( (0.1, 0.2, 0.5), (0.1, 0.5, 0.2), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail( "Clone was modified by changing original's spatial parameters")
def testMakeBadKernels(self): """Attempt to make various invalid kernels; make sure the constructor shows an exception """ kWidth = 4 kHeight = 3 gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) spFunc = afwMath.PolynomialFunction2D(1) kernelList = afwMath.KernelList() kernelList.append( afwMath.FixedKernel( afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight), 0.1))) kernelList.append( afwMath.FixedKernel( afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight), 0.2))) for numKernelParams in (2, 4): spFuncList = afwMath.Function2DList() for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2, spFuncList) self.fail( "Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass for numKernelParams in (1, 3): spFuncList = afwMath.Function2DList() for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.LinearCombinationKernel(kernelList, spFuncList) self.fail( "Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass kParamList = [0.2] * numKernelParams try: afwMath.LinearCombinationKernel(kernelList, kParamList) self.fail( "Should have failed with wrong # of kernel parameters") except pexExcept.Exception: pass try: afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1, spFuncList) self.fail( "Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass for pointX in range(-1, kWidth + 2): for pointY in range(-1, kHeight + 2): if (0 <= pointX < kWidth) and (0 <= pointY < kHeight): continue try: afwMath.DeltaFunctionKernel( kWidth, kHeight, afwGeom.Point2I(pointX, pointY)) self.fail("Should have failed with point not on kernel") except pexExcept.Exception: pass
def setUp(self): self.schema = afwTable.SourceTable.makeMinimalSchema() config = measBase.SingleFrameMeasurementConfig() config.algorithms.names = [ "base_PixelFlags", "base_SdssCentroid", "base_GaussianFlux", "base_SdssShape", "base_CircularApertureFlux", "base_PsfFlux", ] config.algorithms["base_CircularApertureFlux"].radii = [3.0] config.slots.centroid = "base_SdssCentroid" config.slots.psfFlux = "base_PsfFlux" config.slots.apFlux = "base_CircularApertureFlux_3_0" config.slots.modelFlux = None config.slots.instFlux = None config.slots.calibFlux = None config.slots.shape = "base_SdssShape" self.measureTask = measBase.SingleFrameMeasurementTask(self.schema, config=config) width, height = 110, 301 self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height)) self.mi.set(0) sd = 3 # standard deviation of image self.mi.getVariance().set(sd * sd) self.mi.getMask().addMaskPlane("DETECTED") self.FWHM = 5 self.ksize = 31 # size of desired kernel sigma1 = 1.75 sigma2 = 2 * sigma1 self.exposure = afwImage.makeExposure(self.mi) self.exposure.setPsf( measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5 * sigma1, 1, 0.1)) self.exposure.setDetector(DetectorWrapper().detector) # # Make a kernel with the exactly correct basis functions. Useful for debugging # basisKernelList = afwMath.KernelList() for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel( self.ksize, self.ksize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 # 1 => up to linear spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5 * 1e-2, 0.2e-2]]) self.exactPsf = measAlg.PcaPsf(exactKernel) rand = afwMath.Random() # make these tests repeatable by setting seed addNoise = True if addNoise: im = self.mi.getImage() afwMath.randomGaussianImage(im, rand) # N(0, 1) im *= sd # N(0, sd^2) del im xarr, yarr = [], [] for x, y in [ (20, 20), (60, 20), (30, 35), (50, 50), (20, 90), (70, 160), (25, 265), (75, 275), (85, 30), (50, 120), (70, 80), (60, 210), (20, 210), ]: xarr.append(x) yarr.append(y) for x, y in zip(xarr, yarr): dx = rand.uniform() - 0.5 # random (centered) offsets dy = rand.uniform() - 0.5 k = exactKernel.getSpatialFunction(1)( x, y) # functional variation of Kernel ... b = (k * sigma1**2 / ((1 - k) * sigma2**2) ) # ... converted double Gaussian's "b" #flux = 80000 - 20*x - 10*(y/float(height))**2 flux = 80000 * (1 + 0.1 * (rand.uniform() - 0.5)) I0 = flux * (1 + b) / (2 * np.pi * (sigma1**2 + b * sigma2**2)) for iy in range(y - self.ksize // 2, y + self.ksize // 2 + 1): if iy < 0 or iy >= self.mi.getHeight(): continue for ix in range(x - self.ksize // 2, x + self.ksize // 2 + 1): if ix < 0 or ix >= self.mi.getWidth(): continue I = I0 * psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b) Isample = rand.poisson(I) if addNoise else I self.mi.getImage().set( ix, iy, self.mi.getImage().get(ix, iy) + Isample) self.mi.getVariance().set( ix, iy, self.mi.getVariance().get(ix, iy) + I) # bbox = afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.ExtentI(width, height)) self.cellSet = afwMath.SpatialCellSet(bbox, 100) self.footprintSet = afwDetection.FootprintSet( self.mi, afwDetection.Threshold(100), "DETECTED") self.catalog = self.measure(self.footprintSet, self.exposure) for source in self.catalog: try: cand = measAlg.makePsfCandidate(source, self.exposure) self.cellSet.insertCandidate(cand) except Exception as e: print(e) continue