24 from lsstDebug 
import getDebugFrame
 
   27 import lsst.pipe.base.connectionTypes 
as cT
 
   29 from lsst.meas.astrom import AstrometryTask, displayAstrometry, denormalizeMatches
 
   38                             CatalogCalculationTask)
 
   40 from lsst.utils.timer 
import timeMethod
 
   42 from .fakes 
import BaseFakeSourcesTask
 
   43 from .photoCal 
import PhotoCalTask
 
   44 from .computeExposureSummaryStats 
import ComputeExposureSummaryStatsTask
 
   47 __all__ = [
"CalibrateConfig", 
"CalibrateTask"]
 
   53     icSourceSchema = cT.InitInput(
 
   54         doc=
"Schema produced by characterize image task, used to initialize this task",
 
   56         storageClass=
"SourceCatalog",
 
   59     outputSchema = cT.InitOutput(
 
   60         doc=
"Schema after CalibrateTask has been initialized",
 
   62         storageClass=
"SourceCatalog",
 
   66         doc=
"Input image to calibrate",
 
   68         storageClass=
"ExposureF",
 
   69         dimensions=(
"instrument", 
"visit", 
"detector"),
 
   72     background = cT.Input(
 
   73         doc=
"Backgrounds determined by characterize task",
 
   74         name=
"icExpBackground",
 
   75         storageClass=
"Background",
 
   76         dimensions=(
"instrument", 
"visit", 
"detector"),
 
   79     icSourceCat = cT.Input(
 
   80         doc=
"Source catalog created by characterize task",
 
   82         storageClass=
"SourceCatalog",
 
   83         dimensions=(
"instrument", 
"visit", 
"detector"),
 
   86     astromRefCat = cT.PrerequisiteInput(
 
   87         doc=
"Reference catalog to use for astrometry",
 
   89         storageClass=
"SimpleCatalog",
 
   90         dimensions=(
"skypix",),
 
   95     photoRefCat = cT.PrerequisiteInput(
 
   96         doc=
"Reference catalog to use for photometric calibration",
 
   98         storageClass=
"SimpleCatalog",
 
   99         dimensions=(
"skypix",),
 
  104     outputExposure = cT.Output(
 
  105         doc=
"Exposure after running calibration task",
 
  107         storageClass=
"ExposureF",
 
  108         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  111     outputCat = cT.Output(
 
  112         doc=
"Source catalog produced in calibrate task",
 
  114         storageClass=
"SourceCatalog",
 
  115         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  118     outputBackground = cT.Output(
 
  119         doc=
"Background models estimated in calibration task",
 
  120         name=
"calexpBackground",
 
  121         storageClass=
"Background",
 
  122         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  126         doc=
"Source/refObj matches from the astrometry solver",
 
  128         storageClass=
"Catalog",
 
  129         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  132     matchesDenormalized = cT.Output(
 
  133         doc=
"Denormalized matches from astrometry solver",
 
  135         storageClass=
"Catalog",
 
  136         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  142         if config.doAstrometry 
is False:
 
  143             self.prerequisiteInputs.remove(
"astromRefCat")
 
  144         if config.doPhotoCal 
is False:
 
  145             self.prerequisiteInputs.remove(
"photoRefCat")
 
  147         if config.doWriteMatches 
is False or config.doAstrometry 
is False:
 
  148             self.outputs.remove(
"matches")
 
  149         if config.doWriteMatchesDenormalized 
is False or config.doAstrometry 
is False:
 
  150             self.outputs.remove(
"matchesDenormalized")
 
  153 class CalibrateConfig(pipeBase.PipelineTaskConfig, pipelineConnections=CalibrateConnections):
 
  154     """Config for CalibrateTask""" 
  155     doWrite = pexConfig.Field(
 
  158         doc=
"Save calibration results?",
 
  160     doWriteHeavyFootprintsInSources = pexConfig.Field(
 
  163         doc=
"Include HeavyFootprint data in source table? If false then heavy " 
  164             "footprints are saved as normal footprints, which saves some space" 
  166     doWriteMatches = pexConfig.Field(
 
  169         doc=
"Write reference matches (ignored if doWrite or doAstrometry false)?",
 
  171     doWriteMatchesDenormalized = pexConfig.Field(
 
  174         doc=(
"Write reference matches in denormalized format? " 
  175              "This format uses more disk space, but is more convenient to " 
  176              "read. Ignored if doWriteMatches=False or doWrite=False."),
 
  178     doAstrometry = pexConfig.Field(
 
  181         doc=
"Perform astrometric calibration?",
 
  183     astromRefObjLoader = pexConfig.ConfigurableField(
 
  184         target=LoadIndexedReferenceObjectsTask,
 
  185         doc=
"reference object loader for astrometric calibration",
 
  187     photoRefObjLoader = pexConfig.ConfigurableField(
 
  188         target=LoadIndexedReferenceObjectsTask,
 
  189         doc=
"reference object loader for photometric calibration",
 
  191     astrometry = pexConfig.ConfigurableField(
 
  192         target=AstrometryTask,
 
  193         doc=
"Perform astrometric calibration to refine the WCS",
 
  195     requireAstrometry = pexConfig.Field(
 
  198         doc=(
"Raise an exception if astrometry fails? Ignored if doAstrometry " 
  201     doPhotoCal = pexConfig.Field(
 
  204         doc=
"Perform phometric calibration?",
 
  206     requirePhotoCal = pexConfig.Field(
 
  209         doc=(
"Raise an exception if photoCal fails? Ignored if doPhotoCal " 
  212     photoCal = pexConfig.ConfigurableField(
 
  214         doc=
"Perform photometric calibration",
 
  216     icSourceFieldsToCopy = pexConfig.ListField(
 
  218         default=(
"calib_psf_candidate", 
"calib_psf_used", 
"calib_psf_reserved"),
 
  219         doc=(
"Fields to copy from the icSource catalog to the output catalog " 
  220              "for matching sources Any missing fields will trigger a " 
  221              "RuntimeError exception. Ignored if icSourceCat is not provided.")
 
  223     matchRadiusPix = pexConfig.Field(
 
  226         doc=(
"Match radius for matching icSourceCat objects to sourceCat " 
  229     checkUnitsParseStrict = pexConfig.Field(
 
  230         doc=(
"Strictness of Astropy unit compatibility check, can be 'raise', " 
  231              "'warn' or 'silent'"),
 
  235     detection = pexConfig.ConfigurableField(
 
  236         target=SourceDetectionTask,
 
  239     doDeblend = pexConfig.Field(
 
  242         doc=
"Run deblender input exposure" 
  244     deblend = pexConfig.ConfigurableField(
 
  245         target=SourceDeblendTask,
 
  246         doc=
"Split blended sources into their components" 
  248     doSkySources = pexConfig.Field(
 
  251         doc=
"Generate sky sources?",
 
  253     skySources = pexConfig.ConfigurableField(
 
  254         target=SkyObjectsTask,
 
  255         doc=
"Generate sky sources",
 
  257     measurement = pexConfig.ConfigurableField(
 
  258         target=SingleFrameMeasurementTask,
 
  259         doc=
"Measure sources" 
  261     setPrimaryFlags = pexConfig.ConfigurableField(
 
  262         target=SetPrimaryFlagsTask,
 
  263         doc=(
"Set flags for primary source classification in single frame " 
  264              "processing. True if sources are not sky sources and not a parent.")
 
  266     doApCorr = pexConfig.Field(
 
  269         doc=
"Run subtask to apply aperture correction" 
  271     applyApCorr = pexConfig.ConfigurableField(
 
  272         target=ApplyApCorrTask,
 
  273         doc=
"Subtask to apply aperture corrections" 
  278     catalogCalculation = pexConfig.ConfigurableField(
 
  279         target=CatalogCalculationTask,
 
  280         doc=
"Subtask to run catalogCalculation plugins on catalog" 
  282     doInsertFakes = pexConfig.Field(
 
  285         doc=
"Run fake sources injection task" 
  287     insertFakes = pexConfig.ConfigurableField(
 
  288         target=BaseFakeSourcesTask,
 
  289         doc=
"Injection of fake sources for testing purposes (must be " 
  292     doComputeSummaryStats = pexConfig.Field(
 
  295         doc=
"Run subtask to measure exposure summary statistics?" 
  297     computeSummaryStats = pexConfig.ConfigurableField(
 
  298         target=ComputeExposureSummaryStatsTask,
 
  299         doc=
"Subtask to run computeSummaryStats on exposure" 
  301     doWriteExposure = pexConfig.Field(
 
  304         doc=
"Write the calexp? If fakes have been added then we do not want to write out the calexp as a " 
  305             "normal calexp but as a fakes_calexp." 
  310         self.
detectiondetection.doTempLocalBackground = 
False 
  311         self.
deblenddeblend.maxFootprintSize = 2000
 
  312         self.
measurementmeasurement.plugins.names |= [
"base_LocalPhotoCalib", 
"base_LocalWcs"]
 
  316         astromRefCatGen2 = getattr(self.
astromRefObjLoaderastromRefObjLoader, 
"ref_dataset_name", 
None)
 
  317         if astromRefCatGen2 
is not None and astromRefCatGen2 != self.connections.astromRefCat:
 
  319                 f
"Gen2 ({astromRefCatGen2}) and Gen3 ({self.connections.astromRefCat}) astrometry reference " 
  320                 f
"catalogs are different.  These options must be kept in sync until Gen2 is retired." 
  322         photoRefCatGen2 = getattr(self.
photoRefObjLoaderphotoRefObjLoader, 
"ref_dataset_name", 
None)
 
  323         if photoRefCatGen2 
is not None and photoRefCatGen2 != self.connections.photoRefCat:
 
  325                 f
"Gen2 ({photoRefCatGen2}) and Gen3 ({self.connections.photoRefCat}) photometry reference " 
  326                 f
"catalogs are different.  These options must be kept in sync until Gen2 is retired." 
  338     r"""!Calibrate an exposure: measure sources and perform astrometric and 
  339         photometric calibration 
  341     @anchor CalibrateTask_ 
  343     @section pipe_tasks_calibrate_Contents  Contents 
  345      - @ref pipe_tasks_calibrate_Purpose 
  346      - @ref pipe_tasks_calibrate_Initialize 
  347      - @ref pipe_tasks_calibrate_IO 
  348      - @ref pipe_tasks_calibrate_Config 
  349      - @ref pipe_tasks_calibrate_Metadata 
  350      - @ref pipe_tasks_calibrate_Debug 
  353     @section pipe_tasks_calibrate_Purpose  Description 
  355     Given an exposure with a good PSF model and aperture correction map 
  356     (e.g. as provided by @ref CharacterizeImageTask), perform the following 
  358     - Run detection and measurement 
  359     - Run astrometry subtask to fit an improved WCS 
  360     - Run photoCal subtask to fit the exposure's photometric zero-point 
  362     @section pipe_tasks_calibrate_Initialize  Task initialisation 
  364     @copydoc \_\_init\_\_ 
  366     @section pipe_tasks_calibrate_IO  Invoking the Task 
  368     If you want this task to unpersist inputs or persist outputs, then call 
  369     the `runDataRef` method (a wrapper around the `run` method). 
  371     If you already have the inputs unpersisted and do not want to persist the 
  372     output then it is more direct to call the `run` method: 
  374     @section pipe_tasks_calibrate_Config  Configuration parameters 
  376     See @ref CalibrateConfig 
  378     @section pipe_tasks_calibrate_Metadata  Quantities set in exposure Metadata 
  382         <dt>MAGZERO_RMS  <dd>MAGZERO's RMS == sigma reported by photoCal task 
  383         <dt>MAGZERO_NOBJ <dd>Number of stars used == ngood reported by photoCal 
  385         <dt>COLORTERM1   <dd>?? (always 0.0) 
  386         <dt>COLORTERM2   <dd>?? (always 0.0) 
  387         <dt>COLORTERM3   <dd>?? (always 0.0) 
  390     @section pipe_tasks_calibrate_Debug  Debug variables 
  392     The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink 
  393     interface supports a flag 
  394     `--debug` to import `debug.py` from your `$PYTHONPATH`; see @ref baseDebug 
  395     for more about `debug.py`. 
  397     CalibrateTask has a debug dictionary containing one key: 
  400     <dd>frame (an int; <= 0 to not display) in which to display the exposure, 
  401         sources and matches. See @ref lsst.meas.astrom.displayAstrometry for 
  402         the meaning of the various symbols. 
  405     For example, put something like: 
  409             di = lsstDebug.getInfo(name)  # N.b. lsstDebug.Info(name) would 
  410                                           # call us recursively 
  411             if name == "lsst.pipe.tasks.calibrate": 
  418         lsstDebug.Info = DebugInfo 
  420     into your `debug.py` file and run `calibrateTask.py` with the `--debug` 
  423     Some subtasks may have their own debug variables; see individual Task 
  430     ConfigClass = CalibrateConfig
 
  431     _DefaultName = 
"calibrate" 
  432     RunnerClass = pipeBase.ButlerInitializedTaskRunner
 
  434     def __init__(self, butler=None, astromRefObjLoader=None,
 
  435                  photoRefObjLoader=None, icSourceSchema=None,
 
  436                  initInputs=None, **kwargs):
 
  437         """!Construct a CalibrateTask 
  439         @param[in] butler  The butler is passed to the refObjLoader constructor 
  440             in case it is needed.  Ignored if the refObjLoader argument 
  441             provides a loader directly. 
  442         @param[in] astromRefObjLoader  An instance of LoadReferenceObjectsTasks 
  443             that supplies an external reference catalog for astrometric 
  444             calibration.  May be None if the desired loader can be constructed 
  445             from the butler argument or all steps requiring a reference catalog 
  447         @param[in] photoRefObjLoader  An instance of LoadReferenceObjectsTasks 
  448             that supplies an external reference catalog for photometric 
  449             calibration.  May be None if the desired loader can be constructed 
  450             from the butler argument or all steps requiring a reference catalog 
  452         @param[in] icSourceSchema  schema for icSource catalog, or None. 
  453             Schema values specified in config.icSourceFieldsToCopy will be 
  454             taken from this schema. If set to None, no values will be 
  455             propagated from the icSourceCatalog 
  456         @param[in,out] kwargs  other keyword arguments for 
  457             lsst.pipe.base.CmdLineTask 
  461         if icSourceSchema 
is None and butler 
is not None:
 
  463             icSourceSchema = butler.get(
"icSrc_schema", immediate=
True).schema
 
  465         if icSourceSchema 
is None and butler 
is None and initInputs 
is not None:
 
  466             icSourceSchema = initInputs[
'icSourceSchema'].schema
 
  468         if icSourceSchema 
is not None:
 
  471             minimumSchema = afwTable.SourceTable.makeMinimalSchema()
 
  472             self.
schemaMapperschemaMapper.addMinimalSchema(minimumSchema, 
False)
 
  481                                        "Source was detected as an icSource"))
 
  482             missingFieldNames = []
 
  483             for fieldName 
in self.config.icSourceFieldsToCopy:
 
  485                     schemaItem = icSourceSchema.find(fieldName)
 
  487                     missingFieldNames.append(fieldName)
 
  490                     self.
schemaMapperschemaMapper.addMapping(schemaItem.getKey())
 
  492             if missingFieldNames:
 
  493                 raise RuntimeError(
"isSourceCat is missing fields {} " 
  494                                    "specified in icSourceFieldsToCopy" 
  495                                    .
format(missingFieldNames))
 
  502             self.
schemaschema = afwTable.SourceTable.makeMinimalSchema()
 
  503         self.makeSubtask(
'detection', schema=self.
schemaschema)
 
  510         if self.config.doInsertFakes:
 
  511             self.makeSubtask(
"insertFakes")
 
  513         if self.config.doDeblend:
 
  514             self.makeSubtask(
"deblend", schema=self.
schemaschema)
 
  515         if self.config.doSkySources:
 
  516             self.makeSubtask(
"skySources")
 
  517             self.
skySourceKeyskySourceKey = self.
schemaschema.addField(
"sky_source", type=
"Flag", doc=
"Sky objects.")
 
  518         self.makeSubtask(
'measurement', schema=self.
schemaschema,
 
  520         self.makeSubtask(
"setPrimaryFlags", schema=self.
schemaschema, isSingleFrame=
True)
 
  521         if self.config.doApCorr:
 
  522             self.makeSubtask(
'applyApCorr', schema=self.
schemaschema)
 
  523         self.makeSubtask(
'catalogCalculation', schema=self.
schemaschema)
 
  525         if self.config.doAstrometry:
 
  526             if astromRefObjLoader 
is None and butler 
is not None:
 
  527                 self.makeSubtask(
'astromRefObjLoader', butler=butler)
 
  528                 astromRefObjLoader = self.astromRefObjLoader
 
  529             self.makeSubtask(
"astrometry", refObjLoader=astromRefObjLoader,
 
  531         if self.config.doPhotoCal:
 
  532             if photoRefObjLoader 
is None and butler 
is not None:
 
  533                 self.makeSubtask(
'photoRefObjLoader', butler=butler)
 
  534                 photoRefObjLoader = self.photoRefObjLoader
 
  535             self.makeSubtask(
"photoCal", refObjLoader=photoRefObjLoader,
 
  537         if self.config.doComputeSummaryStats:
 
  538             self.makeSubtask(
'computeSummaryStats')
 
  540         if initInputs 
is not None and (astromRefObjLoader 
is not None or photoRefObjLoader 
is not None):
 
  541             raise RuntimeError(
"PipelineTask form of this task should not be initialized with " 
  542                                "reference object loaders.")
 
  547         self.
schemaschema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
 
  554     def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None,
 
  556         """!Calibrate an exposure, optionally unpersisting inputs and 
  559         This is a wrapper around the `run` method that unpersists inputs 
  560         (if `doUnpersist` true) and persists outputs (if `config.doWrite` true) 
  562         @param[in] dataRef  butler data reference corresponding to a science 
  564         @param[in,out] exposure  characterized exposure (an 
  565             lsst.afw.image.ExposureF or similar), or None to unpersist existing 
  566             icExp and icBackground. See `run` method for details of what is 
  568         @param[in,out] background  initial model of background already 
  569             subtracted from exposure (an lsst.afw.math.BackgroundList). May be 
  570             None if no background has been subtracted, though that is unusual 
  571             for calibration. A refined background model is output. Ignored if 
  573         @param[in] icSourceCat  catalog from which to copy the fields specified 
  574             by icSourceKeys, or None; 
  575         @param[in] doUnpersist  unpersist data: 
  576             - if True, exposure, background and icSourceCat are read from 
  577               dataRef and those three arguments must all be None; 
  578             - if False the exposure must be provided; background and 
  579               icSourceCat are optional. True is intended for running as a 
  580               command-line task, False for running as a subtask 
  581         @return same data as the calibrate method 
  583         self.log.
info(
"Processing %s", dataRef.dataId)
 
  586             if any(item 
is not None for item 
in (exposure, background,
 
  588                 raise RuntimeError(
"doUnpersist true; exposure, background " 
  589                                    "and icSourceCat must all be None")
 
  590             exposure = dataRef.get(
"icExp", immediate=
True)
 
  591             background = dataRef.get(
"icExpBackground", immediate=
True)
 
  592             icSourceCat = dataRef.get(
"icSrc", immediate=
True)
 
  593         elif exposure 
is None:
 
  594             raise RuntimeError(
"doUnpersist false; exposure must be provided")
 
  596         exposureIdInfo = dataRef.get(
"expIdInfo")
 
  598         calRes = self.
runrun(
 
  600             exposureIdInfo=exposureIdInfo,
 
  601             background=background,
 
  602             icSourceCat=icSourceCat,
 
  605         if self.config.doWrite:
 
  608                 exposure=calRes.exposure,
 
  609                 background=calRes.background,
 
  610                 sourceCat=calRes.sourceCat,
 
  611                 astromMatches=calRes.astromMatches,
 
  612                 matchMeta=calRes.matchMeta,
 
  618         inputs = butlerQC.get(inputRefs)
 
  619         inputs[
'exposureIdInfo'] = ExposureIdInfo.fromDataId(butlerQC.quantum.dataId, 
"visit_detector")
 
  621         if self.config.doAstrometry:
 
  623                                                           for ref 
in inputRefs.astromRefCat],
 
  624                                                  refCats=inputs.pop(
'astromRefCat'),
 
  625                                                  config=self.config.astromRefObjLoader, log=self.log)
 
  626             self.astrometry.setRefObjLoader(refObjLoader)
 
  628         if self.config.doPhotoCal:
 
  630                                                       for ref 
in inputRefs.photoRefCat],
 
  631                                                       refCats=inputs.pop(
'photoRefCat'),
 
  632                                                       config=self.config.photoRefObjLoader,
 
  634             self.photoCal.match.setRefObjLoader(photoRefObjLoader)
 
  636         outputs = self.
runrun(**inputs)
 
  638         if self.config.doWriteMatches 
and self.config.doAstrometry:
 
  640             normalizedMatches.table.setMetadata(outputs.matchMeta)
 
  641             if self.config.doWriteMatchesDenormalized:
 
  643                 outputs.matchesDenormalized = denormMatches
 
  644             outputs.matches = normalizedMatches
 
  645         butlerQC.put(outputs, outputRefs)
 
  648     def run(self, exposure, exposureIdInfo=None, background=None,
 
  650         """!Calibrate an exposure (science image or coadd) 
  652         @param[in,out] exposure  exposure to calibrate (an 
  653             lsst.afw.image.ExposureF or similar); 
  658             - MaskedImage has background subtracted 
  660             - PhotoCalib is replaced 
  661         @param[in] exposureIdInfo  ID info for exposure (an 
  662             lsst.obs.base.ExposureIdInfo) If not provided, returned 
  663             SourceCatalog IDs will not be globally unique. 
  664         @param[in,out] background  background model already subtracted from 
  665             exposure (an lsst.afw.math.BackgroundList). May be None if no 
  666             background has been subtracted, though that is unusual for 
  667             calibration. A refined background model is output. 
  668         @param[in] icSourceCat  A SourceCatalog from CharacterizeImageTask 
  669             from which we can copy some fields. 
  671         @return pipe_base Struct containing these fields: 
  672         - exposure  calibrate science exposure with refined WCS and PhotoCalib 
  673         - background  model of background subtracted from exposure (an 
  674           lsst.afw.math.BackgroundList) 
  675         - sourceCat  catalog of measured sources 
  676         - astromMatches  list of source/refObj matches from the astrometry 
  680         if exposureIdInfo 
is None:
 
  681             exposureIdInfo = ExposureIdInfo()
 
  683         if background 
is None:
 
  685         sourceIdFactory = exposureIdInfo.makeSourceIdFactory()
 
  686         table = SourceTable.make(self.
schemaschema, sourceIdFactory)
 
  689         detRes = self.detection.
run(table=table, exposure=exposure,
 
  691         sourceCat = detRes.sources
 
  692         if detRes.fpSets.background:
 
  693             for bg 
in detRes.fpSets.background:
 
  694                 background.append(bg)
 
  695         if self.config.doSkySources:
 
  696             skySourceFootprints = self.skySources.
run(mask=exposure.mask, seed=exposureIdInfo.expId)
 
  697             if skySourceFootprints:
 
  698                 for foot 
in skySourceFootprints:
 
  699                     s = sourceCat.addNew()
 
  702         if self.config.doDeblend:
 
  703             self.deblend.
run(exposure=exposure, sources=sourceCat)
 
  704         self.measurement.
run(
 
  707             exposureId=exposureIdInfo.expId
 
  709         if self.config.doApCorr:
 
  710             self.applyApCorr.
run(
 
  712                 apCorrMap=exposure.getInfo().getApCorrMap()
 
  714         self.catalogCalculation.
run(sourceCat)
 
  716         self.setPrimaryFlags.
run(sourceCat)
 
  718         if icSourceCat 
is not None and \
 
  719            len(self.config.icSourceFieldsToCopy) > 0:
 
  727         if not sourceCat.isContiguous():
 
  728             sourceCat = sourceCat.copy(deep=
True)
 
  734         if self.config.doAstrometry:
 
  736                 astromRes = self.astrometry.
run(
 
  740                 astromMatches = astromRes.matches
 
  741                 matchMeta = astromRes.matchMeta
 
  742             except Exception 
as e:
 
  743                 if self.config.requireAstrometry:
 
  745                 self.log.
warning(
"Unable to perform astrometric calibration " 
  746                                  "(%s): attempting to proceed", e)
 
  749         if self.config.doPhotoCal:
 
  751                 photoRes = self.photoCal.
run(exposure, sourceCat=sourceCat, expId=exposureIdInfo.expId)
 
  752                 exposure.setPhotoCalib(photoRes.photoCalib)
 
  754                 self.log.
info(
"Photometric zero-point: %f",
 
  755                               photoRes.photoCalib.instFluxToMagnitude(1.0))
 
  756                 self.
setMetadatasetMetadata(exposure=exposure, photoRes=photoRes)
 
  757             except Exception 
as e:
 
  758                 if self.config.requirePhotoCal:
 
  760                 self.log.
warning(
"Unable to perform photometric calibration " 
  761                                  "(%s): attempting to proceed", e)
 
  762                 self.
setMetadatasetMetadata(exposure=exposure, photoRes=
None)
 
  764         if self.config.doInsertFakes:
 
  765             self.insertFakes.
run(exposure, background=background)
 
  767             table = SourceTable.make(self.
schemaschema, sourceIdFactory)
 
  770             detRes = self.detection.
run(table=table, exposure=exposure,
 
  772             sourceCat = detRes.sources
 
  773             if detRes.fpSets.background:
 
  774                 for bg 
in detRes.fpSets.background:
 
  775                     background.append(bg)
 
  776             if self.config.doDeblend:
 
  777                 self.deblend.
run(exposure=exposure, sources=sourceCat)
 
  778             self.measurement.
run(
 
  781                 exposureId=exposureIdInfo.expId
 
  783             if self.config.doApCorr:
 
  784                 self.applyApCorr.
run(
 
  786                     apCorrMap=exposure.getInfo().getApCorrMap()
 
  788             self.catalogCalculation.
run(sourceCat)
 
  790             if icSourceCat 
is not None and len(self.config.icSourceFieldsToCopy) > 0:
 
  794         if self.config.doComputeSummaryStats:
 
  795             summary = self.computeSummaryStats.
run(exposure=exposure,
 
  797                                                    background=background)
 
  798             exposure.getInfo().setSummaryStats(summary)
 
  805                 matches=astromMatches,
 
  810         return pipeBase.Struct(
 
  812             background=background,
 
  814             astromMatches=astromMatches,
 
  818             outputExposure=exposure,
 
  820             outputBackground=background,
 
  824                      astromMatches, matchMeta):
 
  825         """Write output data to the output repository 
  827         @param[in] dataRef  butler data reference corresponding to a science 
  829         @param[in] exposure  exposure to write 
  830         @param[in] background  background model for exposure 
  831         @param[in] sourceCat  catalog of measured sources 
  832         @param[in] astromMatches  list of source/refObj matches from the 
  835         dataRef.put(sourceCat, 
"src")
 
  836         if self.config.doWriteMatches 
and astromMatches 
is not None:
 
  838             normalizedMatches.table.setMetadata(matchMeta)
 
  839             dataRef.put(normalizedMatches, 
"srcMatch")
 
  840             if self.config.doWriteMatchesDenormalized:
 
  842                 dataRef.put(denormMatches, 
"srcMatchFull")
 
  843         if self.config.doWriteExposure:
 
  844             dataRef.put(exposure, 
"calexp")
 
  845             dataRef.put(background, 
"calexpBackground")
 
  848         """Return a dict of empty catalogs for each catalog dataset produced 
  853         return {
"src": sourceCat}
 
  856         """!Set task and exposure metadata 
  858         Logs a warning and continues if needed data is missing. 
  860         @param[in,out] exposure  exposure whose metadata is to be set 
  861         @param[in]  photoRes  results of running photoCal; if None then it was 
  867         metadata = exposure.getMetadata()
 
  871             exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
 
  872             magZero = photoRes.zp - 2.5*math.log10(exposureTime)
 
  874             self.log.
warning(
"Could not set normalized MAGZERO in header: no " 
  879             metadata.set(
'MAGZERO', magZero)
 
  880             metadata.set(
'MAGZERO_RMS', photoRes.sigma)
 
  881             metadata.set(
'MAGZERO_NOBJ', photoRes.ngood)
 
  882             metadata.set(
'COLORTERM1', 0.0)
 
  883             metadata.set(
'COLORTERM2', 0.0)
 
  884             metadata.set(
'COLORTERM3', 0.0)
 
  885         except Exception 
as e:
 
  886             self.log.
warning(
"Could not set exposure metadata: %s", e)
 
  889         """!Match sources in icSourceCat and sourceCat and copy the specified fields 
  891         @param[in] icSourceCat  catalog from which to copy fields 
  892         @param[in,out] sourceCat  catalog to which to copy fields 
  894         The fields copied are those specified by `config.icSourceFieldsToCopy` 
  895         that actually exist in the schema. This was set up by the constructor 
  896         using self.schemaMapper. 
  899             raise RuntimeError(
"To copy icSource fields you must specify " 
  900                                "icSourceSchema nd icSourceKeys when " 
  901                                "constructing this task")
 
  902         if icSourceCat 
is None or sourceCat 
is None:
 
  903             raise RuntimeError(
"icSourceCat and sourceCat must both be " 
  905         if len(self.config.icSourceFieldsToCopy) == 0:
 
  906             self.log.
warning(
"copyIcSourceFields doing nothing because " 
  907                              "icSourceFieldsToCopy is empty")
 
  911         mc.findOnlyClosest = 
False   
  913                                    self.config.matchRadiusPix, mc)
 
  914         if self.config.doDeblend:
 
  915             deblendKey = sourceCat.schema[
"deblend_nChild"].asKey()
 
  917             matches = [m 
for m 
in matches 
if m[1].get(deblendKey) == 0]
 
  924         for m0, m1, d 
in matches:
 
  926             match = bestMatches.get(id0)
 
  927             if match 
is None or d <= match[2]:
 
  928                 bestMatches[id0] = (m0, m1, d)
 
  929         matches = 
list(bestMatches.values())
 
  934         numMatches = len(matches)
 
  935         numUniqueSources = len(
set(m[1].getId() 
for m 
in matches))
 
  936         if numUniqueSources != numMatches:
 
  937             self.log.
warning(
"%d icSourceCat sources matched only %d sourceCat " 
  938                              "sources", numMatches, numUniqueSources)
 
  940         self.log.
info(
"Copying flags from icSourceCat to sourceCat for " 
  941                       "%d sources", numMatches)
 
  945         for icSrc, src, d 
in matches:
 
  951             icSrcFootprint = icSrc.getFootprint()
 
  953                 icSrc.setFootprint(src.getFootprint())
 
  956                 icSrc.setFootprint(icSrcFootprint)
 
afw::table::PointKey< int > dimensions
Pass parameters to algorithms that match list of sources.
A mapping between the keys of two Schemas, used to copy data between them.
Class for storing ordered metadata with comments.
def __init__(self, *config=None)
Calibrate an exposure: measure sources and perform astrometric and photometric calibration.
def writeOutputs(self, dataRef, exposure, background, sourceCat, astromMatches, matchMeta)
def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None, doUnpersist=True)
Calibrate an exposure, optionally unpersisting inputs and persisting outputs.
def __init__(self, butler=None, astromRefObjLoader=None, photoRefObjLoader=None, icSourceSchema=None, initInputs=None, **kwargs)
Construct a CalibrateTask.
def setMetadata(self, exposure, photoRes=None)
Set task and exposure metadata.
def runQuantum(self, butlerQC, inputRefs, outputRefs)
def getSchemaCatalogs(self)
def copyIcSourceFields(self, icSourceCat, sourceCat)
Match sources in icSourceCat and sourceCat and copy the specified fields.
def run(self, exposure, exposureIdInfo=None, background=None, icSourceCat=None)
Calibrate an exposure (science image or coadd)
daf::base::PropertyList * list
daf::base::PropertySet * set
BaseCatalog packMatches(std::vector< Match< Record1, Record2 > > const &matches)
Return a table representation of a MatchVector that can be used to persist it.
SourceMatchVector matchXy(SourceCatalog const &cat1, SourceCatalog const &cat2, double radius, MatchControl const &mc=MatchControl())
Compute all tuples (s1,s2,d) where s1 belings to cat1, s2 belongs to cat2 and d, the distance between...
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.
def denormalizeMatches(matches, matchMeta=None)
def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def getDebugFrame(debugDisplay, name)
A description of a field in a table.