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