24 from lsstDebug
import getDebugFrame
25 import lsst.pex.config
as pexConfig
29 from lsst.meas.astrom import AstrometryTask, displayAstrometry, denormalizeMatches
38 CatalogCalculationTask,
39 EvaluateLocalCalibrationTask)
41 from .fakes
import BaseFakeSourcesTask
42 from .photoCal
import PhotoCalTask
44 __all__ = [
"CalibrateConfig",
"CalibrateTask"]
50 icSourceSchema = cT.InitInput(
51 doc=
"Schema produced by characterize image task, used to initialize this task",
53 storageClass=
"SourceCatalog",
57 outputSchema = cT.InitOutput(
58 doc=
"Schema after CalibrateTask has been initialized",
60 storageClass=
"SourceCatalog",
65 doc=
"Input image to calibrate",
67 storageClass=
"ExposureF",
68 dimensions=(
"instrument",
"visit",
"detector"),
71 background = cT.Input(
72 doc=
"Backgrounds determined by characterize task",
73 name=
"icExpBackground",
74 storageClass=
"Background",
75 dimensions=(
"instrument",
"visit",
"detector"),
78 icSourceCat = cT.Input(
79 doc=
"Source catalog created by characterize task",
81 storageClass=
"SourceCatalog",
82 dimensions=(
"instrument",
"visit",
"detector"),
85 astromRefCat = cT.PrerequisiteInput(
86 doc=
"Reference catalog to use for astrometry",
88 storageClass=
"SimpleCatalog",
89 dimensions=(
"skypix",),
94 photoRefCat = cT.PrerequisiteInput(
95 doc=
"Reference catalog to use for photometric calibration",
97 storageClass=
"SimpleCatalog",
98 dimensions=(
"skypix",),
103 outputExposure = cT.Output(
104 doc=
"Exposure after running calibration task",
106 storageClass=
"ExposureF",
107 dimensions=(
"instrument",
"visit",
"detector"),
110 outputCat = cT.Output(
111 doc=
"Source catalog produced in calibrate task",
113 storageClass=
"SourceCatalog",
114 dimensions=(
"instrument",
"visit",
"detector"),
117 outputBackground = cT.Output(
118 doc=
"Background models estimated in calibration task",
119 name=
"calexpBackground",
120 storageClass=
"Background",
121 dimensions=(
"instrument",
"visit",
"detector"),
125 doc=
"Source/refObj matches from the astrometry solver",
127 storageClass=
"Catalog",
128 dimensions=(
"instrument",
"visit",
"detector"),
131 matchesDenormalized = cT.Output(
132 doc=
"Denormalized matches from astrometry solver",
134 storageClass=
"Catalog",
135 dimensions=(
"instrument",
"visit",
"detector"),
140 if config.doWriteMatches
is False:
141 self.outputs.remove(
"matches")
142 if config.doWriteMatchesDenormalized
is False:
143 self.outputs.remove(
"matchesDenormalized")
146 class CalibrateConfig(pipeBase.PipelineTaskConfig, pipelineConnections=CalibrateConnections):
147 """Config for CalibrateTask""" 148 doWrite = pexConfig.Field(
151 doc=
"Save calibration results?",
153 doWriteHeavyFootprintsInSources = pexConfig.Field(
156 doc=
"Include HeavyFootprint data in source table? If false then heavy " 157 "footprints are saved as normal footprints, which saves some space" 159 doWriteMatches = pexConfig.Field(
162 doc=
"Write reference matches (ignored if doWrite false)?",
164 doWriteMatchesDenormalized = pexConfig.Field(
167 doc=(
"Write reference matches in denormalized format? " 168 "This format uses more disk space, but is more convenient to " 169 "read. Ignored if doWriteMatches=False or doWrite=False."),
171 doAstrometry = pexConfig.Field(
174 doc=
"Perform astrometric calibration?",
176 astromRefObjLoader = pexConfig.ConfigurableField(
177 target=LoadIndexedReferenceObjectsTask,
178 doc=
"reference object loader for astrometric calibration",
180 photoRefObjLoader = pexConfig.ConfigurableField(
181 target=LoadIndexedReferenceObjectsTask,
182 doc=
"reference object loader for photometric calibration",
184 astrometry = pexConfig.ConfigurableField(
185 target=AstrometryTask,
186 doc=
"Perform astrometric calibration to refine the WCS",
188 requireAstrometry = pexConfig.Field(
191 doc=(
"Raise an exception if astrometry fails? Ignored if doAstrometry " 194 doPhotoCal = pexConfig.Field(
197 doc=
"Perform phometric calibration?",
199 requirePhotoCal = pexConfig.Field(
202 doc=(
"Raise an exception if photoCal fails? Ignored if doPhotoCal " 205 photoCal = pexConfig.ConfigurableField(
207 doc=
"Perform photometric calibration",
209 doEvalLocCalibration = pexConfig.Field(
212 doc=
"Store calibration products (local wcs and PhotoCalib) in output " 215 evalLocCalib = pexConfig.ConfigurableField(
216 target=EvaluateLocalCalibrationTask,
217 doc=
"Task to strip calibrations from an exposure and store their " 218 "local values in the output source catalog." 220 icSourceFieldsToCopy = pexConfig.ListField(
222 default=(
"calib_psf_candidate",
"calib_psf_used",
"calib_psf_reserved"),
223 doc=(
"Fields to copy from the icSource catalog to the output catalog " 224 "for matching sources Any missing fields will trigger a " 225 "RuntimeError exception. Ignored if icSourceCat is not provided.")
227 matchRadiusPix = pexConfig.Field(
230 doc=(
"Match radius for matching icSourceCat objects to sourceCat " 233 checkUnitsParseStrict = pexConfig.Field(
234 doc=(
"Strictness of Astropy unit compatibility check, can be 'raise', " 235 "'warn' or 'silent'"),
239 detection = pexConfig.ConfigurableField(
240 target=SourceDetectionTask,
243 doDeblend = pexConfig.Field(
246 doc=
"Run deblender input exposure" 248 deblend = pexConfig.ConfigurableField(
249 target=SourceDeblendTask,
250 doc=
"Split blended sources into their components" 252 measurement = pexConfig.ConfigurableField(
253 target=SingleFrameMeasurementTask,
254 doc=
"Measure sources" 256 doApCorr = pexConfig.Field(
259 doc=
"Run subtask to apply aperture correction" 261 applyApCorr = pexConfig.ConfigurableField(
262 target=ApplyApCorrTask,
263 doc=
"Subtask to apply aperture corrections" 268 catalogCalculation = pexConfig.ConfigurableField(
269 target=CatalogCalculationTask,
270 doc=
"Subtask to run catalogCalculation plugins on catalog" 272 doInsertFakes = pexConfig.Field(
275 doc=
"Run fake sources injection task" 277 insertFakes = pexConfig.ConfigurableField(
278 target=BaseFakeSourcesTask,
279 doc=
"Injection of fake sources for testing purposes (must be " 282 doWriteExposure = pexConfig.Field(
285 doc=
"Write the calexp? If fakes have been added then we do not want to write out the calexp as a " 286 "normal calexp but as a fakes_calexp." 292 if astromRefCatGen2
is not None and astromRefCatGen2 != self.connections.astromRefCat:
294 f
"Gen2 ({astromRefCatGen2}) and Gen3 ({self.connections.astromRefCat}) astrometry reference " 295 f
"catalogs are different. These options must be kept in sync until Gen2 is retired." 298 if photoRefCatGen2
is not None and photoRefCatGen2 != self.connections.photoRefCat:
300 f
"Gen2 ({photoRefCatGen2}) and Gen3 ({self.connections.photoRefCat}) photometry reference " 301 f
"catalogs are different. These options must be kept in sync until Gen2 is retired." 313 r"""!Calibrate an exposure: measure sources and perform astrometric and 314 photometric calibration 316 @anchor CalibrateTask_ 318 @section pipe_tasks_calibrate_Contents Contents 320 - @ref pipe_tasks_calibrate_Purpose 321 - @ref pipe_tasks_calibrate_Initialize 322 - @ref pipe_tasks_calibrate_IO 323 - @ref pipe_tasks_calibrate_Config 324 - @ref pipe_tasks_calibrate_Metadata 325 - @ref pipe_tasks_calibrate_Debug 328 @section pipe_tasks_calibrate_Purpose Description 330 Given an exposure with a good PSF model and aperture correction map 331 (e.g. as provided by @ref CharacterizeImageTask), perform the following 333 - Run detection and measurement 334 - Run astrometry subtask to fit an improved WCS 335 - Run photoCal subtask to fit the exposure's photometric zero-point 337 @section pipe_tasks_calibrate_Initialize Task initialisation 339 @copydoc \_\_init\_\_ 341 @section pipe_tasks_calibrate_IO Invoking the Task 343 If you want this task to unpersist inputs or persist outputs, then call 344 the `runDataRef` method (a wrapper around the `run` method). 346 If you already have the inputs unpersisted and do not want to persist the 347 output then it is more direct to call the `run` method: 349 @section pipe_tasks_calibrate_Config Configuration parameters 351 See @ref CalibrateConfig 353 @section pipe_tasks_calibrate_Metadata Quantities set in exposure Metadata 357 <dt>MAGZERO_RMS <dd>MAGZERO's RMS == sigma reported by photoCal task 358 <dt>MAGZERO_NOBJ <dd>Number of stars used == ngood reported by photoCal 360 <dt>COLORTERM1 <dd>?? (always 0.0) 361 <dt>COLORTERM2 <dd>?? (always 0.0) 362 <dt>COLORTERM3 <dd>?? (always 0.0) 365 @section pipe_tasks_calibrate_Debug Debug variables 367 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink 368 interface supports a flag 369 `--debug` to import `debug.py` from your `$PYTHONPATH`; see @ref baseDebug 370 for more about `debug.py`. 372 CalibrateTask has a debug dictionary containing one key: 375 <dd>frame (an int; <= 0 to not display) in which to display the exposure, 376 sources and matches. See @ref lsst.meas.astrom.displayAstrometry for 377 the meaning of the various symbols. 380 For example, put something like: 384 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would 385 # call us recursively 386 if name == "lsst.pipe.tasks.calibrate": 393 lsstDebug.Info = DebugInfo 395 into your `debug.py` file and run `calibrateTask.py` with the `--debug` 398 Some subtasks may have their own debug variables; see individual Task 405 ConfigClass = CalibrateConfig
406 _DefaultName =
"calibrate" 407 RunnerClass = pipeBase.ButlerInitializedTaskRunner
409 def __init__(self, butler=None, astromRefObjLoader=None,
410 photoRefObjLoader=None, icSourceSchema=None,
411 initInputs=None, **kwargs):
412 """!Construct a CalibrateTask 414 @param[in] butler The butler is passed to the refObjLoader constructor 415 in case it is needed. Ignored if the refObjLoader argument 416 provides a loader directly. 417 @param[in] astromRefObjLoader An instance of LoadReferenceObjectsTasks 418 that supplies an external reference catalog for astrometric 419 calibration. May be None if the desired loader can be constructed 420 from the butler argument or all steps requiring a reference catalog 422 @param[in] photoRefObjLoader An instance of LoadReferenceObjectsTasks 423 that supplies an external reference catalog for photometric 424 calibration. May be None if the desired loader can be constructed 425 from the butler argument or all steps requiring a reference catalog 427 @param[in] icSourceSchema schema for icSource catalog, or None. 428 Schema values specified in config.icSourceFieldsToCopy will be 429 taken from this schema. If set to None, no values will be 430 propagated from the icSourceCatalog 431 @param[in,out] kwargs other keyword arguments for 432 lsst.pipe.base.CmdLineTask 436 if icSourceSchema
is None and butler
is not None:
438 icSourceSchema = butler.get(
"icSrc_schema", immediate=
True).schema
440 if icSourceSchema
is None and butler
is None and initInputs
is not None:
441 icSourceSchema = initInputs[
'icSourceSchema'].schema
443 if icSourceSchema
is not None:
446 minimumSchema = afwTable.SourceTable.makeMinimalSchema()
447 self.
schemaMapper.addMinimalSchema(minimumSchema,
False)
456 "Source was detected as an icSource"))
457 missingFieldNames = []
458 for fieldName
in self.config.icSourceFieldsToCopy:
460 schemaItem = icSourceSchema.find(fieldName)
462 missingFieldNames.append(fieldName)
467 if missingFieldNames:
468 raise RuntimeError(
"isSourceCat is missing fields {} " 469 "specified in icSourceFieldsToCopy" 470 .
format(missingFieldNames))
477 self.
schema = afwTable.SourceTable.makeMinimalSchema()
478 self.makeSubtask(
'detection', schema=self.
schema)
485 if self.config.doInsertFakes:
486 self.makeSubtask(
"insertFakes")
488 if self.config.doDeblend:
489 self.makeSubtask(
"deblend", schema=self.
schema)
490 self.makeSubtask(
'measurement', schema=self.
schema,
492 if self.config.doApCorr:
493 self.makeSubtask(
'applyApCorr', schema=self.
schema)
494 self.makeSubtask(
'catalogCalculation', schema=self.
schema)
496 if self.config.doAstrometry:
497 if astromRefObjLoader
is None and butler
is not None:
498 self.makeSubtask(
'astromRefObjLoader', butler=butler)
499 astromRefObjLoader = self.astromRefObjLoader
501 self.makeSubtask(
"astrometry", refObjLoader=astromRefObjLoader,
503 if self.config.doPhotoCal:
504 if photoRefObjLoader
is None and butler
is not None:
505 self.makeSubtask(
'photoRefObjLoader', butler=butler)
506 photoRefObjLoader = self.photoRefObjLoader
507 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
508 self.makeSubtask(
"photoCal", refObjLoader=photoRefObjLoader,
511 if self.config.doEvalLocCalibration
and self.config.doAstrometry
and self.config.doPhotoCal:
512 self.makeSubtask(
"evalLocCalib", schema=self.
schema)
514 if initInputs
is not None and (astromRefObjLoader
is not None or photoRefObjLoader
is not None):
515 raise RuntimeError(
"PipelineTask form of this task should not be initialized with " 516 "reference object loaders.")
521 self.
schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
528 def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None,
530 """!Calibrate an exposure, optionally unpersisting inputs and 533 This is a wrapper around the `run` method that unpersists inputs 534 (if `doUnpersist` true) and persists outputs (if `config.doWrite` true) 536 @param[in] dataRef butler data reference corresponding to a science 538 @param[in,out] exposure characterized exposure (an 539 lsst.afw.image.ExposureF or similar), or None to unpersist existing 540 icExp and icBackground. See `run` method for details of what is 542 @param[in,out] background initial model of background already 543 subtracted from exposure (an lsst.afw.math.BackgroundList). May be 544 None if no background has been subtracted, though that is unusual 545 for calibration. A refined background model is output. Ignored if 547 @param[in] icSourceCat catalog from which to copy the fields specified 548 by icSourceKeys, or None; 549 @param[in] doUnpersist unpersist data: 550 - if True, exposure, background and icSourceCat are read from 551 dataRef and those three arguments must all be None; 552 - if False the exposure must be provided; background and 553 icSourceCat are optional. True is intended for running as a 554 command-line task, False for running as a subtask 555 @return same data as the calibrate method 557 self.log.
info(
"Processing %s" % (dataRef.dataId))
560 if any(item
is not None for item
in (exposure, background,
562 raise RuntimeError(
"doUnpersist true; exposure, background " 563 "and icSourceCat must all be None")
564 exposure = dataRef.get(
"icExp", immediate=
True)
565 background = dataRef.get(
"icExpBackground", immediate=
True)
566 icSourceCat = dataRef.get(
"icSrc", immediate=
True)
567 elif exposure
is None:
568 raise RuntimeError(
"doUnpersist false; exposure must be provided")
570 exposureIdInfo = dataRef.get(
"expIdInfo")
574 exposureIdInfo=exposureIdInfo,
575 background=background,
576 icSourceCat=icSourceCat,
579 if self.config.doWrite:
582 exposure=calRes.exposure,
583 background=calRes.background,
584 sourceCat=calRes.sourceCat,
585 astromMatches=calRes.astromMatches,
586 matchMeta=calRes.matchMeta,
592 inputs = butlerQC.get(inputRefs)
593 expId, expBits = butlerQC.quantum.dataId.pack(
"visit_detector",
597 if self.config.doAstrometry:
599 for ref
in inputRefs.astromRefCat],
600 refCats=inputs.pop(
'astromRefCat'),
601 config=self.config.astromRefObjLoader, log=self.log)
603 self.astrometry.setRefObjLoader(refObjLoader)
605 if self.config.doPhotoCal:
607 for ref
in inputRefs.photoRefCat],
608 refCats=inputs.pop(
'photoRefCat'),
609 config=self.config.photoRefObjLoader,
611 self.
pixelMargin = photoRefObjLoader.config.pixelMargin
612 self.photoCal.match.setRefObjLoader(photoRefObjLoader)
614 outputs = self.
run(**inputs)
616 if self.config.doWriteMatches:
618 normalizedMatches.table.setMetadata(outputs.matchMeta)
619 if self.config.doWriteMatchesDenormalized:
621 outputs.matchesDenormalized = denormMatches
622 outputs.matches = normalizedMatches
623 butlerQC.put(outputs, outputRefs)
625 def run(self, exposure, exposureIdInfo=None, background=None,
627 """!Calibrate an exposure (science image or coadd) 629 @param[in,out] exposure exposure to calibrate (an 630 lsst.afw.image.ExposureF or similar); 635 - MaskedImage has background subtracted 637 - PhotoCalib is replaced 638 @param[in] exposureIdInfo ID info for exposure (an 639 lsst.obs.base.ExposureIdInfo) If not provided, returned 640 SourceCatalog IDs will not be globally unique. 641 @param[in,out] background background model already subtracted from 642 exposure (an lsst.afw.math.BackgroundList). May be None if no 643 background has been subtracted, though that is unusual for 644 calibration. A refined background model is output. 645 @param[in] icSourceCat A SourceCatalog from CharacterizeImageTask 646 from which we can copy some fields. 648 @return pipe_base Struct containing these fields: 649 - exposure calibrate science exposure with refined WCS and PhotoCalib 650 - background model of background subtracted from exposure (an 651 lsst.afw.math.BackgroundList) 652 - sourceCat catalog of measured sources 653 - astromMatches list of source/refObj matches from the astrometry 657 if exposureIdInfo
is None:
660 if background
is None:
662 sourceIdFactory = IdFactory.makeSource(exposureIdInfo.expId,
663 exposureIdInfo.unusedBits)
664 table = SourceTable.make(self.
schema, sourceIdFactory)
667 detRes = self.detection.
run(table=table, exposure=exposure,
669 sourceCat = detRes.sources
670 if detRes.fpSets.background:
671 for bg
in detRes.fpSets.background:
672 background.append(bg)
673 if self.config.doDeblend:
674 self.deblend.
run(exposure=exposure, sources=sourceCat)
675 self.measurement.
run(
678 exposureId=exposureIdInfo.expId
680 if self.config.doApCorr:
681 self.applyApCorr.
run(
683 apCorrMap=exposure.getInfo().getApCorrMap()
685 self.catalogCalculation.
run(sourceCat)
687 if icSourceCat
is not None and \
688 len(self.config.icSourceFieldsToCopy) > 0:
696 if not sourceCat.isContiguous():
697 sourceCat = sourceCat.copy(deep=
True)
703 if self.config.doAstrometry:
705 astromRes = self.astrometry.
run(
709 astromMatches = astromRes.matches
710 matchMeta = astromRes.matchMeta
711 except Exception
as e:
712 if self.config.requireAstrometry:
714 self.log.
warn(
"Unable to perform astrometric calibration " 715 "(%s): attempting to proceed" % e)
718 if self.config.doPhotoCal:
720 photoRes = self.photoCal.
run(exposure, sourceCat=sourceCat, expId=exposureIdInfo.expId)
721 exposure.setPhotoCalib(photoRes.photoCalib)
723 self.log.
info(
"Photometric zero-point: %f" %
724 photoRes.photoCalib.instFluxToMagnitude(1.0))
725 self.
setMetadata(exposure=exposure, photoRes=photoRes)
726 except Exception
as e:
727 if self.config.requirePhotoCal:
729 self.log.
warn(
"Unable to perform photometric calibration " 730 "(%s): attempting to proceed" % e)
733 if self.config.doEvalLocCalibration
and self.config.doAstrometry
and self.config.doPhotoCal:
734 self.evalLocCalib.
run(sourceCat, exposure)
736 if self.config.doInsertFakes:
737 self.insertFakes.
run(exposure, background=background)
739 table = SourceTable.make(self.
schema, sourceIdFactory)
742 detRes = self.detection.
run(table=table, exposure=exposure,
744 sourceCat = detRes.sources
745 if detRes.fpSets.background:
746 for bg
in detRes.fpSets.background:
747 background.append(bg)
748 if self.config.doDeblend:
749 self.deblend.
run(exposure=exposure, sources=sourceCat)
750 self.measurement.
run(
753 exposureId=exposureIdInfo.expId
755 if self.config.doApCorr:
756 self.applyApCorr.
run(
758 apCorrMap=exposure.getInfo().getApCorrMap()
760 self.catalogCalculation.
run(sourceCat)
762 if icSourceCat
is not None and len(self.config.icSourceFieldsToCopy) > 0:
771 matches=astromMatches,
776 return pipeBase.Struct(
778 background=background,
780 astromMatches=astromMatches,
784 outputExposure=exposure,
786 outputBackground=background,
789 def writeOutputs(self, dataRef, exposure, background, sourceCat,
790 astromMatches, matchMeta):
791 """Write output data to the output repository 793 @param[in] dataRef butler data reference corresponding to a science 795 @param[in] exposure exposure to write 796 @param[in] background background model for exposure 797 @param[in] sourceCat catalog of measured sources 798 @param[in] astromMatches list of source/refObj matches from the 801 dataRef.put(sourceCat,
"src")
802 if self.config.doWriteMatches
and astromMatches
is not None:
804 normalizedMatches.table.setMetadata(matchMeta)
805 dataRef.put(normalizedMatches,
"srcMatch")
806 if self.config.doWriteMatchesDenormalized:
808 dataRef.put(denormMatches,
"srcMatchFull")
809 if self.config.doWriteExposure:
810 dataRef.put(exposure,
"calexp")
811 dataRef.put(background,
"calexpBackground")
814 """Return a dict of empty catalogs for each catalog dataset produced 819 return {
"src": sourceCat}
822 """!Set task and exposure metadata 824 Logs a warning and continues if needed data is missing. 826 @param[in,out] exposure exposure whose metadata is to be set 827 @param[in] photoRes results of running photoCal; if None then it was 835 exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
836 magZero = photoRes.zp - 2.5*math.log10(exposureTime)
837 self.metadata.
set(
'MAGZERO', magZero)
839 self.log.
warn(
"Could not set normalized MAGZERO in header: no " 843 metadata = exposure.getMetadata()
844 metadata.set(
'MAGZERO_RMS', photoRes.sigma)
845 metadata.set(
'MAGZERO_NOBJ', photoRes.ngood)
846 metadata.set(
'COLORTERM1', 0.0)
847 metadata.set(
'COLORTERM2', 0.0)
848 metadata.set(
'COLORTERM3', 0.0)
849 except Exception
as e:
850 self.log.
warn(
"Could not set exposure metadata: %s" % (e,))
853 """!Match sources in icSourceCat and sourceCat and copy the specified fields 855 @param[in] icSourceCat catalog from which to copy fields 856 @param[in,out] sourceCat catalog to which to copy fields 858 The fields copied are those specified by `config.icSourceFieldsToCopy` 859 that actually exist in the schema. This was set up by the constructor 860 using self.schemaMapper. 863 raise RuntimeError(
"To copy icSource fields you must specify " 864 "icSourceSchema nd icSourceKeys when " 865 "constructing this task")
866 if icSourceCat
is None or sourceCat
is None:
867 raise RuntimeError(
"icSourceCat and sourceCat must both be " 869 if len(self.config.icSourceFieldsToCopy) == 0:
870 self.log.
warn(
"copyIcSourceFields doing nothing because " 871 "icSourceFieldsToCopy is empty")
875 mc.findOnlyClosest =
False 877 self.config.matchRadiusPix, mc)
878 if self.config.doDeblend:
879 deblendKey = sourceCat.schema[
"deblend_nChild"].asKey()
881 matches = [m
for m
in matches
if m[1].get(deblendKey) == 0]
888 for m0, m1, d
in matches:
890 match = bestMatches.get(id0)
891 if match
is None or d <= match[2]:
892 bestMatches[id0] = (m0, m1, d)
893 matches =
list(bestMatches.values())
898 numMatches = len(matches)
899 numUniqueSources = len(
set(m[1].getId()
for m
in matches))
900 if numUniqueSources != numMatches:
901 self.log.
warn(
"{} icSourceCat sources matched only {} sourceCat " 902 "sources".
format(numMatches, numUniqueSources))
904 self.log.
info(
"Copying flags from icSourceCat to sourceCat for " 905 "%s sources" % (numMatches,))
909 for icSrc, src, d
in matches:
915 icSrcFootprint = icSrc.getFootprint()
917 icSrc.setFootprint(src.getFootprint())
920 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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def run(self, exposure, exposureIdInfo=None, background=None, icSourceCat=None)
Calibrate an exposure (science image or coadd)
Class for storing ordered metadata with comments.
A mapping between the keys of two Schemas, used to copy data between them.
def denormalizeMatches(matches, matchMeta=None)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
daf::base::PropertySet * set
def writeOutputs(self, dataRef, exposure, background, sourceCat, astromMatches, matchMeta)
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
Pass parameters to algorithms that match list of sources.
afw::table::PointKey< int > dimensions
def __init__(self, config=None)
template BaseCatalog packMatches(SourceMatchVector const &)
A description of a field in a table.
def setMetadata(self, exposure, photoRes=None)
Set task and exposure metadata.
def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
def getDebugFrame(debugDisplay, name)
def getSchemaCatalogs(self)
SourceMatchVector matchXy(SourceCatalog const &cat, double radius, bool symmetric)
Compute all tuples (s1,s2,d) where s1 != s2, s1 and s2 both belong to cat, and d, the distance betwee...
def runDataRef(self, dataRef, exposure=None, background=None, icSourceCat=None, doUnpersist=True)
Calibrate an exposure, optionally unpersisting inputs and persisting outputs.
daf::base::PropertyList * list
Calibrate an exposure: measure sources and perform astrometric and photometric calibration.
def runQuantum(self, butlerQC, inputRefs, outputRefs)