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 | Private Attributes | List of all members
lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask Class Reference

Psf-match two MaskedImages or Exposures using the sources in the images. More...

Inheritance diagram for lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask:

Public Member Functions

def __init__
 Create the ImagePsfMatchTask. More...
 
def getFwhmPix
 Return the FWHM in pixels of a Psf. More...
 
def matchExposures
 Warp and PSF-match an exposure to the reference. More...
 
def matchMaskedImages
 PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage) More...
 
def subtractExposures
 Register, Psf-match and subtract two Exposures. More...
 
def subtractMaskedImages
 Psf-match and subtract two MaskedImages. More...
 
def getSelectSources
 Get sources to use for Psf-matching. More...
 
def makeCandidateList
 Make a list of acceptable KernelCandidates. More...
 

Public Attributes

 kConfig
 
 selectSchema
 
 selectAlgMetadata
 

Static Public Attributes

 ConfigClass = ImagePsfMatchConfig
 

Private Member Functions

def _adaptCellSize
 NOT IMPLEMENTED YET. More...
 
def _buildCellSet
 Build a SpatialCellSet for use with the solve method. More...
 
def _validateSize
 Return True if two image-like objects are the same size. More...
 
def _validateWcs
 Return True if the WCS of the two Exposures have the same origin and extent. More...
 

Private Attributes

 _warper
 

Detailed Description

Psf-match two MaskedImages or Exposures using the sources in the images.

Contents

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Description

Build a Psf-matching kernel using two input images, either as MaskedImages (in which case they need to be astrometrically aligned) or Exposures (in which case astrometric alignment will happen by default but may be turned off). This requires a list of input Sources which may be provided by the calling Task; if not, the Task will perform a coarse source detection and selection for this purpose. Sources are vetted for signal-to-noise and masked pixels (in both the template and science image), and substamps around each acceptable source are extracted and used to create an instance of KernelCandidate. Each KernelCandidate is then placed within a lsst.afw.math.SpatialCellSet, which is used by an ensemble of lsst.afw.math.CandidateVisitor instances to build the Psf-matching kernel. These visitors include, in the order that they are called: BuildSingleKernelVisitor, KernelSumVisitor, BuildSpatialKernelVisitor, and AssessSpatialKernelVisitor.

Sigma clipping of KernelCandidates is performed as follows:

The actual solving for the kernel (and differential background model) happens in lsst.ip.diffim.PsfMatchTask._solve. This involves a loop over the SpatialCellSet that first builds the per-candidate matching kernel for the requested number of KernelCandidates per cell (PsfMatchConfig.nStarPerCell). The quality of this initial per-candidate difference image is examined, using moments of the pixel residuals in the difference image normalized by the square root of the variance (i.e. sigma); ideally this should follow a normal (0, 1) distribution, but the rejection thresholds are set by the config (PsfMatchConfig.candidateResidualMeanMax and PsfMatchConfig.candidateResidualStdMax). All candidates that pass this initial build are then examined en masse to find the mean/stdev of the kernel sums across all candidates. Objects that are significantly above or below the mean, typically due to variability or sources that are saturated in one image but not the other, are also rejected. This threshold is defined by PsfMatchConfig.maxKsumSigma. Finally, a spatial model is built using all currently-acceptable candidates, and the spatial model used to derive a second set of (spatial) residuals which are again used to reject bad candidates, using the same thresholds as above.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Task initialization

Create the ImagePsfMatchTask.

Parameters
*argsarguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
**kwargskeyword arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__

Upon initialization, the kernel configuration is defined by self.config.kernel.active. The task creates an lsst.afw.math.Warper from the subConfig self.config.kernel.active.warpingConfig. A schema for the selection and measurement of candidate lsst.ip.diffim.KernelCandidates is defined, and used to initize subTasks selectDetection (for candidate detection) and selectMeasurement (for candidate measurement).

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Invoking the Task

There is no run() method for this Task. Instead there are 4 methods that may be used to invoke the Psf-matching. These are matchMaskedImages, subtractMaskedImages, matchExposures, and subtractExposures.

The methods that operate on lsst.afw.image.MaskedImage require that the images already be astrometrically aligned, and are the same shape. The methods that operate on lsst.afw.image.Exposure allow for the input images to be misregistered and potentially be different sizes; by default a lsst.afw.math.LanczosWarpingKernel is used to perform the astrometric alignment. The methods that "match" images return a Psf-matched image, while the methods that "subtract" images return a Psf-matched and template subtracted image.

See each method's returned lsst.pipe.base.Struct for more details.

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Configuration parameters

See ImagePsfMatchConfig

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Quantities set in Metadata

See PsfMatchTask

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Debug variables

The command line task interface supports a flag -d/–debug to import debug.py from your PYTHONPATH. The relevant contents of debug.py for this Task include:

1 import sys
2 import lsstDebug
3 def DebugInfo(name):
4  di = lsstDebug.getInfo(name)
5  if name == "lsst.ip.diffim.psfMatch":
6  di.display = True # enable debug output
7  di.maskTransparency = 80 # ds9 mask transparency
8  di.displayCandidates = True # show all the candidates and residuals
9  di.displayKernelBasis = False # show kernel basis functions
10  di.displayKernelMosaic = True # show kernel realized across the image
11  di.plotKernelSpatialModel = False # show coefficients of spatial model
12  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
13  elif name == "lsst.ip.diffim.imagePsfMatch":
14  di.display = True # enable debug output
15  di.maskTransparency = 30 # ds9 mask transparency
16  di.displayTemplate = True # show full (remapped) template
17  di.displaySciIm = True # show science image to match to
18  di.displaySpatialCells = True # show spatial cells
19  di.displayDiffIm = True # show difference image
20  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
21  elif name == "lsst.ip.diffim.diaCatalogSourceSelector":
22  di.display = False # enable debug output
23  di.maskTransparency = 30 # ds9 mask transparency
24  di.displayExposure = True # show exposure with candidates indicated
25  di.pauseAtEnd = False # pause when done
26  return di
27 lsstDebug.Info = DebugInfo
28 lsstDebug.frame = 1

Note that if you want addional logging info, you may add to your scripts:

1 import lsst.pex.logging as pexLog
2 pexLog.Trace_setVerbosity('lsst.ip.diffim', 5)

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

A complete example of using ImagePsfMatchTask

This code is imagePsfMatchTask.py in the examples directory, and can be run as e.g.

1 examples/imagePsfMatchTask.py --debug
2 examples/imagePsfMatchTask.py --debug --mode="matchExposures"
3 examples/imagePsfMatchTask.py --debug --template /path/to/templateExp.fits --science /path/to/scienceExp.fits
Create a subclass of ImagePsfMatchTask that allows us to either match exposures, or subtract exposures:
1 class MyImagePsfMatchTask(ImagePsfMatchTask):
2  """An override for ImagePsfMatchTask"""
3  def __init__(self, *args, **kwargs):
4  ImagePsfMatchTask.__init__(self, *args, **kwargs)
5 
6  def run(self, templateExp, scienceExp, mode):
7  if mode == "matchExposures":
8  return self.matchExposures(templateExp, scienceExp)
9  elif mode == "subtractExposures":
10  return self.subtractExposures(templateExp, scienceExp)

And allow the user the freedom to either run the script in default mode, or point to their own images on disk. Note that these images must be readable as an lsst.afw.image.Exposure:

1 if __name__ == "__main__":
2  import argparse
3  parser = argparse.ArgumentParser(description="Demonstrate the use of ImagePsfMatchTask")
4 
5  parser.add_argument("--debug", "-d", action="store_true", help="Load debug.py?", default=False)
6  parser.add_argument("--template", "-t", help="Template Exposure to use", default=None)
7  parser.add_argument("--science", "-s", help="Science Exposure to use", default=None)
8  parser.add_argument("--mode", choices=["matchExposures", "subtractExposures"],
9  default="subtractExposures", help="Which method of ImagePsfMatchTask to invoke")
10 
11  args = parser.parse_args()

We have enabled some minor display debugging in this script via the –debug option. However, if you have an lsstDebug debug.py in your PYTHONPATH you will get additional debugging displays. The following block checks for this script:

1  if args.debug:
2  try:
3  import debug
4  # Since I am displaying 2 images here, set the starting frame number for the LSST debug LSST
5  debug.lsstDebug.frame = 3
6  except ImportError as e:
7  print >> sys.stderr, e

Finally, we call a run method that we define below. First set up a Config and modify some of the parameters. E.g. use an "Alard-Lupton" sum-of-Gaussian basis, fit for a differential background, and use low order spatial variation in the kernel and background:
1 def run(args):
2  #
3  # Create the Config and use sum of gaussian basis
4  #
5  config = ImagePsfMatchTask.ConfigClass()
6  config.kernel.name = "AL"
7  config.kernel.active.fitForBackground = True
8  config.kernel.active.spatialKernelOrder = 1
9  config.kernel.active.spatialBgOrder = 0

Make sure the images (if any) that were sent to the script exist on disk and are readable. If no images are sent, make some fake data up for the sake of this example script (have a look at the code if you want more details on generateFakeImages):

1  # Run the requested method of the Task
2  if args.template is not None and args.science is not None:
3  if not os.path.isfile(args.template):
4  raise Exception, "Template image %s does not exist" % (args.template)
5  if not os.path.isfile(args.science):
6  raise Exception, "Science image %s does not exist" % (args.science)
7 
8  try:
9  templateExp = afwImage.ExposureF(args.template)
10  except pexExcept.LsstCppException, e:
11  raise Exception, "Cannot read template image %s" % (args.template)
12  try:
13  scienceExp = afwImage.ExposureF(args.science)
14  except pexExcept.LsstCppException, e:
15  raise Exception, "Cannot read science image %s" % (args.science)
16  else:
17  templateExp, scienceExp = generateFakeImages()
18  config.kernel.active.sizeCellX = 128
19  config.kernel.active.sizeCellY = 128

Create and run the Task:

1  # Create the Task
2  psfMatchTask = MyImagePsfMatchTask(config=config)
3 
4  # Run the Task
5  result = psfMatchTask.run(templateExp, scienceExp, args.mode)

And finally provide some optional debugging displays:

1  if args.debug:
2  # See if the LSST debug has incremented the frame number; if not start with frame 3
3  try:
4  frame = debug.lsstDebug.frame+1
5  except Exception:
6  frame = 3
7  ds9.mtv(result.matchedExposure, frame=frame, title="Example script: Matched Template Image")
8  if result.getDict().has_key("subtractedExposure"):
9  ds9.mtv(result.subtractedExposure, frame=frame+1, title="Example script: Subtracted Image")
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Definition at line 81 of file imagePsfMatch.py.

Constructor & Destructor Documentation

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.__init__ (   self,
  args,
  kwargs 
)

Create the ImagePsfMatchTask.

Parameters
*argsarguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
**kwargskeyword arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__

Upon initialization, the kernel configuration is defined by self.config.kernel.active. The task creates an lsst.afw.math.Warper from the subConfig self.config.kernel.active.warpingConfig. A schema for the selection and measurement of candidate lsst.ip.diffim.KernelCandidates is defined, and used to initize subTasks selectDetection (for candidate detection) and selectMeasurement (for candidate measurement).

Definition at line 269 of file imagePsfMatch.py.

270  def __init__(self, *args, **kwargs):
271  """!Create the ImagePsfMatchTask
272 
273  \param *args arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
274  \param **kwargs keyword arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
275 
276  Upon initialization, the kernel configuration is defined by self.config.kernel.active.
277  The task creates an lsst.afw.math.Warper from the subConfig self.config.kernel.active.warpingConfig.
278  A schema for the selection and measurement of candidate lsst.ip.diffim.KernelCandidates is
279  defined, and used to initize subTasks selectDetection (for candidate detection) and selectMeasurement
280  (for candidate measurement).
281  """
282  PsfMatchTask.__init__(self, *args, **kwargs)
283  self.kConfig = self.config.kernel.active
284  self._warper = afwMath.Warper.fromConfig(self.kConfig.warpingConfig)
285  self.selectSchema = afwTable.SourceTable.makeMinimalSchema()
287  self.makeSubtask("selectDetection", schema=self.selectSchema)
288  self.makeSubtask("selectMeasurement", schema=self.selectSchema, algMetadata=self.selectAlgMetadata)
Class for storing ordered metadata with comments.
Definition: PropertyList.h:81
def __init__
Create the ImagePsfMatchTask.

Member Function Documentation

def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask._adaptCellSize (   self,
  candidateList 
)
private

NOT IMPLEMENTED YET.

Definition at line 698 of file imagePsfMatch.py.

699  def _adaptCellSize(self, candidateList):
700  """! NOT IMPLEMENTED YET"""
701  return self.kConfig.sizeCellX, self.kConfig.sizeCellY
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask._buildCellSet (   self,
  templateMaskedImage,
  scienceMaskedImage,
  candidateList 
)
private

Build a SpatialCellSet for use with the solve method.

Parameters
templateMaskedImage:MaskedImage to PSF-matched to scienceMaskedImage
scienceMaskedImage:reference MaskedImage
candidateList:a list of footprints/maskedImages for kernel candidates; if None then source detection is run.
  • Currently supported: list of Footprints or measAlg.PsfCandidateF
Returns
kernelCellSet: a SpatialCellSet for use with self._solve

Definition at line 702 of file imagePsfMatch.py.

703  def _buildCellSet(self, templateMaskedImage, scienceMaskedImage, candidateList):
704  """!Build a SpatialCellSet for use with the solve method
705 
706  @param templateMaskedImage: MaskedImage to PSF-matched to scienceMaskedImage
707  @param scienceMaskedImage: reference MaskedImage
708  @param candidateList: a list of footprints/maskedImages for kernel candidates;
709  if None then source detection is run.
710  - Currently supported: list of Footprints or measAlg.PsfCandidateF
711 
712  @return kernelCellSet: a SpatialCellSet for use with self._solve
713  """
714  if not candidateList:
715  raise RuntimeError("Candidate list must be populated by makeCandidateList")
716 
717  sizeCellX, sizeCellY = self._adaptCellSize(candidateList)
718 
719  # Object to store the KernelCandidates for spatial modeling
720  kernelCellSet = afwMath.SpatialCellSet(templateMaskedImage.getBBox(),
721  sizeCellX, sizeCellY)
722 
723  policy = pexConfig.makePolicy(self.kConfig)
724  # Place candidates within the spatial grid
725  for cand in candidateList:
726  bbox = cand['footprint'].getBBox()
727 
728  tmi = afwImage.MaskedImageF(templateMaskedImage, bbox)
729  smi = afwImage.MaskedImageF(scienceMaskedImage, bbox)
730  cand = diffimLib.makeKernelCandidate(cand['source'], tmi, smi, policy)
731 
732  self.log.logdebug("Candidate %d at %f, %f" % (cand.getId(), cand.getXCenter(), cand.getYCenter()))
733  kernelCellSet.insertCandidate(cand)
734 
735  return kernelCellSet
def _buildCellSet
Build a SpatialCellSet for use with the solve method.
A collection of SpatialCells covering an entire image.
Definition: SpatialCell.h:378
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask._validateSize (   self,
  templateMaskedImage,
  scienceMaskedImage 
)
private

Return True if two image-like objects are the same size.

Definition at line 736 of file imagePsfMatch.py.

737  def _validateSize(self, templateMaskedImage, scienceMaskedImage):
738  """!Return True if two image-like objects are the same size
739  """
740  return templateMaskedImage.getDimensions() == scienceMaskedImage.getDimensions()
def _validateSize
Return True if two image-like objects are the same size.
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask._validateWcs (   self,
  templateExposure,
  scienceExposure 
)
private

Return True if the WCS of the two Exposures have the same origin and extent.

Definition at line 741 of file imagePsfMatch.py.

742  def _validateWcs(self, templateExposure, scienceExposure):
743  """!Return True if the WCS of the two Exposures have the same origin and extent
744  """
745  templateWcs = templateExposure.getWcs()
746  scienceWcs = scienceExposure.getWcs()
747  templateBBox = templateExposure.getBBox()
748  scienceBBox = scienceExposure.getBBox()
749 
750  # LLC
751  templateOrigin = templateWcs.pixelToSky(afwGeom.Point2D(templateBBox.getBegin()))
752  scienceOrigin = scienceWcs.pixelToSky(afwGeom.Point2D(scienceBBox.getBegin()))
753 
754  # URC
755  templateLimit = templateWcs.pixelToSky(afwGeom.Point2D(templateBBox.getEnd()))
756  scienceLimit = scienceWcs.pixelToSky(afwGeom.Point2D(scienceBBox.getEnd()))
757 
758  self.log.info("Template Wcs : %f,%f -> %f,%f" %
759  (templateOrigin[0], templateOrigin[1],
760  templateLimit[0], templateLimit[1]))
761  self.log.info("Science Wcs : %f,%f -> %f,%f" %
762  (scienceOrigin[0], scienceOrigin[1],
763  scienceLimit[0], scienceLimit[1]))
764 
765  templateBBox = afwGeom.Box2D(templateOrigin.getPosition(), templateLimit.getPosition())
766  scienceBBox = afwGeom.Box2D(scienceOrigin.getPosition(), scienceLimit.getPosition())
767  if not (templateBBox.overlaps(scienceBBox)):
768  raise RuntimeError("Input images do not overlap at all")
769 
770  if ( (templateOrigin.getPosition() != scienceOrigin.getPosition()) or
771  (templateLimit.getPosition() != scienceLimit.getPosition()) or
772  (templateExposure.getDimensions() != scienceExposure.getDimensions())):
773  return False
774  return True
def _validateWcs
Return True if the WCS of the two Exposures have the same origin and extent.
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.getFwhmPix (   self,
  psf 
)

Return the FWHM in pixels of a Psf.

Definition at line 289 of file imagePsfMatch.py.

290  def getFwhmPix(self, psf):
291  """!Return the FWHM in pixels of a Psf"""
292  sigPix = psf.computeShape().getDeterminantRadius()
293  return sigPix * sigma2fwhm
def getFwhmPix
Return the FWHM in pixels of a Psf.
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.getSelectSources (   self,
  exposure,
  sigma = None,
  doSmooth = True,
  idFactory = None 
)

Get sources to use for Psf-matching.

This method runs detection and measurement on an exposure. The returned set of sources will be used as candidates for Psf-matching.

Parameters
exposure:Exposure on which to run detection/measurement
sigma:Detection threshold
doSmooth:Whether or not to smooth the Exposure with Psf before detection
idFactory:Factory for the generation of Source ids
Returns
source catalog containing candidates for the Psf-matching

Definition at line 613 of file imagePsfMatch.py.

614  def getSelectSources(self, exposure, sigma=None, doSmooth=True, idFactory=None):
615  """!Get sources to use for Psf-matching
616 
617  This method runs detection and measurement on an exposure.
618  The returned set of sources will be used as candidates for
619  Psf-matching.
620 
621  @param exposure: Exposure on which to run detection/measurement
622  @param sigma: Detection threshold
623  @param doSmooth: Whether or not to smooth the Exposure with Psf before detection
624  @param idFactory: Factory for the generation of Source ids
625 
626  @return source catalog containing candidates for the Psf-matching
627  """
628 
629  if idFactory:
630  table = afwTable.SourceTable.make(self.selectSchema, idFactory)
631  else:
632  table = afwTable.SourceTable.make(self.selectSchema)
633  mi = exposure.getMaskedImage()
634 
635  imArr = mi.getImage().getArray()
636  maskArr = mi.getMask().getArray()
637  miArr = np.ma.masked_array(imArr, mask=maskArr)
638  try:
639  bkgd = getBackground(mi, self.kConfig.afwBackgroundConfig).getImageF()
640  except Exception:
641  self.log.warn("Failed to get background model. Falling back to median background estimation")
642  bkgd = np.ma.extras.median(miArr)
643 
644 
645  #Take off background for detection
646  mi -= bkgd
647  try:
648  table.setMetadata(self.selectAlgMetadata)
649  detRet = self.selectDetection.makeSourceCatalog(
650  table=table,
651  exposure=exposure,
652  sigma=sigma,
653  doSmooth=doSmooth
654  )
655  selectSources = detRet.sources
656  self.selectMeasurement.run(measCat=selectSources, exposure=exposure)
657  finally:
658  # Put back on the background in case it is needed down stream
659  mi += bkgd
660  del bkgd
661  return selectSources
def getSelectSources
Get sources to use for Psf-matching.
def getBackground
Estimate the background of an image (a thin layer on lsst.afw.math.makeBackground) ...
Definition: detection.py:555
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.makeCandidateList (   self,
  templateExposure,
  scienceExposure,
  kernelSize,
  candidateList = None 
)

Make a list of acceptable KernelCandidates.

Accept or generate a list of candidate sources for Psf-matching, and examine the Mask planes in both of the images for indications of bad pixels

Parameters
templateExposure:Exposure that will be convolved
scienceExposure:Exposure that will be matched-to
kernelSize:Dimensions of the Psf-matching Kernel, used to grow detection footprints
candidateList:List of Sources to examine
Returns
a list of dicts having a "source" and "footprint" field for the Sources deemed to be appropriate for Psf matching

Definition at line 662 of file imagePsfMatch.py.

663  def makeCandidateList(self, templateExposure, scienceExposure, kernelSize, candidateList=None):
664  """!Make a list of acceptable KernelCandidates
665 
666  Accept or generate a list of candidate sources for
667  Psf-matching, and examine the Mask planes in both of the
668  images for indications of bad pixels
669 
670  @param templateExposure: Exposure that will be convolved
671  @param scienceExposure: Exposure that will be matched-to
672  @param kernelSize: Dimensions of the Psf-matching Kernel, used to grow detection footprints
673  @param candidateList: List of Sources to examine
674 
675  @return a list of dicts having a "source" and "footprint"
676  field for the Sources deemed to be appropriate for Psf
677  matching
678  """
679  if candidateList is None:
680  candidateList = self.getSelectSources(scienceExposure)
681 
682  if len(candidateList) < 1:
683  raise RuntimeError("No candidates in candidateList")
684 
685  listTypes = set(type(x) for x in candidateList)
686  if (not len(listTypes) == 1) or (type(listTypes.pop()) != type(afwTable.SourceRecord)):
687  raise RuntimeError("Can only make candidate list from set of SourceRecords. Got %s instead." \
688  % (type(candidateList[0])))
689  candidateList = diffimTools.sourceToFootprintList(candidateList,
690  templateExposure, scienceExposure,
691  kernelSize,
692  self.kConfig.detectionConfig,
693  self.log)
694  if len(candidateList) == 0:
695  raise RuntimeError("Cannot find any objects suitable for KernelCandidacy")
696 
697  return candidateList
def getSelectSources
Get sources to use for Psf-matching.
def makeCandidateList
Make a list of acceptable KernelCandidates.
Record class that contains measurements made on a single exposure.
Definition: Source.h:81
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.matchExposures (   self,
  templateExposure,
  scienceExposure,
  templateFwhmPix = None,
  scienceFwhmPix = None,
  candidateList = None,
  doWarping = True,
  convolveTemplate = True 
)

Warp and PSF-match an exposure to the reference.

Do the following, in order:

Parameters
templateExposure:Exposure to warp and PSF-match to the reference masked image
scienceExposure:Exposure whose WCS and PSF are to be matched to
templateFwhmPix:FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix:FWHM (in pixels) of the Psf in the science image
candidateList:a list of footprints/maskedImages for kernel candidates; if None then source detection is run.
  • Currently supported: list of Footprints or measAlg.PsfCandidateF
doWarping:what to do if templateExposure's and scienceExposure's WCSs do not match:
  • if True then warp templateExposure to match scienceExposure
  • if False then raise an Exception
convolveTemplate:convolve the template image or the science image
  • if True, templateExposure is warped if doWarping, templateExposure is convolved
  • if False, templateExposure is warped if doWarping, scienceExposure is convolved
Returns
a pipeBase.Struct containing these fields:
  • matchedImage: the PSF-matched exposure = warped templateExposure convolved by psfMatchingKernel. This has:
    • the same parent bbox, Wcs and Calib as scienceExposure
    • the same filter as templateExposure
    • no Psf (because the PSF-matching process does not compute one)
  • psfMatchingKernel: the PSF matching kernel
  • backgroundModel: differential background model
  • kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel

Raise a RuntimeError if doWarping is False and templateExposure's and scienceExposure's WCSs do not match

Definition at line 297 of file imagePsfMatch.py.

298  candidateList=None, doWarping=True, convolveTemplate=True):
299  """!Warp and PSF-match an exposure to the reference
300 
301  Do the following, in order:
302  - Warp templateExposure to match scienceExposure,
303  if doWarping True and their WCSs do not already match
304  - Determine a PSF matching kernel and differential background model
305  that matches templateExposure to scienceExposure
306  - Convolve templateExposure by PSF matching kernel
307 
308  @param templateExposure: Exposure to warp and PSF-match to the reference masked image
309  @param scienceExposure: Exposure whose WCS and PSF are to be matched to
310  @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve)
311  @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image
312  @param candidateList: a list of footprints/maskedImages for kernel candidates;
313  if None then source detection is run.
314  - Currently supported: list of Footprints or measAlg.PsfCandidateF
315  @param doWarping: what to do if templateExposure's and scienceExposure's WCSs do not match:
316  - if True then warp templateExposure to match scienceExposure
317  - if False then raise an Exception
318  @param convolveTemplate: convolve the template image or the science image
319  - if True, templateExposure is warped if doWarping, templateExposure is convolved
320  - if False, templateExposure is warped if doWarping, scienceExposure is convolved
321 
322  @return a pipeBase.Struct containing these fields:
323  - matchedImage: the PSF-matched exposure =
324  warped templateExposure convolved by psfMatchingKernel. This has:
325  - the same parent bbox, Wcs and Calib as scienceExposure
326  - the same filter as templateExposure
327  - no Psf (because the PSF-matching process does not compute one)
328  - psfMatchingKernel: the PSF matching kernel
329  - backgroundModel: differential background model
330  - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel
331 
332  Raise a RuntimeError if doWarping is False and templateExposure's and scienceExposure's
333  WCSs do not match
334  """
335  if not self._validateWcs(templateExposure, scienceExposure):
336  if doWarping:
337  self.log.info("Astrometrically registering template to science image")
338  templatePsf = templateExposure.getPsf()
339  templateExposure = self._warper.warpExposure(scienceExposure.getWcs(),
340  templateExposure, destBBox=scienceExposure.getBBox())
341  templateExposure.setPsf(templatePsf)
342  else:
343  pexLog.Trace(self.log.getName(), 1, "ERROR: Input images not registered")
344  raise RuntimeError("Input images not registered")
345  if templateFwhmPix is None:
346  if not templateExposure.hasPsf():
347  self.log.warn("No estimate of Psf FWHM for template image")
348  else:
349  templateFwhmPix = self.getFwhmPix(templateExposure.getPsf())
350 
351  if scienceFwhmPix is None:
352  if not scienceExposure.hasPsf():
353  self.log.warn("No estimate of Psf FWHM for science image")
354  else:
355  scienceFwhmPix = self.getFwhmPix(scienceExposure.getPsf())
356 
357 
358  kernelSize = makeKernelBasisList(self.kConfig, templateFwhmPix, scienceFwhmPix)[0].getWidth()
359  candidateList = self.makeCandidateList(templateExposure, scienceExposure, kernelSize, candidateList)
360 
361  if convolveTemplate:
362  results = self.matchMaskedImages(
363  templateExposure.getMaskedImage(), scienceExposure.getMaskedImage(), candidateList,
364  templateFwhmPix=templateFwhmPix, scienceFwhmPix=scienceFwhmPix)
365  else:
366  results = self.matchMaskedImages(
367  scienceExposure.getMaskedImage(), templateExposure.getMaskedImage(), candidateList,
368  templateFwhmPix=scienceFwhmPix, scienceFwhmPix=templateFwhmPix)
369 
370  psfMatchedExposure = afwImage.makeExposure(results.matchedImage, scienceExposure.getWcs())
371  psfMatchedExposure.setFilter(templateExposure.getFilter())
372  psfMatchedExposure.setCalib(scienceExposure.getCalib())
373  results.warpedExposure = templateExposure
374  results.matchedExposure = psfMatchedExposure
375  return results
def getFwhmPix
Return the FWHM in pixels of a Psf.
def matchMaskedImages
PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage) ...
limited backward compatibility to the DC2 run-time trace facilities
Definition: Trace.h:93
def makeCandidateList
Make a list of acceptable KernelCandidates.
def _validateWcs
Return True if the WCS of the two Exposures have the same origin and extent.
Exposure< ImagePixelT, MaskPixelT, VariancePixelT >::Ptr makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, boost::shared_ptr< Wcs const > wcs=boost::shared_ptr< Wcs const >())
Definition: Exposure.h:308
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.matchMaskedImages (   self,
  templateMaskedImage,
  scienceMaskedImage,
  candidateList,
  templateFwhmPix = None,
  scienceFwhmPix = None 
)

PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage)

Do the following, in order:

Parameters
templateMaskedImage:masked image to PSF-match to the reference masked image; must be warped to match the reference masked image
scienceMaskedImage:maskedImage whose PSF is to be matched to
templateFwhmPix:FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix:FWHM (in pixels) of the Psf in the science image
candidateList:a list of footprints/maskedImages for kernel candidates; if None then source detection is run.
  • Currently supported: list of Footprints or measAlg.PsfCandidateF
Returns
a pipeBase.Struct containing these fields:
  • psfMatchedMaskedImage: the PSF-matched masked image = templateMaskedImage convolved with psfMatchingKernel. This has the same xy0, dimensions and wcs as scienceMaskedImage.
  • psfMatchingKernel: the PSF matching kernel
  • backgroundModel: differential background model
  • kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel

Raise a RuntimeError if input images have different dimensions

Definition at line 378 of file imagePsfMatch.py.

379  templateFwhmPix=None, scienceFwhmPix=None):
380  """!PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage)
381 
382  Do the following, in order:
383  - Determine a PSF matching kernel and differential background model
384  that matches templateMaskedImage to scienceMaskedImage
385  - Convolve templateMaskedImage by the PSF matching kernel
386 
387  @param templateMaskedImage: masked image to PSF-match to the reference masked image;
388  must be warped to match the reference masked image
389  @param scienceMaskedImage: maskedImage whose PSF is to be matched to
390  @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve)
391  @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image
392  @param candidateList: a list of footprints/maskedImages for kernel candidates;
393  if None then source detection is run.
394  - Currently supported: list of Footprints or measAlg.PsfCandidateF
395 
396  @return a pipeBase.Struct containing these fields:
397  - psfMatchedMaskedImage: the PSF-matched masked image =
398  templateMaskedImage convolved with psfMatchingKernel.
399  This has the same xy0, dimensions and wcs as scienceMaskedImage.
400  - psfMatchingKernel: the PSF matching kernel
401  - backgroundModel: differential background model
402  - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel
403 
404  Raise a RuntimeError if input images have different dimensions
405  """
406 
407  import lsstDebug
408  display = lsstDebug.Info(__name__).display
409  displayTemplate = lsstDebug.Info(__name__).displayTemplate
410  displaySciIm = lsstDebug.Info(__name__).displaySciIm
411  displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells
412  maskTransparency = lsstDebug.Info(__name__).maskTransparency
413  if not maskTransparency:
414  maskTransparency = 0
415  if display:
416  ds9.setMaskTransparency(maskTransparency)
417 
418  if not candidateList:
419  raise RuntimeError("Candidate list must be populated by makeCandidateList")
420 
421  if not self._validateSize(templateMaskedImage, scienceMaskedImage):
422  pexLog.Trace(self.log.getName(), 1, "ERROR: Input images different size")
423  raise RuntimeError("Input images different size")
424 
425  if display and displayTemplate:
426  ds9.mtv(templateMaskedImage, frame=lsstDebug.frame, title="Image to convolve")
427  lsstDebug.frame += 1
428 
429  if display and displaySciIm:
430  ds9.mtv(scienceMaskedImage, frame=lsstDebug.frame, title="Image to not convolve")
431  lsstDebug.frame += 1
432 
433  kernelCellSet = self._buildCellSet(templateMaskedImage,
434  scienceMaskedImage,
435  candidateList)
436 
437  if display and displaySpatialCells:
438  diUtils.showKernelSpatialCells(scienceMaskedImage, kernelCellSet,
439  symb="o", ctype=ds9.CYAN, ctypeUnused=ds9.YELLOW, ctypeBad=ds9.RED,
440  size=4, frame=lsstDebug.frame, title="Image to not convolve")
441  lsstDebug.frame += 1
442 
443  if templateFwhmPix and scienceFwhmPix:
444  self.log.info("Matching Psf FWHM %.2f -> %.2f pix" % (templateFwhmPix, scienceFwhmPix))
445 
446  if self.kConfig.useBicForKernelBasis:
447  tmpKernelCellSet = self._buildCellSet(templateMaskedImage,
448  scienceMaskedImage,
449  candidateList)
450  nbe = diffimTools.NbasisEvaluator(self.kConfig, templateFwhmPix, scienceFwhmPix)
451  bicDegrees = nbe(tmpKernelCellSet, self.log)
452  basisList = makeKernelBasisList(self.kConfig, templateFwhmPix, scienceFwhmPix,
453  alardDegGauss=bicDegrees[0], metadata=self.metadata)
454  del tmpKernelCellSet
455  else:
456  basisList = makeKernelBasisList(self.kConfig, templateFwhmPix, scienceFwhmPix,
457  metadata=self.metadata)
458 
459  spatialSolution, psfMatchingKernel, backgroundModel = self._solve(kernelCellSet, basisList)
460 
461 
462 
463 
464  psfMatchedMaskedImage = afwImage.MaskedImageF(templateMaskedImage.getBBox())
465  doNormalize = False
466  afwMath.convolve(psfMatchedMaskedImage, templateMaskedImage, psfMatchingKernel, doNormalize)
467  return pipeBase.Struct(
468  matchedImage=psfMatchedMaskedImage,
469  psfMatchingKernel=psfMatchingKernel,
470  backgroundModel=backgroundModel,
471  kernelCellSet=kernelCellSet,
472  )
limited backward compatibility to the DC2 run-time trace facilities
Definition: Trace.h:93
def _validateSize
Return True if two image-like objects are the same size.
def _buildCellSet
Build a SpatialCellSet for use with the solve method.
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, bool doNormalize, bool doCopyEdge=false)
Old, deprecated version of convolve.
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.subtractExposures (   self,
  templateExposure,
  scienceExposure,
  templateFwhmPix = None,
  scienceFwhmPix = None,
  candidateList = None,
  doWarping = True,
  convolveTemplate = True 
)

Register, Psf-match and subtract two Exposures.

Do the following, in order:

Parameters
templateExposure:exposure to PSF-match to scienceExposure
scienceExposure:reference Exposure
templateFwhmPix:FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix:FWHM (in pixels) of the Psf in the science image
candidateList:a list of footprints/maskedImages for kernel candidates; if None then source detection is run.
  • Currently supported: list of Footprints or measAlg.PsfCandidateF
doWarping:what to do if templateExposure's and scienceExposure's WCSs do not match:
  • if True then warp templateExposure to match scienceExposure
  • if False then raise an Exception
convolveTemplate:convolve the template image or the science image
  • if True, templateExposure is warped if doWarping, templateExposure is convolved
  • if False, templateExposure is warped if doWarping, scienceExposure is convolved
Returns
a pipeBase.Struct containing these fields:
  • subtractedExposure: subtracted Exposure = scienceExposure - (matchedImage + backgroundModel)
  • matchedImage: templateExposure after warping to match templateExposure (if doWarping true), and convolving with psfMatchingKernel
  • psfMatchingKernel: PSF matching kernel
  • backgroundModel: differential background model
  • kernelCellSet: SpatialCellSet used to determine PSF matching kernel

Definition at line 476 of file imagePsfMatch.py.

477  candidateList=None, doWarping=True, convolveTemplate=True):
478  """!Register, Psf-match and subtract two Exposures
479 
480  Do the following, in order:
481  - Warp templateExposure to match scienceExposure, if their WCSs do not already match
482  - Determine a PSF matching kernel and differential background model
483  that matches templateExposure to scienceExposure
484  - PSF-match templateExposure to scienceExposure
485  - Compute subtracted exposure (see return values for equation).
486 
487  @param templateExposure: exposure to PSF-match to scienceExposure
488  @param scienceExposure: reference Exposure
489  @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve)
490  @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image
491  @param candidateList: a list of footprints/maskedImages for kernel candidates;
492  if None then source detection is run.
493  - Currently supported: list of Footprints or measAlg.PsfCandidateF
494  @param doWarping: what to do if templateExposure's and scienceExposure's WCSs do not match:
495  - if True then warp templateExposure to match scienceExposure
496  - if False then raise an Exception
497  @param convolveTemplate: convolve the template image or the science image
498  - if True, templateExposure is warped if doWarping, templateExposure is convolved
499  - if False, templateExposure is warped if doWarping, scienceExposure is convolved
500 
501  @return a pipeBase.Struct containing these fields:
502  - subtractedExposure: subtracted Exposure = scienceExposure - (matchedImage + backgroundModel)
503  - matchedImage: templateExposure after warping to match templateExposure (if doWarping true),
504  and convolving with psfMatchingKernel
505  - psfMatchingKernel: PSF matching kernel
506  - backgroundModel: differential background model
507  - kernelCellSet: SpatialCellSet used to determine PSF matching kernel
508  """
509  results = self.matchExposures(
510  templateExposure=templateExposure,
511  scienceExposure=scienceExposure,
512  templateFwhmPix=templateFwhmPix,
513  scienceFwhmPix=scienceFwhmPix,
514  candidateList=candidateList,
515  doWarping=doWarping,
516  convolveTemplate=convolveTemplate
517  )
518 
519  subtractedExposure = afwImage.ExposureF(scienceExposure, True)
520  if convolveTemplate:
521  subtractedMaskedImage = subtractedExposure.getMaskedImage()
522  subtractedMaskedImage -= results.matchedExposure.getMaskedImage()
523  subtractedMaskedImage -= results.backgroundModel
524  else:
525  subtractedExposure.setMaskedImage(results.warpedExposure.getMaskedImage())
526  subtractedMaskedImage = subtractedExposure.getMaskedImage()
527  subtractedMaskedImage -= results.matchedExposure.getMaskedImage()
528  subtractedMaskedImage -= results.backgroundModel
529 
530  # Preserve polarity of differences
531  subtractedMaskedImage *= -1
532 
533  # Place back on native photometric scale
534  subtractedMaskedImage /= results.psfMatchingKernel.computeImage(
535  afwImage.ImageD(results.psfMatchingKernel.getDimensions()), False)
536 
537  import lsstDebug
538  display = lsstDebug.Info(__name__).display
539  displayDiffIm = lsstDebug.Info(__name__).displayDiffIm
540  maskTransparency = lsstDebug.Info(__name__).maskTransparency
541  if not maskTransparency:
542  maskTransparency = 0
543  if display:
544  ds9.setMaskTransparency(maskTransparency)
545  if display and displayDiffIm:
546  ds9.mtv(templateExposure, frame=lsstDebug.frame, title="Template")
547  lsstDebug.frame += 1
548  ds9.mtv(results.matchedExposure, frame=lsstDebug.frame, title="Matched template")
549  lsstDebug.frame += 1
550  ds9.mtv(scienceExposure, frame=lsstDebug.frame, title="Science Image")
551  lsstDebug.frame += 1
552  ds9.mtv(subtractedExposure, frame=lsstDebug.frame, title="Difference Image")
553  lsstDebug.frame += 1
554 
555  results.subtractedExposure = subtractedExposure
556  return results
def matchExposures
Warp and PSF-match an exposure to the reference.
def lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.subtractMaskedImages (   self,
  templateMaskedImage,
  scienceMaskedImage,
  candidateList,
  templateFwhmPix = None,
  scienceFwhmPix = None 
)

Psf-match and subtract two MaskedImages.

Do the following, in order:

Parameters
templateMaskedImage:MaskedImage to PSF-match to scienceMaskedImage
scienceMaskedImage:reference MaskedImage
templateFwhmPix:FWHM (in pixels) of the Psf in the template image (image to convolve)
scienceFwhmPix:FWHM (in pixels) of the Psf in the science image
candidateList:a list of footprints/maskedImages for kernel candidates; if None then source detection is run.
  • Currently supported: list of Footprints or measAlg.PsfCandidateF
Returns
a pipeBase.Struct containing these fields:
  • subtractedMaskedImage = scienceMaskedImage - (matchedImage + backgroundModel)
  • matchedImage: templateMaskedImage convolved with psfMatchingKernel
  • psfMatchingKernel: PSF matching kernel
  • backgroundModel: differential background model
  • kernelCellSet: SpatialCellSet used to determine PSF matching kernel

Definition at line 559 of file imagePsfMatch.py.

560  templateFwhmPix=None, scienceFwhmPix=None):
561  """!Psf-match and subtract two MaskedImages
562 
563  Do the following, in order:
564  - PSF-match templateMaskedImage to scienceMaskedImage
565  - Determine the differential background
566  - Return the difference: scienceMaskedImage -
567  ((warped templateMaskedImage convolved with psfMatchingKernel) + backgroundModel)
568 
569  @param templateMaskedImage: MaskedImage to PSF-match to scienceMaskedImage
570  @param scienceMaskedImage: reference MaskedImage
571  @param templateFwhmPix: FWHM (in pixels) of the Psf in the template image (image to convolve)
572  @param scienceFwhmPix: FWHM (in pixels) of the Psf in the science image
573  @param candidateList: a list of footprints/maskedImages for kernel candidates;
574  if None then source detection is run.
575  - Currently supported: list of Footprints or measAlg.PsfCandidateF
576 
577  @return a pipeBase.Struct containing these fields:
578  - subtractedMaskedImage = scienceMaskedImage - (matchedImage + backgroundModel)
579  - matchedImage: templateMaskedImage convolved with psfMatchingKernel
580  - psfMatchingKernel: PSF matching kernel
581  - backgroundModel: differential background model
582  - kernelCellSet: SpatialCellSet used to determine PSF matching kernel
583  """
584  if not candidateList:
585  raise RuntimeError("Candidate list must be populated by makeCandidateList")
586 
587  results = self.matchMaskedImages(
588  templateMaskedImage=templateMaskedImage,
589  scienceMaskedImage=scienceMaskedImage,
590  candidateList=candidateList,
591  templateFwhmPix=templateFwhmPix,
592  scienceFwhmPix=scienceFwhmPix,
593  )
594 
595  subtractedMaskedImage = afwImage.MaskedImageF(scienceMaskedImage, True)
596  subtractedMaskedImage -= results.matchedImage
597  subtractedMaskedImage -= results.backgroundModel
598  results.subtractedMaskedImage = subtractedMaskedImage
599 
600  import lsstDebug
601  display = lsstDebug.Info(__name__).display
602  displayDiffIm = lsstDebug.Info(__name__).displayDiffIm
603  maskTransparency = lsstDebug.Info(__name__).maskTransparency
604  if not maskTransparency:
605  maskTransparency = 0
606  if display:
607  ds9.setMaskTransparency(maskTransparency)
608  if display and displayDiffIm:
609  ds9.mtv(subtractedMaskedImage, frame=lsstDebug.frame)
610  lsstDebug.frame += 1
611 
612  return results
def matchMaskedImages
PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage) ...

Member Data Documentation

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask._warper
private

Definition at line 283 of file imagePsfMatch.py.

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.ConfigClass = ImagePsfMatchConfig
static

Definition at line 267 of file imagePsfMatch.py.

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.kConfig

Definition at line 282 of file imagePsfMatch.py.

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.selectAlgMetadata

Definition at line 285 of file imagePsfMatch.py.

lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask.selectSchema

Definition at line 284 of file imagePsfMatch.py.


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