LSSTApplications  17.0+11,17.0+34,17.0+56,17.0+57,17.0+59,17.0+7,17.0-1-g377950a+33,17.0.1-1-g114240f+2,17.0.1-1-g4d4fbc4+28,17.0.1-1-g55520dc+49,17.0.1-1-g5f4ed7e+52,17.0.1-1-g6dd7d69+17,17.0.1-1-g8de6c91+11,17.0.1-1-gb9095d2+7,17.0.1-1-ge9fec5e+5,17.0.1-1-gf4e0155+55,17.0.1-1-gfc65f5f+50,17.0.1-1-gfc6fb1f+20,17.0.1-10-g87f9f3f+1,17.0.1-11-ge9de802+16,17.0.1-16-ga14f7d5c+4,17.0.1-17-gc79d625+1,17.0.1-17-gdae4c4a+8,17.0.1-2-g26618f5+29,17.0.1-2-g54f2ebc+9,17.0.1-2-gf403422+1,17.0.1-20-g2ca2f74+6,17.0.1-23-gf3eadeb7+1,17.0.1-3-g7e86b59+39,17.0.1-3-gb5ca14a,17.0.1-3-gd08d533+40,17.0.1-30-g596af8797,17.0.1-4-g59d126d+4,17.0.1-4-gc69c472+5,17.0.1-6-g5afd9b9+4,17.0.1-7-g35889ee+1,17.0.1-7-gc7c8782+18,17.0.1-9-gc4bbfb2+3,w.2019.22
LSSTDataManagementBasePackage
diffimTools.py
Go to the documentation of this file.
1 # This file is part of ip_diffim.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 __all__ = ["backgroundSubtract", "writeKernelCellSet", "sourceToFootprintList", "NbasisEvaluator"]
23 
24 # python
25 import time
26 import os
27 from collections import Counter
28 import numpy as np
29 
30 # all the c++ level classes and routines
31 from . import diffimLib
32 
33 # all the other LSST packages
34 import lsst.afw.geom as afwGeom
35 import lsst.afw.image as afwImage
36 import lsst.afw.table as afwTable
37 import lsst.afw.detection as afwDetect
38 import lsst.afw.math.mathLib as afwMath
39 from lsst.log import Log
40 import lsst.pex.config as pexConfig
41 from .makeKernelBasisList import makeKernelBasisList
42 
43 # Helper functions for ipDiffim; mostly viewing of results and writing
44 # debugging info to disk.
45 
46 
49 
50 
51 def makeFlatNoiseImage(mi, seedStat=afwMath.MAX):
52  img = mi.getImage()
53  seed = int(10.*afwMath.makeStatistics(mi.getImage(), seedStat).getValue() + 1)
54  rdm = afwMath.Random(afwMath.Random.MT19937, seed)
55  rdmImage = img.Factory(img.getDimensions())
56  afwMath.randomGaussianImage(rdmImage, rdm)
57  return rdmImage
58 
59 
61  """Return a Poisson noise image based on im
62 
63  Parameters
64  ----------
65  im : `lsst.afw.image.Image`
66  image; the output image has the same dtype, dimensions, and shape
67  and its expectation value is the value of ``im`` at each pixel
68 
69  Returns
70  -------
71  noiseIm : `lsst.afw.image.Image`
72  Newly constructed image instance, same type as ``im``.
73 
74  Notes
75  -----
76  - Warning: This uses an undocumented numpy API (the documented API
77  uses a single float expectation value instead of an array).
78 
79  - Uses numpy.random; you may wish to call numpy.random.seed first.
80  """
81  import numpy.random as rand
82  imArr = im.getArray()
83  noiseIm = im.Factory(im.getBBox())
84  noiseArr = noiseIm.getArray()
85 
86  with np.errstate(invalid='ignore'):
87  intNoiseArr = rand.poisson(imArr)
88 
89  noiseArr[:, :] = intNoiseArr.astype(noiseArr.dtype)
90  return noiseIm
91 
92 
97 
98 
99 def fakeCoeffs():
100  kCoeffs = ((1.0, 0.0, 0.0),
101  (0.005, -0.000001, 0.000001),
102  (0.005, 0.000004, 0.000004),
103  (-0.001, -0.000030, 0.000030),
104  (-0.001, 0.000015, 0.000015),
105  (-0.005, -0.000050, 0.000050))
106  return kCoeffs
107 
108 
109 def makeFakeKernelSet(sizeCell=128, nCell=3,
110  deltaFunctionCounts=1.e4, tGaussianWidth=1.0,
111  addNoise=True, bgValue=100., display=False):
112  """Generate test template and science images with sources.
113 
114  Parameters
115  ----------
116  sizeCell : `int`, optional
117  Size of the square spatial cells in pixels.
118  nCell : `int`, optional
119  Number of adjacent spatial cells in both direction in both images.
120  deltaFunctionCounts : `float`, optional
121  Flux value for the template image sources.
122  tGaussianWidth : `float`, optional
123  Sigma of the generated Gaussian PSF sources in the template image.
124  addNoise : `bool`, optional
125  If `True`, Poisson noise is added to both the generated template
126  and science images.
127  bgValue : `float`, optional
128  Background level to be added to the generated science image.
129  display : `bool`, optional
130  If `True` displays the generated template and science images by
131  `lsst.afw.display.Display`.
132 
133  Notes
134  -----
135  - The generated images consist of adjacent ``nCell x nCell`` cells, each
136  of pixel size ``sizeCell x sizeCell``.
137  - The sources in the science image are generated by convolving the
138  template by ``sKernel``. ``sKernel`` is a spatial `LinearCombinationKernel`
139  of hard wired kernel bases functions. The linear combination has first
140  order polynomial spatial dependence with polynomial parameters from ``fakeCoeffs()``.
141  - The template image sources are generated in the center of each spatial
142  cell from one pixel, set to `deltaFunctionCounts` counts, then convolved
143  by a 2D Gaussian with sigma of `tGaussianWidth` along each axis.
144  - The sources are also returned in ``kernelCellSet`` each source is "detected"
145  exactly at the center of a cell.
146 
147  Returns
148  -------
149  tMi : `lsst.afw.image.MaskedImage`
150  Generated template image.
151  sMi : `lsst.afw.image.MaskedImage`
152  Generated science image.
153  sKernel : `lsst.afw.math.LinearCombinationKernel`
154  The spatial kernel used to generate the sources in the science image.
155  kernelCellSet : `lsst.afw.math.SpatialCellSet`
156  Cell grid of `lsst.afw.math.SpatialCell` instances, containing
157  `lsst.ip.diffim.KernelCandidate` instances around all the generated sources
158  in the science image.
159  configFake : `lsst.ip.diffim.ImagePsfMatchConfig`
160  Config instance used in the image generation.
161  """
162  from . import imagePsfMatch
163  configFake = imagePsfMatch.ImagePsfMatchConfig()
164  configFake.kernel.name = "AL"
165  subconfigFake = configFake.kernel.active
166  subconfigFake.alardNGauss = 1
167  subconfigFake.alardSigGauss = [2.5, ]
168  subconfigFake.alardDegGauss = [2, ]
169  subconfigFake.sizeCellX = sizeCell
170  subconfigFake.sizeCellY = sizeCell
171  subconfigFake.spatialKernelOrder = 1
172  subconfigFake.spatialModelType = "polynomial"
173  subconfigFake.singleKernelClipping = False # variance is a hack
174  subconfigFake.spatialKernelClipping = False # variance is a hack
175  if bgValue > 0.0:
176  subconfigFake.fitForBackground = True
177 
178  policyFake = pexConfig.makePolicy(subconfigFake)
179 
180  basisList = makeKernelBasisList(subconfigFake)
181  kSize = subconfigFake.kernelSize
182 
183  # This sets the final extent of each convolved delta function
184  gaussKernelWidth = sizeCell//2
185 
186  # This sets the scale over which pixels are correlated in the
187  # spatial convolution; should be at least as big as the kernel you
188  # are trying to fit for
189  spatialKernelWidth = kSize
190 
191  # Number of bad pixels due to convolutions
192  border = (gaussKernelWidth + spatialKernelWidth)//2
193 
194  # Make a fake image with a matrix of delta functions
195  totalSize = nCell*sizeCell + 2*border
196  tim = afwImage.ImageF(afwGeom.Extent2I(totalSize, totalSize))
197  for x in range(nCell):
198  for y in range(nCell):
199  tim[x*sizeCell + sizeCell//2 + border - 1,
200  y*sizeCell + sizeCell//2 + border - 1,
201  afwImage.LOCAL] = deltaFunctionCounts
202 
203  # Turn this into stars with a narrow width; conserve counts
204  gaussFunction = afwMath.GaussianFunction2D(tGaussianWidth, tGaussianWidth)
205  gaussKernel = afwMath.AnalyticKernel(gaussKernelWidth, gaussKernelWidth, gaussFunction)
206  cim = afwImage.ImageF(tim.getDimensions())
207  afwMath.convolve(cim, tim, gaussKernel, True)
208  tim = cim
209 
210  # Trim off border pixels
211  bbox = gaussKernel.shrinkBBox(tim.getBBox(afwImage.LOCAL))
212  tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)
213 
214  # Now make a science image which is this convolved with some
215  # spatial function. Use input basis list.
216  polyFunc = afwMath.PolynomialFunction2D(1)
217  kCoeffs = fakeCoeffs()
218  nToUse = min(len(kCoeffs), len(basisList))
219 
220  # Make the full convolved science image
221  sKernel = afwMath.LinearCombinationKernel(basisList[:nToUse], polyFunc)
222  sKernel.setSpatialParameters(kCoeffs[:nToUse])
223  sim = afwImage.ImageF(tim.getDimensions())
224  afwMath.convolve(sim, tim, sKernel, True)
225 
226  # Get the good subregion
227  bbox = sKernel.shrinkBBox(sim.getBBox(afwImage.LOCAL))
228 
229  # Add background
230  sim += bgValue
231 
232  # Watch out for negative values
233  tim += 2*np.abs(np.min(tim.getArray()))
234 
235  # Add noise?
236  if addNoise:
237  sim = makePoissonNoiseImage(sim)
238  tim = makePoissonNoiseImage(tim)
239 
240  # And turn into MaskedImages
241  sim = afwImage.ImageF(sim, bbox, afwImage.LOCAL)
242  svar = afwImage.ImageF(sim, True)
243  smask = afwImage.Mask(sim.getDimensions())
244  smask.set(0x0)
245  sMi = afwImage.MaskedImageF(sim, smask, svar)
246 
247  tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)
248  tvar = afwImage.ImageF(tim, True)
249  tmask = afwImage.Mask(tim.getDimensions())
250  tmask.set(0x0)
251  tMi = afwImage.MaskedImageF(tim, tmask, tvar)
252 
253  if display:
254  import lsst.afw.display as afwDisplay
255  afwDisplay.Display(frame=1).mtv(tMi)
256  afwDisplay.Display(frame=2).mtv(sMi)
257 
258  # Finally, make a kernelSet from these 2 images
260  afwGeom.Extent2I(sizeCell*nCell,
261  sizeCell*nCell)),
262  sizeCell,
263  sizeCell)
264  stampHalfWidth = 2*kSize
265  for x in range(nCell):
266  for y in range(nCell):
267  xCoord = x*sizeCell + sizeCell//2
268  yCoord = y*sizeCell + sizeCell//2
269  p0 = afwGeom.Point2I(xCoord - stampHalfWidth,
270  yCoord - stampHalfWidth)
271  p1 = afwGeom.Point2I(xCoord + stampHalfWidth,
272  yCoord + stampHalfWidth)
273  bbox = afwGeom.Box2I(p0, p1)
274  tsi = afwImage.MaskedImageF(tMi, bbox, origin=afwImage.LOCAL)
275  ssi = afwImage.MaskedImageF(sMi, bbox, origin=afwImage.LOCAL)
276 
277  kc = diffimLib.makeKernelCandidate(xCoord, yCoord, tsi, ssi, policyFake)
278  kernelCellSet.insertCandidate(kc)
279 
280  tMi.setXY0(0, 0)
281  sMi.setXY0(0, 0)
282  return tMi, sMi, sKernel, kernelCellSet, configFake
283 
284 
285 
288 
289 def backgroundSubtract(config, maskedImages):
290  """Subtract the background from masked images.
291 
292  Parameters
293  ----------
294  config : TODO: DM-17458
295  TODO: DM-17458
296  maskedImages : `list` of `lsst.afw.image.MaskedImage`
297  TODO: DM-17458
298 
299  Returns
300  -------
301  TODO: DM-17458
302  TODO: DM-17458
303  """
304  backgrounds = []
305  t0 = time.time()
306  algorithm = config.algorithm
307  binsize = config.binSize
308  undersample = config.undersampleStyle
309  bctrl = afwMath.BackgroundControl(algorithm)
310  bctrl.setUndersampleStyle(undersample)
311  for maskedImage in maskedImages:
312  bctrl.setNxSample(maskedImage.getWidth()//binsize + 1)
313  bctrl.setNySample(maskedImage.getHeight()//binsize + 1)
314  image = maskedImage.getImage()
315  backobj = afwMath.makeBackground(image, bctrl)
316 
317  image -= backobj.getImageF()
318  backgrounds.append(backobj.getImageF())
319  del backobj
320 
321  t1 = time.time()
322  logger = Log.getLogger("ip.diffim.backgroundSubtract")
323  logger.debug("Total time for background subtraction : %.2f s", (t1 - t0))
324  return backgrounds
325 
326 
329 
330 
331 def writeKernelCellSet(kernelCellSet, psfMatchingKernel, backgroundModel, outdir):
332  """TODO: DM-17458
333 
334  Parameters
335  ----------
336  kernelCellSet : TODO: DM-17458
337  TODO: DM-17458
338  psfMatchingKernel : TODO: DM-17458
339  TODO: DM-17458
340  backgroundModel : TODO: DM-17458
341  TODO: DM-17458
342  outdir : TODO: DM-17458
343  TODO: DM-17458
344  """
345  if not os.path.isdir(outdir):
346  os.makedirs(outdir)
347 
348  for cell in kernelCellSet.getCellList():
349  for cand in cell.begin(False): # False = include bad candidates
350  if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
351  xCand = int(cand.getXCenter())
352  yCand = int(cand.getYCenter())
353  idCand = cand.getId()
354  diffIm = cand.getDifferenceImage(diffimLib.KernelCandidateF.ORIG)
355  kernel = cand.getKernelImage(diffimLib.KernelCandidateF.ORIG)
356  diffIm.writeFits(os.path.join(outdir, 'diffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
357  kernel.writeFits(os.path.join(outdir, 'kernel_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
358 
359  # Diffim from spatial model
360  ski = afwImage.ImageD(kernel.getDimensions())
361  psfMatchingKernel.computeImage(ski, False, xCand, yCand)
362  sk = afwMath.FixedKernel(ski)
363  sbg = backgroundModel(xCand, yCand)
364  sdmi = cand.getDifferenceImage(sk, sbg)
365  sdmi.writeFits(os.path.join(outdir, 'sdiffim_c%d_x%d_y%d.fits' % (idCand, xCand, yCand)))
366 
367 
370 
371 
372 def sourceToFootprintList(candidateInList, templateExposure, scienceExposure, kernelSize, config, log):
373  """Convert a list of sources for the PSF-matching Kernel to Footprints.
374 
375  Parameters
376  ----------
377  candidateInList : TODO: DM-17458
378  Input list of Sources
379  templateExposure : TODO: DM-17458
380  Template image, to be checked for Mask bits in Source Footprint
381  scienceExposure : TODO: DM-17458
382  Science image, to be checked for Mask bits in Source Footprint
383  kernelSize : TODO: DM-17458
384  TODO: DM-17458
385  config : TODO: DM-17458
386  Config that defines the Mask planes that indicate an invalid Source and Bbox grow radius
387  log : TODO: DM-17458
388  Log for output
389 
390  Returns
391  -------
392  candidateOutList : `list`
393  a list of dicts having a "source" and "footprint" field, to be used for Psf-matching
394 
395  Raises
396  ------
397  RuntimeError
398  TODO: DM-17458
399 
400  Notes
401  -----
402  Takes an input list of Sources that were selected to constrain
403  the Psf-matching Kernel and turns them into a List of Footprints,
404  which are used to seed a set of KernelCandidates. The function
405  checks both the template and science image for masked pixels,
406  rejecting the Source if certain Mask bits (defined in config) are
407  set within the Footprint.
408  """
409 
410  candidateOutList = []
411  fsb = diffimLib.FindSetBitsU()
412  badBitMask = 0
413  for mp in config.badMaskPlanes:
414  badBitMask |= afwImage.Mask.getPlaneBitMask(mp)
415  bbox = scienceExposure.getBBox()
416 
417  # Size to grow Sources
418  if config.scaleByFwhm:
419  fpGrowPix = int(config.fpGrowKernelScaling*kernelSize + 0.5)
420  else:
421  fpGrowPix = config.fpGrowPix
422  log.info("Growing %d kernel candidate stars by %d pixels", len(candidateInList), fpGrowPix)
423 
424  for kernelCandidate in candidateInList:
425  if not type(kernelCandidate) == afwTable.SourceRecord:
426  raise RuntimeError("Candiate not of type afwTable.SourceRecord")
427  bm1 = 0
428  bm2 = 0
429  center = afwGeom.Point2I(scienceExposure.getWcs().skyToPixel(kernelCandidate.getCoord()))
430  if center[0] < bbox.getMinX() or center[0] > bbox.getMaxX():
431  continue
432  if center[1] < bbox.getMinY() or center[1] > bbox.getMaxY():
433  continue
434 
435  xmin = center[0] - fpGrowPix
436  xmax = center[0] + fpGrowPix
437  ymin = center[1] - fpGrowPix
438  ymax = center[1] + fpGrowPix
439 
440  # Keep object centered
441  if (xmin - bbox.getMinX()) < 0:
442  xmax += (xmin - bbox.getMinX())
443  xmin -= (xmin - bbox.getMinX())
444  if (ymin - bbox.getMinY()) < 0:
445  ymax += (ymin - bbox.getMinY())
446  ymin -= (ymin - bbox.getMinY())
447  if (bbox.getMaxX() - xmax) < 0:
448  xmin -= (bbox.getMaxX() - xmax)
449  xmax += (bbox.getMaxX() - xmax)
450  if (bbox.getMaxY() - ymax) < 0:
451  ymin -= (bbox.getMaxY() - ymax)
452  ymax += (bbox.getMaxY() - ymax)
453  if xmin > xmax or ymin > ymax:
454  continue
455 
456  kbbox = afwGeom.Box2I(afwGeom.Point2I(xmin, ymin), afwGeom.Point2I(xmax, ymax))
457  try:
458  fsb.apply(afwImage.MaskedImageF(templateExposure.getMaskedImage(), kbbox, deep=False).getMask())
459  bm1 = fsb.getBits()
460  fsb.apply(afwImage.MaskedImageF(scienceExposure.getMaskedImage(), kbbox, deep=False).getMask())
461  bm2 = fsb.getBits()
462  except Exception:
463  pass
464  else:
465  if not((bm1 & badBitMask) or (bm2 & badBitMask)):
466  candidateOutList.append({'source': kernelCandidate,
467  'footprint': afwDetect.Footprint(afwGeom.SpanSet(kbbox))})
468  log.info("Selected %d / %d sources for KernelCandidacy", len(candidateOutList), len(candidateInList))
469  return candidateOutList
470 
471 
472 def sourceTableToCandidateList(sourceTable, templateExposure, scienceExposure, kConfig, dConfig, log,
473  basisList, doBuild=False):
474  """Convert a list of Sources into KernelCandidates.
475 
476  The KernelCandidates are used for fitting the Psf-matching kernel.
477 
478  Parameters
479  ----------
480  sourceTable : TODO: DM-17458
481  TODO: DM-17458
482  templateExposure : TODO: DM-17458
483  TODO: DM-17458
484  scienceExposure : TODO: DM-17458
485  TODO: DM-17458
486  kConfig : TODO: DM-17458
487  TODO: DM-17458
488  dConfig : TODO: DM-17458
489  TODO: DM-17458
490  log : TODO: DM-17458
491  TODO: DM-17458
492  basisList : TODO: DM-17458
493  TODO: DM-17458
494  doBuild : `bool`, optional
495  TODO: DM-17458
496 
497  Returns
498  -------
499  TODO: DM-17458
500  TODO: DM-17458
501  """
502  kernelSize = basisList[0].getWidth()
503  footprintList = sourceToFootprintList(list(sourceTable), templateExposure, scienceExposure,
504  kernelSize, dConfig, log)
505  candList = []
506 
507  if doBuild and not basisList:
508  doBuild = False
509  else:
510  policy = pexConfig.makePolicy(kConfig)
511  visitor = diffimLib.BuildSingleKernelVisitorF(basisList, policy)
512 
513  policy = pexConfig.makePolicy(kConfig)
514  for cand in footprintList:
515  bbox = cand['footprint'].getBBox()
516  tmi = afwImage.MaskedImageF(templateExposure.getMaskedImage(), bbox)
517  smi = afwImage.MaskedImageF(scienceExposure.getMaskedImage(), bbox)
518  kCand = diffimLib.makeKernelCandidate(cand['source'], tmi, smi, policy)
519  if doBuild:
520  visitor.processCandidate(kCand)
521  kCand.setStatus(afwMath.SpatialCellCandidate.UNKNOWN)
522  candList.append(kCand)
523  return candList
524 
525 
526 
529 
530 
532  """A functor to evaluate the Bayesian Information Criterion for the number of basis sets
533  going into the kernel fitting"""
534 
535  def __init__(self, psfMatchConfig, psfFwhmPixTc, psfFwhmPixTnc):
536  self.psfMatchConfig = psfMatchConfig
537  self.psfFwhmPixTc = psfFwhmPixTc
538  self.psfFwhmPixTnc = psfFwhmPixTnc
539  if not self.psfMatchConfig.kernelBasisSet == "alard-lupton":
540  raise RuntimeError("BIC only implemnted for AL (alard lupton) basis")
541 
542  def __call__(self, kernelCellSet, log):
543  d1, d2, d3 = self.psfMatchConfig.alardDegGauss
544  bicArray = {}
545  for d1i in range(1, d1 + 1):
546  for d2i in range(1, d2 + 1):
547  for d3i in range(1, d3 + 1):
548  dList = [d1i, d2i, d3i]
549  bicConfig = type(self.psfMatchConfig)(self.psfMatchConfig, alardDegGauss=dList)
550  kList = makeKernelBasisList(bicConfig, self.psfFwhmPixTc, self.psfFwhmPixTnc)
551  k = len(kList)
552  visitor = diffimLib.BuildSingleKernelVisitorF(kList, pexConfig.makePolicy(bicConfig))
553  visitor.setSkipBuilt(False)
554  kernelCellSet.visitCandidates(visitor, bicConfig.nStarPerCell)
555 
556  for cell in kernelCellSet.getCellList():
557  for cand in cell.begin(False): # False = include bad candidates
558  if cand.getStatus() != afwMath.SpatialCellCandidate.GOOD:
559  continue
560  diffIm = cand.getDifferenceImage(diffimLib.KernelCandidateF.RECENT)
561  bbox = cand.getKernel(diffimLib.KernelCandidateF.RECENT).shrinkBBox(
562  diffIm.getBBox(afwImage.LOCAL))
563  diffIm = type(diffIm)(diffIm, bbox, True)
564  chi2 = diffIm.getImage().getArray()**2/diffIm.getVariance().getArray()
565  n = chi2.shape[0]*chi2.shape[1]
566  bic = np.sum(chi2) + k*np.log(n)
567  if cand.getId() not in bicArray:
568  bicArray[cand.getId()] = {}
569  bicArray[cand.getId()][(d1i, d2i, d3i)] = bic
570 
571  bestConfigs = []
572  for candId in bicArray:
573  cconfig, cvals = list(bicArray[candId].keys()), list(bicArray[candId].values())
574  idx = np.argsort(cvals)
575  bestConfig = cconfig[idx[0]]
576  bestConfigs.append(bestConfig)
577 
578  counter = Counter(bestConfigs).most_common(3)
579  log.info("B.I.C. prefers basis complexity %s %d times; %s %d times; %s %d times",
580  counter[0][0], counter[0][1],
581  counter[1][0], counter[1][1],
582  counter[2][0], counter[2][1])
583  return counter[0][0], counter[1][0], counter[2][0]
def makeFlatNoiseImage(mi, seedStat=afwMath.MAX)
Add noise.
Definition: diffimTools.py:51
def makeKernelBasisList(config, targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, metadata=None)
def fakeCoeffs()
Make fake images for testing; one is a delta function (or narrow gaussian) and the other is a convolu...
Definition: diffimTools.py:99
A compact representation of a collection of pixels.
Definition: SpanSet.h:77
std::shared_ptr< Background > makeBackground(ImageT const &img, BackgroundControl const &bgCtrl)
A convenience function that uses function overloading to make the correct type of Background...
Definition: Background.h:562
Pass parameters to a Background object.
Definition: Background.h:57
int min
def backgroundSubtract(config, maskedImages)
Background subtraction for ip_diffim.
Definition: diffimTools.py:289
def makeFakeKernelSet(sizeCell=128, nCell=3, deltaFunctionCounts=1.e4, tGaussianWidth=1.0, addNoise=True, bgValue=100., display=False)
Definition: diffimTools.py:111
Definition: Log.h:691
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
Definition: Statistics.h:520
A collection of SpatialCells covering an entire image.
Definition: SpatialCell.h:387
def writeKernelCellSet(kernelCellSet, psfMatchingKernel, backgroundModel, outdir)
More coarse debugging.
Definition: diffimTools.py:331
table::Key< int > type
Definition: Detector.cc:167
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:78
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:741
void randomGaussianImage(ImageT *image, Random &rand)
Set image to random numbers with a gaussian N(0, 1) distribution.
Definition: RandomImage.cc:130
def mtv(data, frame=None, title="", wcs=None, args, kwargs)
Definition: ds9.py:93
Class to describe the properties of a detected object from an image.
Definition: Footprint.h:62
def sourceTableToCandidateList(sourceTable, templateExposure, scienceExposure, kConfig, dConfig, log, basisList, doBuild=False)
Definition: diffimTools.py:473
Record class that contains measurements made on a single exposure.
Definition: Source.h:82
def __init__(self, psfMatchConfig, psfFwhmPixTc, psfFwhmPixTnc)
Definition: diffimTools.py:535
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, bool doNormalize, bool doCopyEdge=false)
Old, deprecated version of convolve.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
A kernel described by a function.
Definition: Kernel.h:573
An integer coordinate rectangle.
Definition: Box.h:54
daf::base::PropertyList * list
Definition: fits.cc:885
def __call__(self, kernelCellSet, log)
Definition: diffimTools.py:542
A class that can be used to generate sequences of random numbers according to a number of different a...
Definition: Random.h:57
def sourceToFootprintList(candidateInList, templateExposure, scienceExposure, kernelSize, config, log)
Converting types.
Definition: diffimTools.py:372
A kernel created from an Image.
Definition: Kernel.h:509