24 from lsstDebug
import getDebugFrame
25 import lsst.pex.config
as pexConfig
29 from lsst.meas.astrom import AstrometryTask, displayAstrometry, denormalizeMatches
36 from lsst.meas.base import (SingleFrameMeasurementTask, ApplyApCorrTask,
37 CatalogCalculationTask)
39 from .fakes
import BaseFakeSourcesTask
40 from .photoCal
import PhotoCalTask
42 __all__ = [
"CalibrateConfig",
"CalibrateTask"]
45 class CalibrateConnections(pipeBase.PipelineTaskConnections, dimensions=(
"instrument",
"visit",
"detector"),
48 icSourceSchema = cT.InitInput(
49 doc=
"Schema produced by characterize image task, used to initialize this task",
51 storageClass=
"SourceCatalog",
55 outputSchema = cT.InitOutput(
56 doc=
"Schema after CalibrateTask has been initialized",
58 storageClass=
"SourceCatalog",
63 doc=
"Input image to calibrate",
65 storageClass=
"ExposureF",
66 dimensions=(
"instrument",
"visit",
"detector"),
69 background = cT.Input(
70 doc=
"Backgrounds determined by characterize task",
71 name=
"icExpBackground",
72 storageClass=
"Background",
73 dimensions=(
"instrument",
"visit",
"detector"),
76 icSourceCat = cT.Input(
77 doc=
"Source catalog created by characterize task",
79 storageClass=
"SourceCatalog",
80 dimensions=(
"instrument",
"visit",
"detector"),
83 astromRefCat = cT.PrerequisiteInput(
84 doc=
"Reference catalog to use for astrometry",
86 storageClass=
"SimpleCatalog",
87 dimensions=(
"skypix",),
92 photoRefCat = cT.PrerequisiteInput(
93 doc=
"Reference catalog to use for photometric calibration",
95 storageClass=
"SimpleCatalog",
96 dimensions=(
"skypix",),
101 outputExposure = cT.Output(
102 doc=
"Exposure after running calibration task",
104 storageClass=
"ExposureF",
105 dimensions=(
"instrument",
"visit",
"detector"),
108 outputCat = cT.Output(
109 doc=
"Source catalog produced in calibrate task",
111 storageClass=
"SourceCatalog",
112 dimensions=(
"instrument",
"visit",
"detector"),
115 outputBackground = cT.Output(
116 doc=
"Background models estimated in calibration task",
117 name=
"calexpBackground",
118 storageClass=
"Background",
119 dimensions=(
"instrument",
"visit",
"detector"),
123 doc=
"Source/refObj matches from the astrometry solver",
125 storageClass=
"Catalog",
126 dimensions=(
"instrument",
"visit",
"detector"),
129 matchesDenormalized = cT.Output(
130 doc=
"Denormalized matches from astrometry solver",
132 storageClass=
"Catalog",
133 dimensions=(
"instrument",
"visit",
"detector"),
138 if config.doWriteMatches
is False:
139 self.outputs.remove(
"matches")
140 if config.doWriteMatchesDenormalized
is False:
141 self.outputs.remove(
"matchesDenormalized")
144 class CalibrateConfig(pipeBase.PipelineTaskConfig, pipelineConnections=CalibrateConnections):
145 """Config for CalibrateTask""" 146 doWrite = pexConfig.Field(
149 doc=
"Save calibration results?",
151 doWriteHeavyFootprintsInSources = pexConfig.Field(
154 doc=
"Include HeavyFootprint data in source table? If false then heavy " 155 "footprints are saved as normal footprints, which saves some space" 157 doWriteMatches = pexConfig.Field(
160 doc=
"Write reference matches (ignored if doWrite false)?",
162 doWriteMatchesDenormalized = pexConfig.Field(
165 doc=(
"Write reference matches in denormalized format? " 166 "This format uses more disk space, but is more convenient to " 167 "read. Ignored if doWriteMatches=False or doWrite=False."),
169 doAstrometry = pexConfig.Field(
172 doc=
"Perform astrometric calibration?",
174 astromRefObjLoader = pexConfig.ConfigurableField(
175 target=LoadIndexedReferenceObjectsTask,
176 doc=
"reference object loader for astrometric calibration",
178 photoRefObjLoader = pexConfig.ConfigurableField(
179 target=LoadIndexedReferenceObjectsTask,
180 doc=
"reference object loader for photometric calibration",
182 astrometry = pexConfig.ConfigurableField(
183 target=AstrometryTask,
184 doc=
"Perform astrometric calibration to refine the WCS",
186 requireAstrometry = pexConfig.Field(
189 doc=(
"Raise an exception if astrometry fails? Ignored if doAstrometry " 192 doPhotoCal = pexConfig.Field(
195 doc=
"Perform phometric calibration?",
197 requirePhotoCal = pexConfig.Field(
200 doc=(
"Raise an exception if photoCal fails? Ignored if doPhotoCal " 203 photoCal = pexConfig.ConfigurableField(
205 doc=
"Perform photometric calibration",
207 icSourceFieldsToCopy = pexConfig.ListField(
209 default=(
"calib_psf_candidate",
"calib_psf_used",
"calib_psf_reserved"),
210 doc=(
"Fields to copy from the icSource catalog to the output catalog " 211 "for matching sources Any missing fields will trigger a " 212 "RuntimeError exception. Ignored if icSourceCat is not provided.")
214 matchRadiusPix = pexConfig.Field(
217 doc=(
"Match radius for matching icSourceCat objects to sourceCat " 220 checkUnitsParseStrict = pexConfig.Field(
221 doc=(
"Strictness of Astropy unit compatibility check, can be 'raise', " 222 "'warn' or 'silent'"),
226 detection = pexConfig.ConfigurableField(
227 target=SourceDetectionTask,
230 doDeblend = pexConfig.Field(
233 doc=
"Run deblender input exposure" 235 deblend = pexConfig.ConfigurableField(
236 target=SourceDeblendTask,
237 doc=
"Split blended sources into their components" 239 measurement = pexConfig.ConfigurableField(
240 target=SingleFrameMeasurementTask,
241 doc=
"Measure sources" 243 doApCorr = pexConfig.Field(
246 doc=
"Run subtask to apply aperture correction" 248 applyApCorr = pexConfig.ConfigurableField(
249 target=ApplyApCorrTask,
250 doc=
"Subtask to apply aperture corrections" 255 catalogCalculation = pexConfig.ConfigurableField(
256 target=CatalogCalculationTask,
257 doc=
"Subtask to run catalogCalculation plugins on catalog" 259 doInsertFakes = pexConfig.Field(
262 doc=
"Run fake sources injection task" 264 insertFakes = pexConfig.ConfigurableField(
265 target=BaseFakeSourcesTask,
266 doc=
"Injection of fake sources for testing purposes (must be " 269 doWriteExposure = pexConfig.Field(
272 doc=
"Write the calexp? If fakes have been added then we do not want to write out the calexp as a " 273 "normal calexp but as a fakes_calexp." 285 r"""!Calibrate an exposure: measure sources and perform astrometric and 286 photometric calibration 288 @anchor CalibrateTask_ 290 @section pipe_tasks_calibrate_Contents Contents 292 - @ref pipe_tasks_calibrate_Purpose 293 - @ref pipe_tasks_calibrate_Initialize 294 - @ref pipe_tasks_calibrate_IO 295 - @ref pipe_tasks_calibrate_Config 296 - @ref pipe_tasks_calibrate_Metadata 297 - @ref pipe_tasks_calibrate_Debug 300 @section pipe_tasks_calibrate_Purpose Description 302 Given an exposure with a good PSF model and aperture correction map 303 (e.g. as provided by @ref CharacterizeImageTask), perform the following 305 - Run detection and measurement 306 - Run astrometry subtask to fit an improved WCS 307 - Run photoCal subtask to fit the exposure's photometric zero-point 309 @section pipe_tasks_calibrate_Initialize Task initialisation 311 @copydoc \_\_init\_\_ 313 @section pipe_tasks_calibrate_IO Invoking the Task 315 If you want this task to unpersist inputs or persist outputs, then call 316 the `runDataRef` method (a wrapper around the `run` method). 318 If you already have the inputs unpersisted and do not want to persist the 319 output then it is more direct to call the `run` method: 321 @section pipe_tasks_calibrate_Config Configuration parameters 323 See @ref CalibrateConfig 325 @section pipe_tasks_calibrate_Metadata Quantities set in exposure Metadata 329 <dt>MAGZERO_RMS <dd>MAGZERO's RMS == sigma reported by photoCal task 330 <dt>MAGZERO_NOBJ <dd>Number of stars used == ngood reported by photoCal 332 <dt>COLORTERM1 <dd>?? (always 0.0) 333 <dt>COLORTERM2 <dd>?? (always 0.0) 334 <dt>COLORTERM3 <dd>?? (always 0.0) 337 @section pipe_tasks_calibrate_Debug Debug variables 339 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink 340 interface supports a flag 341 `--debug` to import `debug.py` from your `$PYTHONPATH`; see @ref baseDebug 342 for more about `debug.py`. 344 CalibrateTask has a debug dictionary containing one key: 347 <dd>frame (an int; <= 0 to not display) in which to display the exposure, 348 sources and matches. See @ref lsst.meas.astrom.displayAstrometry for 349 the meaning of the various symbols. 352 For example, put something like: 356 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would 357 # call us recursively 358 if name == "lsst.pipe.tasks.calibrate": 365 lsstDebug.Info = DebugInfo 367 into your `debug.py` file and run `calibrateTask.py` with the `--debug` 370 Some subtasks may have their own debug variables; see individual Task 377 ConfigClass = CalibrateConfig
378 _DefaultName =
"calibrate" 379 RunnerClass = pipeBase.ButlerInitializedTaskRunner
381 def __init__(self, butler=None, astromRefObjLoader=None,
382 photoRefObjLoader=None, icSourceSchema=None,
383 initInputs=None, **kwargs):
384 """!Construct a CalibrateTask 386 @param[in] butler The butler is passed to the refObjLoader constructor 387 in case it is needed. Ignored if the refObjLoader argument 388 provides a loader directly. 389 @param[in] astromRefObjLoader An instance of LoadReferenceObjectsTasks 390 that supplies an external reference catalog for astrometric 391 calibration. May be None if the desired loader can be constructed 392 from the butler argument or all steps requiring a reference catalog 394 @param[in] photoRefObjLoader An instance of LoadReferenceObjectsTasks 395 that supplies an external reference catalog for photometric 396 calibration. May be None if the desired loader can be constructed 397 from the butler argument or all steps requiring a reference catalog 399 @param[in] icSourceSchema schema for icSource catalog, or None. 400 Schema values specified in config.icSourceFieldsToCopy will be 401 taken from this schema. If set to None, no values will be 402 propagated from the icSourceCatalog 403 @param[in,out] kwargs other keyword arguments for 404 lsst.pipe.base.CmdLineTask 408 if icSourceSchema
is None and butler
is not None:
410 icSourceSchema = butler.get(
"icSrc_schema", immediate=
True).schema
412 if icSourceSchema
is None and butler
is None and initInputs
is not None:
413 icSourceSchema = initInputs[
'icSourceSchema'].schema
415 if icSourceSchema
is not None:
418 minimumSchema = afwTable.SourceTable.makeMinimalSchema()
419 self.
schemaMapper.addMinimalSchema(minimumSchema,
False)
427 afwTable.Field[
"Flag"](
"calib_detected",
428 "Source was detected as an icSource"))
429 missingFieldNames = []
430 for fieldName
in self.config.icSourceFieldsToCopy:
432 schemaItem = icSourceSchema.find(fieldName)
434 missingFieldNames.append(fieldName)
439 if missingFieldNames:
440 raise RuntimeError(
"isSourceCat is missing fields {} " 441 "specified in icSourceFieldsToCopy" 442 .format(missingFieldNames))
449 self.
schema = afwTable.SourceTable.makeMinimalSchema()
450 self.makeSubtask(
'detection', schema=self.
schema)
457 if self.config.doInsertFakes:
458 self.makeSubtask(
"insertFakes")
460 if self.config.doDeblend:
461 self.makeSubtask(
"deblend", schema=self.
schema)
462 self.makeSubtask(
'measurement', schema=self.
schema,
464 if self.config.doApCorr:
465 self.makeSubtask(
'applyApCorr', schema=self.
schema)
466 self.makeSubtask(
'catalogCalculation', schema=self.
schema)
468 if self.config.doAstrometry:
469 if astromRefObjLoader
is None and butler
is not None:
470 self.makeSubtask(
'astromRefObjLoader', butler=butler)
471 astromRefObjLoader = self.astromRefObjLoader
473 self.makeSubtask(
"astrometry", refObjLoader=astromRefObjLoader,
475 if self.config.doPhotoCal:
476 if photoRefObjLoader
is None and butler
is not None:
477 self.makeSubtask(
'photoRefObjLoader', butler=butler)
478 photoRefObjLoader = self.photoRefObjLoader
479 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
480 self.makeSubtask(
"photoCal", refObjLoader=photoRefObjLoader,
483 if initInputs
is not None and (astromRefObjLoader
is not None or photoRefObjLoader
is not None):
484 raise RuntimeError(
"PipelineTask form of this task should not be initialized with " 485 "reference object loaders.")
490 self.
schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
492 sourceCatSchema = afwTable.SourceCatalog(self.
schema)
497 def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None,
499 """!Calibrate an exposure, optionally unpersisting inputs and 502 This is a wrapper around the `run` method that unpersists inputs 503 (if `doUnpersist` true) and persists outputs (if `config.doWrite` true) 505 @param[in] dataRef butler data reference corresponding to a science 507 @param[in,out] exposure characterized exposure (an 508 lsst.afw.image.ExposureF or similar), or None to unpersist existing 509 icExp and icBackground. See `run` method for details of what is 511 @param[in,out] background initial model of background already 512 subtracted from exposure (an lsst.afw.math.BackgroundList). May be 513 None if no background has been subtracted, though that is unusual 514 for calibration. A refined background model is output. Ignored if 516 @param[in] icSourceCat catalog from which to copy the fields specified 517 by icSourceKeys, or None; 518 @param[in] doUnpersist unpersist data: 519 - if True, exposure, background and icSourceCat are read from 520 dataRef and those three arguments must all be None; 521 - if False the exposure must be provided; background and 522 icSourceCat are optional. True is intended for running as a 523 command-line task, False for running as a subtask 524 @return same data as the calibrate method 526 self.log.info(
"Processing %s" % (dataRef.dataId))
529 if any(item
is not None for item
in (exposure, background,
531 raise RuntimeError(
"doUnpersist true; exposure, background " 532 "and icSourceCat must all be None")
533 exposure = dataRef.get(
"icExp", immediate=
True)
534 background = dataRef.get(
"icExpBackground", immediate=
True)
535 icSourceCat = dataRef.get(
"icSrc", immediate=
True)
536 elif exposure
is None:
537 raise RuntimeError(
"doUnpersist false; exposure must be provided")
539 exposureIdInfo = dataRef.get(
"expIdInfo")
543 exposureIdInfo=exposureIdInfo,
544 background=background,
545 icSourceCat=icSourceCat,
548 if self.config.doWrite:
551 exposure=calRes.exposure,
552 background=calRes.background,
553 sourceCat=calRes.sourceCat,
554 astromMatches=calRes.astromMatches,
555 matchMeta=calRes.matchMeta,
561 inputs = butlerQC.get(inputRefs)
562 expId, expBits = butlerQC.registry.packDataId(
"visit_detector",
563 butlerQC.quantum.dataId,
565 inputs[
'exposureIdInfo'] = ExposureIdInfo(expId, expBits)
567 if self.config.doAstrometry:
568 refObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
569 for ref
in inputRefs.astromRefCat],
570 refCats=inputs.pop(
'astromRefCat'),
571 config=self.config.astromRefObjLoader, log=self.log)
573 self.astrometry.setRefObjLoader(refObjLoader)
575 if self.config.doPhotoCal:
576 photoRefObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
577 for ref
in inputRefs.photoRefCat],
578 refCats=inputs.pop(
'photoRefCat'),
579 config=self.config.photoRefObjLoader,
581 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
582 self.photoCal.match.setRefObjLoader(photoRefObjLoader)
584 outputs = self.
run(**inputs)
586 if self.config.doWriteMatches:
587 normalizedMatches = afwTable.packMatches(outputs.astromMatches)
588 normalizedMatches.table.setMetadata(outputs.matchMeta)
589 if self.config.doWriteMatchesDenormalized:
590 denormMatches = denormalizeMatches(outputs.astromMatches, outputs.matchMeta)
591 outputs.matchesDenormalized = denormMatches
592 outputs.matches = normalizedMatches
593 butlerQC.put(outputs, outputRefs)
595 def run(self, exposure, exposureIdInfo=None, background=None,
597 """!Calibrate an exposure (science image or coadd) 599 @param[in,out] exposure exposure to calibrate (an 600 lsst.afw.image.ExposureF or similar); 605 - MaskedImage has background subtracted 607 - PhotoCalib is replaced 608 @param[in] exposureIdInfo ID info for exposure (an 609 lsst.obs.base.ExposureIdInfo) If not provided, returned 610 SourceCatalog IDs will not be globally unique. 611 @param[in,out] background background model already subtracted from 612 exposure (an lsst.afw.math.BackgroundList). May be None if no 613 background has been subtracted, though that is unusual for 614 calibration. A refined background model is output. 615 @param[in] icSourceCat A SourceCatalog from CharacterizeImageTask 616 from which we can copy some fields. 618 @return pipe_base Struct containing these fields: 619 - exposure calibrate science exposure with refined WCS and PhotoCalib 620 - background model of background subtracted from exposure (an 621 lsst.afw.math.BackgroundList) 622 - sourceCat catalog of measured sources 623 - astromMatches list of source/refObj matches from the astrometry 627 if exposureIdInfo
is None:
628 exposureIdInfo = ExposureIdInfo()
630 if background
is None:
631 background = BackgroundList()
632 sourceIdFactory = IdFactory.makeSource(exposureIdInfo.expId,
633 exposureIdInfo.unusedBits)
634 table = SourceTable.make(self.
schema, sourceIdFactory)
637 detRes = self.detection.
run(table=table, exposure=exposure,
639 sourceCat = detRes.sources
640 if detRes.fpSets.background:
641 for bg
in detRes.fpSets.background:
642 background.append(bg)
643 if self.config.doDeblend:
644 self.deblend.
run(exposure=exposure, sources=sourceCat)
645 self.measurement.
run(
648 exposureId=exposureIdInfo.expId
650 if self.config.doApCorr:
651 self.applyApCorr.
run(
653 apCorrMap=exposure.getInfo().getApCorrMap()
655 self.catalogCalculation.
run(sourceCat)
657 if icSourceCat
is not None and \
658 len(self.config.icSourceFieldsToCopy) > 0:
666 if not sourceCat.isContiguous():
667 sourceCat = sourceCat.copy(deep=
True)
673 if self.config.doAstrometry:
675 astromRes = self.astrometry.
run(
679 astromMatches = astromRes.matches
680 matchMeta = astromRes.matchMeta
681 except Exception
as e:
682 if self.config.requireAstrometry:
684 self.log.warn(
"Unable to perform astrometric calibration " 685 "(%s): attempting to proceed" % e)
688 if self.config.doPhotoCal:
690 photoRes = self.photoCal.
run(exposure, sourceCat=sourceCat, expId=exposureIdInfo.expId)
691 exposure.setPhotoCalib(photoRes.photoCalib)
693 self.log.info(
"Photometric zero-point: %f" %
694 photoRes.photoCalib.instFluxToMagnitude(1.0))
695 self.
setMetadata(exposure=exposure, photoRes=photoRes)
696 except Exception
as e:
697 if self.config.requirePhotoCal:
699 self.log.warn(
"Unable to perform photometric calibration " 700 "(%s): attempting to proceed" % e)
703 if self.config.doInsertFakes:
704 self.insertFakes.
run(exposure, background=background)
706 table = SourceTable.make(self.
schema, sourceIdFactory)
709 detRes = self.detection.
run(table=table, exposure=exposure,
711 sourceCat = detRes.sources
712 if detRes.fpSets.background:
713 for bg
in detRes.fpSets.background:
714 background.append(bg)
715 if self.config.doDeblend:
716 self.deblend.
run(exposure=exposure, sources=sourceCat)
717 self.measurement.
run(
720 exposureId=exposureIdInfo.expId
722 if self.config.doApCorr:
723 self.applyApCorr.
run(
725 apCorrMap=exposure.getInfo().getApCorrMap()
727 self.catalogCalculation.
run(sourceCat)
729 if icSourceCat
is not None and \
730 len(self.config.icSourceFieldsToCopy) > 0:
734 frame = getDebugFrame(self._display,
"calibrate")
739 matches=astromMatches,
744 return pipeBase.Struct(
746 background=background,
748 astromMatches=astromMatches,
752 outputExposure=exposure,
754 outputBackground=background,
757 def writeOutputs(self, dataRef, exposure, background, sourceCat,
758 astromMatches, matchMeta):
759 """Write output data to the output repository 761 @param[in] dataRef butler data reference corresponding to a science 763 @param[in] exposure exposure to write 764 @param[in] background background model for exposure 765 @param[in] sourceCat catalog of measured sources 766 @param[in] astromMatches list of source/refObj matches from the 769 dataRef.put(sourceCat,
"src")
770 if self.config.doWriteMatches
and astromMatches
is not None:
771 normalizedMatches = afwTable.packMatches(astromMatches)
772 normalizedMatches.table.setMetadata(matchMeta)
773 dataRef.put(normalizedMatches,
"srcMatch")
774 if self.config.doWriteMatchesDenormalized:
775 denormMatches = denormalizeMatches(astromMatches, matchMeta)
776 dataRef.put(denormMatches,
"srcMatchFull")
777 if self.config.doWriteExposure:
778 dataRef.put(exposure,
"calexp")
779 dataRef.put(background,
"calexpBackground")
782 """Return a dict of empty catalogs for each catalog dataset produced 785 sourceCat = afwTable.SourceCatalog(self.
schema)
787 return {
"src": sourceCat}
790 """!Set task and exposure metadata 792 Logs a warning and continues if needed data is missing. 794 @param[in,out] exposure exposure whose metadata is to be set 795 @param[in] photoRes results of running photoCal; if None then it was 803 exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
804 magZero = photoRes.zp - 2.5*math.log10(exposureTime)
805 self.metadata.set(
'MAGZERO', magZero)
807 self.log.warn(
"Could not set normalized MAGZERO in header: no " 811 metadata = exposure.getMetadata()
812 metadata.set(
'MAGZERO_RMS', photoRes.sigma)
813 metadata.set(
'MAGZERO_NOBJ', photoRes.ngood)
814 metadata.set(
'COLORTERM1', 0.0)
815 metadata.set(
'COLORTERM2', 0.0)
816 metadata.set(
'COLORTERM3', 0.0)
817 except Exception
as e:
818 self.log.warn(
"Could not set exposure metadata: %s" % (e,))
821 """!Match sources in icSourceCat and sourceCat and copy the specified fields 823 @param[in] icSourceCat catalog from which to copy fields 824 @param[in,out] sourceCat catalog to which to copy fields 826 The fields copied are those specified by `config.icSourceFieldsToCopy` 827 that actually exist in the schema. This was set up by the constructor 828 using self.schemaMapper. 831 raise RuntimeError(
"To copy icSource fields you must specify " 832 "icSourceSchema nd icSourceKeys when " 833 "constructing this task")
834 if icSourceCat
is None or sourceCat
is None:
835 raise RuntimeError(
"icSourceCat and sourceCat must both be " 837 if len(self.config.icSourceFieldsToCopy) == 0:
838 self.log.warn(
"copyIcSourceFields doing nothing because " 839 "icSourceFieldsToCopy is empty")
842 mc = afwTable.MatchControl()
843 mc.findOnlyClosest =
False 844 matches = afwTable.matchXy(icSourceCat, sourceCat,
845 self.config.matchRadiusPix, mc)
846 if self.config.doDeblend:
847 deblendKey = sourceCat.schema[
"deblend_nChild"].asKey()
849 matches = [m
for m
in matches
if m[1].get(deblendKey) == 0]
856 for m0, m1, d
in matches:
858 match = bestMatches.get(id0)
859 if match
is None or d <= match[2]:
860 bestMatches[id0] = (m0, m1, d)
861 matches = list(bestMatches.values())
866 numMatches = len(matches)
867 numUniqueSources = len(set(m[1].getId()
for m
in matches))
868 if numUniqueSources != numMatches:
869 self.log.warn(
"{} icSourceCat sources matched only {} sourceCat " 870 "sources".format(numMatches, numUniqueSources))
872 self.log.info(
"Copying flags from icSourceCat to sourceCat for " 873 "%s sources" % (numMatches,))
877 for icSrc, src, d
in matches:
883 icSrcFootprint = icSrc.getFootprint()
885 icSrc.setFootprint(src.getFootprint())
888 icSrc.setFootprint(icSrcFootprint)
def copyIcSourceFields(self, icSourceCat, sourceCat)
Match sources in icSourceCat and sourceCat and copy the specified fields.
def __init__(self, butler=None, astromRefObjLoader=None, photoRefObjLoader=None, icSourceSchema=None, initInputs=None, kwargs)
Construct a CalibrateTask.
def run(self, exposure, exposureIdInfo=None, background=None, icSourceCat=None)
Calibrate an exposure (science image or coadd)
def writeOutputs(self, dataRef, exposure, background, sourceCat, astromMatches, matchMeta)
def __init__(self, config=None)
def setMetadata(self, exposure, photoRes=None)
Set task and exposure metadata.
def getSchemaCatalogs(self)
def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None, doUnpersist=True)
Calibrate an exposure, optionally unpersisting inputs and persisting outputs.
Calibrate an exposure: measure sources and perform astrometric and photometric calibration.
def runQuantum(self, butlerQC, inputRefs, outputRefs)