def testLinearCombinationKernelDelta(self): """Test LinearCombinationKernel using a set of delta basis functions """ kWidth = 3 kHeight = 2 # create list of kernels basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight) basisImArrList = [] for basisKernel in basisKernelList: basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray()) kParams = [0.0] * len(basisKernelList) kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams) self.assert_(kernel.isDeltaFunctionBasis()) self.basicTests(kernel, len(kParams)) 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 numpy.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % \ (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False)
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 = [] 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)) kernelResized = self.verifyResized(kernel) self.basicTests(kernelResized, 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(f"{kernel.__class__.__name__} = {kImArr} != " f"{basisImArrList[ii]} for the {ii}'th basis kernel") if np.allclose(kImArr, modBasisImArrList[ii]): self.fail(f"{kernel.__class__.__name__} = {kImArr} != " f"{modBasisImArrList[ii]} for *modified* {ii}'th basis kernel") kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False)
def makeTest1(doAddNoise): gaussian1 = afwMath.GaussianFunction2D(1.*gScale, 1.*gScale, 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, doNorm) image1 *= scaling # total counts = scaling image1 = image1.convertF() mask1 = afwImage.Mask(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2.*gScale, 1.5*gScale, 0.5*np.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, doNorm) image2 *= scaling # total counts = scaling image2 = image2.convertF() mask2 = afwImage.Mask(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2
def makeTest2(doAddNoise, shiftX=5, shiftY=3): gaussian1 = afwMath.GaussianFunction2D(1., 1., 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, False) image1 *= 10000 image1 = image1.convertF() #### boxA = afwGeom.Box2I(afwGeom.PointI(imSize // 2, imSize // 2), afwGeom.ExtentI(imSize // 2, imSize // 2)) boxB = afwGeom.Box2I( afwGeom.PointI(imSize // 2 - shiftX, imSize // 2 - shiftY), afwGeom.ExtentI(imSize // 2, imSize // 2)) subregA = afwImage.ImageF(image1, boxA, afwImage.PARENT) subregB = afwImage.ImageF(image1, boxB, afwImage.PARENT, True) subregA += subregB ### mask1 = afwImage.MaskU(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2., 1.5, 0.5 * num.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, False) image2 *= 10000 image2 = image2.convertF() mask2 = afwImage.MaskU(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2
def testWriteReadF64(self): """Test writing then reading an F64 image""" with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: im = afwImage.ImageD(afwGeom.Extent2I(100, 100)) im.set(666) im.writeFits(tmpFile) afwImage.ImageD(tmpFile)
def makeTest1(doAddNoise): gaussian1 = afwMath.GaussianFunction2D(1., 1., 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, False) image1 *= 10000 image1 = image1.convertF() mask1 = afwImage.Mask(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2., 1.5, 0.5 * num.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, False) image2 *= 10000 image2 = image2.convertF() mask2 = afwImage.Mask(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2
def buildCModelImages(exposure, record, config): """ Create Images out of the CModel for the given record Parameters ---------- exposure : `lsst.afw.image.Exposure` Exposure object that contains the source which was modeled record : `lsst.afw.table.SourceRecord` Record object which contains the measurements made on the source config : `lsst.meas.modelfit.CModel(SingleFrame/Forced)Config` Configuration object of the CModel plugin used in the measurement process Returns ------- subImage : `lsst.afw.image.ImageD` Sub image of the original data taken from a region defined by the bounding box of the footprint for the object defined in the given source record devIm : `lsst.afw.image.ImageD` Image created from the dev component of the CModel for the supplied record at the same pixel locations as subImage expIm: `lsst.afw.image.ImageD` Image created from the exp component of the CModel for the supplied record at the same pixel locations as subImage jointIm : Image created from the joint fit of the dev and exp components of the CModel for the supplied record at the same pixel locations as subImage """ dev, exp, jointDev, jointExp = reconstructCModel(exposure, record, config) # Get exposure cutout footBBox = record.getFootprint().getBBox() subImage = afwImage.ImageD(exposure.getImage().convertD(), footBBox) # Build the psf shapeletPsfKey = shapelet.MultiShapeletFunctionKey( record.schema[config.psfName]) psfApprox = record.get(shapeletPsfKey) # Build the dev Image from the shapelet function devIm = afwImage.ImageD(footBBox) dev = dev.convolve(psfApprox) dev.evaluate().addToImage(devIm) # Build the exp image from the shapelet function expIm = afwImage.ImageD(footBBox) exp = exp.convolve(psfApprox) exp.evaluate().addToImage(expIm) # Build the joint image from the shapelet function jointIm = afwImage.ImageD(footBBox) jointDev = jointDev.convolve(psfApprox) jointExp = jointExp.convolve(psfApprox) jointDev.evaluate().addToImage(jointIm) jointExp.evaluate().addToImage(jointIm) return subImage, devIm, expIm, jointIm
def testSVAnalyticKernel(self): """Test spatially varying AnalyticKernel using a Gaussian function Just tests cloning. """ kWidth = 5 kHeight = 8 # spatial model spFunc = 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, 1.0, 0.0), (1.0, 0.0, 1.0), (0.5, 0.5, 0.5), ) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc, spFunc) 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), (0.2, 0.3, 0.3), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail( "Clone was modified by changing original's spatial parameters") # # check that we can construct a FixedKernel from a LinearCombinationKernel # x, y = 100, 200 kernel2 = afwMath.FixedKernel(kernel, lsst.geom.PointD(x, y)) self.assertTrue(re.search("AnalyticKernel", kernel.toString())) self.assertFalse(kernel2.isSpatiallyVarying()) self.assertTrue(re.search("FixedKernel", kernel2.toString())) self.assertTrue(kernel.isSpatiallyVarying()) kim = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kim, True, x, y) kim2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(kim2, True) assert_allclose(kim.getArray(), kim2.getArray())
def directCompare(infile, filt, x, y, soft_bias=1000, amp=30000, outfile="/tmp/sdss_psf.fits"): if filt not in filtToHdu.keys(): print("INVALID FILTER", filt) sys.exit(1) # Make the kernel image from LSST psf = convertpsField(infile, filt, trim=False) kernel = psf.getKernel() # Assumes you have built dervish and have read_PSF in your path # # read_PSF takes coordinates in the order row,col or y,x cmd = "read_PSF %s %s %f %f %s" % (infile, filtToHdu[filt], y, x, outfile) os.system(cmd) if not os.path.isfile(outfile): print("Cannot find SDSS-derived kernel", outfile) sys.exit(1) if False: # Default version that integerizes Psf kImage1 = afwImage.ImageD(outfile) kImage1 -= soft_bias kImage1 /= (amp - soft_bias) maxVal = afwMath.makeStatistics(kImage1, afwMath.MAX).getValue(afwMath.MAX) print("TEST 1", maxVal == 1.0) kImage1.writeFits("/tmp/sdss_psf_scaled.fits") else: # Hacked version of main_PSF.c that writes floats kImage1 = afwImage.ImageD(outfile) maxVal = afwMath.makeStatistics(kImage1, afwMath.MAX).getValue(afwMath.MAX) kImage1 /= maxVal kImage1.writeFits("/tmp/sdss_psf_scaled.fits") # kImage2 = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kImage2, True, x, y) maxVal = afwMath.makeStatistics(kImage2, afwMath.MAX).getValue(afwMath.MAX) kImage2 /= maxVal kImage2.writeFits("/tmp/kernel.fits") kImage3 = afwImage.ImageD(kImage2, True) kImage3 -= kImage1 kImage3.writeFits("/tmp/diff.fits") residSum = afwMath.makeStatistics(kImage3, afwMath.SUM).getValue(afwMath.SUM) print("TEST 2", residSum) kImage4 = afwImage.ImageD(kImage2, True) kImage4 /= kImage1 kImage4.writeFits("/tmp/rat.fits")
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 = [] kernelList.append(afwMath.FixedKernel( afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight), 0.1))) kernelList.append(afwMath.FixedKernel( afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight), 0.2))) for numKernelParams in (2, 4): spFuncList = [] 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 = [] 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, lsst.geom.Point2I(pointX, pointY)) self.fail("Should have failed with point not on kernel") except pexExcept.Exception: pass
def displayFitter(self, zfitter, pupil): data = zfitter.maskedImage.getImage().getArray() model = zfitter.constructModelImage(zfitter.result.params) resid = data - model mtv(afwImage.ImageD(data.astype(np.float64)), frame=1, title="data") mtv(afwImage.ImageD(model.astype(np.float64)), frame=2, title="model") mtv(afwImage.ImageD(resid.astype(np.float64)), frame=3, title="resid") mtv(afwImage.ImageD(pupil.illuminated.astype(np.float64)), frame=4, title="pupil") input("Press Enter to continue...")
def compareKernels(self, kernel1, kernel2, compareParams=True, newCtr1=(0, 0)): """Compare two kernels; return None if they match, else return a string kernelDescribing a difference. kernel1: one kernel to test kernel2: the other kernel to test compareParams: compare spatial parameters and kernel parameters if they exist newCtr: if not None then set the center of kernel1 and see if it changes the center of kernel2 """ retStrs = [] if kernel1.getDimensions() != kernel2.getDimensions(): retStrs.append("dimensions differ: %s != %s" % (kernel1.getDimensions(), kernel2.getDimensions())) ctr1 = kernel1.getCtrX(), kernel1.getCtrY() ctr2 = kernel2.getCtrX(), kernel2.getCtrY() if ctr1 != ctr2: retStrs.append("centers differ: %s != %s" % (ctr1, ctr2)) if kernel1.isSpatiallyVarying() != kernel2.isSpatiallyVarying(): retStrs.append( "isSpatiallyVarying differs: %s != %s" % (kernel1.isSpatiallyVarying(), kernel2.isSpatiallyVarying())) if compareParams: retStrs = self._compareParams(kernel1, kernel2, retStrs) if retStrs: return "; ".join(retStrs) im1 = afwImage.ImageD(kernel1.getDimensions()) im2 = afwImage.ImageD(kernel2.getDimensions()) posList = self._makePositionList(kernel1) for doNormalize in (False, True): for pos in posList: kernel1.computeImage(im1, doNormalize, pos[0], pos[1]) kernel2.computeImage(im2, doNormalize, pos[0], pos[1]) im1Arr = im1.getArray() im2Arr = im2.getArray() if not np.allclose(im1Arr, im2Arr): print("im1Arr =", im1Arr) print("im2Arr =", im2Arr) return "kernel images do not match at %s with doNormalize=%s" % ( pos, doNormalize) if newCtr1 is not None: kernel1.setCtrX(newCtr1[0]) kernel1.setCtrY(newCtr1[1]) newCtr2 = kernel2.getCtrX(), kernel2.getCtrY() if ctr2 != newCtr2: return "changing center of kernel1 to %s changed the center of kernel2 from %s to %s" % \ (newCtr1, ctr2, newCtr2)
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 testWriteReadF64(self): """Test writing then reading an F64 image""" imPath = "data" if os.path.exists("tests"): imPath = os.path.join("tests", imPath) imPath = os.path.join(imPath, "smallD.fits") im = afwImage.ImageD(afwGeom.Extent2I(100, 100)) im.set(666) im.writeFits(imPath) newIm = afwImage.ImageD(imPath) os.remove(imPath)
def testFixedKernel(self): """Test FixedKernel using a ramp function """ kWidth = 5 kHeight = 6 inArr = np.arange(kWidth * kHeight, dtype=float) inArr.shape = [kWidth, kHeight] inImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for row in range(inImage.getHeight()): for col in range(inImage.getWidth()): inImage.set(col, row, inArr[col, row]) k = afwMath.FixedKernel(inImage) pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation( os.path.join(testPath, "data", "kernel1.boost")) persistence = dafPersist.Persistence.getPersistence(pol) 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("FixedKernel", storageList2, additionalData) k2 = afwMath.FixedKernel.swigConvert(x) self.kernelCheck(k, k2) outImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(outImage, False) outArr = outImage.getArray().transpose() if not np.allclose(inArr, outArr): self.fail("%s = %s != %s (not normalized)" % (k2.__class__.__name__, inArr, outArr)) normInArr = inArr / inArr.sum() normOutImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(normOutImage, True) normOutArr = normOutImage.getArray().transpose() if not np.allclose(normOutArr, normInArr): self.fail("%s = %s != %s (normalized)" % (k2.__class__.__name__, normInArr, normOutArr))
def _compareKernelImages(self, psf1, psf2): """Test that overlapping portions of kernel images are identical. """ im1 = psf1.computeKernelImage() im2 = psf2.computeKernelImage() bboxIntersection = im1.getBBox() bboxIntersection.clip(im2.getBBox()) im1Intersection = afwImage.ImageD(im1, bboxIntersection) im2Intersection = afwImage.ImageD(im2, bboxIntersection) scale1 = im1.getArray().sum() / im1Intersection.getArray().sum() scale2 = im2.getArray().sum() / im2Intersection.getArray().sum() im1Arr = scale1 * im1Intersection.getArray() im2Arr = scale2 * im2Intersection.getArray() self.assertTrue(np.allclose(im1Arr, im2Arr), "kernel images %s, %s do not match" % (im1Arr, im2Arr))
def showPsf(psf, eigenValues=None, XY=None, normalize=True, display=None): """Display a PSF's eigen images If normalize is True, set the largest absolute value of each eigenimage to 1.0 (n.b. sum == 0.0 for i > 0) """ if eigenValues: coeffs = eigenValues elif XY is not None: coeffs = psf.getLocalKernel(lsst.geom.PointD(XY[0], XY[1])).getKernelParameters() else: coeffs = None mos = displayUtils.Mosaic(gutter=2, background=-0.1) for i, k in enumerate(psf.getKernel().getKernelList()): im = afwImage.ImageD(k.getDimensions()) k.computeImage(im, False) if normalize: im /= numpy.max(numpy.abs(im.getArray())) if coeffs: mos.append(im, "%g" % (coeffs[i]/coeffs[0])) else: mos.append(im) if not display: display = afwDisplay.Display() mos.makeMosaic(display=display, title="Kernel Basis Functions") return mos
def writeKernelCellSet(kernelCellSet, psfMatchingKernel, backgroundModel, outdir): if not os.path.isdir(outdir): os.makedirs(outdir) for cell in kernelCellSet.getCellList(): for cand in cell.begin(False): # False = include bad candidates if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD: xCand = int(cand.getXCenter()) yCand = int(cand.getYCenter()) idCand = cand.getId() diffIm = cand.getDifferenceImage( diffimLib.KernelCandidateF.ORIG) kernel = cand.getKernelImage(diffimLib.KernelCandidateF.ORIG) diffIm.writeFits( os.path.join( outdir, 'diffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand))) kernel.writeFits( os.path.join( outdir, 'kernel_c%d_x%d_y%d.fits' % (idCand, xCand, yCand))) # Diffim from spatial model ski = afwImage.ImageD(kernel.getDimensions()) psfMatchingKernel.computeImage(ski, False, xCand, yCand) sk = afwMath.FixedKernel(ski) sbg = backgroundModel(xCand, yCand) sdmi = cand.getDifferenceImage(sk, sbg) sdmi.writeFits( os.path.join( outdir, 'sdiffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
def testU16(self): """Test reading U16 image""" im = afwImage.ImageD(os.path.join(dataDir, "small_img.fits")) col, row, val = 0, 0, 1154 self.assertEqual(im.get(col, row), val)
def _doConvolve(exposure, kernel): """Convolve an Exposure with a decorrelation convolution kernel. Parameters ---------- exposure : `lsst.afw.image.Exposure` Input exposure to be convolved. kernel : `numpy.array` Input 2-d numpy.array to convolve the image with Returns ------- out : `lsst.afw.image.Exposure` a new Exposure with the convolved pixels and the (possibly re-centered) kernel. Notes ----- We re-center the kernel if necessary and return the possibly re-centered kernel """ kernelImg = afwImage.ImageD(kernel.shape[0], kernel.shape[1]) kernelImg.getArray()[:, :] = kernel kern = afwMath.FixedKernel(kernelImg) maxloc = np.unravel_index(np.argmax(kernel), kernel.shape) kern.setCtrX(maxloc[0]) kern.setCtrY(maxloc[1]) outExp = exposure.clone() # Do this to keep WCS, PSF, masks, etc. convCntrl = afwMath.ConvolutionControl(False, True, 0) afwMath.convolve(outExp.getMaskedImage(), exposure.getMaskedImage(), kern, convCntrl) return outExp, kern
def testDeltaFunctionKernel(self): """Test DeltaFunctionKernel """ for kWidth in range(1, 4): for kHeight in range(1, 4): for activeCol in range(kWidth): for activeRow in range(kHeight): kernel = afwMath.DeltaFunctionKernel( kWidth, kHeight, lsst.geom.Point2I(activeCol, activeRow)) with lsst.utils.tests.getTempFilePath( ".fits") as filename: kernel.writeFits(filename) k2 = afwMath.DeltaFunctionKernel.readFits(filename) self.kernelCheck(kernel, k2) self.assertEqual(kernel.getPixel(), k2.getPixel()) kImage = afwImage.ImageD(k2.getDimensions()) kSum = k2.computeImage(kImage, False) self.assertEqual(kSum, 1.0) kArr = kImage.getArray().transpose() self.assertEqual(kArr[activeCol, activeRow], 1.0) kArr[activeCol, activeRow] = 0.0 self.assertEqual(kArr.sum(), 0.0)
def _makeAndTestUncorrectedDiffim(self): """Create the (un-decorrelated) diffim, and verify that its variance is too low. """ # Create the matching kernel. We used Gaussian PSFs for im1 and im2, so we can compute the "expected" # matching kernel sigma. psf1_sig = self.im1ex.getPsf().computeShape().getDeterminantRadius() psf2_sig = self.im2ex.getPsf().computeShape().getDeterminantRadius() sig_match = np.sqrt((psf1_sig**2. - psf2_sig**2.)) # Sanity check - make sure PSFs are correct. self.assertFloatsAlmostEqual(sig_match, np.sqrt((self.psf1_sigma**2. - self.psf2_sigma**2.)), rtol=2e-5) # mKernel = measAlg.SingleGaussianPsf(31, 31, sig_match) x0 = np.arange(-16, 16, 1) y0 = x0.copy() x0im, y0im = np.meshgrid(x0, y0) matchingKernel = singleGaussian2d(x0im, y0im, -1., -1., sigma_x=sig_match, sigma_y=sig_match) kernelImg = afwImage.ImageD(matchingKernel.shape[0], matchingKernel.shape[1]) kernelImg.getArray()[:, :] = matchingKernel mKernel = afwMath.FixedKernel(kernelImg) # Create the matched template by convolving the template with the matchingKernel matched_im2ex = self.im2ex.clone() convCntrl = afwMath.ConvolutionControl(False, True, 0) afwMath.convolve(matched_im2ex.getMaskedImage(), self.im2ex.getMaskedImage(), mKernel, convCntrl) # Expected (ideal) variance of difference image expected_var = self.svar + self.tvar if verbose: print('EXPECTED VARIANCE:', expected_var) # Create the diffim (uncorrected) # Uncorrected diffim exposure - variance plane is wrong (too low) tmp_diffExp = self.im1ex.getMaskedImage().clone() tmp_diffExp -= matched_im2ex.getMaskedImage() var = self._computeVarianceMean(tmp_diffExp) self.assertLess(var, expected_var) # Uncorrected diffim exposure - variance is wrong (too low) - same as above but on pixels diffExp = self.im1ex.clone() tmp = diffExp.getMaskedImage() tmp -= matched_im2ex.getMaskedImage() var = self._computePixelVariance(diffExp.getMaskedImage()) self.assertLess(var, expected_var) # Uncorrected diffim exposure - variance plane is wrong (too low) mn = self._computeVarianceMean(diffExp.getMaskedImage()) self.assertLess(mn, expected_var) if verbose: print('UNCORRECTED VARIANCE:', var, mn) return diffExp, mKernel, expected_var
def makeExposure(imgArray, psfArray, imgVariance): """! Convert an image numpy.array and corresponding PSF numpy.array into an exposure. Add the (constant) variance plane equal to `imgVariance`. @param imgArray 2-d numpy.array containing the image @param psfArray 2-d numpy.array containing the PSF image @param imgVariance variance of input image @return a new exposure containing the image, PSF and desired variance plane """ # All this code to convert the template image array/psf array into an exposure. bbox = geom.Box2I( geom.Point2I(0, 0), geom.Point2I(imgArray.shape[1] - 1, imgArray.shape[0] - 1)) im1ex = afwImage.ExposureD(bbox) im1ex.getMaskedImage().getImage().getArray()[:, :] = imgArray im1ex.getMaskedImage().getVariance().getArray()[:, :] = imgVariance psfBox = geom.Box2I(geom.Point2I(-12, -12), geom.Point2I(12, 12)) # a 25x25 pixel psf psf = afwImage.ImageD(psfBox) psfBox.shift(geom.Extent2I(size[0] // 2, size[1] // 2)) im1_psf_sub = psfArray[psfBox.getMinX():psfBox.getMaxX() + 1, psfBox.getMinY():psfBox.getMaxY() + 1] psf.getArray()[:, :] = im1_psf_sub psfK = afwMath.FixedKernel(psf) psfNew = measAlg.KernelPsf(psfK) im1ex.setPsf(psfNew) wcs = makeWcs() im1ex.setWcs(wcs) return im1ex
def makeExposure(imgArray, psfArray, imgVariance): """Convert an image and corresponding PSF into an exposure. Set the (constant) variance plane equal to ``imgVariance``. Parameters ---------- imgArray : `numpy.ndarray` 2D array containing the image. psfArray : `numpy.ndarray` 2D array containing the PSF image. imgVariance : `float` or `numpy.ndarray` Set the variance plane to this value. If an array, must be broadcastable to ``imgArray.shape``. Returns ------- im1ex : `lsst.afw.image.Exposure` The new exposure. """ # All this code to convert the template image array/psf array into an exposure. bbox = geom.Box2I(geom.Point2I(0, 0), geom.Point2I(imgArray.shape[1] - 1, imgArray.shape[0] - 1)) im1ex = afwImage.ExposureD(bbox) im1ex.image.array[:, :] = imgArray im1ex.variance.array[:, :] = imgVariance psfBox = geom.Box2I(geom.Point2I(-12, -12), geom.Point2I(12, 12)) # a 25x25 pixel psf psf = afwImage.ImageD(psfBox) psfBox.shift(geom.Extent2I(-(-size[0]//2), -(-size[1]//2))) # -N//2 != -(N//2) for odd numbers im1_psf_sub = psfArray[psfBox.getMinY():psfBox.getMaxY() + 1, psfBox.getMinX():psfBox.getMaxX() + 1] psf.getArray()[:, :] = im1_psf_sub psfK = afwMath.FixedKernel(psf) psfNew = measAlg.KernelPsf(psfK) im1ex.setPsf(psfNew) wcs = makeWcs() im1ex.setWcs(wcs) return im1ex
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 = [] 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 testDeltaFunctionKernel(self): """Test DeltaFunctionKernel """ for kWidth in range(1, 4): for kHeight in range(1, 4): for activeCol in range(kWidth): for activeRow in range(kHeight): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, lsst.geom.Point2I(activeCol, activeRow)) kImage = afwImage.ImageD(kernel.getDimensions()) kSum = kernel.computeImage(kImage, False) self.assertEqual(kSum, 1.0) kArr = kImage.getArray().transpose() self.assertEqual(kArr[activeCol, activeRow], 1.0) kArr[activeCol, activeRow] = 0.0 self.assertEqual(kArr.sum(), 0.0) errStr = self.compareKernels(kernel, kernel.clone()) if errStr: self.fail(errStr) self.assertRaises(pexExcept.InvalidParameterError, afwMath.DeltaFunctionKernel, 0, kHeight, lsst.geom.Point2I(kWidth, kHeight)) self.assertRaises(pexExcept.InvalidParameterError, afwMath.DeltaFunctionKernel, kWidth, 0, lsst.geom.Point2I(kWidth, kHeight)) kernel = afwMath.DeltaFunctionKernel(5, 6, lsst.geom.Point2I(1, 1)) self.basicTests(kernel, 0) kernelResized = self.verifyResized(kernel, oddPadRaises=True) self.basicTests(kernelResized, 0) self.verifyCache(kernel, hasCache=False)
def setUp(self): self.val = 10 self.nRow, self.nCol = 100, 200 self.sctrl = afwMath.StatisticsControl() # Integers self.mimgI = afwImage.MaskedImageI( afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgI.set(self.val, 0x0, self.val) self.imgI = afwImage.ImageI(afwGeom.Extent2I(self.nRow, self.nCol), self.val) # TODO: pybind11, this should probably be ndarray self.vecI = [self.val for i in range(self.nRow * self.nCol)] # floats self.mimgF = afwImage.MaskedImageF( afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgF.set(self.val, 0x0, self.val) self.imgF = afwImage.ImageF(afwGeom.Extent2I(self.nRow, self.nCol), self.val) # TODO: pybind11, this should probably be ndarray self.vecF = [float(self.val) for i in range(self.nRow * self.nCol)] # doubles self.mimgD = afwImage.MaskedImageD( afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgD.set(self.val, 0x0, self.val) self.imgD = afwImage.ImageD(afwGeom.Extent2I(self.nRow, self.nCol), self.val) # TODO: pybind11, this should probably be ndarray self.vecD = [float(self.val) for i in range(self.nRow * self.nCol)] self.imgList = [self.imgI, self.imgF, self.imgD] self.mimgList = [self.mimgI, self.mimgF, self.mimgD] self.vecList = [self.vecI, self.vecF, self.vecD]
def setUp(self): self.val = 10 self.nRow, self.nCol = 100, 200 self.sctrl = afwMath.StatisticsControl() # Integers self.mimgI = afwImage.MaskedImageI(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgI.set(self.val, 0x0, self.val) self.imgI = afwImage.ImageI(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecI = afwMath.vectorI(self.nRow*self.nCol, self.val) # floats self.mimgF = afwImage.MaskedImageF(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgF.set(self.val, 0x0, self.val) self.imgF = afwImage.ImageF(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecF = afwMath.vectorF(self.nRow*self.nCol, self.val) # doubles self.mimgD = afwImage.MaskedImageD(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgD.set(self.val, 0x0, self.val) self.imgD = afwImage.ImageD(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecD = afwMath.vectorD(self.nRow*self.nCol, self.val) self.imgList = [self.imgI, self.imgF, self.imgD] self.mimgList = [self.mimgI, self.mimgF, self.mimgD] self.vecList = [self.vecI, self.vecF, self.vecD]
def checkEdge(self, footprint): """Check that Footprint::findEdgePixels() works""" bbox = footprint.getBBox() bbox.grow(3) def makeImage(area): """Make an ImageF with 1 in the footprint, and 0 elsewhere""" ones = afwImage.ImageI(bbox) ones.set(1) image = afwImage.ImageI(bbox) image.set(0) if isinstance(area, afwDetect.Footprint): area.spans.copyImage(ones, image) if isinstance(area, afwGeom.SpanSet): area.copyImage(ones, image) return image edges = self.foot.spans.findEdgePixels() edgeImage = makeImage(edges) # Find edges with an edge-detection kernel image = makeImage(self.foot) kernel = afwImage.ImageD(3, 3) kernel[1, 1, afwImage.LOCAL] = 4 for x, y in [(1, 2), (0, 1), (1, 0), (2, 1)]: kernel[x, y, afwImage.LOCAL] = -1 kernel.setXY0(1, 1) result = afwImage.ImageI(bbox) result.set(0) afwMath.convolve(result, image, afwMath.FixedKernel(kernel), afwMath.ConvolutionControl(False)) result.getArray().__imul__(image.getArray()) trueEdges = np.where(result.getArray() > 0, 1, 0) self.assertTrue(np.all(trueEdges == edgeImage.getArray()))
def testGaussianWithNoise(self): # Convolve a real image with a gaussian and try and recover # it. Add noise and perform the same test. gsize = self.ps["kernelSize"] gaussFunction = afwMath.GaussianFunction2D(2, 3) gaussKernel = afwMath.AnalyticKernel(gsize, gsize, gaussFunction) kImageIn = afwImage.ImageD(geom.Extent2I(gsize, gsize)) kSumIn = gaussKernel.computeImage(kImageIn, False) imX, imY = self.templateExposure2.getMaskedImage().getDimensions() smi = afwImage.MaskedImageF(geom.Extent2I(imX, imY)) afwMath.convolve(smi, self.templateExposure2.getMaskedImage(), gaussKernel, False) bbox = gaussKernel.shrinkBBox(smi.getBBox(afwImage.LOCAL)) tmi2 = afwImage.MaskedImageF(self.templateExposure2.getMaskedImage(), bbox, origin=afwImage.LOCAL) smi2 = afwImage.MaskedImageF(smi, bbox, origin=afwImage.LOCAL) kc = ipDiffim.KernelCandidateF(self.x02, self.y02, tmi2, smi2, self.ps) kList = ipDiffim.makeKernelBasisList(self.subconfig) kc.build(kList) self.assertEqual(kc.isInitialized(), True) kImageOut = kc.getImage() soln = kc.getKernelSolution(ipDiffim.KernelCandidateF.RECENT) self.assertAlmostEqual(soln.getKsum(), kSumIn) # 8.7499380640430563e-06 != 0.0 within 7 places self.assertAlmostEqual(soln.getBackground(), 0.0, 4) for j in range(kImageOut.getHeight()): for i in range(kImageOut.getWidth()): # in the outskirts of the kernel, the ratio can get screwed because of low S/N # e.g. 7.45817359824e-09 vs. 1.18062529402e-08 # in the guts of the kernel it should look closer if kImageIn[i, j, afwImage.LOCAL] > 1e-4: # sigh, too bad this sort of thing fails.. # 0.99941584433815966 != 1.0 within 3 places self.assertAlmostEqual(kImageOut[i, j, afwImage.LOCAL]/kImageIn[i, j, afwImage.LOCAL], 1.0, 2) # now repeat with noise added; decrease precision of comparison self.addNoise(smi2) kc = ipDiffim.KernelCandidateF(self.x02, self.y02, tmi2, smi2, self.ps) kList = ipDiffim.makeKernelBasisList(self.subconfig) kc.build(kList) self.assertEqual(kc.isInitialized(), True) kImageOut = kc.getImage() soln = kc.getKernelSolution(ipDiffim.KernelCandidateF.RECENT) self.assertAlmostEqual(soln.getKsum(), kSumIn, 3) if not self.ps.get("fitForBackground"): self.assertEqual(soln.getBackground(), 0.0) for j in range(kImageOut.getHeight()): for i in range(kImageOut.getWidth()): if kImageIn[i, j, afwImage.LOCAL] > 1e-2: self.assertAlmostEqual(kImageOut[i, j, afwImage.LOCAL], kImageIn[i, j, afwImage.LOCAL], 2)