LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Static Private Attributes | List of all members
lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask Class Reference
Inheritance diagram for lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask:

Public Member Functions

def __init__
 
def run
 
def selectRefExposure
 
def matchBackgrounds
 

Public Attributes

 sctrl
 
 debugDataIdString
 

Static Public Attributes

 ConfigClass = MatchBackgroundsConfig
 

Private Member Functions

def _debugPlot
 
def _gridImage
 

Static Private Attributes

string _DefaultName = "matchBackgrounds"
 

Detailed Description

Definition at line 137 of file matchBackgrounds.py.

Constructor & Destructor Documentation

def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.__init__ (   self,
  args,
  kwargs 
)

Definition at line 140 of file matchBackgrounds.py.

141  def __init__(self, *args, **kwargs):
142  pipeBase.Task.__init__(self, *args, **kwargs)
145  self.sctrl.setAndMask(afwImage.MaskU.getPlaneBitMask(self.config.badMaskPlanes))
146  self.sctrl.setNanSafe(True)
Pass parameters to a Statistics objectA class to pass parameters which control how the stats are calc...
Definition: Statistics.h:92

Member Function Documentation

def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask._debugPlot (   self,
  X,
  Y,
  Z,
  dZ,
  modelImage,
  bbox,
  model,
  resids 
)
private
Generate a plot showing the background fit and residuals.

It is called when lsstDebug.Info(__name__).savefig = True
Saves the fig to lsstDebug.Info(__name__).figpath
Displays on screen if lsstDebug.Info(__name__).display = True

@param X: array of x positions
@param Y: array of y positions
@param Z: array of the grid values that were interpolated
@param dZ: array of the error on the grid values
@param modelImage: image ofthe model of the fit
@param model: array of len(Z) containing the grid values predicted by the model
@param resids: Z - model

Definition at line 485 of file matchBackgrounds.py.

486  def _debugPlot(self, X, Y, Z, dZ, modelImage, bbox, model, resids):
487  """Generate a plot showing the background fit and residuals.
488 
489  It is called when lsstDebug.Info(__name__).savefig = True
490  Saves the fig to lsstDebug.Info(__name__).figpath
491  Displays on screen if lsstDebug.Info(__name__).display = True
492 
493  @param X: array of x positions
494  @param Y: array of y positions
495  @param Z: array of the grid values that were interpolated
496  @param dZ: array of the error on the grid values
497  @param modelImage: image ofthe model of the fit
498  @param model: array of len(Z) containing the grid values predicted by the model
499  @param resids: Z - model
500  """
501  import matplotlib.pyplot as plt
502  import matplotlib.colors
503  from mpl_toolkits.axes_grid1 import ImageGrid
504  zeroIm = afwImage.MaskedImageF(afwGeom.Box2I(bbox))
505  zeroIm += modelImage
506  x0, y0 = zeroIm.getXY0()
507  dx, dy = zeroIm.getDimensions()
508  if len(Z) == 0:
509  self.log.warn("No grid. Skipping plot generation.")
510  else:
511  max, min = numpy.max(Z), numpy.min(Z)
512  norm = matplotlib.colors.normalize(vmax=max, vmin= min)
513  maxdiff = numpy.max(numpy.abs(resids))
514  diffnorm = matplotlib.colors.normalize(vmax=maxdiff, vmin= -maxdiff)
515  rms = numpy.sqrt(numpy.mean(resids**2))
516  fig = plt.figure(1, (8, 6))
517  meanDz = numpy.mean(dZ)
518  grid = ImageGrid(fig, 111, nrows_ncols = (1, 2), axes_pad=0.1,
519  share_all=True, label_mode = "L", cbar_mode = "each",
520  cbar_size = "7%", cbar_pad="2%", cbar_location = "top")
521  im = grid[0].imshow(zeroIm.getImage().getArray(),
522  extent=(x0, x0+dx, y0+dy, y0), norm = norm,
523  cmap='Spectral')
524  im = grid[0].scatter(X, Y, c=Z, s = 15.*meanDz/dZ, edgecolor='none', norm=norm,
525  marker='o',cmap='Spectral')
526  im2 = grid[1].scatter(X, Y, c=resids, edgecolor='none', norm=diffnorm,
527  marker='s', cmap='seismic')
528  grid.cbar_axes[0].colorbar(im)
529  grid.cbar_axes[1].colorbar(im2)
530  grid[0].axis([x0, x0+dx, y0+dy, y0])
531  grid[1].axis([x0, x0+dx, y0+dy, y0])
532  grid[0].set_xlabel("model and grid")
533  grid[1].set_xlabel("residuals. rms = %0.3f"%(rms))
534  if lsstDebug.Info(__name__).savefig:
535  fig.savefig(lsstDebug.Info(__name__).figpath + self.debugDataIdString + '.png')
536  if lsstDebug.Info(__name__).display:
537  plt.show()
538  plt.clf()
An integer coordinate rectangle.
Definition: Box.h:53
def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask._gridImage (   self,
  maskedImage,
  binsize,
  statsFlag 
)
private
Private method to grid an image for debugging

Definition at line 539 of file matchBackgrounds.py.

540  def _gridImage(self, maskedImage, binsize, statsFlag):
541  """Private method to grid an image for debugging"""
542  width, height = maskedImage.getDimensions()
543  x0, y0 = maskedImage.getXY0()
544  xedges = numpy.arange(0, width, binsize)
545  yedges = numpy.arange(0, height, binsize)
546  xedges = numpy.hstack(( xedges, width )) #add final edge
547  yedges = numpy.hstack(( yedges, height )) #add final edge
548 
549  # Use lists/append to protect against the case where
550  # a bin has no valid pixels and should not be included in the fit
551  bgX = []
552  bgY = []
553  bgZ = []
554  bgdZ = []
555 
556  for ymin, ymax in zip(yedges[0:-1],yedges[1:]):
557  for xmin, xmax in zip(xedges[0:-1],xedges[1:]):
558  subBBox = afwGeom.Box2I(afwGeom.PointI(int(x0 + xmin),int(y0 + ymin)),
559  afwGeom.PointI(int(x0 + xmax-1),int(y0 + ymax-1)))
560  subIm = afwImage.MaskedImageF(maskedImage, subBBox, afwImage.PARENT, False)
561  stats = afwMath.makeStatistics(subIm,
562  afwMath.MEAN|afwMath.MEANCLIP|afwMath.MEDIAN| \
563  afwMath.NPOINT|afwMath.STDEV,
564  self.sctrl)
565  npoints, _ = stats.getResult(afwMath.NPOINT)
566  if npoints >= 2:
567  stdev, _ = stats.getResult(afwMath.STDEV)
568  if stdev < self.config.gridStdevEpsilon:
569  stdev = self.config.gridStdevEpsilon
570  bgX.append(0.5 * (x0 + xmin + x0 + xmax))
571  bgY.append(0.5 * (y0 + ymin + y0 + ymax))
572  bgdZ.append(stdev/numpy.sqrt(npoints))
573  est, _ = stats.getResult(statsFlag)
574  bgZ.append(est)
575 
576  return numpy.array(bgX), numpy.array(bgY), numpy.array(bgZ), numpy.array(bgdZ)
577 
An integer coordinate rectangle.
Definition: Box.h:53
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1082
def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.matchBackgrounds (   self,
  refExposure,
  sciExposure 
)
Match science exposure's background level to that of reference exposure.

Process creates a difference image of the reference exposure minus the science exposure, and then
generates an afw.math.Background object. It assumes (but does not require/check) that the mask plane
already has detections set. If detections have not been set/masked, sources will bias the
background estimation. 
The 'background' of the difference image is smoothed by spline interpolation (by the Background class)
or by polynomial interpolation by the Approximate class. This model of difference image is added to the
science exposure in memory.
Fit diagnostics are also calculated and returned.

@param[in] refExposure: reference exposure
@param[in,out] sciExposure: science exposure; modified by changing the background level
    to match that of the reference exposure
@returns a pipBase.Struct with fields:
    - backgroundModel: an afw.math.Approximate or an afw.math.Background.
    - fitRMS: rms of the fit. This is the sqrt(mean(residuals**2)).
    - matchedMSE: the MSE of the reference and matched images: mean((refImage - matchedSciImage)**2);
      should be comparable to difference image's mean variance.
    - diffImVar: the mean variance of the difference image.

Definition at line 330 of file matchBackgrounds.py.

331  def matchBackgrounds(self, refExposure, sciExposure):
332  """
333  Match science exposure's background level to that of reference exposure.
334 
335  Process creates a difference image of the reference exposure minus the science exposure, and then
336  generates an afw.math.Background object. It assumes (but does not require/check) that the mask plane
337  already has detections set. If detections have not been set/masked, sources will bias the
338  background estimation.
339  The 'background' of the difference image is smoothed by spline interpolation (by the Background class)
340  or by polynomial interpolation by the Approximate class. This model of difference image is added to the
341  science exposure in memory.
342  Fit diagnostics are also calculated and returned.
343 
344  @param[in] refExposure: reference exposure
345  @param[in,out] sciExposure: science exposure; modified by changing the background level
346  to match that of the reference exposure
347  @returns a pipBase.Struct with fields:
348  - backgroundModel: an afw.math.Approximate or an afw.math.Background.
349  - fitRMS: rms of the fit. This is the sqrt(mean(residuals**2)).
350  - matchedMSE: the MSE of the reference and matched images: mean((refImage - matchedSciImage)**2);
351  should be comparable to difference image's mean variance.
352  - diffImVar: the mean variance of the difference image.
353  """
354 
355  if lsstDebug.Info(__name__).savefits:
356  refExposure.writeFits(lsstDebug.Info(__name__).figpath + 'refExposure.fits')
357  sciExposure.writeFits(lsstDebug.Info(__name__).figpath + 'sciExposure.fits')
358 
359  # Check Configs for polynomials:
360  if self.config.usePolynomial:
361  x, y = sciExposure.getDimensions()
362  shortSideLength = min(x, y)
363  if shortSideLength < self.config.binSize:
364  raise ValueError("%d = config.binSize > shorter dimension = %d" % (self.config.binSize,
365  shortSideLength))
366  npoints = shortSideLength // self.config.binSize
367  if shortSideLength % self.config.binSize != 0:
368  npoints += 1
369 
370  if self.config.order > npoints - 1:
371  raise ValueError("%d = config.order > npoints - 1 = %d" % (self.config.order, npoints - 1))
372 
373  # Check that exposures are same shape
374  if (sciExposure.getDimensions() != refExposure.getDimensions()):
375  wSci, hSci = sciExposure.getDimensions()
376  wRef, hRef = refExposure.getDimensions()
377  raise RuntimeError(
378  "Exposures are different dimensions. sci:(%i, %i) vs. ref:(%i, %i)" %
379  (wSci,hSci,wRef,hRef))
380 
381  statsFlag = getattr(afwMath, self.config.gridStatistic)
382  self.sctrl.setNumSigmaClip(self.config.numSigmaClip)
383  self.sctrl.setNumIter(self.config.numIter)
384 
385  im = refExposure.getMaskedImage()
386  diffMI = im.Factory(im,True)
387  diffMI -= sciExposure.getMaskedImage()
388 
389  width = diffMI.getWidth()
390  height = diffMI.getHeight()
391  nx = width // self.config.binSize
392  if width % self.config.binSize != 0:
393  nx += 1
394  ny = height // self.config.binSize
395  if height % self.config.binSize != 0:
396  ny += 1
397 
398  bctrl = afwMath.BackgroundControl(nx, ny, self.sctrl, statsFlag)
399  bctrl.setUndersampleStyle(self.config.undersampleStyle)
400  bctrl.setInterpStyle(self.config.interpStyle)
401 
402  bkgd = afwMath.makeBackground(diffMI, bctrl)
403 
404  # Some config and input checks if config.usePolynomial:
405  # 1) Check that order/bin size make sense:
406  # 2) Change binsize or order if underconstrained.
407  if self.config.usePolynomial:
408  order = self.config.order
409  bgX, bgY, bgZ, bgdZ = self._gridImage(diffMI, self.config.binSize, statsFlag)
410  minNumberGridPoints = min(len(set(bgX)),len(set(bgY)))
411  if len(bgZ) == 0:
412  raise ValueError("No overlap with reference. Nothing to match")
413  elif minNumberGridPoints <= self.config.order:
414  #must either lower order or raise number of bins or throw exception
415  if self.config.undersampleStyle == "THROW_EXCEPTION":
416  raise ValueError("Image does not cover enough of ref image for order and binsize")
417  elif self.config.undersampleStyle == "REDUCE_INTERP_ORDER":
418  self.log.warn("Reducing order to %d"%(minNumberGridPoints - 1))
419  order = minNumberGridPoints - 1
420  elif self.config.undersampleStyle == "INCREASE_NXNYSAMPLE":
421  newBinSize = (minNumberGridPoints*self.config.binSize)// (self.config.order +1)
422  bctrl.setNxSample(newBinSize)
423  bctrl.setNySample(newBinSize)
424  bkgd = afwMath.makeBackground(diffMI, bctrl) #do over
425  self.log.warn("Decreasing binsize to %d"%(newBinSize))
426 
427  #If there is no variance in any image pixels, do not weight bins by inverse variance
428  isUniformImageDiff = not numpy.any(bgdZ > self.config.gridStdevEpsilon)
429  weightByInverseVariance = False if isUniformImageDiff else self.config.approxWeighting
430 
431  #Add offset to sciExposure
432  try:
433  if self.config.usePolynomial:
434  actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV,
435  order, order, weightByInverseVariance)
436  undersampleStyle = getattr(afwMath, self.config.undersampleStyle)
437  approx = bkgd.getApproximate(actrl,undersampleStyle)
438  bkgdImage = approx.getImage()
439  else:
440  bkgdImage = bkgd.getImageF()
441  except Exception, e:
442  raise RuntimeError("Background/Approximation failed to interp image %s: %s" % (
443  self.debugDataIdString, e))
444 
445  sciMI = sciExposure.getMaskedImage()
446  sciMI += bkgdImage
447  del sciMI
448 
449  #Need RMS from fit: 2895 will replace this:
450  rms = 0.0
451  X, Y, Z, dZ = self._gridImage(diffMI, self.config.binSize, statsFlag)
452  x0, y0 = diffMI.getXY0()
453  modelValueArr = numpy.empty(len(Z))
454  for i in range(len(X)):
455  modelValueArr[i] = bkgdImage.get(int(X[i]-x0),int(Y[i]-y0))
456  resids = Z - modelValueArr
457  rms = numpy.sqrt(numpy.mean(resids[~numpy.isnan(resids)]**2))
458 
459  if lsstDebug.Info(__name__).savefits:
460  sciExposure.writeFits(lsstDebug.Info(__name__).figpath + 'sciMatchedExposure.fits')
461 
462  if lsstDebug.Info(__name__).savefig:
463  bbox = afwGeom.Box2D(refExposure.getMaskedImage().getBBox())
464  try:
465  self._debugPlot(X, Y, Z, dZ, bkgdImage, bbox, modelValueArr, resids)
466  except Exception, e:
467  self.log.warn('Debug plot not generated: %s'%(e))
468 
469  meanVar = afwMath.makeStatistics(diffMI.getVariance(),diffMI.getMask(),
470  afwMath.MEANCLIP, self.sctrl).getValue()
471 
472  diffIm = diffMI.getImage()
473  diffIm -= bkgdImage #diffMI should now have a mean ~ 0
474  del diffIm
475  mse = afwMath.makeStatistics(diffMI, afwMath.MEANSQUARE, self.sctrl).getValue()
476 
477  outBkgd = approx if self.config.usePolynomial else bkgd
478 
479 
480  return pipeBase.Struct(
481  backgroundModel = outBkgd,
482  fitRMS = rms,
483  matchedMSE = mse,
484  diffImVar = meanVar)
boost::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:467
Pass parameters to a Background object.
Definition: Background.h:61
Control how to make an approximation.
Definition: Approximate.h:47
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1082
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.run (   self,
  expRefList,
  expDatasetType,
  imageScalerList = None,
  refExpDataRef = None,
  refImageScaler = None 
)
Match the backgrounds of a list of coadd temp exposures to a reference coadd temp exposure.

Choose a refExpDataRef automatically if none supplied.

@param[in] expRefList: list of data references to science exposures to be background-matched;
    all exposures must exist.
@param[in] expDatasetType: dataset type of exposures, e.g. 'goodSeeingCoadd_tempExp'
@param[in] imageScalerList: list of image scalers (coaddUtils.ImageScaler);
    if None then the images are not scaled
@param[in] refExpDataRef: data reference for the reference exposure.
    If None, then this task selects the best exposures from expRefList.
    if not None then must be one of the exposures in expRefList.
@param[in] refImageScaler: image scaler for reference image;
    ignored if refExpDataRef is None, else scaling is not performed if None

@return: a pipBase.Struct containing these fields:
- backgroundInfoList: a list of pipeBase.Struct, one per exposure in expRefList,
    each of which contains these fields:
    - isReference: this is the reference exposure (only one returned Struct will
contain True for this value, unless the ref exposure is listed multiple times)
    - backgroundModel: differential background model (afw.Math.Background or afw.Math.Approximate).
Add this to the science exposure to match the reference exposure.
    - fitRMS: rms of the fit. This is the sqrt(mean(residuals**2)).
    - matchedMSE: the MSE of the reference and matched images: mean((refImage - matchedSciImage)**2);
      should be comparable to difference image's mean variance.
    - diffImVar: the mean variance of the difference image.
    All fields except isReference will be None if isReference True or the fit failed.

@warning: all exposures must exist on disk

Definition at line 148 of file matchBackgrounds.py.

149  def run(self, expRefList, expDatasetType, imageScalerList=None, refExpDataRef=None, refImageScaler=None):
150  """Match the backgrounds of a list of coadd temp exposures to a reference coadd temp exposure.
151 
152  Choose a refExpDataRef automatically if none supplied.
153 
154  @param[in] expRefList: list of data references to science exposures to be background-matched;
155  all exposures must exist.
156  @param[in] expDatasetType: dataset type of exposures, e.g. 'goodSeeingCoadd_tempExp'
157  @param[in] imageScalerList: list of image scalers (coaddUtils.ImageScaler);
158  if None then the images are not scaled
159  @param[in] refExpDataRef: data reference for the reference exposure.
160  If None, then this task selects the best exposures from expRefList.
161  if not None then must be one of the exposures in expRefList.
162  @param[in] refImageScaler: image scaler for reference image;
163  ignored if refExpDataRef is None, else scaling is not performed if None
164 
165  @return: a pipBase.Struct containing these fields:
166  - backgroundInfoList: a list of pipeBase.Struct, one per exposure in expRefList,
167  each of which contains these fields:
168  - isReference: this is the reference exposure (only one returned Struct will
169  contain True for this value, unless the ref exposure is listed multiple times)
170  - backgroundModel: differential background model (afw.Math.Background or afw.Math.Approximate).
171  Add this to the science exposure to match the reference exposure.
172  - fitRMS: rms of the fit. This is the sqrt(mean(residuals**2)).
173  - matchedMSE: the MSE of the reference and matched images: mean((refImage - matchedSciImage)**2);
174  should be comparable to difference image's mean variance.
175  - diffImVar: the mean variance of the difference image.
176  All fields except isReference will be None if isReference True or the fit failed.
177 
178  @warning: all exposures must exist on disk
179  """
180 
181  numExp = len(expRefList)
182  if numExp < 1:
183  raise pipeBase.TaskError("No exposures to match")
184 
185  if expDatasetType is None:
186  raise pipeBase.TaskError("Must specify expDatasetType")
187 
188  if imageScalerList is None:
189  self.log.info("imageScalerList is None; no scaling will be performed")
190  imageScalerList = [None] * numExp
191 
192  if len(expRefList) != len(imageScalerList):
193  raise RuntimeError("len(expRefList) = %s != %s = len(imageScalerList)" % \
194  (len(expRefList), len(imageScalerList)))
195 
196  refInd = None
197  if refExpDataRef is None:
198  # select the best reference exposure from expRefList
199  refInd = self.selectRefExposure(
200  expRefList = expRefList,
201  imageScalerList = imageScalerList,
202  expDatasetType = expDatasetType,
203  )
204  refExpDataRef = expRefList[refInd]
205  refImageScaler = imageScalerList[refInd]
206 
207  # refIndSet is the index of all exposures in expDataList that match the reference.
208  # It is used to avoid background-matching an exposure to itself. It is a list
209  # because it is possible (though unlikely) that expDataList will contain duplicates.
210  expKeyList = refExpDataRef.butlerSubset.butler.getKeys(expDatasetType)
211  refMatcher = DataRefMatcher(refExpDataRef.butlerSubset.butler, expDatasetType)
212  refIndSet = set(refMatcher.matchList(ref0 = refExpDataRef, refList = expRefList))
213 
214  if refInd is not None and refInd not in refIndSet:
215  raise RuntimeError("Internal error: selected reference %s not found in expRefList")
216 
217  refExposure = refExpDataRef.get(expDatasetType, immediate=True)
218  if refImageScaler is not None:
219  refMI = refExposure.getMaskedImage()
220  refImageScaler.scaleMaskedImage(refMI)
221 
222  debugIdKeyList = tuple(set(expKeyList) - set(['tract','patch']))
223 
224  self.log.info("Matching %d Exposures" % (numExp))
225 
226  backgroundInfoList = []
227  for ind, (toMatchRef, imageScaler) in enumerate(zip(expRefList, imageScalerList)):
228  if ind in refIndSet:
229  backgroundInfoStruct = pipeBase.Struct(
230  isReference = True,
231  backgroundModel = None,
232  fitRMS = 0.0,
233  matchedMSE = None,
234  diffImVar = None,
235  )
236  else:
237  self.log.info("Matching background of %s to %s" % (toMatchRef.dataId, refExpDataRef.dataId))
238  try:
239  toMatchExposure = toMatchRef.get(expDatasetType, immediate=True)
240  if imageScaler is not None:
241  toMatchMI = toMatchExposure.getMaskedImage()
242  imageScaler.scaleMaskedImage(toMatchMI)
243  #store a string specifying the visit to label debug plot
244  self.debugDataIdString = ''.join([str(toMatchRef.dataId[vk]) for vk in debugIdKeyList])
245  backgroundInfoStruct = self.matchBackgrounds(
246  refExposure = refExposure,
247  sciExposure = toMatchExposure,
248  )
249  backgroundInfoStruct.isReference = False
250  except Exception, e:
251  self.log.warn("Failed to fit background %s: %s" % (toMatchRef.dataId, e))
252  backgroundInfoStruct = pipeBase.Struct(
253  isReference = False,
254  backgroundModel = None,
255  fitRMS = None,
256  matchedMSE = None,
257  diffImVar = None,
258  )
259 
260  backgroundInfoList.append(backgroundInfoStruct)
261 
262  return pipeBase.Struct(
263  backgroundInfoList = backgroundInfoList)
def lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.selectRefExposure (   self,
  expRefList,
  imageScalerList,
  expDatasetType 
)
Find best exposure to use as the reference exposure

Calculate an appropriate reference exposure by minimizing a cost function that penalizes
high variance,  high background level, and low coverage. Use the following config parameters:
- bestRefWeightCoverage
- bestRefWeightVariance
- bestRefWeightLevel

@param[in] expRefList: list of data references to exposures.
    Retrieves dataset type specified by expDatasetType.
    If an exposure is not found, it is skipped with a warning.
@param[in] imageScalerList: list of image scalers (coaddUtils.ImageScaler);
    must be the same length as expRefList
@param[in] expDatasetType: dataset type of exposure: e.g. 'goodSeeingCoadd_tempExp'

@return: index of best exposure

@raise pipeBase.TaskError if none of the exposures in expRefList are found.

Definition at line 265 of file matchBackgrounds.py.

266  def selectRefExposure(self, expRefList, imageScalerList, expDatasetType):
267  """Find best exposure to use as the reference exposure
268 
269  Calculate an appropriate reference exposure by minimizing a cost function that penalizes
270  high variance, high background level, and low coverage. Use the following config parameters:
271  - bestRefWeightCoverage
272  - bestRefWeightVariance
273  - bestRefWeightLevel
274 
275  @param[in] expRefList: list of data references to exposures.
276  Retrieves dataset type specified by expDatasetType.
277  If an exposure is not found, it is skipped with a warning.
278  @param[in] imageScalerList: list of image scalers (coaddUtils.ImageScaler);
279  must be the same length as expRefList
280  @param[in] expDatasetType: dataset type of exposure: e.g. 'goodSeeingCoadd_tempExp'
281 
282  @return: index of best exposure
283 
284  @raise pipeBase.TaskError if none of the exposures in expRefList are found.
285  """
286  self.log.info("Calculating best reference visit")
287  varList = []
288  meanBkgdLevelList = []
289  coverageList = []
290 
291  if len(expRefList) != len(imageScalerList):
292  raise RuntimeError("len(expRefList) = %s != %s = len(imageScalerList)" % \
293  (len(expRefList), len(imageScalerList)))
294 
295  for expRef, imageScaler in zip(expRefList, imageScalerList):
296  exposure = expRef.get(expDatasetType, immediate=True)
297  maskedImage = exposure.getMaskedImage()
298  if imageScaler is not None:
299  try:
300  imageScaler.scaleMaskedImage(maskedImage)
301  except:
302  #need to put a place holder in Arr
303  varList.append(numpy.nan)
304  meanBkgdLevelList.append(numpy.nan)
305  coverageList.append(numpy.nan)
306  continue
307  statObjIm = afwMath.makeStatistics(maskedImage.getImage(), maskedImage.getMask(),
308  afwMath.MEAN | afwMath.NPOINT | afwMath.VARIANCE, self.sctrl)
309  meanVar, meanVarErr = statObjIm.getResult(afwMath.VARIANCE)
310  meanBkgdLevel, meanBkgdLevelErr = statObjIm.getResult(afwMath.MEAN)
311  npoints, npointsErr = statObjIm.getResult(afwMath.NPOINT)
312  varList.append(meanVar)
313  meanBkgdLevelList.append(meanBkgdLevel)
314  coverageList.append(npoints)
315  if not coverageList:
316  raise pipeBase.TaskError(
317  "None of the candidate %s exist; cannot select best reference exposure" % (expDatasetType,))
318 
319  # Normalize metrics to range from 0 to 1
320  varArr = numpy.array(varList)/numpy.nanmax(varList)
321  meanBkgdLevelArr = numpy.array(meanBkgdLevelList)/numpy.nanmax(meanBkgdLevelList)
322  coverageArr = numpy.nanmin(coverageList)/numpy.array(coverageList)
323 
324  costFunctionArr = self.config.bestRefWeightVariance * varArr
325  costFunctionArr += self.config.bestRefWeightLevel * meanBkgdLevelArr
326  costFunctionArr += self.config.bestRefWeightCoverage * coverageArr
327  return numpy.nanargmin(costFunctionArr)
328 
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1082

Member Data Documentation

string lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask._DefaultName = "matchBackgrounds"
staticprivate

Definition at line 139 of file matchBackgrounds.py.

lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.ConfigClass = MatchBackgroundsConfig
static

Definition at line 138 of file matchBackgrounds.py.

lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.debugDataIdString

Definition at line 243 of file matchBackgrounds.py.

lsst.pipe.tasks.matchBackgrounds.MatchBackgroundsTask.sctrl

Definition at line 143 of file matchBackgrounds.py.


The documentation for this class was generated from the following file: