SnapPsfMatchTask

class lsst.ip.diffim.SnapPsfMatchTask(*args, **kwargs)

Bases: ImagePsfMatchTask

Image-based Psf-matching of two subsequent snaps from the same visit

Notes

This Task differs from ImagePsfMatchTask in that it matches two Exposures assuming that the images have been acquired very closely in time. Under this assumption, the astrometric misalignments and/or relative distortions should be within a pixel, and the Psf-shapes should be very similar. As a consequence, the default configurations for this class assume a very simple solution.

  • The spatial variation in the kernel (SnapPsfMatchConfig.spatialKernelOrder) is assumed to be zero

  • With no spatial variation, we turn of the spatial

    clipping loops (SnapPsfMatchConfig.spatialKernelClipping)

  • The differential background is not fit for (SnapPsfMatchConfig.fitForBackground)

  • The kernel is expected to be appx.

    a delta function, and has a small size (SnapPsfMatchConfig.kernelSize)

The sub-configurations for the Alard-Lupton (SnapPsfMatchConfigAL) and delta-function (SnapPsfMatchConfigDF) bases also are designed to generate a small, simple kernel.

Task initialization

Initialization is the same as base class ImagePsfMatch.__init__, with the difference being that the Task’s ConfigClass is SnapPsfMatchConfig.

Invoking the Task

The Task is only configured to have a subtractExposures method, which in turn calls ImagePsfMatchTask.subtractExposures.

Configuration parameters

See SnapPsfMatchConfig, which uses either SnapPsfMatchConfigDF and SnapPsfMatchConfigAL as its active configuration.

Debug variables

The lsst.pipe.base.cmdLineTask.CmdLineTask command line task interface supports a flag -d/–debug to importdebug.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.utils.logging as logUtils
logUtils.trace_set_at("lsst.ip.diffim", 4)

Examples

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

examples/snapPsfMatchTask.py
examples/snapPsfMatchTask.py --debug
examples/snapPsfMatchTask.py --debug --template /path/to/templateExp.fits
--science /path/to/scienceExp.fits

First, create a subclass of SnapPsfMatchTask that accepts two exposures. Ideally these exposures would have been taken back-to-back, such that the pointing/background/Psf does not vary substantially between the two:

class MySnapPsfMatchTask(SnapPsfMatchTask):
    def __init__(self, *args, **kwargs):
        SnapPsfMatchTask.__init__(self, *args, **kwargs)
    def run(self, templateExp, scienceExp):
        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

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Demonstrate the use of ImagePsfMatchTask")
    parser.add_argument("--debug", "-d", action="store_true", help="Load debug.py?", default=False)
    parser.add_argument("--template", "-t", help="Template Exposure to use", default=None)
    parser.add_argument("--science", "-s", help="Science Exposure to use", default=None)
    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.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 choose the basis set to use:

def run(args):
    #
    # Create the Config and use sum of gaussian basis
    #
    config = SnapPsfMatchTask.ConfigClass()
    config.doWarping = True
    config.kernel.name = "AL"

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; as a detail of how the fake images were made, you do have to fit for a differential background):

# 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.fitForBackground = True
    config.kernel.active.spatialBgOrder = 0
    config.kernel.active.sizeCellX = 128
    config.kernel.active.sizeCellY = 128

Display the two images if -debug

if args.debug:
    afwDisplay.Display(frame=1).mtv(templateExp, title="Example script: Input Template")
    afwDisplay.Display(frame=2).mtv(scienceExp, title="Example script: Input Science Image")

Create and run the Task

# Create the Task
psfMatchTask = MySnapPsfMatchTask(config=config)
# Run the Task
result = psfMatchTask.run(templateExp, scienceExp)

And finally provide optional debugging display of the Psf-matched (via the Psf models) science image:

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[, position])

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.

makeKernelBasisList([targetFwhmPix, ...])

Wrapper to set log messages for lsst.ip.diffim.makeKernelBasisList.

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() None

Empty (clear) the metadata for this Task and all sub-Tasks.

getAllSchemaCatalogs() Dict[str, Any]

Get schema catalogs for all tasks in the hierarchy, combining the results into a single dict.

Returns:
schemacatalogsdict

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.

getFullMetadata() TaskMetadata

Get metadata for all tasks.

Returns:
metadataTaskMetadata

The 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.

getFullName() str

Get the task name as a hierarchical name including parent task names.

Returns:
fullNamestr

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”.

getFwhmPix(psf, position=None)

Return the FWHM in pixels of a Psf.

getName() str

Get the name of the task.

Returns:
taskNamestr

Name of the task.

See also

getFullName
getSchemaCatalogs() Dict[str, Any]

Get the schemas generated by this task.

Returns:
schemaCatalogsdict

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.

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:
exposurelsst.afw.image.Exposure

Exposure on which to run detection/measurement

sigmafloat

Detection threshold

doSmoothbool

Whether or not to smooth the Exposure with Psf before detection

idFactory

Factory for the generation of Source ids

Returns:
selectSources

source catalog containing candidates for the Psf-matching

getTaskDict() Dict[str, ReferenceType[Task]]

Get a dictionary of all tasks as a shallow copy.

Returns:
taskDictdict

Dictionary containing full task name: task object for the top-level task and all subtasks, sub-subtasks, etc.

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:
templateExposurelsst.afw.image.Exposure

Exposure that will be convolved

scienceExposurelsst.afw.image.Exposure

Exposure that will be matched-to

kernelSizefloat

Dimensions of the Psf-matching Kernel, used to grow detection footprints

candidateListlist, 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:
candidateListlist of dict

A list of dicts having a “source” and “footprint” field for the Sources deemed to be appropriate for Psf matching

classmethod makeField(doc: str) ConfigurableField

Make a lsst.pex.config.ConfigurableField for this task.

Parameters:
docstr

Help text for the field.

Returns:
configurableFieldlsst.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")
makeKernelBasisList(targetFwhmPix=None, referenceFwhmPix=None, basisDegGauss=None, basisSigmaGauss=None, metadata=None)

Wrapper to set log messages for lsst.ip.diffim.makeKernelBasisList.

Parameters:
targetFwhmPixfloat, optional

Passed on to lsst.ip.diffim.generateAlardLuptonBasisList. Not used for delta function basis sets.

referenceFwhmPixfloat, optional

Passed on to lsst.ip.diffim.generateAlardLuptonBasisList. Not used for delta function basis sets.

basisDegGausslist of int, optional

Passed on to lsst.ip.diffim.generateAlardLuptonBasisList. Not used for delta function basis sets.

basisSigmaGausslist of int, optional

Passed on to lsst.ip.diffim.generateAlardLuptonBasisList. Not used for delta function basis sets.

metadatalsst.daf.base.PropertySet, optional

Passed on to lsst.ip.diffim.generateAlardLuptonBasisList. Not used for delta function basis sets.

Returns:
basisList: list of lsst.afw.math.kernel.FixedKernel

List of basis kernels.

makeSubtask(name: str, **keyArgs: Any) None

Create a subtask as a new instance as the name attribute of this task.

Parameters:
namestr

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 of ConfigurableField or RegistryField.

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:
templateExposurelsst.afw.image.Exposure

Exposure to warp and PSF-match to the reference masked image

scienceExposurelsst.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)

scienceFwhmPixfloat

FWHM (in pixels) of the Psf in the science image

candidateListlist, optional

a list of footprints/maskedImages for kernel candidates; if None then source detection is run.

  • Currently supported: list of Footprints or measAlg.PsfCandidateF

doWarpingbool

what to do if templateExposure and scienceExposure WCSs do not match:

  • if True then warp templateExposure to match scienceExposure

  • if False then raise an Exception

convolveTemplatebool

Whether to 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:
resultslsst.pipe.base.Struct

An lsst.pipe.base.Struct containing these fields:

  • matchedImagethe 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 kernel

  • backgroundModel : differential background model

  • kernelCellSet : SpatialCellSet used to solve for the PSF matching kernel

Raises:
RuntimeError

Raised if doWarping is False and templateExposure and scienceExposure 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:
templateMaskedImagelsst.afw.image.MaskedImage

masked image to PSF-match to the reference masked image; must be warped to match the reference masked image

scienceMaskedImagelsst.afw.image.MaskedImage

maskedImage whose PSF is to be matched to

templateFwhmPixfloat

FWHM (in pixels) of the Psf in the template image (image to convolve)

scienceFwhmPixfloat

FWHM (in pixels) of the Psf in the science image

candidateListlist, 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:
resultcallable
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 as scienceMaskedImage.

  • 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)

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:
templateExposurelsst.afw.image.ExposureF

Exposure to PSF-match to scienceExposure

scienceExposurelsst.afw.image.ExposureF

Reference Exposure

templateFwhmPixfloat

FWHM (in pixels) of the Psf in the template image (image to convolve)

scienceFwhmPixfloat

FWHM (in pixels) of the Psf in the science image

candidateListlist, optional

A list of footprints/maskedImages for kernel candidates; if None then source detection is run.

  • Currently supported: list of Footprints or measAlg.PsfCandidateF

doWarpingbool

What to do if templateExposure` and scienceExposure WCSs do not match:

  • if True then warp templateExposure to match scienceExposure

  • if False then raise an Exception

convolveTemplatebool

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:
resultlsst.pipe.base.Struct

An lsst.pipe.base.Struct containing these fields:

  • subtractedExposuresubtracted Exposure

    scienceExposure - (matchedImage + backgroundModel)

  • matchedImagetemplateExposure 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

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:
templateMaskedImagelsst.afw.image.MaskedImage

MaskedImage to PSF-match to scienceMaskedImage

scienceMaskedImagelsst.afw.image.MaskedImage

Reference MaskedImage

templateFwhmPixfloat

FWHM (in pixels) of the Psf in the template image (image to convolve)

scienceFwhmPixfloat

FWHM (in pixels) of the Psf in the science image

candidateListlist, 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:
resultslsst.pipe.base.Struct

An lsst.pipe.base.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

timer(name: str, logLevel: int = 10) Iterator[None]

Context manager to log performance data for an arbitrary block of code.

Parameters:
namestr

Name of code being timed; data will be logged using item name: Start and End.

logLevel

A logging level constant.

See also

timer.logInfo

Examples

Creating a timer context:

with self.timer("someCodeToTime"):
    pass  # code to time