22 __all__ = [
"SnapPsfMatchConfigDF",
"SnapPsfMatchConfigAL",
"SnapPsfMatchConfig",
"SnapPsfMatchTask"]
25 from .psfMatch
import PsfMatchConfigDF, PsfMatchConfigAL
26 from .imagePsfMatch
import ImagePsfMatchTask, ImagePsfMatchConfig
30 """Delta-function Psf-matching config optimized for snap subtraction""" 33 PsfMatchConfigDF.setDefaults(self)
45 """Sum-of-Gaussian (Alard-Lupton) Psf-matching config optimized for snap subtraction""" 48 PsfMatchConfigAL.setDefaults(self)
57 kernel = pexConfig.ConfigChoiceField(
60 AL=SnapPsfMatchConfigAL,
61 DF=SnapPsfMatchConfigDF
66 doWarping = pexConfig.Field(
68 doc=
"Warp the snaps?",
73 ImagePsfMatchConfig.setDefaults(self)
76 self.
kernel.active.spatialKernelOrder = 0
79 self.
kernel.active.fitForBackground =
False 82 self.
kernel.active.kernelSize = 7
85 self.
kernel.active.spatialKernelClipping =
False 89 """Image-based Psf-matching of two subsequent snaps from the same visit 93 This Task differs from ImagePsfMatchTask in that it matches two Exposures assuming that the images have 94 been acquired very closely in time. Under this assumption, the astrometric misalignments and/or 95 relative distortions should be within a pixel, and the Psf-shapes should be very similar. As a 96 consequence, the default configurations for this class assume a very simple solution. 98 - The spatial variation in the kernel (SnapPsfMatchConfig.spatialKernelOrder) is assumed to be zero 100 - With no spatial variation, we turn of the spatial 101 clipping loops (SnapPsfMatchConfig.spatialKernelClipping) 103 - The differential background is not fit for (SnapPsfMatchConfig.fitForBackground) 105 - The kernel is expected to be appx. 106 a delta function, and has a small size (SnapPsfMatchConfig.kernelSize) 108 The sub-configurations for the Alard-Lupton (SnapPsfMatchConfigAL) 109 and delta-function (SnapPsfMatchConfigDF) 110 bases also are designed to generate a small, simple kernel. 114 Initialization is the same as base class ImagePsfMatch.__init__, 115 with the difference being that the Task's 116 ConfigClass is SnapPsfMatchConfig. 120 The Task is only configured to have a subtractExposures method, which in turn calls 121 ImagePsfMatchTask.subtractExposures. 123 Configuration parameters 125 See SnapPsfMatchConfig, which uses either SnapPsfMatchConfigDF and SnapPsfMatchConfigAL 126 as its active configuration. 130 The lsst.pipe.base.cmdLineTask.CmdLineTask command line task interface supports a 131 flag -d/--debug to importdebug.py from your PYTHONPATH. The relevant contents of debug.py 132 for this Task include: 139 di = lsstDebug.getInfo(name) 140 if name == "lsst.ip.diffim.psfMatch": 141 di.display = True # enable debug output 142 di.maskTransparency = 80 # display mask transparency 143 di.displayCandidates = True # show all the candidates and residuals 144 di.displayKernelBasis = False # show kernel basis functions 145 di.displayKernelMosaic = True # show kernel realized across the image 146 di.plotKernelSpatialModel = False # show coefficients of spatial model 147 di.showBadCandidates = True # show the bad candidates (red) along with good (green) 148 elif name == "lsst.ip.diffim.imagePsfMatch": 149 di.display = True # enable debug output 150 di.maskTransparency = 30 # display mask transparency 151 di.displayTemplate = True # show full (remapped) template 152 di.displaySciIm = True # show science image to match to 153 di.displaySpatialCells = True # show spatial cells 154 di.displayDiffIm = True # show difference image 155 di.showBadCandidates = True # show the bad candidates (red) along with good (green) 156 elif name == "lsst.ip.diffim.diaCatalogSourceSelector": 157 di.display = False # enable debug output 158 di.maskTransparency = 30 # display mask transparency 159 di.displayExposure = True # show exposure with candidates indicated 160 di.pauseAtEnd = False # pause when done 162 lsstDebug.Info = DebugInfo 165 Note that if you want addional logging info, you may add to your scripts: 169 import lsst.log.utils as logUtils 170 logUtils.traceSetAt("ip.diffim", 4) 174 This code is snapPsfMatchTask.py in the examples directory, and can be run as e.g. 178 examples/snapPsfMatchTask.py 179 examples/snapPsfMatchTask.py --debug 180 examples/snapPsfMatchTask.py --debug --template /path/to/templateExp.fits 181 --science /path/to/scienceExp.fits 183 First, create a subclass of SnapPsfMatchTask that accepts two exposures. 184 Ideally these exposures would have been taken back-to-back, 185 such that the pointing/background/Psf does not vary substantially between the two: 189 class MySnapPsfMatchTask(SnapPsfMatchTask): 190 def __init__(self, *args, **kwargs): 191 SnapPsfMatchTask.__init__(self, *args, **kwargs) 192 def run(self, templateExp, scienceExp): 193 return self.subtractExposures(templateExp, scienceExp) 195 And allow the user the freedom to either run the script in default mode, 196 or point to their own images on disk. Note that these images must be 197 readable as an lsst.afw.image.Exposure 201 if __name__ == "__main__": 203 parser = argparse.ArgumentParser(description="Demonstrate the use of ImagePsfMatchTask") 204 parser.add_argument("--debug", "-d", action="store_true", help="Load debug.py?", default=False) 205 parser.add_argument("--template", "-t", help="Template Exposure to use", default=None) 206 parser.add_argument("--science", "-s", help="Science Exposure to use", default=None) 207 args = parser.parse_args() 209 We have enabled some minor display debugging in this script via the –debug option. However, 210 if you have an lsstDebug debug.in your PYTHONPATH you will get additional debugging displays. 211 The following block checks for this script 218 # Since I am displaying 2 images here, set the starting frame number for the LSST debug LSST 219 debug.lsstDebug.frame = 3 220 except ImportError as e: 221 print(e, file=sys.stderr) 223 Finally, we call a run method that we define below. 224 First set up a Config and choose the basis set to use: 230 # Create the Config and use sum of gaussian basis 232 config = SnapPsfMatchTask.ConfigClass() 233 config.doWarping = True 234 config.kernel.name = "AL" 236 Make sure the images (if any) that were sent to the script exist on disk and are readable. 237 If no images are sent, make some fake data up for the sake of this example script 238 (have a look at the code if you want more details on generateFakeImages; 239 as a detail of how the fake images were made, you do have to fit for a differential background): 243 # Run the requested method of the Task 244 if args.template is not None and args.science is not None: 245 if not os.path.isfile(args.template): 246 raise Exception("Template image %s does not exist" % (args.template)) 247 if not os.path.isfile(args.science): 248 raise Exception("Science image %s does not exist" % (args.science)) 250 templateExp = afwImage.ExposureF(args.template) 251 except Exception as e: 252 raise Exception("Cannot read template image %s" % (args.template)) 254 scienceExp = afwImage.ExposureF(args.science) 255 except Exception as e: 256 raise Exception("Cannot read science image %s" % (args.science)) 258 templateExp, scienceExp = generateFakeImages() 259 config.kernel.active.fitForBackground = True 260 config.kernel.active.spatialBgOrder = 0 261 config.kernel.active.sizeCellX = 128 262 config.kernel.active.sizeCellY = 128 264 Display the two images if -debug 269 afwDisplay.Display(frame=1).mtv(templateExp, title="Example script: Input Template") 270 afwDisplay.Display(frame=2).mtv(scienceExp, title="Example script: Input Science Image") 272 Create and run the Task 277 psfMatchTask = MySnapPsfMatchTask(config=config) 279 result = psfMatchTask.run(templateExp, scienceExp) 281 And finally provide optional debugging display of the Psf-matched (via the Psf models) science image: 286 # See if the LSST debug has incremented the frame number; if not start with frame 3 288 frame = debug.lsstDebug.frame + 1 291 afwDisplay.Display(frame=frame).mtv(result.matchedExposure, 292 title="Example script: Matched Template Image") 293 if "subtractedExposure" in result.getDict(): 294 afwDisplay.Display(frame=frame + 1).mtv(result.subtractedExposure, 295 title="Example script: Subtracted Image") 299 ConfigClass = SnapPsfMatchConfig
303 templateFwhmPix=None, scienceFwhmPix=None,
305 return ImagePsfMatchTask.subtractExposures(self,
306 templateExposure=templateExposure,
307 scienceExposure=scienceExposure,
308 templateFwhmPix=templateFwhmPix,
309 scienceFwhmPix=scienceFwhmPix,
310 candidateList=candidateList,
311 doWarping=self.config.doWarping,
def subtractExposures(self, templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None)