1 from builtins
import range
2 from builtins
import object
28 from collections
import Counter
32 from .
import diffimLib
42 from .makeKernelBasisList
import makeKernelBasisList
56 rdmImage = img.Factory(img.getDimensions())
62 """Return a Poisson noise image based on im 64 Uses numpy.random; you may wish to call numpy.random.seed first. 66 @warning This uses an undocumented numpy API (the documented API 67 uses a single float expectation value instead of an array). 69 @param[in] im image; the output image has the same dimensions and shape 70 and its expectation value is the value of im at each pixel 72 import numpy.random
as rand
74 noiseIm = im.Factory(im.getBBox())
75 noiseArr = noiseIm.getArray()
77 with np.errstate(invalid=
'ignore'):
78 intNoiseArr = rand.poisson(imArr)
80 noiseArr[:, :] = intNoiseArr.astype(noiseArr.dtype)
91 kCoeffs = ((1.0, 0.0, 0.0),
92 (0.005, -0.000001, 0.000001),
93 (0.005, 0.000004, 0.000004),
94 (-0.001, -0.000030, 0.000030),
95 (-0.001, 0.000015, 0.000015),
96 (-0.005, -0.000050, 0.000050))
101 deltaFunctionCounts=1.e4, tGaussianWidth=1.0,
102 addNoise=True, bgValue=100., display=False):
104 from .
import imagePsfMatch
106 configFake.kernel.name =
"AL" 107 subconfigFake = configFake.kernel.active
108 subconfigFake.alardNGauss = 1
109 subconfigFake.alardSigGauss = [2.5, ]
110 subconfigFake.alardDegGauss = [2, ]
111 subconfigFake.sizeCellX = sizeCell
112 subconfigFake.sizeCellY = sizeCell
113 subconfigFake.spatialKernelOrder = 1
114 subconfigFake.spatialModelType =
"polynomial" 115 subconfigFake.singleKernelClipping =
False 116 subconfigFake.spatialKernelClipping =
False 118 subconfigFake.fitForBackground =
True 120 policyFake = pexConfig.makePolicy(subconfigFake)
123 kSize = subconfigFake.kernelSize
126 gaussKernelWidth = sizeCell//2
131 spatialKernelWidth = kSize
134 border = (gaussKernelWidth + spatialKernelWidth)//2
137 totalSize = nCell * sizeCell + 2*border
139 for x
in range(nCell):
140 for y
in range(nCell):
141 tim.set(x*sizeCell + sizeCell//2 + border - 1,
142 y*sizeCell + sizeCell//2 + border - 1,
146 gaussFunction = afwMath.GaussianFunction2D(tGaussianWidth, tGaussianWidth)
148 cim = afwImage.ImageF(tim.getDimensions())
153 bbox = gaussKernel.shrinkBBox(tim.getBBox(afwImage.LOCAL))
154 tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)
158 polyFunc = afwMath.PolynomialFunction2D(1)
160 nToUse = min(len(kCoeffs), len(basisList))
164 sKernel.setSpatialParameters(kCoeffs[:nToUse])
165 sim = afwImage.ImageF(tim.getDimensions())
169 bbox = sKernel.shrinkBBox(sim.getBBox(afwImage.LOCAL))
175 tim += 2 * np.abs(np.min(tim.getArray()))
183 sim = afwImage.ImageF(sim, bbox, afwImage.LOCAL)
184 svar = afwImage.ImageF(sim,
True)
187 sMi = afwImage.MaskedImageF(sim, smask, svar)
189 tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)
190 tvar = afwImage.ImageF(tim,
True)
193 tMi = afwImage.MaskedImageF(tim, tmask, tvar)
197 ds9.mtv(tMi, frame=1)
198 ds9.mtv(sMi, frame=2)
206 stampHalfWidth = 2 * kSize
207 for x
in range(nCell):
208 for y
in range(nCell):
209 xCoord = x * sizeCell + sizeCell // 2
210 yCoord = y * sizeCell + sizeCell // 2
212 yCoord - stampHalfWidth)
214 yCoord + stampHalfWidth)
216 tsi = afwImage.MaskedImageF(tMi, bbox, origin=afwImage.LOCAL)
217 ssi = afwImage.MaskedImageF(sMi, bbox, origin=afwImage.LOCAL)
219 kc = diffimLib.makeKernelCandidate(xCoord, yCoord, tsi, ssi, policyFake)
220 kernelCellSet.insertCandidate(kc)
224 return tMi, sMi, sKernel, kernelCellSet, configFake
234 algorithm = config.algorithm
235 binsize = config.binSize
236 undersample = config.undersampleStyle
238 bctrl.setUndersampleStyle(undersample)
239 for maskedImage
in maskedImages:
240 bctrl.setNxSample(maskedImage.getWidth()//binsize + 1)
241 bctrl.setNySample(maskedImage.getHeight()//binsize + 1)
242 image = maskedImage.getImage()
245 image -= backobj.getImageF()
246 backgrounds.append(backobj.getImageF())
250 logger = Log.getLogger(
"ip.diffim.backgroundSubtract")
251 logger.debug(
"Total time for background subtraction : %.2f s", (t1-t0))
260 if not os.path.isdir(outdir):
263 for cell
in kernelCellSet.getCellList():
264 for cand
in cell.begin(
False):
265 if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
266 xCand = int(cand.getXCenter())
267 yCand = int(cand.getYCenter())
268 idCand = cand.getId()
269 diffIm = cand.getDifferenceImage(diffimLib.KernelCandidateF.ORIG)
270 kernel = cand.getKernelImage(diffimLib.KernelCandidateF.ORIG)
271 diffIm.writeFits(os.path.join(outdir,
'diffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
272 kernel.writeFits(os.path.join(outdir,
'kernel_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
275 ski = afwImage.ImageD(kernel.getDimensions())
276 psfMatchingKernel.computeImage(ski,
False, xCand, yCand)
278 sbg = backgroundModel(xCand, yCand)
279 sdmi = cand.getDifferenceImage(sk, sbg)
280 sdmi.writeFits(os.path.join(outdir,
'sdiffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
288 """ Takes an input list of Sources that were selected to constrain 289 the Psf-matching Kernel and turns them into a List of Footprints, 290 which are used to seed a set of KernelCandidates. The function 291 checks both the template and science image for masked pixels, 292 rejecting the Source if certain Mask bits (defined in config) are 293 set within the Footprint. 295 @param candidateInList: Input list of Sources 296 @param templateExposure: Template image, to be checked for Mask bits in Source Footprint 297 @param scienceExposure: Science image, to be checked for Mask bits in Source Footprint 298 @param config: Config that defines the Mask planes that indicate an invalid Source and Bbox grow radius 299 @param log: Log for output 301 @return a list of dicts having a "source" and "footprint" field, to be used for Psf-matching 304 candidateOutList = []
305 fsb = diffimLib.FindSetBitsU()
307 for mp
in config.badMaskPlanes:
308 badBitMask |= afwImage.Mask.getPlaneBitMask(mp)
309 bbox = scienceExposure.getBBox()
312 if config.scaleByFwhm:
313 fpGrowPix = int(config.fpGrowKernelScaling * kernelSize + 0.5)
315 fpGrowPix = config.fpGrowPix
316 log.info(
"Growing %d kernel candidate stars by %d pixels", len(candidateInList), fpGrowPix)
318 for kernelCandidate
in candidateInList:
319 if not type(kernelCandidate) == afwTable.SourceRecord:
320 raise RuntimeError(
"Candiate not of type afwTable.SourceRecord")
323 center =
afwGeom.Point2I(scienceExposure.getWcs().skyToPixel(kernelCandidate.getCoord()))
324 if center[0] < bbox.getMinX()
or center[0] > bbox.getMaxX():
326 if center[1] < bbox.getMinY()
or center[1] > bbox.getMaxY():
329 xmin = center[0] - fpGrowPix
330 xmax = center[0] + fpGrowPix
331 ymin = center[1] - fpGrowPix
332 ymax = center[1] + fpGrowPix
335 if (xmin - bbox.getMinX()) < 0:
336 xmax += (xmin - bbox.getMinX())
337 xmin -= (xmin - bbox.getMinX())
338 if (ymin - bbox.getMinY()) < 0:
339 ymax += (ymin - bbox.getMinY())
340 ymin -= (ymin - bbox.getMinY())
341 if (bbox.getMaxX() - xmax) < 0:
342 xmin -= (bbox.getMaxX() - xmax)
343 xmax += (bbox.getMaxX() - xmax)
344 if (bbox.getMaxY() - ymax) < 0:
345 ymin -= (bbox.getMaxY() - ymax)
346 ymax += (bbox.getMaxY() - ymax)
347 if xmin > xmax
or ymin > ymax:
352 fsb.apply(afwImage.MaskedImageF(templateExposure.getMaskedImage(), kbbox, deep=
False).getMask())
354 fsb.apply(afwImage.MaskedImageF(scienceExposure.getMaskedImage(), kbbox, deep=
False).getMask())
359 if not((bm1 & badBitMask)
or (bm2 & badBitMask)):
360 candidateOutList.append({
'source': kernelCandidate,
362 log.info(
"Selected %d / %d sources for KernelCandidacy", len(candidateOutList), len(candidateInList))
363 return candidateOutList
367 basisList, doBuild=False):
368 """Takes an input list of Sources, and turns them into 369 KernelCandidates for fitting of the Psf-matching kernel.""" 370 kernelSize = basisList[0].getWidth()
372 kernelSize, dConfig, log)
375 if doBuild
and not basisList:
378 policy = pexConfig.makePolicy(kConfig)
379 visitor = diffimLib.BuildSingleKernelVisitorF(basisList, policy)
381 policy = pexConfig.makePolicy(kConfig)
382 for cand
in footprintList:
383 bbox = cand[
'footprint'].getBBox()
384 tmi = afwImage.MaskedImageF(templateExposure.getMaskedImage(), bbox)
385 smi = afwImage.MaskedImageF(scienceExposure.getMaskedImage(), bbox)
386 kCand = diffimLib.makeKernelCandidate(cand[
'source'], tmi, smi, policy)
388 visitor.processCandidate(kCand)
389 kCand.setStatus(afwMath.SpatialCellCandidate.UNKNOWN)
390 candList.append(kCand)
400 """A functor to evaluate the Bayesian Information Criterion for the number of basis sets 401 going into the kernel fitting""" 403 def __init__(self, psfMatchConfig, psfFwhmPixTc, psfFwhmPixTnc):
408 raise RuntimeError(
"BIC only implemnted for AL (alard lupton) basis")
413 for d1i
in range(1, d1+1):
414 for d2i
in range(1, d2+1):
415 for d3i
in range(1, d3+1):
416 dList = [d1i, d2i, d3i]
420 visitor = diffimLib.BuildSingleKernelVisitorF(kList, pexConfig.makePolicy(bicConfig))
421 visitor.setSkipBuilt(
False)
422 kernelCellSet.visitCandidates(visitor, bicConfig.nStarPerCell)
424 for cell
in kernelCellSet.getCellList():
425 for cand
in cell.begin(
False):
426 if cand.getStatus() != afwMath.SpatialCellCandidate.GOOD:
428 diffIm = cand.getDifferenceImage(diffimLib.KernelCandidateF.RECENT)
429 bbox = cand.getKernel(diffimLib.KernelCandidateF.RECENT).shrinkBBox(
430 diffIm.getBBox(afwImage.LOCAL))
431 diffIm = type(diffIm)(diffIm, bbox,
True)
432 chi2 = diffIm.getImage().getArray()**2 / diffIm.getVariance().getArray()
433 n = chi2.shape[0] * chi2.shape[1]
434 bic = np.sum(chi2) + k * np.log(n)
435 if cand.getId()
not in bicArray:
436 bicArray[cand.getId()] = {}
437 bicArray[cand.getId()][(d1i, d2i, d3i)] = bic
440 for candId
in bicArray:
441 cconfig, cvals = list(bicArray[candId].keys()), list(bicArray[candId].values())
442 idx = np.argsort(cvals)
443 bestConfig = cconfig[idx[0]]
444 bestConfigs.append(bestConfig)
446 counter = Counter(bestConfigs).most_common(3)
447 log.info(
"B.I.C. prefers basis complexity %s %d times; %s %d times; %s %d times",
448 counter[0][0], counter[0][1],
449 counter[1][0], counter[1][1],
450 counter[2][0], counter[2][1])
451 return counter[0][0], counter[1][0], counter[2][0]
Configuration for image-to-image Psf matching.
def makeKernelBasisList(config, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, metadata=None)
std::shared_ptr< Background > makeBackground(ImageT const &img, BackgroundControl const &bgCtrl)
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
void randomGaussianImage(ImageT *image, Random &rand)
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, bool doNormalize, bool doCopyEdge=false)