ImagePsfMatchTask¶
-
class
lsst.ip.diffim.
ImagePsfMatchTask
(*args, **kwargs)¶ Bases:
lsst.ip.diffim.PsfMatchTask
Psf-match two MaskedImages or Exposures using the sources in the images.
Parameters: - args :
Arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
- kwargs :
Keyword arguments to be passed to lsst.ip.diffim.PsfMatchTask.__init__
Notes
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).
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:
- BuildSingleKernelVisitor, using the substamp diffim residuals from the per-source kernel fit,
- if PsfMatchConfig.singleKernelClipping is True
- KernelSumVisitor, using the mean and standard deviation of the kernel sum from all candidates,
- if PsfMatchConfig.kernelSumClipping is True
- AssessSpatialKernelVisitor, using the substamp diffim ressiduals from the spatial kernel fit,
- if PsfMatchConfig.spatialKernelClipping is True
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.
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
, andsubtractExposures
.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.
Debug variables
The lsst.pipe.base.cmdLineTask.CmdLineTask 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:
import sys import lsstDebug def DebugInfo(name): di = lsstDebug.getInfo(name) if name == "lsst.ip.diffim.psfMatch": di.display = True # enable debug output di.maskTransparency = 80 # display mask transparency di.displayCandidates = True # show all the candidates and residuals di.displayKernelBasis = False # show kernel basis functions di.displayKernelMosaic = True # show kernel realized across the image di.plotKernelSpatialModel = False # show coefficients of spatial model di.showBadCandidates = True # show the bad candidates (red) along with good (green) elif name == "lsst.ip.diffim.imagePsfMatch": di.display = True # enable debug output di.maskTransparency = 30 # display mask transparency di.displayTemplate = True # show full (remapped) template di.displaySciIm = True # show science image to match to di.displaySpatialCells = True # show spatial cells di.displayDiffIm = True # show difference image di.showBadCandidates = True # show the bad candidates (red) along with good (green) elif name == "lsst.ip.diffim.diaCatalogSourceSelector": di.display = False # enable debug output di.maskTransparency = 30 # display mask transparency di.displayExposure = True # show exposure with candidates indicated di.pauseAtEnd = False # pause when done return di lsstDebug.Info = DebugInfo lsstDebug.frame = 1
Note that if you want addional logging info, you may add to your scripts:
import lsst.log.utils as logUtils logUtils.traceSetAt("ip.diffim", 4)
Examples
A complete example of using ImagePsfMatchTask
This code is imagePsfMatchTask.py in the examples directory, and can be run as e.g.
examples/imagePsfMatchTask.py --debug examples/imagePsfMatchTask.py --debug --mode="matchExposures" 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:
class MyImagePsfMatchTask(ImagePsfMatchTask): def __init__(self, args, kwargs): ImagePsfMatchTask.__init__(self, args, kwargs) def run(self, templateExp, scienceExp, mode): if mode == "matchExposures": return self.matchExposures(templateExp, scienceExp) elif mode == "subtractExposures": 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.
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:
if args.debug: try: import debug # Since I am displaying 2 images here, set the starting frame number for the LSST debug LSST debug.lsstDebug.frame = 3 except ImportError as e: print(e, file=sys.stderr)
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:
def run(args): # # Create the Config and use sum of gaussian basis # config = ImagePsfMatchTask.ConfigClass() config.kernel.name = "AL" config.kernel.active.fitForBackground = True config.kernel.active.spatialKernelOrder = 1 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):
# Run the requested method of the Task if args.template is not None and args.science is not None: if not os.path.isfile(args.template): raise FileNotFoundError("Template image %s does not exist" % (args.template)) if not os.path.isfile(args.science): raise FileNotFoundError("Science image %s does not exist" % (args.science)) try: templateExp = afwImage.ExposureF(args.template) except Exception as e: raise RuntimeError("Cannot read template image %s" % (args.template)) try: scienceExp = afwImage.ExposureF(args.science) except Exception as e: raise RuntimeError("Cannot read science image %s" % (args.science)) else: templateExp, scienceExp = generateFakeImages() config.kernel.active.sizeCellX = 128 config.kernel.active.sizeCellY = 128
Create and run the Task:
# Create the Task psfMatchTask = MyImagePsfMatchTask(config=config) # Run the Task result = psfMatchTask.run(templateExp, scienceExp, args.mode)
And finally provide some optional debugging displays:
if args.debug: # See if the LSST debug has incremented the frame number; if not start with frame 3 try: frame = debug.lsstDebug.frame + 1 except Exception: frame = 3 afwDisplay.Display(frame=frame).mtv(result.matchedExposure, title="Example script: Matched Template Image") if "subtractedExposure" in result.getDict(): afwDisplay.Display(frame=frame + 1).mtv(result.subtractedExposure, title="Example script: Subtracted Image")
Methods Summary
emptyMetadata
()Empty (clear) the metadata for this Task and all sub-Tasks. getAllSchemaCatalogs
()Get schema catalogs for all tasks in the hierarchy, combining the results into a single dict. getFullMetadata
()Get metadata for all tasks. getFullName
()Get the task name as a hierarchical name including parent task names. getFwhmPix
(psf)Return the FWHM in pixels of a Psf. getName
()Get the name of the task. getSchemaCatalogs
()Get the schemas generated by this task. getSelectSources
(exposure[, sigma, …])Get sources to use for Psf-matching. getTaskDict
()Get a dictionary of all tasks as a shallow copy. makeCandidateList
(templateExposure, …[, …])Make a list of acceptable KernelCandidates. makeField
(doc)Make a lsst.pex.config.ConfigurableField
for this task.makeSubtask
(name, **keyArgs)Create a subtask as a new instance as the name
attribute of this task.matchExposures
(templateExposure, scienceExposure)Warp and PSF-match an exposure to the reference. matchMaskedImages
(templateMaskedImage, …)PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage). subtractExposures
(templateExposure, …[, …])Register, Psf-match and subtract two Exposures. subtractMaskedImages
(templateMaskedImage, …)Psf-match and subtract two MaskedImages. timer
(name[, logLevel])Context manager to log performance data for an arbitrary block of code. Methods Documentation
-
emptyMetadata
()¶ Empty (clear) the metadata for this Task and all sub-Tasks.
-
getAllSchemaCatalogs
()¶ Get schema catalogs for all tasks in the hierarchy, combining the results into a single dict.
Returns: - schemacatalogs :
dict
Keys are butler dataset type, values are a empty catalog (an instance of the appropriate
lsst.afw.table
Catalog type) for all tasks in the hierarchy, from the top-level task down through all subtasks.
Notes
This method may be called on any task in the hierarchy; it will return the same answer, regardless.
The default implementation should always suffice. If your subtask uses schemas the override
Task.getSchemaCatalogs
, not this method.- schemacatalogs :
-
getFullMetadata
()¶ Get metadata for all tasks.
Returns: - metadata :
lsst.daf.base.PropertySet
The
PropertySet
keys are the full task name. Values are metadata for the top-level task and all subtasks, sub-subtasks, etc.
Notes
The returned metadata includes timing information (if
@timer.timeMethod
is used) and any metadata set by the task. The name of each item consists of the full task name with.
replaced by:
, followed by.
and the name of the item, e.g.:topLevelTaskName:subtaskName:subsubtaskName.itemName
using
:
in the full task name disambiguates the rare situation that a task has a subtask and a metadata item with the same name.- metadata :
-
getFullName
()¶ Get the task name as a hierarchical name including parent task names.
Returns: - fullName :
str
The full name consists of the name of the parent task and each subtask separated by periods. For example:
- The full name of top-level task “top” is simply “top”.
- The full name of subtask “sub” of top-level task “top” is “top.sub”.
- The full name of subtask “sub2” of subtask “sub” of top-level task “top” is “top.sub.sub2”.
- fullName :
-
getFwhmPix
(psf)¶ Return the FWHM in pixels of a Psf.
-
getSchemaCatalogs
()¶ Get the schemas generated by this task.
Returns: - schemaCatalogs :
dict
Keys are butler dataset type, values are an empty catalog (an instance of the appropriate
lsst.afw.table
Catalog type) for this task.
See also
Task.getAllSchemaCatalogs
Notes
Warning
Subclasses that use schemas must override this method. The default implementation returns an empty dict.
This method may be called at any time after the Task is constructed, which means that all task schemas should be computed at construction time, not when data is actually processed. This reflects the philosophy that the schema should not depend on the data.
Returning catalogs rather than just schemas allows us to save e.g. slots for SourceCatalog as well.
- schemaCatalogs :
-
getSelectSources
(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: Returns: - selectSources :
source catalog containing candidates for the Psf-matching
-
getTaskDict
()¶ Get a dictionary of all tasks as a shallow copy.
Returns: - taskDict :
dict
Dictionary containing full task name: task object for the top-level task and all subtasks, sub-subtasks, etc.
- taskDict :
-
makeCandidateList
(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 :
lsst.afw.image.Exposure
Exposure that will be convolved
- scienceExposure :
lsst.afw.image.Exposure
Exposure that will be matched-to
- kernelSize :
float
Dimensions of the Psf-matching Kernel, used to grow detection footprints
- candidateList :
list
, optional List of Sources to examine. Elements must be of type afw.table.Source or a type that wraps a Source and has a getSource() method, such as meas.algorithms.PsfCandidateF.
Returns: - templateExposure :
-
classmethod
makeField
(doc)¶ Make a
lsst.pex.config.ConfigurableField
for this task.Parameters: - doc :
str
Help text for the field.
Returns: - configurableField :
lsst.pex.config.ConfigurableField
A
ConfigurableField
for this task.
Examples
Provides a convenient way to specify this task is a subtask of another task.
Here is an example of use:
class OtherTaskConfig(lsst.pex.config.Config): aSubtask = ATaskClass.makeField("brief description of task")
- doc :
-
makeSubtask
(name, **keyArgs)¶ Create a subtask as a new instance as the
name
attribute of this task.Parameters: - name :
str
Brief name of the subtask.
- keyArgs
Extra keyword arguments used to construct the task. The following arguments are automatically provided and cannot be overridden:
- “config”.
- “parentTask”.
Notes
The subtask must be defined by
Task.config.name
, an instance ofConfigurableField
orRegistryField
.- name :
-
matchExposures
(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:
- Warp templateExposure to match scienceExposure,
- if doWarping True and their WCSs do not already match
- Determine a PSF matching kernel and differential background model
- that matches templateExposure to scienceExposure
- Convolve templateExposure by PSF matching kernel
Parameters: - templateExposure :
lsst.afw.image.Exposure
Exposure to warp and PSF-match to the reference masked image
- scienceExposure :
lsst.afw.image.Exposure
Exposure whose WCS and PSF are to be matched to
- templateFwhmPix :`float`
FWHM (in pixels) of the Psf in the template image (image to convolve)
- scienceFwhmPix :
float
FWHM (in pixels) of the Psf in the science image
- candidateList :
list
, optional a list of footprints/maskedImages for kernel candidates; if
None
then source detection is run.- Currently supported: list of Footprints or measAlg.PsfCandidateF
- doWarping :
bool
what to do if
templateExposure
andscienceExposure
WCSs do not match:- convolveTemplate :
bool
Whether to convolve the template image or the science image:
Returns: - results :
lsst.pipe.base.Struct
An
lsst.pipe.base.Struct
containing these fields:matchedImage
: the PSF-matched exposure =- Warped
templateExposure
convolved by psfMatchingKernel. This has:- the same parent bbox, Wcs and PhotoCalib as scienceExposure
- the same filter as templateExposure
- no Psf (because the PSF-matching process does not compute one)
psfMatchingKernel
: the PSF matching kernelbackgroundModel
: differential background modelkernelCellSet
: SpatialCellSet used to solve for the PSF matching kernel
Raises: - RuntimeError
Raised if doWarping is False and
templateExposure
andscienceExposure
WCSs do not match
-
matchMaskedImages
(templateMaskedImage, scienceMaskedImage, candidateList, templateFwhmPix=None, scienceFwhmPix=None)¶ PSF-match a MaskedImage (templateMaskedImage) to a reference MaskedImage (scienceMaskedImage).
Do the following, in order:
- Determine a PSF matching kernel and differential background model
- that matches templateMaskedImage to scienceMaskedImage
- Convolve templateMaskedImage by the PSF matching kernel
Parameters: - templateMaskedImage :
lsst.afw.image.MaskedImage
masked image to PSF-match to the reference masked image; must be warped to match the reference masked image
- scienceMaskedImage :
lsst.afw.image.MaskedImage
maskedImage whose PSF is to be matched to
- templateFwhmPix :
float
FWHM (in pixels) of the Psf in the template image (image to convolve)
- scienceFwhmPix :
float
FWHM (in pixels) of the Psf in the science image
- candidateList :
list
, optional A list of footprints/maskedImages for kernel candidates; if
None
then source detection is run.- Currently supported: list of Footprints or measAlg.PsfCandidateF
Returns: - result :
callable
- An `lsst.pipe.base.Struct` containing these fields:
- - psfMatchedMaskedImage: the PSF-matched masked image =
templateMaskedImage
convolved with psfMatchingKernel. This has the same xy0, dimensions and wcs asscienceMaskedImage
.- - psfMatchingKernel: the PSF matching kernel
- - backgroundModel: differential background model
- - kernelCellSet: SpatialCellSet used to solve for the PSF matching kernel
Raises: - RuntimeError
Raised if input images have different dimensions
-
subtractExposures
(templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None, doWarping=True, convolveTemplate=True)¶ Register, Psf-match and subtract two Exposures.
Do the following, in order:
- Warp templateExposure to match scienceExposure, if their WCSs do not already match
- Determine a PSF matching kernel and differential background model
- that matches templateExposure to scienceExposure
- PSF-match templateExposure to scienceExposure
- Compute subtracted exposure (see return values for equation).
Parameters: - templateExposure :
lsst.afw.image.Exposure
Exposure to PSF-match to scienceExposure
- scienceExposure :
lsst.afw.image.Exposure
Reference Exposure
- templateFwhmPix :
float
FWHM (in pixels) of the Psf in the template image (image to convolve)
- scienceFwhmPix :
float
FWHM (in pixels) of the Psf in the science image
- candidateList :
list
, optional A list of footprints/maskedImages for kernel candidates; if
None
then source detection is run.- Currently supported: list of Footprints or measAlg.PsfCandidateF
- doWarping :
bool
What to do if
templateExposure`
andscienceExposure
WCSs do not match:- convolveTemplate :
bool
Convolve the template image or the science image
Returns: - result :
lsst.pipe.base.Struct
An
lsst.pipe.base.Struct
containing these fields:subtractedExposure
: subtracted ExposurescienceExposure - (matchedImage + backgroundModel)
matchedImage
:templateExposure
after warping to matchtemplateExposure
(if doWarping true), and convolving with psfMatchingKernel
psfMatchingKernel
: PSF matching kernelbackgroundModel
: differential background modelkernelCellSet
: SpatialCellSet used to determine PSF matching kernel
-
subtractMaskedImages
(templateMaskedImage, scienceMaskedImage, candidateList, templateFwhmPix=None, scienceFwhmPix=None)¶ Psf-match and subtract two MaskedImages.
Do the following, in order:
- PSF-match templateMaskedImage to scienceMaskedImage
- Determine the differential background
- Return the difference: scienceMaskedImage
- ((warped templateMaskedImage convolved with psfMatchingKernel) + backgroundModel)
Parameters: - templateMaskedImage :
lsst.afw.image.MaskedImage
MaskedImage to PSF-match to
scienceMaskedImage
- scienceMaskedImage :
lsst.afw.image.MaskedImage
Reference MaskedImage
- templateFwhmPix :
float
FWHM (in pixels) of the Psf in the template image (image to convolve)
- scienceFwhmPix :
float
FWHM (in pixels) of the Psf in the science image
- candidateList :
list
, optional A list of footprints/maskedImages for kernel candidates; if
None
then source detection is run.- Currently supported: list of Footprints or measAlg.PsfCandidateF
Returns: - results :
lsst.pipe.base.Struct
An
lsst.pipe.base.Struct
containing these fields:subtractedMaskedImage
:scienceMaskedImage
- (matchedImage + backgroundModel)matchedImage
: templateMaskedImage convolved with psfMatchingKernelpsfMatchingKernel`
: PSF matching kernelbackgroundModel
: differential background modelkernelCellSet
: SpatialCellSet used to determine PSF matching kernel
-
timer
(name, logLevel=10000)¶ Context manager to log performance data for an arbitrary block of code.
Parameters: - name :
str
Name of code being timed; data will be logged using item name:
Start
andEnd
.- logLevel
A
lsst.log
level constant.
See also
timer.logInfo
Examples
Creating a timer context:
with self.timer("someCodeToTime"): pass # code to time
- name :