24 from lsstDebug
import getDebugFrame
25 import lsst.pex.config
as pexConfig
29 from lsst.meas.astrom import AstrometryTask, displayAstrometry, denormalizeMatches
38 CatalogCalculationTask)
40 from .fakes
import BaseFakeSourcesTask
41 from .photoCal
import PhotoCalTask
43 __all__ = [
"CalibrateConfig",
"CalibrateTask"]
46 class CalibrateConnections(pipeBase.PipelineTaskConnections, dimensions=(
"instrument",
"visit",
"detector"),
49 icSourceSchema = cT.InitInput(
50 doc=
"Schema produced by characterize image task, used to initialize this task",
52 storageClass=
"SourceCatalog",
56 outputSchema = cT.InitOutput(
57 doc=
"Schema after CalibrateTask has been initialized",
59 storageClass=
"SourceCatalog",
64 doc=
"Input image to calibrate",
66 storageClass=
"ExposureF",
67 dimensions=(
"instrument",
"visit",
"detector"),
70 background = cT.Input(
71 doc=
"Backgrounds determined by characterize task",
72 name=
"icExpBackground",
73 storageClass=
"Background",
74 dimensions=(
"instrument",
"visit",
"detector"),
77 icSourceCat = cT.Input(
78 doc=
"Source catalog created by characterize task",
80 storageClass=
"SourceCatalog",
81 dimensions=(
"instrument",
"visit",
"detector"),
84 astromRefCat = cT.PrerequisiteInput(
85 doc=
"Reference catalog to use for astrometry",
87 storageClass=
"SimpleCatalog",
88 dimensions=(
"skypix",),
93 photoRefCat = cT.PrerequisiteInput(
94 doc=
"Reference catalog to use for photometric calibration",
96 storageClass=
"SimpleCatalog",
97 dimensions=(
"skypix",),
102 outputExposure = cT.Output(
103 doc=
"Exposure after running calibration task",
105 storageClass=
"ExposureF",
106 dimensions=(
"instrument",
"visit",
"detector"),
109 outputCat = cT.Output(
110 doc=
"Source catalog produced in calibrate task",
112 storageClass=
"SourceCatalog",
113 dimensions=(
"instrument",
"visit",
"detector"),
116 outputBackground = cT.Output(
117 doc=
"Background models estimated in calibration task",
118 name=
"calexpBackground",
119 storageClass=
"Background",
120 dimensions=(
"instrument",
"visit",
"detector"),
124 doc=
"Source/refObj matches from the astrometry solver",
126 storageClass=
"Catalog",
127 dimensions=(
"instrument",
"visit",
"detector"),
130 matchesDenormalized = cT.Output(
131 doc=
"Denormalized matches from astrometry solver",
133 storageClass=
"Catalog",
134 dimensions=(
"instrument",
"visit",
"detector"),
139 if config.doWriteMatches
is False:
140 self.outputs.remove(
"matches")
141 if config.doWriteMatchesDenormalized
is False:
142 self.outputs.remove(
"matchesDenormalized")
145 class CalibrateConfig(pipeBase.PipelineTaskConfig, pipelineConnections=CalibrateConnections):
146 """Config for CalibrateTask""" 147 doWrite = pexConfig.Field(
150 doc=
"Save calibration results?",
152 doWriteHeavyFootprintsInSources = pexConfig.Field(
155 doc=
"Include HeavyFootprint data in source table? If false then heavy " 156 "footprints are saved as normal footprints, which saves some space" 158 doWriteMatches = pexConfig.Field(
161 doc=
"Write reference matches (ignored if doWrite false)?",
163 doWriteMatchesDenormalized = pexConfig.Field(
166 doc=(
"Write reference matches in denormalized format? " 167 "This format uses more disk space, but is more convenient to " 168 "read. Ignored if doWriteMatches=False or doWrite=False."),
170 doAstrometry = pexConfig.Field(
173 doc=
"Perform astrometric calibration?",
175 astromRefObjLoader = pexConfig.ConfigurableField(
176 target=LoadIndexedReferenceObjectsTask,
177 doc=
"reference object loader for astrometric calibration",
179 photoRefObjLoader = pexConfig.ConfigurableField(
180 target=LoadIndexedReferenceObjectsTask,
181 doc=
"reference object loader for photometric calibration",
183 astrometry = pexConfig.ConfigurableField(
184 target=AstrometryTask,
185 doc=
"Perform astrometric calibration to refine the WCS",
187 requireAstrometry = pexConfig.Field(
190 doc=(
"Raise an exception if astrometry fails? Ignored if doAstrometry " 193 doPhotoCal = pexConfig.Field(
196 doc=
"Perform phometric calibration?",
198 requirePhotoCal = pexConfig.Field(
201 doc=(
"Raise an exception if photoCal fails? Ignored if doPhotoCal " 204 photoCal = pexConfig.ConfigurableField(
206 doc=
"Perform photometric calibration",
208 icSourceFieldsToCopy = pexConfig.ListField(
210 default=(
"calib_psf_candidate",
"calib_psf_used",
"calib_psf_reserved"),
211 doc=(
"Fields to copy from the icSource catalog to the output catalog " 212 "for matching sources Any missing fields will trigger a " 213 "RuntimeError exception. Ignored if icSourceCat is not provided.")
215 matchRadiusPix = pexConfig.Field(
218 doc=(
"Match radius for matching icSourceCat objects to sourceCat " 221 checkUnitsParseStrict = pexConfig.Field(
222 doc=(
"Strictness of Astropy unit compatibility check, can be 'raise', " 223 "'warn' or 'silent'"),
227 detection = pexConfig.ConfigurableField(
228 target=SourceDetectionTask,
231 doDeblend = pexConfig.Field(
234 doc=
"Run deblender input exposure" 236 deblend = pexConfig.ConfigurableField(
237 target=SourceDeblendTask,
238 doc=
"Split blended sources into their components" 240 measurement = pexConfig.ConfigurableField(
241 target=SingleFrameMeasurementTask,
242 doc=
"Measure sources" 244 doApCorr = pexConfig.Field(
247 doc=
"Run subtask to apply aperture correction" 249 applyApCorr = pexConfig.ConfigurableField(
250 target=ApplyApCorrTask,
251 doc=
"Subtask to apply aperture corrections" 256 catalogCalculation = pexConfig.ConfigurableField(
257 target=CatalogCalculationTask,
258 doc=
"Subtask to run catalogCalculation plugins on catalog" 260 doInsertFakes = pexConfig.Field(
263 doc=
"Run fake sources injection task" 265 insertFakes = pexConfig.ConfigurableField(
266 target=BaseFakeSourcesTask,
267 doc=
"Injection of fake sources for testing purposes (must be " 270 doWriteExposure = pexConfig.Field(
273 doc=
"Write the calexp? If fakes have been added then we do not want to write out the calexp as a " 274 "normal calexp but as a fakes_calexp." 279 self.
detection.doTempLocalBackground =
False 280 self.
deblend.maxFootprintSize = 2000
285 if astromRefCatGen2
is not None and astromRefCatGen2 != self.connections.astromRefCat:
287 f
"Gen2 ({astromRefCatGen2}) and Gen3 ({self.connections.astromRefCat}) astrometry reference " 288 f
"catalogs are different. These options must be kept in sync until Gen2 is retired." 291 if photoRefCatGen2
is not None and photoRefCatGen2 != self.connections.photoRefCat:
293 f
"Gen2 ({photoRefCatGen2}) and Gen3 ({self.connections.photoRefCat}) photometry reference " 294 f
"catalogs are different. These options must be kept in sync until Gen2 is retired." 306 r"""!Calibrate an exposure: measure sources and perform astrometric and 307 photometric calibration 309 @anchor CalibrateTask_ 311 @section pipe_tasks_calibrate_Contents Contents 313 - @ref pipe_tasks_calibrate_Purpose 314 - @ref pipe_tasks_calibrate_Initialize 315 - @ref pipe_tasks_calibrate_IO 316 - @ref pipe_tasks_calibrate_Config 317 - @ref pipe_tasks_calibrate_Metadata 318 - @ref pipe_tasks_calibrate_Debug 321 @section pipe_tasks_calibrate_Purpose Description 323 Given an exposure with a good PSF model and aperture correction map 324 (e.g. as provided by @ref CharacterizeImageTask), perform the following 326 - Run detection and measurement 327 - Run astrometry subtask to fit an improved WCS 328 - Run photoCal subtask to fit the exposure's photometric zero-point 330 @section pipe_tasks_calibrate_Initialize Task initialisation 332 @copydoc \_\_init\_\_ 334 @section pipe_tasks_calibrate_IO Invoking the Task 336 If you want this task to unpersist inputs or persist outputs, then call 337 the `runDataRef` method (a wrapper around the `run` method). 339 If you already have the inputs unpersisted and do not want to persist the 340 output then it is more direct to call the `run` method: 342 @section pipe_tasks_calibrate_Config Configuration parameters 344 See @ref CalibrateConfig 346 @section pipe_tasks_calibrate_Metadata Quantities set in exposure Metadata 350 <dt>MAGZERO_RMS <dd>MAGZERO's RMS == sigma reported by photoCal task 351 <dt>MAGZERO_NOBJ <dd>Number of stars used == ngood reported by photoCal 353 <dt>COLORTERM1 <dd>?? (always 0.0) 354 <dt>COLORTERM2 <dd>?? (always 0.0) 355 <dt>COLORTERM3 <dd>?? (always 0.0) 358 @section pipe_tasks_calibrate_Debug Debug variables 360 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink 361 interface supports a flag 362 `--debug` to import `debug.py` from your `$PYTHONPATH`; see @ref baseDebug 363 for more about `debug.py`. 365 CalibrateTask has a debug dictionary containing one key: 368 <dd>frame (an int; <= 0 to not display) in which to display the exposure, 369 sources and matches. See @ref lsst.meas.astrom.displayAstrometry for 370 the meaning of the various symbols. 373 For example, put something like: 377 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would 378 # call us recursively 379 if name == "lsst.pipe.tasks.calibrate": 386 lsstDebug.Info = DebugInfo 388 into your `debug.py` file and run `calibrateTask.py` with the `--debug` 391 Some subtasks may have their own debug variables; see individual Task 398 ConfigClass = CalibrateConfig
399 _DefaultName =
"calibrate" 400 RunnerClass = pipeBase.ButlerInitializedTaskRunner
402 def __init__(self, butler=None, astromRefObjLoader=None,
403 photoRefObjLoader=None, icSourceSchema=None,
404 initInputs=None, **kwargs):
405 """!Construct a CalibrateTask 407 @param[in] butler The butler is passed to the refObjLoader constructor 408 in case it is needed. Ignored if the refObjLoader argument 409 provides a loader directly. 410 @param[in] astromRefObjLoader An instance of LoadReferenceObjectsTasks 411 that supplies an external reference catalog for astrometric 412 calibration. May be None if the desired loader can be constructed 413 from the butler argument or all steps requiring a reference catalog 415 @param[in] photoRefObjLoader An instance of LoadReferenceObjectsTasks 416 that supplies an external reference catalog for photometric 417 calibration. May be None if the desired loader can be constructed 418 from the butler argument or all steps requiring a reference catalog 420 @param[in] icSourceSchema schema for icSource catalog, or None. 421 Schema values specified in config.icSourceFieldsToCopy will be 422 taken from this schema. If set to None, no values will be 423 propagated from the icSourceCatalog 424 @param[in,out] kwargs other keyword arguments for 425 lsst.pipe.base.CmdLineTask 429 if icSourceSchema
is None and butler
is not None:
431 icSourceSchema = butler.get(
"icSrc_schema", immediate=
True).schema
433 if icSourceSchema
is None and butler
is None and initInputs
is not None:
434 icSourceSchema = initInputs[
'icSourceSchema'].schema
436 if icSourceSchema
is not None:
439 minimumSchema = afwTable.SourceTable.makeMinimalSchema()
440 self.
schemaMapper.addMinimalSchema(minimumSchema,
False)
448 afwTable.Field[
"Flag"](
"calib_detected",
449 "Source was detected as an icSource"))
450 missingFieldNames = []
451 for fieldName
in self.config.icSourceFieldsToCopy:
453 schemaItem = icSourceSchema.find(fieldName)
455 missingFieldNames.append(fieldName)
460 if missingFieldNames:
461 raise RuntimeError(
"isSourceCat is missing fields {} " 462 "specified in icSourceFieldsToCopy" 463 .format(missingFieldNames))
470 self.
schema = afwTable.SourceTable.makeMinimalSchema()
471 self.makeSubtask(
'detection', schema=self.
schema)
478 if self.config.doInsertFakes:
479 self.makeSubtask(
"insertFakes")
481 if self.config.doDeblend:
482 self.makeSubtask(
"deblend", schema=self.
schema)
483 self.makeSubtask(
'measurement', schema=self.
schema,
485 if self.config.doApCorr:
486 self.makeSubtask(
'applyApCorr', schema=self.
schema)
487 self.makeSubtask(
'catalogCalculation', schema=self.
schema)
489 if self.config.doAstrometry:
490 if astromRefObjLoader
is None and butler
is not None:
491 self.makeSubtask(
'astromRefObjLoader', butler=butler)
492 astromRefObjLoader = self.astromRefObjLoader
494 self.makeSubtask(
"astrometry", refObjLoader=astromRefObjLoader,
496 if self.config.doPhotoCal:
497 if photoRefObjLoader
is None and butler
is not None:
498 self.makeSubtask(
'photoRefObjLoader', butler=butler)
499 photoRefObjLoader = self.photoRefObjLoader
500 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
501 self.makeSubtask(
"photoCal", refObjLoader=photoRefObjLoader,
504 if initInputs
is not None and (astromRefObjLoader
is not None or photoRefObjLoader
is not None):
505 raise RuntimeError(
"PipelineTask form of this task should not be initialized with " 506 "reference object loaders.")
511 self.
schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
513 sourceCatSchema = afwTable.SourceCatalog(self.
schema)
518 def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None,
520 """!Calibrate an exposure, optionally unpersisting inputs and 523 This is a wrapper around the `run` method that unpersists inputs 524 (if `doUnpersist` true) and persists outputs (if `config.doWrite` true) 526 @param[in] dataRef butler data reference corresponding to a science 528 @param[in,out] exposure characterized exposure (an 529 lsst.afw.image.ExposureF or similar), or None to unpersist existing 530 icExp and icBackground. See `run` method for details of what is 532 @param[in,out] background initial model of background already 533 subtracted from exposure (an lsst.afw.math.BackgroundList). May be 534 None if no background has been subtracted, though that is unusual 535 for calibration. A refined background model is output. Ignored if 537 @param[in] icSourceCat catalog from which to copy the fields specified 538 by icSourceKeys, or None; 539 @param[in] doUnpersist unpersist data: 540 - if True, exposure, background and icSourceCat are read from 541 dataRef and those three arguments must all be None; 542 - if False the exposure must be provided; background and 543 icSourceCat are optional. True is intended for running as a 544 command-line task, False for running as a subtask 545 @return same data as the calibrate method 547 self.log.info(
"Processing %s" % (dataRef.dataId))
550 if any(item
is not None for item
in (exposure, background,
552 raise RuntimeError(
"doUnpersist true; exposure, background " 553 "and icSourceCat must all be None")
554 exposure = dataRef.get(
"icExp", immediate=
True)
555 background = dataRef.get(
"icExpBackground", immediate=
True)
556 icSourceCat = dataRef.get(
"icSrc", immediate=
True)
557 elif exposure
is None:
558 raise RuntimeError(
"doUnpersist false; exposure must be provided")
560 exposureIdInfo = dataRef.get(
"expIdInfo")
564 exposureIdInfo=exposureIdInfo,
565 background=background,
566 icSourceCat=icSourceCat,
569 if self.config.doWrite:
572 exposure=calRes.exposure,
573 background=calRes.background,
574 sourceCat=calRes.sourceCat,
575 astromMatches=calRes.astromMatches,
576 matchMeta=calRes.matchMeta,
582 inputs = butlerQC.get(inputRefs)
583 expId, expBits = butlerQC.quantum.dataId.pack(
"visit_detector",
585 inputs[
'exposureIdInfo'] = ExposureIdInfo(expId, expBits)
587 if self.config.doAstrometry:
588 refObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
589 for ref
in inputRefs.astromRefCat],
590 refCats=inputs.pop(
'astromRefCat'),
591 config=self.config.astromRefObjLoader, log=self.log)
593 self.astrometry.setRefObjLoader(refObjLoader)
595 if self.config.doPhotoCal:
596 photoRefObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
597 for ref
in inputRefs.photoRefCat],
598 refCats=inputs.pop(
'photoRefCat'),
599 config=self.config.photoRefObjLoader,
601 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
602 self.photoCal.match.setRefObjLoader(photoRefObjLoader)
604 outputs = self.
run(**inputs)
606 if self.config.doWriteMatches:
607 normalizedMatches = afwTable.packMatches(outputs.astromMatches)
608 normalizedMatches.table.setMetadata(outputs.matchMeta)
609 if self.config.doWriteMatchesDenormalized:
610 denormMatches = denormalizeMatches(outputs.astromMatches, outputs.matchMeta)
611 outputs.matchesDenormalized = denormMatches
612 outputs.matches = normalizedMatches
613 butlerQC.put(outputs, outputRefs)
615 def run(self, exposure, exposureIdInfo=None, background=None,
617 """!Calibrate an exposure (science image or coadd) 619 @param[in,out] exposure exposure to calibrate (an 620 lsst.afw.image.ExposureF or similar); 625 - MaskedImage has background subtracted 627 - PhotoCalib is replaced 628 @param[in] exposureIdInfo ID info for exposure (an 629 lsst.obs.base.ExposureIdInfo) If not provided, returned 630 SourceCatalog IDs will not be globally unique. 631 @param[in,out] background background model already subtracted from 632 exposure (an lsst.afw.math.BackgroundList). May be None if no 633 background has been subtracted, though that is unusual for 634 calibration. A refined background model is output. 635 @param[in] icSourceCat A SourceCatalog from CharacterizeImageTask 636 from which we can copy some fields. 638 @return pipe_base Struct containing these fields: 639 - exposure calibrate science exposure with refined WCS and PhotoCalib 640 - background model of background subtracted from exposure (an 641 lsst.afw.math.BackgroundList) 642 - sourceCat catalog of measured sources 643 - astromMatches list of source/refObj matches from the astrometry 647 if exposureIdInfo
is None:
648 exposureIdInfo = ExposureIdInfo()
650 if background
is None:
651 background = BackgroundList()
652 sourceIdFactory = IdFactory.makeSource(exposureIdInfo.expId,
653 exposureIdInfo.unusedBits)
654 table = SourceTable.make(self.
schema, sourceIdFactory)
657 detRes = self.detection.
run(table=table, exposure=exposure,
659 sourceCat = detRes.sources
660 if detRes.fpSets.background:
661 for bg
in detRes.fpSets.background:
662 background.append(bg)
663 if self.config.doDeblend:
664 self.deblend.
run(exposure=exposure, sources=sourceCat)
665 self.measurement.
run(
668 exposureId=exposureIdInfo.expId
670 if self.config.doApCorr:
671 self.applyApCorr.
run(
673 apCorrMap=exposure.getInfo().getApCorrMap()
675 self.catalogCalculation.
run(sourceCat)
677 if icSourceCat
is not None and \
678 len(self.config.icSourceFieldsToCopy) > 0:
686 if not sourceCat.isContiguous():
687 sourceCat = sourceCat.copy(deep=
True)
693 if self.config.doAstrometry:
695 astromRes = self.astrometry.
run(
699 astromMatches = astromRes.matches
700 matchMeta = astromRes.matchMeta
701 except Exception
as e:
702 if self.config.requireAstrometry:
704 self.log.warn(
"Unable to perform astrometric calibration " 705 "(%s): attempting to proceed" % e)
708 if self.config.doPhotoCal:
710 photoRes = self.photoCal.
run(exposure, sourceCat=sourceCat, expId=exposureIdInfo.expId)
711 exposure.setPhotoCalib(photoRes.photoCalib)
713 self.log.info(
"Photometric zero-point: %f" %
714 photoRes.photoCalib.instFluxToMagnitude(1.0))
715 self.
setMetadata(exposure=exposure, photoRes=photoRes)
716 except Exception
as e:
717 if self.config.requirePhotoCal:
719 self.log.warn(
"Unable to perform photometric calibration " 720 "(%s): attempting to proceed" % e)
723 if self.config.doInsertFakes:
724 self.insertFakes.
run(exposure, background=background)
726 table = SourceTable.make(self.
schema, sourceIdFactory)
729 detRes = self.detection.
run(table=table, exposure=exposure,
731 sourceCat = detRes.sources
732 if detRes.fpSets.background:
733 for bg
in detRes.fpSets.background:
734 background.append(bg)
735 if self.config.doDeblend:
736 self.deblend.
run(exposure=exposure, sources=sourceCat)
737 self.measurement.
run(
740 exposureId=exposureIdInfo.expId
742 if self.config.doApCorr:
743 self.applyApCorr.
run(
745 apCorrMap=exposure.getInfo().getApCorrMap()
747 self.catalogCalculation.
run(sourceCat)
749 if icSourceCat
is not None and len(self.config.icSourceFieldsToCopy) > 0:
753 frame = getDebugFrame(self._display,
"calibrate")
758 matches=astromMatches,
763 return pipeBase.Struct(
765 background=background,
767 astromMatches=astromMatches,
771 outputExposure=exposure,
773 outputBackground=background,
776 def writeOutputs(self, dataRef, exposure, background, sourceCat,
777 astromMatches, matchMeta):
778 """Write output data to the output repository 780 @param[in] dataRef butler data reference corresponding to a science 782 @param[in] exposure exposure to write 783 @param[in] background background model for exposure 784 @param[in] sourceCat catalog of measured sources 785 @param[in] astromMatches list of source/refObj matches from the 788 dataRef.put(sourceCat,
"src")
789 if self.config.doWriteMatches
and astromMatches
is not None:
790 normalizedMatches = afwTable.packMatches(astromMatches)
791 normalizedMatches.table.setMetadata(matchMeta)
792 dataRef.put(normalizedMatches,
"srcMatch")
793 if self.config.doWriteMatchesDenormalized:
794 denormMatches = denormalizeMatches(astromMatches, matchMeta)
795 dataRef.put(denormMatches,
"srcMatchFull")
796 if self.config.doWriteExposure:
797 dataRef.put(exposure,
"calexp")
798 dataRef.put(background,
"calexpBackground")
801 """Return a dict of empty catalogs for each catalog dataset produced 804 sourceCat = afwTable.SourceCatalog(self.
schema)
806 return {
"src": sourceCat}
809 """!Set task and exposure metadata 811 Logs a warning and continues if needed data is missing. 813 @param[in,out] exposure exposure whose metadata is to be set 814 @param[in] photoRes results of running photoCal; if None then it was 820 metadata = exposure.getMetadata()
824 exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
825 magZero = photoRes.zp - 2.5*math.log10(exposureTime)
827 self.log.warn(
"Could not set normalized MAGZERO in header: no " 832 metadata.set(
'MAGZERO', magZero)
833 metadata.set(
'MAGZERO_RMS', photoRes.sigma)
834 metadata.set(
'MAGZERO_NOBJ', photoRes.ngood)
835 metadata.set(
'COLORTERM1', 0.0)
836 metadata.set(
'COLORTERM2', 0.0)
837 metadata.set(
'COLORTERM3', 0.0)
838 except Exception
as e:
839 self.log.warn(
"Could not set exposure metadata: %s" % (e,))
842 """!Match sources in icSourceCat and sourceCat and copy the specified fields 844 @param[in] icSourceCat catalog from which to copy fields 845 @param[in,out] sourceCat catalog to which to copy fields 847 The fields copied are those specified by `config.icSourceFieldsToCopy` 848 that actually exist in the schema. This was set up by the constructor 849 using self.schemaMapper. 852 raise RuntimeError(
"To copy icSource fields you must specify " 853 "icSourceSchema nd icSourceKeys when " 854 "constructing this task")
855 if icSourceCat
is None or sourceCat
is None:
856 raise RuntimeError(
"icSourceCat and sourceCat must both be " 858 if len(self.config.icSourceFieldsToCopy) == 0:
859 self.log.warn(
"copyIcSourceFields doing nothing because " 860 "icSourceFieldsToCopy is empty")
863 mc = afwTable.MatchControl()
864 mc.findOnlyClosest =
False 865 matches = afwTable.matchXy(icSourceCat, sourceCat,
866 self.config.matchRadiusPix, mc)
867 if self.config.doDeblend:
868 deblendKey = sourceCat.schema[
"deblend_nChild"].asKey()
870 matches = [m
for m
in matches
if m[1].get(deblendKey) == 0]
877 for m0, m1, d
in matches:
879 match = bestMatches.get(id0)
880 if match
is None or d <= match[2]:
881 bestMatches[id0] = (m0, m1, d)
882 matches = list(bestMatches.values())
887 numMatches = len(matches)
888 numUniqueSources = len(set(m[1].getId()
for m
in matches))
889 if numUniqueSources != numMatches:
890 self.log.warn(
"{} icSourceCat sources matched only {} sourceCat " 891 "sources".format(numMatches, numUniqueSources))
893 self.log.info(
"Copying flags from icSourceCat to sourceCat for " 894 "%s sources" % (numMatches,))
898 for icSrc, src, d
in matches:
904 icSrcFootprint = icSrc.getFootprint()
906 icSrc.setFootprint(src.getFootprint())
909 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)