LSSTApplications  16.0-10-g0ee56ad+5,16.0-11-ga33d1f2+5,16.0-12-g3ef5c14+3,16.0-12-g71e5ef5+18,16.0-12-gbdf3636+3,16.0-13-g118c103+3,16.0-13-g8f68b0a+3,16.0-15-gbf5c1cb+4,16.0-16-gfd17674+3,16.0-17-g7c01f5c+3,16.0-18-g0a50484+1,16.0-20-ga20f992+8,16.0-21-g0e05fd4+6,16.0-21-g15e2d33+4,16.0-22-g62d8060+4,16.0-22-g847a80f+4,16.0-25-gf00d9b8+1,16.0-28-g3990c221+4,16.0-3-gf928089+3,16.0-32-g88a4f23+5,16.0-34-gd7987ad+3,16.0-37-gc7333cb+2,16.0-4-g10fc685+2,16.0-4-g18f3627+26,16.0-4-g5f3a788+26,16.0-5-gaf5c3d7+4,16.0-5-gcc1f4bb+1,16.0-6-g3b92700+4,16.0-6-g4412fcd+3,16.0-6-g7235603+4,16.0-69-g2562ce1b+2,16.0-8-g14ebd58+4,16.0-8-g2df868b+1,16.0-8-g4cec79c+6,16.0-8-gadf6c7a+1,16.0-8-gfc7ad86,16.0-82-g59ec2a54a+1,16.0-9-g5400cdc+2,16.0-9-ge6233d7+5,master-g2880f2d8cf+3,v17.0.rc1
LSSTDataManagementBasePackage
snapPsfMatch.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2016 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 __all__ = ["SnapPsfMatchConfigDF", "SnapPsfMatchConfigAL", "SnapPsfMatchConfig", "SnapPsfMatchTask"]
24 
25 import lsst.pex.config as pexConfig
26 from .psfMatch import PsfMatchConfigDF, PsfMatchConfigAL
27 from .imagePsfMatch import ImagePsfMatchTask, ImagePsfMatchConfig
28 
29 
31  """Delta-function Psf-matching config optimized for snap subtraction"""
32 
33  def setDefaults(self):
34  PsfMatchConfigDF.setDefaults(self)
35 
36  # No regularization
37  self.useRegularization = False
38 
39  # Pca
41  self.subtractMeanForPca = True
43 
44 
46  """Sum-of-Gaussian (Alard-Lupton) Psf-matching config optimized for snap subtraction"""
47 
48  def setDefaults(self):
49  PsfMatchConfigAL.setDefaults(self)
50 
51  # Simple basis set
52  self.alardNGauss = 2
53  self.alardDegGauss = (4, 2)
54  self.alardSigGauss = (1.0, 2.5)
55 
56 
58  kernel = pexConfig.ConfigChoiceField(
59  doc="kernel type",
60  typemap=dict(
61  AL=SnapPsfMatchConfigAL,
62  DF=SnapPsfMatchConfigDF
63  ),
64  default="AL",
65  )
66 
67  doWarping = pexConfig.Field(
68  dtype=bool,
69  doc="Warp the snaps?",
70  default=False
71  )
72 
73  def setDefaults(self):
74  ImagePsfMatchConfig.setDefaults(self)
75 
76  # No spatial variation in model
77  self.kernel.active.spatialKernelOrder = 0
78 
79  # Don't fit for differential background
80  self.kernel.active.fitForBackground = False
81 
82  # Small kernel size
83  self.kernel.active.kernelSize = 7
84 
85  # With zero spatial order don't worry about spatial clipping
86  self.kernel.active.spatialKernelClipping = False
87 
88 
90  """Image-based Psf-matching of two subsequent snaps from the same visit
91 
92  Notes
93  -----
94  This Task differs from ImagePsfMatchTask in that it matches two Exposures assuming that the images have
95  been acquired very closely in time. Under this assumption, the astrometric misalignments and/or
96  relative distortions should be within a pixel, and the Psf-shapes should be very similar. As a
97  consequence, the default configurations for this class assume a very simple solution.
98 
99  - The spatial variation in the kernel (SnapPsfMatchConfig.spatialKernelOrder) is assumed to be zero
100 
101  - With no spatial variation, we turn of the spatial
102  clipping loops (SnapPsfMatchConfig.spatialKernelClipping)
103 
104  - The differential background is not fit for (SnapPsfMatchConfig.fitForBackground)
105 
106  - The kernel is expected to be appx.
107  a delta function, and has a small size (SnapPsfMatchConfig.kernelSize)
108 
109  The sub-configurations for the Alard-Lupton (SnapPsfMatchConfigAL)
110  and delta-function (SnapPsfMatchConfigDF)
111  bases also are designed to generate a small, simple kernel.
112 
113  Task initialization
114 
115  Initialization is the same as base class ImagePsfMatch.__init__,
116  with the difference being that the Task's
117  ConfigClass is SnapPsfMatchConfig.
118 
119  Invoking the Task
120 
121  The Task is only configured to have a subtractExposures method, which in turn calls
122  ImagePsfMatchTask.subtractExposures.
123 
124  Configuration parameters
125 
126  See SnapPsfMatchConfig, which uses either SnapPsfMatchConfigDF and SnapPsfMatchConfigAL
127  as its active configuration.
128 
129  Debug variables
130 
131  The lsst.pipe.base.cmdLineTask.CmdLineTask command line task interface supports a
132  flag -d/--debug to importdebug.py from your PYTHONPATH. The relevant contents of debug.py
133  for this Task include:
134 
135  .. code-block:: py
136 
137  import sys
138  import lsstDebug
139  def DebugInfo(name):
140  di = lsstDebug.getInfo(name)
141  if name == "lsst.ip.diffim.psfMatch":
142  di.display = True # enable debug output
143  di.maskTransparency = 80 # ds9 mask transparency
144  di.displayCandidates = True # show all the candidates and residuals
145  di.displayKernelBasis = False # show kernel basis functions
146  di.displayKernelMosaic = True # show kernel realized across the image
147  di.plotKernelSpatialModel = False # show coefficients of spatial model
148  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
149  elif name == "lsst.ip.diffim.imagePsfMatch":
150  di.display = True # enable debug output
151  di.maskTransparency = 30 # ds9 mask transparency
152  di.displayTemplate = True # show full (remapped) template
153  di.displaySciIm = True # show science image to match to
154  di.displaySpatialCells = True # show spatial cells
155  di.displayDiffIm = True # show difference image
156  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
157  elif name == "lsst.ip.diffim.diaCatalogSourceSelector":
158  di.display = False # enable debug output
159  di.maskTransparency = 30 # ds9 mask transparency
160  di.displayExposure = True # show exposure with candidates indicated
161  di.pauseAtEnd = False # pause when done
162  return di
163  lsstDebug.Info = DebugInfo
164  lsstDebug.frame = 1
165 
166  Note that if you want addional logging info, you may add to your scripts:
167 
168  .. code-block:: py
169 
170  import lsst.log.utils as logUtils
171  logUtils.traceSetAt("ip.diffim", 4)
172 
173  Examples
174  --------
175  This code is snapPsfMatchTask.py in the examples directory, and can be run as e.g.
176 
177  .. code-block:: py
178 
179  examples/snapPsfMatchTask.py
180  examples/snapPsfMatchTask.py --debug
181  examples/snapPsfMatchTask.py --debug --template /path/to/templateExp.fits
182  --science /path/to/scienceExp.fits
183 
184  First, create a subclass of SnapPsfMatchTask that accepts two exposures.
185  Ideally these exposures would have been taken back-to-back,
186  such that the pointing/background/Psf does not vary substantially between the two:
187 
188  .. code-block:: py
189 
190  class MySnapPsfMatchTask(SnapPsfMatchTask):
191  def __init__(self, *args, **kwargs):
192  SnapPsfMatchTask.__init__(self, *args, **kwargs)
193  def run(self, templateExp, scienceExp):
194  return self.subtractExposures(templateExp, scienceExp)
195 
196  And allow the user the freedom to either run the script in default mode,
197  or point to their own images on disk. Note that these images must be
198  readable as an lsst.afw.image.Exposure
199 
200  .. code-block:: py
201 
202  if __name__ == "__main__":
203  import argparse
204  parser = argparse.ArgumentParser(description="Demonstrate the use of ImagePsfMatchTask")
205  parser.add_argument("--debug", "-d", action="store_true", help="Load debug.py?", default=False)
206  parser.add_argument("--template", "-t", help="Template Exposure to use", default=None)
207  parser.add_argument("--science", "-s", help="Science Exposure to use", default=None)
208  args = parser.parse_args()
209 
210  We have enabled some minor display debugging in this script via the –debug option. However,
211  if you have an lsstDebug debug.in your PYTHONPATH you will get additional debugging displays.
212  The following block checks for this script
213 
214  .. code-block:: py
215 
216  if args.debug:
217  try:
218  import debug
219  # Since I am displaying 2 images here, set the starting frame number for the LSST debug LSST
220  debug.lsstDebug.frame = 3
221  except ImportError as e:
222  print(e, file=sys.stderr)
223 
224  Finally, we call a run method that we define below.
225  First set up a Config and choose the basis set to use:
226 
227  .. code-block:: py
228 
229  def run(args):
230  #
231  # Create the Config and use sum of gaussian basis
232  #
233  config = SnapPsfMatchTask.ConfigClass()
234  config.doWarping = True
235  config.kernel.name = "AL"
236 
237  Make sure the images (if any) that were sent to the script exist on disk and are readable.
238  If no images are sent, make some fake data up for the sake of this example script
239  (have a look at the code if you want more details on generateFakeImages;
240  as a detail of how the fake images were made, you do have to fit for a differential background):
241 
242  .. code-block:: py
243 
244  # Run the requested method of the Task
245  if args.template is not None and args.science is not None:
246  if not os.path.isfile(args.template):
247  raise Exception("Template image %s does not exist" % (args.template))
248  if not os.path.isfile(args.science):
249  raise Exception("Science image %s does not exist" % (args.science))
250  try:
251  templateExp = afwImage.ExposureF(args.template)
252  except Exception as e:
253  raise Exception("Cannot read template image %s" % (args.template))
254  try:
255  scienceExp = afwImage.ExposureF(args.science)
256  except Exception as e:
257  raise Exception("Cannot read science image %s" % (args.science))
258  else:
259  templateExp, scienceExp = generateFakeImages()
260  config.kernel.active.fitForBackground = True
261  config.kernel.active.spatialBgOrder = 0
262  config.kernel.active.sizeCellX = 128
263  config.kernel.active.sizeCellY = 128
264 
265  Display the two images if -debug
266 
267  .. code-block:: py
268 
269  if args.debug:
270  ds9.mtv(templateExp, frame=1, title="Example script: Input Template")
271  ds9.mtv(scienceExp, frame=2, title="Example script: Input Science Image")
272 
273  Create and run the Task
274 
275  .. code-block:: py
276 
277  # Create the Task
278  psfMatchTask = MySnapPsfMatchTask(config=config)
279  # Run the Task
280  result = psfMatchTask.run(templateExp, scienceExp)
281 
282  And finally provide optional debugging display of the Psf-matched (via the Psf models) science image:
283 
284  .. code-block:: py
285 
286  if args.debug:
287  # See if the LSST debug has incremented the frame number; if not start with frame 3
288  try:
289  frame = debug.lsstDebug.frame + 1
290  except Exception:
291  frame = 3
292  ds9.mtv(result.matchedExposure, frame=frame, title="Example script: Matched Template Image")
293  if "subtractedExposure" in result.getDict():
294  ds9.mtv(result.subtractedExposure, frame=frame+1, title="Example script: Subtracted Image")
295 
296  """
297 
298  ConfigClass = SnapPsfMatchConfig
299 
300  # Override ImagePsfMatchTask.subtractExposures to set doWarping on config.doWarping
301  def subtractExposures(self, templateExposure, scienceExposure,
302  templateFwhmPix=None, scienceFwhmPix=None,
303  candidateList=None):
304  return ImagePsfMatchTask.subtractExposures(self,
305  templateExposure=templateExposure,
306  scienceExposure=scienceExposure,
307  templateFwhmPix=templateFwhmPix,
308  scienceFwhmPix=scienceFwhmPix,
309  candidateList=candidateList,
310  doWarping=self.config.doWarping,
311  )
def subtractExposures(self, templateExposure, scienceExposure, templateFwhmPix=None, scienceFwhmPix=None, candidateList=None)