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
characterizeImage.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2015 AURA/LSST.
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 <https://www.lsstcorp.org/LegalNotices/>.
21 #
22 import numpy as np
23 
24 from lsstDebug import getDebugFrame
25 import lsst.afw.table as afwTable
26 import lsst.pex.config as pexConfig
27 import lsst.pipe.base as pipeBase
28 import lsst.daf.base as dafBase
29 from lsst.afw.math import BackgroundList
30 from lsst.afw.table import SourceTable, SourceCatalog, IdFactory
31 from lsst.meas.algorithms import SubtractBackgroundTask, SourceDetectionTask, MeasureApCorrTask
32 from lsst.meas.algorithms.installGaussianPsf import InstallGaussianPsfTask
33 from lsst.meas.astrom import RefMatchTask, displayAstrometry
34 from lsst.meas.extensions.astrometryNet import LoadAstrometryNetObjectsTask
35 from lsst.obs.base import ExposureIdInfo
36 from lsst.meas.base import SingleFrameMeasurementTask, ApplyApCorrTask, CatalogCalculationTask
37 from lsst.meas.deblender import SourceDeblendTask
38 from .measurePsf import MeasurePsfTask
39 from .repair import RepairTask
40 
41 __all__ = ["CharacterizeImageConfig", "CharacterizeImageTask"]
42 
43 
44 class CharacterizeImageConfig(pipeBase.PipelineTaskConfig):
45  # Gen3 IO options
46  exposure = pipeBase.InputDatasetField(
47  doc="Input exposure data",
48  name="postISRCCD",
49  scalar=True,
50  storageClass="ExposureF",
51  dimensions=["Instrument", "Visit", "Detector"],
52  )
53  characterized = pipeBase.OutputDatasetField(
54  doc="Output characterized data.",
55  name="icExp",
56  scalar=True,
57  storageClass="ExposureF",
58  dimensions=["Instrument", "Visit", "Detector"],
59  )
60  sourceCat = pipeBase.OutputDatasetField(
61  doc="Output source catalog.",
62  name="icSrc",
63  scalar=True,
64  storageClass="SourceCatalog",
65  dimensions=["Instrument", "Visit", "Detector"],
66  )
67  backgroundModel = pipeBase.OutputDatasetField(
68  doc="Output background model.",
69  name="icExpBackground",
70  scalar=True,
71  storageClass="Background",
72  dimensions=["Instrument", "Visit", "Detector"],
73  )
74  outputSchema = pipeBase.InitOutputDatasetField(
75  doc="Schema of the catalog produced by CharacterizeImage",
76  name="icSrc_schema",
77  storageClass="SourceCatalog",
78  )
79 
80  """!Config for CharacterizeImageTask"""
81  doMeasurePsf = pexConfig.Field(
82  dtype=bool,
83  default=True,
84  doc="Measure PSF? If False then for all subsequent operations use either existing PSF "
85  "model when present, or install simple PSF model when not (see installSimplePsf "
86  "config options)"
87  )
88  doWrite = pexConfig.Field(
89  dtype=bool,
90  default=True,
91  doc="Persist results?",
92  )
93  doWriteExposure = pexConfig.Field(
94  dtype=bool,
95  default=True,
96  doc="Write icExp and icExpBackground in addition to icSrc? Ignored if doWrite False.",
97  )
98  psfIterations = pexConfig.RangeField(
99  dtype=int,
100  default=2,
101  min=1,
102  doc="Number of iterations of detect sources, measure sources, "
103  "estimate PSF. If useSimplePsf is True then 2 should be plenty; "
104  "otherwise more may be wanted.",
105  )
106  background = pexConfig.ConfigurableField(
107  target=SubtractBackgroundTask,
108  doc="Configuration for initial background estimation",
109  )
110  detection = pexConfig.ConfigurableField(
111  target=SourceDetectionTask,
112  doc="Detect sources"
113  )
114  doDeblend = pexConfig.Field(
115  dtype=bool,
116  default=True,
117  doc="Run deblender input exposure"
118  )
119  deblend = pexConfig.ConfigurableField(
120  target=SourceDeblendTask,
121  doc="Split blended source into their components"
122  )
123  measurement = pexConfig.ConfigurableField(
124  target=SingleFrameMeasurementTask,
125  doc="Measure sources"
126  )
127  doApCorr = pexConfig.Field(
128  dtype=bool,
129  default=True,
130  doc="Run subtasks to measure and apply aperture corrections"
131  )
132  measureApCorr = pexConfig.ConfigurableField(
133  target=MeasureApCorrTask,
134  doc="Subtask to measure aperture corrections"
135  )
136  applyApCorr = pexConfig.ConfigurableField(
137  target=ApplyApCorrTask,
138  doc="Subtask to apply aperture corrections"
139  )
140  # If doApCorr is False, and the exposure does not have apcorrections already applied, the
141  # active plugins in catalogCalculation almost certainly should not contain the characterization plugin
142  catalogCalculation = pexConfig.ConfigurableField(
143  target=CatalogCalculationTask,
144  doc="Subtask to run catalogCalculation plugins on catalog"
145  )
146  useSimplePsf = pexConfig.Field(
147  dtype=bool,
148  default=True,
149  doc="Replace the existing PSF model with a simplified version that has the same sigma "
150  "at the start of each PSF determination iteration? Doing so makes PSF determination "
151  "converge more robustly and quickly.",
152  )
153  installSimplePsf = pexConfig.ConfigurableField(
154  target=InstallGaussianPsfTask,
155  doc="Install a simple PSF model",
156  )
157  refObjLoader = pexConfig.ConfigurableField(
158  target=LoadAstrometryNetObjectsTask,
159  doc="reference object loader",
160  )
161  ref_match = pexConfig.ConfigurableField(
162  target=RefMatchTask,
163  doc="Task to load and match reference objects. Only used if measurePsf can use matches. "
164  "Warning: matching will only work well if the initial WCS is accurate enough "
165  "to give good matches (roughly: good to 3 arcsec across the CCD).",
166  )
167  measurePsf = pexConfig.ConfigurableField(
168  target=MeasurePsfTask,
169  doc="Measure PSF",
170  )
171  repair = pexConfig.ConfigurableField(
172  target=RepairTask,
173  doc="Remove cosmic rays",
174  )
175  checkUnitsParseStrict = pexConfig.Field(
176  doc="Strictness of Astropy unit compatibility check, can be 'raise', 'warn' or 'silent'",
177  dtype=str,
178  default="raise",
179  )
180 
181  def setDefaults(self):
182  super().setDefaults()
183  # just detect bright stars; includeThresholdMultipler=10 seems large,
184  # but these are the values we have been using
185  self.detection.thresholdValue = 5.0
186  self.detection.includeThresholdMultiplier = 10.0
187  # do not deblend, as it makes a mess
188  self.doDeblend = False
189  # measure and apply aperture correction; note: measuring and applying aperture
190  # correction are disabled until the final measurement, after PSF is measured
191  self.doApCorr = True
192  # minimal set of measurements needed to determine PSF
193  self.measurement.plugins.names = [
194  "base_PixelFlags",
195  "base_SdssCentroid",
196  "base_SdssShape",
197  "base_GaussianFlux",
198  "base_PsfFlux",
199  "base_CircularApertureFlux",
200  ]
201  self.quantum.dimensions = ("Instrument", "Visit", "Detector")
202 
203  def validate(self):
204  if self.doApCorr and not self.measurePsf:
205  raise RuntimeError("Must measure PSF to measure aperture correction, "
206  "because flags determined by PSF measurement are used to identify "
207  "sources used to measure aperture correction")
208 
209 
215 
216 
217 class CharacterizeImageTask(pipeBase.PipelineTask, pipeBase.CmdLineTask):
218  r"""!Measure bright sources and use this to estimate background and PSF of an exposure
219 
220  @anchor CharacterizeImageTask_
221 
222  @section pipe_tasks_characterizeImage_Contents Contents
223 
224  - @ref pipe_tasks_characterizeImage_Purpose
225  - @ref pipe_tasks_characterizeImage_Initialize
226  - @ref pipe_tasks_characterizeImage_IO
227  - @ref pipe_tasks_characterizeImage_Config
228  - @ref pipe_tasks_characterizeImage_Debug
229 
230 
231  @section pipe_tasks_characterizeImage_Purpose Description
232 
233  Given an exposure with defects repaired (masked and interpolated over, e.g. as output by IsrTask):
234  - detect and measure bright sources
235  - repair cosmic rays
236  - measure and subtract background
237  - measure PSF
238 
239  @section pipe_tasks_characterizeImage_Initialize Task initialisation
240 
241  @copydoc \_\_init\_\_
242 
243  @section pipe_tasks_characterizeImage_IO Invoking the Task
244 
245  If you want this task to unpersist inputs or persist outputs, then call
246  the `runDataRef` method (a thin wrapper around the `run` method).
247 
248  If you already have the inputs unpersisted and do not want to persist the output
249  then it is more direct to call the `run` method:
250 
251  @section pipe_tasks_characterizeImage_Config Configuration parameters
252 
253  See @ref CharacterizeImageConfig
254 
255  @section pipe_tasks_characterizeImage_Debug Debug variables
256 
257  The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink interface supports a flag
258  `--debug` to import `debug.py` from your `$PYTHONPATH`; see @ref baseDebug for more about `debug.py`.
259 
260  CharacterizeImageTask has a debug dictionary with the following keys:
261  <dl>
262  <dt>frame
263  <dd>int: if specified, the frame of first debug image displayed (defaults to 1)
264  <dt>repair_iter
265  <dd>bool; if True display image after each repair in the measure PSF loop
266  <dt>background_iter
267  <dd>bool; if True display image after each background subtraction in the measure PSF loop
268  <dt>measure_iter
269  <dd>bool; if True display image and sources at the end of each iteration of the measure PSF loop
270  See @ref lsst.meas.astrom.displayAstrometry for the meaning of the various symbols.
271  <dt>psf
272  <dd>bool; if True display image and sources after PSF is measured;
273  this will be identical to the final image displayed by measure_iter if measure_iter is true
274  <dt>repair
275  <dd>bool; if True display image and sources after final repair
276  <dt>measure
277  <dd>bool; if True display image and sources after final measurement
278  </dl>
279 
280  For example, put something like:
281  @code{.py}
282  import lsstDebug
283  def DebugInfo(name):
284  di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
285  if name == "lsst.pipe.tasks.characterizeImage":
286  di.display = dict(
287  repair = True,
288  )
289 
290  return di
291 
292  lsstDebug.Info = DebugInfo
293  @endcode
294  into your `debug.py` file and run `calibrateTask.py` with the `--debug` flag.
295 
296  Some subtasks may have their own debug variables; see individual Task documentation.
297  """
298 
299  # Example description used to live here, removed 2-20-2017 by MSSG
300 
301  ConfigClass = CharacterizeImageConfig
302  _DefaultName = "characterizeImage"
303  RunnerClass = pipeBase.ButlerInitializedTaskRunner
304 
305  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
306  if 'exposureIdInfo' not in inputData.keys():
307  packer = butler.registry.makeDataIdPacker("VisitDetector",
308  inputDataIds['exposure'])
309  exposureIdInfo = ExposureIdInfo()
310  exposureIdInfo.expId = packer.pack(inputDataIds['exposure'])
311  exposureIdInfo.expBits = packer.maxBits
312  inputData['exposureIdInfo'] = exposureIdInfo
313 
314  return super().adaptArgsAndRun(inputData, inputDataIds, outputDataIds, butler)
315 
316  def __init__(self, butler=None, refObjLoader=None, schema=None, **kwargs):
317  """!Construct a CharacterizeImageTask
318 
319  @param[in] butler A butler object is passed to the refObjLoader constructor in case
320  it is needed to load catalogs. May be None if a catalog-based star selector is
321  not used, if the reference object loader constructor does not require a butler,
322  or if a reference object loader is passed directly via the refObjLoader argument.
323  @param[in] refObjLoader An instance of LoadReferenceObjectsTasks that supplies an
324  external reference catalog to a catalog-based star selector. May be None if a
325  catalog star selector is not used or the loader can be constructed from the
326  butler argument.
327  @param[in,out] schema initial schema (an lsst.afw.table.SourceTable), or None
328  @param[in,out] kwargs other keyword arguments for lsst.pipe.base.CmdLineTask
329  """
330  super().__init__(**kwargs)
331 
332  if schema is None:
333  schema = SourceTable.makeMinimalSchema()
334  self.schema = schema
335  self.makeSubtask("background")
336  self.makeSubtask("installSimplePsf")
337  self.makeSubtask("repair")
338  self.makeSubtask("measurePsf", schema=self.schema)
339  if self.config.doMeasurePsf and self.measurePsf.usesMatches:
340  if not refObjLoader:
341  self.makeSubtask('refObjLoader', butler=butler)
342  refObjLoader = self.refObjLoader
343  self.makeSubtask("ref_match", refObjLoader=refObjLoader)
345  self.makeSubtask('detection', schema=self.schema)
346  if self.config.doDeblend:
347  self.makeSubtask("deblend", schema=self.schema)
348  self.makeSubtask('measurement', schema=self.schema, algMetadata=self.algMetadata)
349  if self.config.doApCorr:
350  self.makeSubtask('measureApCorr', schema=self.schema)
351  self.makeSubtask('applyApCorr', schema=self.schema)
352  self.makeSubtask('catalogCalculation', schema=self.schema)
353  self._initialFrame = getDebugFrame(self._display, "frame") or 1
354  self._frame = self._initialFrame
355  self.schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
356 
358  outputCatSchema = afwTable.SourceCatalog(self.schema)
359  outputCatSchema.getTable().setMetadata(self.algMetadata)
360  return {'outputSchema': outputCatSchema}
361 
362  @pipeBase.timeMethod
363  def runDataRef(self, dataRef, exposure=None, background=None, doUnpersist=True):
364  """!Characterize a science image and, if wanted, persist the results
365 
366  This simply unpacks the exposure and passes it to the characterize method to do the work.
367 
368  @param[in] dataRef: butler data reference for science exposure
369  @param[in,out] exposure exposure to characterize (an lsst.afw.image.ExposureF or similar).
370  If None then unpersist from "postISRCCD".
371  The following changes are made, depending on the config:
372  - set psf to the measured PSF
373  - set apCorrMap to the measured aperture correction
374  - subtract background
375  - interpolate over cosmic rays
376  - update detection and cosmic ray mask planes
377  @param[in,out] background initial model of background already subtracted from exposure
378  (an lsst.afw.math.BackgroundList). May be None if no background has been subtracted,
379  which is typical for image characterization.
380  A refined background model is output.
381  @param[in] doUnpersist if True the exposure is read from the repository
382  and the exposure and background arguments must be None;
383  if False the exposure must be provided.
384  True is intended for running as a command-line task, False for running as a subtask
385 
386  @return same data as the characterize method
387  """
388  self._frame = self._initialFrame # reset debug display frame
389  self.log.info("Processing %s" % (dataRef.dataId))
390 
391  if doUnpersist:
392  if exposure is not None or background is not None:
393  raise RuntimeError("doUnpersist true; exposure and background must be None")
394  exposure = dataRef.get("postISRCCD", immediate=True)
395  elif exposure is None:
396  raise RuntimeError("doUnpersist false; exposure must be provided")
397 
398  exposureIdInfo = dataRef.get("expIdInfo")
399 
400  charRes = self.run(
401  exposure=exposure,
402  exposureIdInfo=exposureIdInfo,
403  background=background,
404  )
405 
406  if self.config.doWrite:
407  dataRef.put(charRes.sourceCat, "icSrc")
408  if self.config.doWriteExposure:
409  dataRef.put(charRes.exposure, "icExp")
410  dataRef.put(charRes.background, "icExpBackground")
411 
412  return charRes
413 
414  @pipeBase.timeMethod
415  def run(self, exposure, exposureIdInfo=None, background=None):
416  """!Characterize a science image
417 
418  Peforms the following operations:
419  - Iterate the following config.psfIterations times, or once if config.doMeasurePsf false:
420  - detect and measure sources and estimate PSF (see detectMeasureAndEstimatePsf for details)
421  - interpolate over cosmic rays
422  - perform final measurement
423 
424  @param[in,out] exposure exposure to characterize (an lsst.afw.image.ExposureF or similar).
425  The following changes are made:
426  - update or set psf
427  - set apCorrMap
428  - update detection and cosmic ray mask planes
429  - subtract background and interpolate over cosmic rays
430  @param[in] exposureIdInfo ID info for exposure (an lsst.obs.base.ExposureIdInfo).
431  If not provided, returned SourceCatalog IDs will not be globally unique.
432  @param[in,out] background initial model of background already subtracted from exposure
433  (an lsst.afw.math.BackgroundList). May be None if no background has been subtracted,
434  which is typical for image characterization.
435 
436  @return pipe_base Struct containing these fields, all from the final iteration
437  of detectMeasureAndEstimatePsf:
438  - exposure: characterized exposure; image is repaired by interpolating over cosmic rays,
439  mask is updated accordingly, and the PSF model is set
440  - sourceCat: detected sources (an lsst.afw.table.SourceCatalog)
441  - background: model of background subtracted from exposure (an lsst.afw.math.BackgroundList)
442  - psfCellSet: spatial cells of PSF candidates (an lsst.afw.math.SpatialCellSet)
443  """
444  self._frame = self._initialFrame # reset debug display frame
445 
446  if not self.config.doMeasurePsf and not exposure.hasPsf():
447  self.log.warn("Source catalog detected and measured with placeholder or default PSF")
448  self.installSimplePsf.run(exposure=exposure)
449 
450  if exposureIdInfo is None:
451  exposureIdInfo = ExposureIdInfo()
452 
453  # subtract an initial estimate of background level
454  background = self.background.run(exposure).background
455 
456  psfIterations = self.config.psfIterations if self.config.doMeasurePsf else 1
457  for i in range(psfIterations):
458  dmeRes = self.detectMeasureAndEstimatePsf(
459  exposure=exposure,
460  exposureIdInfo=exposureIdInfo,
461  background=background,
462  )
463 
464  psf = dmeRes.exposure.getPsf()
465  psfSigma = psf.computeShape().getDeterminantRadius()
466  psfDimensions = psf.computeImage().getDimensions()
467  medBackground = np.median(dmeRes.background.getImage().getArray())
468  self.log.info("iter %s; PSF sigma=%0.2f, dimensions=%s; median background=%0.2f" %
469  (i + 1, psfSigma, psfDimensions, medBackground))
470 
471  self.display("psf", exposure=dmeRes.exposure, sourceCat=dmeRes.sourceCat)
472 
473  # perform final repair with final PSF
474  self.repair.run(exposure=dmeRes.exposure)
475  self.display("repair", exposure=dmeRes.exposure, sourceCat=dmeRes.sourceCat)
476 
477  # perform final measurement with final PSF, including measuring and applying aperture correction,
478  # if wanted
479  self.measurement.run(measCat=dmeRes.sourceCat, exposure=dmeRes.exposure,
480  exposureId=exposureIdInfo.expId)
481  if self.config.doApCorr:
482  apCorrMap = self.measureApCorr.run(exposure=dmeRes.exposure, catalog=dmeRes.sourceCat).apCorrMap
483  dmeRes.exposure.getInfo().setApCorrMap(apCorrMap)
484  self.applyApCorr.run(catalog=dmeRes.sourceCat, apCorrMap=exposure.getInfo().getApCorrMap())
485  self.catalogCalculation.run(dmeRes.sourceCat)
486 
487  self.display("measure", exposure=dmeRes.exposure, sourceCat=dmeRes.sourceCat)
488 
489  return pipeBase.Struct(
490  exposure=dmeRes.exposure,
491  sourceCat=dmeRes.sourceCat,
492  background=dmeRes.background,
493  psfCellSet=dmeRes.psfCellSet,
494 
495  characterized=dmeRes.exposure,
496  backgroundModel=dmeRes.background
497  )
498 
499  @pipeBase.timeMethod
500  def detectMeasureAndEstimatePsf(self, exposure, exposureIdInfo, background):
501  """!Perform one iteration of detect, measure and estimate PSF
502 
503  Performs the following operations:
504  - if config.doMeasurePsf or not exposure.hasPsf():
505  - install a simple PSF model (replacing the existing one, if need be)
506  - interpolate over cosmic rays with keepCRs=True
507  - estimate background and subtract it from the exposure
508  - detect, deblend and measure sources, and subtract a refined background model;
509  - if config.doMeasurePsf:
510  - measure PSF
511 
512  @param[in,out] exposure exposure to characterize (an lsst.afw.image.ExposureF or similar)
513  The following changes are made:
514  - update or set psf
515  - update detection and cosmic ray mask planes
516  - subtract background
517  @param[in] exposureIdInfo ID info for exposure (an lsst.obs_base.ExposureIdInfo)
518  @param[in,out] background initial model of background already subtracted from exposure
519  (an lsst.afw.math.BackgroundList).
520 
521  @return pipe_base Struct containing these fields, all from the final iteration
522  of detect sources, measure sources and estimate PSF:
523  - exposure characterized exposure; image is repaired by interpolating over cosmic rays,
524  mask is updated accordingly, and the PSF model is set
525  - sourceCat detected sources (an lsst.afw.table.SourceCatalog)
526  - background model of background subtracted from exposure (an lsst.afw.math.BackgroundList)
527  - psfCellSet spatial cells of PSF candidates (an lsst.afw.math.SpatialCellSet)
528  """
529  # install a simple PSF model, if needed or wanted
530  if not exposure.hasPsf() or (self.config.doMeasurePsf and self.config.useSimplePsf):
531  self.log.warn("Source catalog detected and measured with placeholder or default PSF")
532  self.installSimplePsf.run(exposure=exposure)
533 
534  # run repair, but do not interpolate over cosmic rays (do that elsewhere, with the final PSF model)
535  self.repair.run(exposure=exposure, keepCRs=True)
536  self.display("repair_iter", exposure=exposure)
537 
538  if background is None:
539  background = BackgroundList()
540 
541  sourceIdFactory = IdFactory.makeSource(exposureIdInfo.expId, exposureIdInfo.unusedBits)
542  table = SourceTable.make(self.schema, sourceIdFactory)
543  table.setMetadata(self.algMetadata)
544 
545  detRes = self.detection.run(table=table, exposure=exposure, doSmooth=True)
546  sourceCat = detRes.sources
547  if detRes.fpSets.background:
548  for bg in detRes.fpSets.background:
549  background.append(bg)
550 
551  if self.config.doDeblend:
552  self.deblend.run(exposure=exposure, sources=sourceCat)
553 
554  self.measurement.run(measCat=sourceCat, exposure=exposure, exposureId=exposureIdInfo.expId)
555 
556  measPsfRes = pipeBase.Struct(cellSet=None)
557  if self.config.doMeasurePsf:
558  if self.measurePsf.usesMatches:
559  matches = self.ref_match.loadAndMatch(exposure=exposure, sourceCat=sourceCat).matches
560  else:
561  matches = None
562  measPsfRes = self.measurePsf.run(exposure=exposure, sources=sourceCat, matches=matches,
563  expId=exposureIdInfo.expId)
564  self.display("measure_iter", exposure=exposure, sourceCat=sourceCat)
565 
566  return pipeBase.Struct(
567  exposure=exposure,
568  sourceCat=sourceCat,
569  background=background,
570  psfCellSet=measPsfRes.cellSet,
571  )
572 
573  def getSchemaCatalogs(self):
574  """Return a dict of empty catalogs for each catalog dataset produced by this task.
575  """
576  sourceCat = SourceCatalog(self.schema)
577  sourceCat.getTable().setMetadata(self.algMetadata)
578  return {"icSrc": sourceCat}
579 
580  def display(self, itemName, exposure, sourceCat=None):
581  """Display exposure and sources on next frame, if display of itemName has been requested
582 
583  @param[in] itemName name of item in debugInfo
584  @param[in] exposure exposure to display
585  @param[in] sourceCat source catalog to display
586  """
587  val = getDebugFrame(self._display, itemName)
588  if not val:
589  return
590 
591  displayAstrometry(exposure=exposure, sourceCat=sourceCat, frame=self._frame, pause=False)
592  self._frame += 1
def display(self, itemName, exposure, sourceCat=None)
Class for storing ordered metadata with comments.
Definition: PropertyList.h:68
def run(self, exposure, exposureIdInfo=None, background=None)
Characterize a science image.
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
Measure bright sources and use this to estimate background and PSF of an exposure.
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)
def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
Definition: display.py:35
def getDebugFrame(debugDisplay, name)
Definition: lsstDebug.py:90
def runDataRef(self, dataRef, exposure=None, background=None, doUnpersist=True)
Characterize a science image and, if wanted, persist the results.
def __init__(self, butler=None, refObjLoader=None, schema=None, kwargs)
Construct a CharacterizeImageTask.
def detectMeasureAndEstimatePsf(self, exposure, exposureIdInfo, background)
Perform one iteration of detect, measure and estimate PSF.