26 from lsst.pipe.base import CmdLineTask, Struct, TaskRunner, ArgumentParser, ButlerInitializedTaskRunner
27 from lsst.pex.config import Config, Field, ListField, ConfigurableField, RangeField, ConfigField
29 from lsst.meas.base import SingleFrameMeasurementTask, ApplyApCorrTask, CatalogCalculationTask
44 * deepCoadd_det: detections from what used to be processCoadd (tract, patch, filter)
45 * deepCoadd_mergeDet: merged detections (tract, patch)
46 * deepCoadd_meas: measurements of merged detections (tract, patch, filter)
47 * deepCoadd_ref: reference sources (tract, patch)
48 All of these have associated *_schema catalogs that require no data ID and hold no records.
50 In addition, we have a schema-only dataset, which saves the schema for the PeakRecords in
51 the mergeDet, meas, and ref dataset Footprints:
52 * deepCoadd_peak_schema
57 """Construct a getSchemaCatalogs instance method
59 These are identical for most of the classes here, so we'll consolidate
62 datasetSuffix: Suffix of dataset name, e.g., "src" for "deepCoadd_src"
64 def getSchemaCatalogs(self):
65 """Return a dict of empty catalogs for each catalog dataset produced by this task."""
67 if hasattr(self,
"algMetadata"):
68 src.getTable().setMetadata(self.algMetadata)
69 return {self.config.coaddName +
"Coadd_" + datasetSuffix: src}
70 return getSchemaCatalogs
73 """Construct a makeIdFactory instance method
75 These are identical for all the classes here, so this consolidates
78 datasetName: Dataset name without the coadd name prefix, e.g., "CoaddId" for "deepCoaddId"
80 def makeIdFactory(self, dataRef):
81 """Return an IdFactory for setting the detection identifiers
83 The actual parameters used in the IdFactory are provided by
84 the butler (through the provided data reference.
86 expBits = dataRef.get(self.config.coaddName + datasetName +
"_bits")
87 expId = long(dataRef.get(self.config.coaddName + datasetName))
88 return afwTable.IdFactory.makeSource(expId, 64 - expBits)
92 """Given a longer, camera-specific filter name (e.g. "HSC-I") return its shorthand name ("i").
103 \anchor DetectCoaddSourcesConfig_
105 \brief Configuration parameters for the DetectCoaddSourcesTask
107 doScaleVariance = Field(dtype=bool, default=
True, doc=
"Scale variance plane using empirical noise?")
108 detection = ConfigurableField(target=SourceDetectionTask, doc=
"Source detection")
109 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
110 mask = ListField(dtype=str, default=[
"DETECTED",
"BAD",
"SAT",
"NO_DATA",
"INTRP"],
111 doc=
"Mask planes for pixels to ignore when scaling variance")
114 Config.setDefaults(self)
115 self.detection.thresholdType =
"pixel_stdev"
116 self.detection.isotropicGrow =
True
118 self.detection.background.useApprox =
False
119 self.detection.background.binSize = 4096
120 self.detection.background.undersampleStyle =
'REDUCE_INTERP_ORDER'
131 \anchor DetectCoaddSourcesTask_
133 \brief Detect sources on a coadd
135 \section pipe_tasks_multiBand_Contents Contents
137 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Purpose
138 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Initialize
139 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Run
140 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Config
141 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Debug
142 - \ref pipe_tasks_multiband_DetectCoaddSourcesTask_Example
144 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Purpose Description
146 Command-line task that detects sources on a coadd of exposures obtained with a single filter.
148 Coadding individual visits requires each exposure to be warped. This introduces covariance in the noise
149 properties across pixels. Before detection, we correct the coadd variance by scaling the variance plane
150 in the coadd to match the observed variance. This is an approximate approach -- strictly, we should
151 propagate the full covariance matrix -- but it is simple and works well in practice.
153 After scaling the variance plane, we detect sources and generate footprints by delegating to the \ref
154 SourceDetectionTask_ "detection" subtask.
157 deepCoadd{tract,patch,filter}: ExposureF
159 deepCoadd_det{tract,patch,filter}: SourceCatalog (only parent Footprints)
160 \n deepCoadd_calexp{tract,patch,filter}: Variance scaled, background-subtracted input
162 \n deepCoadd_calexp_background{tract,patch,filter}: BackgroundList
166 DetectCoaddSourcesTask delegates most of its work to the \ref SourceDetectionTask_ "detection" subtask.
167 You can retarget this subtask if you wish.
169 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Initialize Task initialization
171 \copydoc \_\_init\_\_
173 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Run Invoking the Task
177 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Config Configuration parameters
179 See \ref DetectCoaddSourcesConfig_ "DetectSourcesConfig"
181 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Debug Debug variables
183 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
184 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
187 DetectCoaddSourcesTask has no debug variables of its own because it relegates all the work to
188 \ref SourceDetectionTask_ "SourceDetectionTask"; see the documetation for
189 \ref SourceDetectionTask_ "SourceDetectionTask" for further information.
191 \section pipe_tasks_multiband_DetectCoaddSourcesTask_Example A complete example of using DetectCoaddSourcesTask
193 DetectCoaddSourcesTask is meant to be run after assembling a coadded image in a given band. The purpose of
194 the task is to update the background, detect all sources in a single band and generate a set of parent
195 footprints. Subsequent tasks in the multi-band processing procedure will merge sources across bands and,
196 eventually, perform forced photometry. Command-line usage of DetectCoaddSourcesTask expects a data
197 reference to the coadd to be processed. A list of the available optional arguments can be obtained by
198 calling detectCoaddSources.py with the `--help` command line argument:
200 detectCoaddSources.py --help
203 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
204 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has followed
205 steps 1 - 4 at \ref pipeTasks_multiBand, one may detect all the sources in each coadd as follows:
207 detectCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I
209 that will process the HSC-I band data. The results are written to
210 `$CI_HSC_DIR/DATA/deepCoadd-results/HSC-I`.
212 It is also necessary to run:
214 detectCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-R
216 to generate the sources catalogs for the HSC-R band required by the next step in the multi-band
217 processing procedure: \ref MergeDetectionsTask_ "MergeDetectionsTask".
219 _DefaultName =
"detectCoaddSources"
220 ConfigClass = DetectCoaddSourcesConfig
226 parser = ArgumentParser(name=cls._DefaultName)
227 parser.add_id_argument(
"--id",
"deepCoadd", help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=r",
228 ContainerClass=ExistingCoaddDataIdContainer)
233 \brief Initialize the task. Create the \ref SourceDetectionTask_ "detection" subtask.
235 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
237 \param[in] schema: initial schema for the output catalog, modified-in place to include all
238 fields set by this task. If None, the source minimal schema will be used.
239 \param[in] **kwargs: keyword arguments to be passed to lsst.pipe.base.task.Task.__init__
241 CmdLineTask.__init__(self, **kwargs)
243 schema = afwTable.SourceTable.makeMinimalSchema()
245 self.makeSubtask(
"detection", schema=self.
schema)
249 \brief Run detection on a coadd.
251 Invokes \ref runDetection and then uses \ref write to output the
254 \param[in] patchRef: data reference for patch
256 exposure = patchRef.get(self.config.coaddName +
"Coadd", immediate=
True)
258 self.
write(exposure, results, patchRef)
263 \brief Run detection on an exposure.
265 First scale the variance plane to match the observed variance
266 using \ref scaleVariance. Then invoke the \ref SourceDetectionTask_ "detection" subtask to
269 \param[in] exposure: Exposure on which to detect
270 \param[in] idFactory: IdFactory to set source identifiers
272 \return a pipe.base.Struct with fields
273 - sources: catalog of detections
274 - backgrounds: list of backgrounds
276 if self.config.doScaleVariance:
277 scaleVariance(exposure.getMaskedImage(), self.config.mask, log=self.log)
278 backgrounds = afwMath.BackgroundList()
279 table = afwTable.SourceTable.make(self.
schema, idFactory)
280 detections = self.detection.makeSourceCatalog(table, exposure)
281 sources = detections.sources
282 fpSets = detections.fpSets
283 if fpSets.background:
284 backgrounds.append(fpSets.background)
285 return Struct(sources=sources, backgrounds=backgrounds)
287 def write(self, exposure, results, patchRef):
289 \brief Write out results from runDetection.
291 \param[in] exposure: Exposure to write out
292 \param[in] results: Struct returned from runDetection
293 \param[in] patchRef: data reference for patch
295 coaddName = self.config.coaddName +
"Coadd"
296 patchRef.put(results.backgrounds, coaddName +
"_calexp_background")
297 patchRef.put(results.sources, coaddName +
"_det")
298 patchRef.put(exposure, coaddName +
"_calexp")
304 \anchor MergeSourcesRunner_
306 \brief Task runner for the \ref MergeSourcesTask_ "MergeSourcesTask". Required because the run method
307 requires a list of dataRefs rather than a single dataRef.
311 \brief Provide a butler to the Task constructor.
313 \param[in] parsedCmd the parsed command
314 \param[in] args tuple of a list of data references and kwargs (un-used)
315 \throws RuntimeError if both parsedCmd & args are None
317 if parsedCmd
is not None:
318 butler = parsedCmd.butler
319 elif args
is not None:
320 dataRefList, kwargs = args
321 butler = dataRefList[0].getButler()
323 raise RuntimeError(
"Neither parsedCmd or args specified")
324 return self.TaskClass(config=self.config, log=self.log, butler=butler)
329 \brief Provide a list of patch references for each patch.
331 The patch references within the list will have different filters.
333 \param[in] parsedCmd the parsed command
334 \param **kwargs key word arguments (unused)
335 \throws RuntimeError if multiple references are provided for the same combination of tract, patch and
339 for ref
in parsedCmd.id.refList:
340 tract = ref.dataId[
"tract"]
341 patch = ref.dataId[
"patch"]
342 filter = ref.dataId[
"filter"]
343 if not tract
in refList:
345 if not patch
in refList[tract]:
346 refList[tract][patch] = {}
347 if filter
in refList[tract][patch]:
348 raise RuntimeError(
"Multiple versions of %s" % (ref.dataId,))
349 refList[tract][patch][filter] = ref
350 return [(p.values(), kwargs)
for t
in refList.itervalues()
for p
in t.itervalues()]
355 \anchor MergeSourcesConfig_
357 \brief Configuration for merging sources.
359 priorityList = ListField(dtype=str, default=[],
360 doc=
"Priority-ordered list of bands for the merge.")
361 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
364 Config.validate(self)
366 raise RuntimeError(
"No priority list provided")
371 \anchor MergeSourcesTask_
373 \brief A base class for merging source catalogs.
375 Merging detections (MergeDetectionsTask) and merging measurements (MergeMeasurementsTask) are
376 so similar that it makes sense to re-use the code, in the form of this abstract base class.
378 NB: Do not use this class directly. Instead use one of the child classes that inherit from
379 MergeSourcesTask such as \ref MergeDetectionsTask_ "MergeDetectionsTask" or \ref MergeMeasurementsTask_
380 "MergeMeasurementsTask"
382 Sub-classes should set the following class variables:
383 * `_DefaultName`: name of Task
384 * `inputDataset`: name of dataset to read
385 * `outputDataset`: name of dataset to write
386 * `getSchemaCatalogs` to the result of `_makeGetSchemaCatalogs(outputDataset)`
388 In addition, sub-classes must implement the mergeCatalogs method.
391 ConfigClass = MergeSourcesConfig
392 RunnerClass = MergeSourcesRunner
395 getSchemaCatalogs =
None
400 \brief Create a suitable ArgumentParser.
402 We will use the ArgumentParser to get a provide a list of data
403 references for patches; the RunnerClass will sort them into lists
404 of data references for the same patch
406 parser = ArgumentParser(name=cls._DefaultName)
407 parser.add_id_argument(
"--id",
"deepCoadd_" + cls.inputDataset,
408 ContainerClass=ExistingCoaddDataIdContainer,
409 help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=g^r^i")
414 \brief Obtain the input schema either directly or froma butler reference.
416 \param[in] butler butler reference to obtain the input schema from
417 \param[in] schema the input schema
420 assert butler
is not None,
"Neither butler nor schema specified"
421 schema = butler.get(self.config.coaddName +
"Coadd_" + self.
inputDataset +
"_schema",
422 immediate=
True).schema
425 def __init__(self, butler=None, schema=None, **kwargs):
427 \brief Initialize the task.
429 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
430 \param[in] schema the schema of the detection catalogs used as input to this one
431 \param[in] butler a butler used to read the input schema from disk, if schema is None
433 Derived classes should use the getInputSchema() method to handle the additional
434 arguments and retreive the actual input schema.
436 CmdLineTask.__init__(self, **kwargs)
438 def run(self, patchRefList):
440 \brief Merge coadd sources from multiple bands. Calls \ref mergeCatalogs which must be defined in
441 subclasses that inherit from MergeSourcesTask.
443 \param[in] patchRefList list of data references for each filter
445 catalogs = dict(self.
readCatalog(patchRef)
for patchRef
in patchRefList)
446 mergedCatalog = self.
mergeCatalogs(catalogs, patchRefList[0])
447 self.
write(patchRefList[0], mergedCatalog)
451 \brief Read input catalog.
453 We read the input dataset provided by the 'inputDataset'
456 \param[in] patchRef data reference for patch
457 \return tuple consisting of the filter name and the catalog
459 filterName = patchRef.dataId[
"filter"]
460 catalog = patchRef.get(self.config.coaddName +
"Coadd_" + self.
inputDataset, immediate=
True)
461 self.log.info(
"Read %d sources for filter %s: %s" % (len(catalog), filterName, patchRef.dataId))
462 return filterName, catalog
466 \brief Merge multiple catalogs. This function must be defined in all subclasses that inherit from
469 \param[in] catalogs dict mapping filter name to source catalog
471 \return merged catalog
473 raise NotImplementedError()
477 \brief Write the output.
479 \param[in] patchRef data reference for patch
480 \param[in] catalog catalog
482 We write as the dataset provided by the 'outputDataset'
485 patchRef.put(catalog, self.config.coaddName +
"Coadd_" + self.
outputDataset)
488 mergeDataId = patchRef.dataId.copy()
489 del mergeDataId[
"filter"]
490 self.log.info(
"Wrote merged catalog: %s" % (mergeDataId,))
494 \brief No metadata to write, and not sure how to write it for a list of dataRefs.
499 class CullPeaksConfig(Config):
501 \anchor CullPeaksConfig_
503 \brief Configuration for culling garbage peaks after merging footprints.
505 Peaks may also be culled after detection or during deblending; this configuration object
506 only deals with culling after merging Footprints.
508 These cuts are based on three quantities:
509 - nBands: the number of bands in which the peak was detected
510 - peakRank: the position of the peak within its family, sorted from brightest to faintest.
511 - peakRankNormalized: the peak rank divided by the total number of peaks in the family.
513 The formula that identifie peaks to cull is:
515 nBands < nBandsSufficient
516 AND (rank >= rankSufficient)
517 AND (rank >= rankConsider OR rank >= rankNormalizedConsider)
519 To disable peak culling, simply set nBandsSafe=1.
522 nBandsSufficient = RangeField(dtype=int, default=2, min=1,
523 doc=
"Always keep peaks detected in this many bands")
524 rankSufficient = RangeField(dtype=int, default=20, min=1,
525 doc=
"Always keep this many peaks in each family")
526 rankConsidered = RangeField(dtype=int, default=30, min=1,
527 doc=(
"Keep peaks with less than this rank that also match the "
528 "rankNormalizedConsidered condition."))
529 rankNormalizedConsidered = RangeField(dtype=float, default=0.7, min=0.0,
530 doc=(
"Keep peaks with less than this normalized rank that"
531 " also match the rankConsidered condition."))
536 \anchor MergeDetectionsConfig_
538 \brief Configuration parameters for the MergeDetectionsTask.
540 minNewPeak = Field(dtype=float, default=1,
541 doc=
"Minimum distance from closest peak to create a new one (in arcsec).")
543 maxSamePeak = Field(dtype=float, default=0.3,
544 doc=
"When adding new catalogs to the merge, all peaks less than this distance "
545 " (in arcsec) to an existing peak will be flagged as detected in that catalog.")
546 cullPeaks = ConfigField(dtype=CullPeaksConfig, doc=
"Configuration for how to cull peaks.")
548 skyFilterName = Field(dtype=str, default=
"sky",
549 doc=
"Name of `filter' used to label sky objects (e.g. flag merge_peak_sky is set)\n"
550 "(N.b. should be in MergeMeasurementsConfig.pseudoFilterList)")
551 skySourceRadius = Field(dtype=float, default=8,
552 doc=
"Radius, in pixels, of sky objects")
553 skyGrowDetectedFootprints = Field(dtype=int, default=0,
554 doc=
"Number of pixels to grow the detected footprint mask when adding sky objects")
555 nSkySourcesPerPatch = Field(dtype=int, default=100,
556 doc=
"Try to add this many sky objects to the mergeDet list, which will\n"
557 "then be measured along with the detected objects in sourceMeasurementTask")
558 nTrialSkySourcesPerPatch = Field(dtype=int, default=
None, optional=
True,
559 doc=
"Maximum number of trial sky object positions\n"
560 "(default: nSkySourcesPerPatch*nTrialSkySourcesPerPatchMultiplier)")
561 nTrialSkySourcesPerPatchMultiplier = Field(dtype=int, default=5,
562 doc=
"Set nTrialSkySourcesPerPatch to\n"
563 " nSkySourcesPerPatch*nTrialSkySourcesPerPatchMultiplier\n"
564 "if nTrialSkySourcesPerPatch is None")
575 \anchor MergeDetectionsTask_
577 \brief Merge coadd detections from multiple bands.
579 \section pipe_tasks_multiBand_Contents Contents
581 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Purpose
582 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Init
583 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Run
584 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Config
585 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Debug
586 - \ref pipe_tasks_multiband_MergeDetectionsTask_Example
588 \section pipe_tasks_multiBand_MergeDetectionsTask_Purpose Description
590 Command-line task that merges sources detected in coadds of exposures obtained with different filters.
592 To perform photometry consistently across coadds in multiple filter bands, we create a master catalog of
593 sources from all bands by merging the sources (peaks & footprints) detected in each coadd, while keeping
594 track of which band each source originates in.
596 The catalog merge is performed by \ref getMergedSourceCatalog. Spurious peaks detected around bright
597 objects are culled as described in \ref CullPeaksConfig_.
600 deepCoadd_det{tract,patch,filter}: SourceCatalog (only parent Footprints)
602 deepCoadd_mergeDet{tract,patch}: SourceCatalog (only parent Footprints)
606 MergeDetectionsTask subclasses \ref MergeSourcesTask_ "MergeSourcesTask".
608 \section pipe_tasks_multiBand_MergeDetectionsTask_Init Task initialisation
610 \copydoc \_\_init\_\_
612 \section pipe_tasks_multiBand_MergeDetectionsTask_Run Invoking the Task
616 \section pipe_tasks_multiBand_MergeDetectionsTask_Config Configuration parameters
618 See \ref MergeDetectionsConfig_
620 \section pipe_tasks_multiBand_MergeDetectionsTask_Debug Debug variables
622 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a flag \c -d
623 to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py files.
625 MergeDetectionsTask has no debug variables.
627 \section pipe_tasks_multiband_MergeDetectionsTask_Example A complete example of using MergeDetectionsTask
629 MergeDetectionsTask is meant to be run after detecting sources in coadds generated for the chosen subset
630 of the available bands.
631 The purpose of the task is to merge sources (peaks & footprints) detected in the coadds generated from the
632 chosen subset of filters.
633 Subsequent tasks in the multi-band processing procedure will deblend the generated master list of sources
634 and, eventually, perform forced photometry.
635 Command-line usage of MergeDetectionsTask expects data references for all the coadds to be processed.
636 A list of the available optional arguments can be obtained by calling mergeCoaddDetections.py with the
637 `--help` command line argument:
639 mergeCoaddDetections.py --help
642 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
643 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
644 step 5 at \ref pipeTasks_multiBand, one may merge the catalogs of sources from each coadd as follows:
646 mergeCoaddDetections.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I^HSC-R
648 This will merge the HSC-I & -R band parent source catalogs and write the results to
649 `$CI_HSC_DIR/DATA/deepCoadd-results/merged/0/5,4/mergeDet-0-5,4.fits`.
651 The next step in the multi-band processing procedure is
652 \ref MeasureMergedCoaddSourcesTask_ "MeasureMergedCoaddSourcesTask"
654 ConfigClass = MergeDetectionsConfig
655 _DefaultName =
"mergeCoaddDetections"
657 outputDataset =
"mergeDet"
660 def __init__(self, butler=None, schema=None, **kwargs):
662 \brief Initialize the merge detections task.
664 A \ref FootprintMergeList_ "FootprintMergeList" will be used to
665 merge the source catalogs.
667 Additional keyword arguments (forwarded to MergeSourcesTask.__init__):
668 \param[in] schema the schema of the detection catalogs used as input to this one
669 \param[in] butler a butler used to read the input schema from disk, if schema is None
670 \param[in] **kwargs keyword arguments to be passed to MergeSourcesTask.__init__
672 The task will set its own self.schema attribute to the schema of the output merged catalog.
674 MergeSourcesTask.__init__(self, butler=butler, schema=schema, **kwargs)
678 if self.config.nSkySourcesPerPatch > 0:
679 filterNames += [self.config.skyFilterName]
684 \brief Merge multiple catalogs.
686 After ordering the catalogs and filters in priority order,
687 \ref getMergedSourceCatalog of the \ref FootprintMergeList_ "FootprintMergeList" created by
688 \ref \_\_init\_\_ is used to perform the actual merging. Finally, \ref cullPeaks is used to remove
689 garbage peaks detected around bright objects.
693 \param[out] mergedList
697 skyInfo =
getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
698 tractWcs = skyInfo.wcs
699 peakDistance = self.config.minNewPeak / tractWcs.pixelScale().asArcseconds()
700 samePeakDistance = self.config.maxSamePeak / tractWcs.pixelScale().asArcseconds()
703 orderedCatalogs = [catalogs[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
705 if band
in catalogs.keys()]
707 mergedList = self.merged.getMergedSourceCatalog(orderedCatalogs, orderedBands, peakDistance,
714 skySourceFootprints = self.
getSkySourceFootprints(mergedList, skyInfo, self.config.skyGrowDetectedFootprints)
715 if skySourceFootprints:
716 key = mergedList.schema.find(
"merge_footprint_%s" % self.config.skyFilterName).key
718 for foot
in skySourceFootprints:
719 s = mergedList.addNew()
723 self.log.info(
"Added %d sky sources (%.0f%% of requested)",
724 len(skySourceFootprints), 100*len(skySourceFootprints)/float(self.config.nSkySourcesPerPatch))
727 for record
in mergedList:
728 record.getFootprint().sortPeaks()
729 self.log.info(
"Merged to %d sources" % len(mergedList))
736 \brief Attempt to remove garbage peaks (mostly on the outskirts of large blends).
738 \param[in] catalog Source catalog
740 keys = [item.key
for item
in self.merged.getPeakSchema().extract(
"merge.peak.*").itervalues()]
743 for parentSource
in catalog:
746 keptPeaks = parentSource.getFootprint().getPeaks()
747 oldPeaks = list(keptPeaks)
749 familySize = len(oldPeaks)
750 totalPeaks += familySize
751 for rank, peak
in enumerate(oldPeaks):
752 if ((rank < self.config.cullPeaks.rankSufficient)
or
753 (self.config.cullPeaks.nBandsSufficient > 1
and
754 sum([peak.get(k)
for k
in keys]) >= self.config.cullPeaks.nBandsSufficient)
or
755 (rank < self.config.cullPeaks.rankConsidered
and
756 rank < self.config.cullPeaks.rankNormalizedConsidered * familySize)):
757 keptPeaks.append(peak)
760 self.log.info(
"Culled %d of %d peaks" % (culledPeaks, totalPeaks))
764 Return a dict of empty catalogs for each catalog dataset produced by this task.
766 \param[out] dictionary of empty catalogs
770 return {self.config.coaddName +
"Coadd_mergeDet": mergeDet,
771 self.config.coaddName +
"Coadd_peak": peak}
775 \brief Return a list of Footprints of sky objects which don't overlap with anything in mergedList
777 \param mergedList The merged Footprints from all the input bands
778 \param skyInfo A description of the patch
779 \param growDetectedFootprints The number of pixels to grow the detected footprints
782 if self.config.nSkySourcesPerPatch <= 0:
785 skySourceRadius = self.config.skySourceRadius
786 nSkySourcesPerPatch = self.config.nSkySourcesPerPatch
787 nTrialSkySourcesPerPatch = self.config.nTrialSkySourcesPerPatch
788 if nTrialSkySourcesPerPatch
is None:
789 nTrialSkySourcesPerPatch = self.config.nTrialSkySourcesPerPatchMultiplier*nSkySourcesPerPatch
795 patchBBox = skyInfo.patchInfo.getOuterBBox()
796 mask = afwImage.MaskU(patchBBox)
797 detectedMask = mask.getPlaneBitMask(
"DETECTED")
799 foot = s.getFootprint()
800 if growDetectedFootprints > 0:
804 xmin, ymin = patchBBox.getMin()
805 xmax, ymax = patchBBox.getMax()
807 xmin += skySourceRadius + 1
808 ymin += skySourceRadius + 1
809 xmax -= skySourceRadius + 1
810 ymax -= skySourceRadius + 1
812 skySourceFootprints = []
813 for i
in range(nTrialSkySourcesPerPatch):
814 if len(skySourceFootprints) == nSkySourcesPerPatch:
817 x = int(numpy.random.uniform(xmin, xmax))
818 y = int(numpy.random.uniform(ymin, ymax))
820 foot.setPeakSchema(self.merged.getPeakSchema())
822 if not foot.overlapsMask(mask):
823 foot.addPeak(x, y, 0)
824 foot.getPeaks()[0].set(
"merge_peak_%s" % self.config.skyFilterName,
True)
825 skySourceFootprints.append(foot)
827 return skySourceFootprints
833 \anchor MeasureMergedCoaddSourcesConfig_
835 \brief Configuration parameters for the MeasureMergedCoaddSourcesTask
837 doDeblend = Field(dtype=bool, default=
True, doc=
"Deblend sources?")
838 deblend = ConfigurableField(target=SourceDeblendTask, doc=
"Deblend sources")
839 measurement = ConfigurableField(target=SingleFrameMeasurementTask, doc=
"Source measurement")
840 setPrimaryFlags = ConfigurableField(target=SetPrimaryFlagsTask, doc=
"Set flags for primary tract/patch")
841 doPropagateFlags = Field(
842 dtype=bool, default=
True,
843 doc=
"Whether to match sources to CCD catalogs to propagate flags (to e.g. identify PSF stars)"
845 propagateFlags = ConfigurableField(target=PropagateVisitFlagsTask, doc=
"Propagate visit flags to coadd")
846 doMatchSources = Field(dtype=bool, default=
True, doc=
"Match sources to reference catalog?")
847 match = ConfigurableField(target=DirectMatchTask, doc=
"Matching to reference catalog")
848 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
849 checkUnitsParseStrict = Field(
850 doc =
"Strictness of Astropy unit compatibility check, can be 'raise', 'warn' or 'silent'",
857 doc =
"Apply aperture corrections"
859 applyApCorr = ConfigurableField(
860 target = ApplyApCorrTask,
861 doc =
"Subtask to apply aperture corrections"
863 doRunCatalogCalculation = Field(
866 doc =
'Run catalogCalculation task'
868 catalogCalculation = ConfigurableField(
869 target = CatalogCalculationTask,
870 doc =
"Subtask to run catalogCalculation plugins on catalog"
874 Config.setDefaults(self)
875 self.deblend.propagateAllPeaks =
True
876 self.measurement.plugins.names |= [
'base_InputCount']
879 self.measurement.plugins[
'base_PixelFlags'].masksFpAnywhere = [
'CLIPPED']
890 \anchor MeasureMergedCoaddSourcesTask_
892 \brief Deblend sources from master catalog in each coadd seperately and measure.
894 \section pipe_tasks_multiBand_Contents Contents
896 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Purpose
897 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Initialize
898 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Run
899 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Config
900 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Debug
901 - \ref pipe_tasks_multiband_MeasureMergedCoaddSourcesTask_Example
903 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Purpose Description
905 Command-line task that uses peaks and footprints from a master catalog to perform deblending and
906 measurement in each coadd.
908 Given a master input catalog of sources (peaks and footprints), deblend and measure each source on the
909 coadd. Repeating this procedure with the same master catalog across multiple coadds will generate a
910 consistent set of child sources.
912 The deblender retains all peaks and deblends any missing peaks (dropouts in that band) as PSFs. Source
913 properties are measured and the \c is-primary flag (indicating sources with no children) is set. Visit
914 flags are propagated to the coadd sources.
916 Optionally, we can match the coadd sources to an external reference catalog.
919 deepCoadd_mergeDet{tract,patch}: SourceCatalog
920 \n deepCoadd_calexp{tract,patch,filter}: ExposureF
922 deepCoadd_meas{tract,patch,filter}: SourceCatalog
926 MeasureMergedCoaddSourcesTask delegates most of its work to a set of sub-tasks:
929 <DT> \ref SourceDeblendTask_ "deblend"
930 <DD> Deblend all the sources from the master catalog.</DD>
931 <DT> \ref SingleFrameMeasurementTask_ "measurement"
932 <DD> Measure source properties of deblended sources.</DD>
933 <DT> \ref SetPrimaryFlagsTask_ "setPrimaryFlags"
934 <DD> Set flag 'is-primary' as well as related flags on sources. 'is-primary' is set for sources that are
935 not at the edge of the field and that have either not been deblended or are the children of deblended
937 <DT> \ref PropagateVisitFlagsTask_ "propagateFlags"
938 <DD> Propagate flags set in individual visits to the coadd.</DD>
939 <DT> \ref DirectMatchTask_ "match"
940 <DD> Match input sources to a reference catalog (optional).
943 These subtasks may be retargeted as required.
945 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Initialize Task initialization
947 \copydoc \_\_init\_\_
949 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Run Invoking the Task
953 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Config Configuration parameters
955 See \ref MeasureMergedCoaddSourcesConfig_
957 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Debug Debug variables
959 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
960 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
963 MeasureMergedCoaddSourcesTask has no debug variables of its own because it delegates all the work to
964 the various sub-tasks. See the documetation for individual sub-tasks for more information.
966 \section pipe_tasks_multiband_MeasureMergedCoaddSourcesTask_Example A complete example of using MeasureMergedCoaddSourcesTask
968 After MeasureMergedCoaddSourcesTask has been run on multiple coadds, we have a set of per-band catalogs.
969 The next stage in the multi-band processing procedure will merge these measurements into a suitable
970 catalog for driving forced photometry.
972 Command-line usage of MeasureMergedCoaddSourcesTask expects a data reference to the coadds to be processed.
973 A list of the available optional arguments can be obtained by calling measureCoaddSources.py with the
974 `--help` command line argument:
976 measureCoaddSources.py --help
979 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
980 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
981 step 6 at \ref pipeTasks_multiBand, one may perform deblending and measure sources in the HSC-I band
984 measureCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I
986 This will process the HSC-I band data. The results are written in
987 `$CI_HSC_DIR/DATA/deepCoadd-results/HSC-I/0/5,4/meas-HSC-I-0-5,4.fits
989 It is also necessary to run
991 measureCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-R
993 to generate the sources catalogs for the HSC-R band required by the next step in the multi-band
994 procedure: \ref MergeMeasurementsTask_ "MergeMeasurementsTask".
996 _DefaultName =
"measureCoaddSources"
997 ConfigClass = MeasureMergedCoaddSourcesConfig
998 RunnerClass = ButlerInitializedTaskRunner
1004 parser = ArgumentParser(name=cls._DefaultName)
1005 parser.add_id_argument(
"--id",
"deepCoadd_calexp",
1006 help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=r",
1007 ContainerClass=ExistingCoaddDataIdContainer)
1010 def __init__(self, butler=None, schema=None, peakSchema=None, **kwargs):
1012 \brief Initialize the task.
1014 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
1015 \param[in] schema: the schema of the merged detection catalog used as input to this one
1016 \param[in] peakSchema: the schema of the PeakRecords in the Footprints in the merged detection catalog
1017 \param[in] butler: a butler used to read the input schemas from disk, if schema or peakSchema is None
1019 The task will set its own self.schema attribute to the schema of the output measurement catalog.
1020 This will include all fields from the input schema, as well as additional fields for all the
1023 CmdLineTask.__init__(self, **kwargs)
1025 assert butler
is not None,
"Neither butler nor schema is defined"
1026 schema = butler.get(self.config.coaddName +
"Coadd_mergeDet_schema", immediate=
True).schema
1028 self.schemaMapper.addMinimalSchema(schema)
1029 self.
schema = self.schemaMapper.getOutputSchema()
1031 if self.config.doDeblend:
1032 if peakSchema
is None:
1033 assert butler
is not None,
"Neither butler nor peakSchema is defined"
1034 peakSchema = butler.get(self.config.coaddName +
"Coadd_peak_schema", immediate=
True).schema
1035 self.makeSubtask(
"deblend", schema=self.
schema, peakSchema=peakSchema)
1036 self.makeSubtask(
"measurement", schema=self.
schema, algMetadata=self.
algMetadata)
1037 self.makeSubtask(
"setPrimaryFlags", schema=self.
schema)
1038 if self.config.doMatchSources:
1039 self.makeSubtask(
"match", butler=butler)
1040 if self.config.doPropagateFlags:
1041 self.makeSubtask(
"propagateFlags", schema=self.
schema)
1042 self.schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
1043 if self.config.doApCorr:
1044 self.makeSubtask(
"applyApCorr", schema=self.
schema)
1045 if self.config.doRunCatalogCalculation:
1046 self.makeSubtask(
"catalogCalculation", schema=self.
schema)
1050 \brief Deblend and measure.
1052 \param[in] patchRef: Patch reference.
1054 Deblend each source in every coadd and measure. Set 'is-primary' and related flags. Propagate flags
1055 from individual visits. Optionally match the sources to a reference catalog and write the matches.
1056 Finally, write the deblended sources and measurements out.
1058 exposure = patchRef.get(self.config.coaddName +
"Coadd_calexp", immediate=
True)
1060 if self.config.doDeblend:
1061 self.deblend.run(exposure, sources)
1063 bigKey = sources.schema[
"deblend_parentTooBig"].asKey()
1064 numBig = sum((s.get(bigKey)
for s
in sources))
1066 self.log.warn(
"Patch %s contains %d large footprints that were not deblended" %
1067 (patchRef.dataId, numBig))
1069 table = sources.getTable()
1072 self.measurement.run(sources, exposure, exposureId=self.
getExposureId(patchRef))
1074 if self.config.doApCorr:
1075 self.applyApCorr.run(
1077 apCorrMap = exposure.getInfo().getApCorrMap()
1080 if self.config.doRunCatalogCalculation:
1081 self.catalogCalculation.run(sources)
1083 skyInfo =
getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
1084 self.setPrimaryFlags.run(sources, skyInfo.skyMap, skyInfo.tractInfo, skyInfo.patchInfo,
1085 includeDeblend=self.config.doDeblend)
1086 if self.config.doPropagateFlags:
1087 self.propagateFlags.run(patchRef.getButler(), sources, self.propagateFlags.getCcdInputs(exposure),
1089 if self.config.doMatchSources:
1091 self.
write(patchRef, sources)
1095 \brief Read input sources.
1097 \param[in] dataRef: Data reference for catalog of merged detections
1098 \return List of sources in merged catalog
1100 We also need to add columns to hold the measurements we're about to make
1101 so we can measure in-place.
1103 merged = dataRef.get(self.config.coaddName +
"Coadd_mergeDet", immediate=
True)
1104 self.log.info(
"Read %d detections: %s" % (len(merged), dataRef.dataId))
1107 idFactory.notify(s.getId())
1108 table = afwTable.SourceTable.make(self.
schema, idFactory)
1115 \brief Write matches of the sources to the astrometric reference catalog.
1117 We use the Wcs in the exposure to match sources.
1119 \param[in] dataRef: data reference
1120 \param[in] exposure: exposure with Wcs
1121 \param[in] sources: source catalog
1123 result = self.match.run(sources, exposure.getInfo().getFilter().getName())
1126 matches.table.setMetadata(result.matchMeta)
1127 dataRef.put(matches, self.config.coaddName +
"Coadd_srcMatch")
1131 \brief Write the source catalog.
1133 \param[in] dataRef: data reference
1134 \param[in] sources: source catalog
1136 dataRef.put(sources, self.config.coaddName +
"Coadd_meas")
1137 self.log.info(
"Wrote %d sources: %s" % (len(sources), dataRef.dataId))
1140 return long(dataRef.get(self.config.coaddName +
"CoaddId"))
1146 \anchor MergeMeasurementsConfig_
1148 \brief Configuration parameters for the MergeMeasurementsTask
1150 pseudoFilterList = ListField(dtype=str, default=[
"sky"],
1151 doc=
"Names of filters which may have no associated detection\n"
1152 "(N.b. should include MergeDetectionsConfig.skyFilterName)")
1153 snName = Field(dtype=str, default=
"base_PsfFlux",
1154 doc=
"Name of flux measurement for calculating the S/N when choosing the reference band.")
1155 minSN = Field(dtype=float, default=10.,
1156 doc=
"If the S/N from the priority band is below this value (and the S/N "
1157 "is larger than minSNDiff compared to the priority band), use the band with "
1158 "the largest S/N as the reference band.")
1159 minSNDiff = Field(dtype=float, default=3.,
1160 doc=
"If the difference in S/N between another band and the priority band is larger "
1161 "than this value (and the S/N in the priority band is less than minSN) "
1162 "use the band with the largest S/N as the reference band")
1163 flags = ListField(dtype=str, doc=
"Require that these flags, if available, are not set",
1164 default=[
"base_PixelFlags_flag_interpolatedCenter",
"base_PsfFlux_flag",
1165 "ext_photometryKron_KronFlux_flag",
"modelfit_CModel_flag",])
1176 \anchor MergeMeasurementsTask_
1178 \brief Merge measurements from multiple bands
1180 \section pipe_tasks_multiBand_Contents Contents
1182 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Purpose
1183 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Initialize
1184 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Run
1185 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Config
1186 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Debug
1187 - \ref pipe_tasks_multiband_MergeMeasurementsTask_Example
1189 \section pipe_tasks_multiBand_MergeMeasurementsTask_Purpose Description
1191 Command-line task that merges measurements from multiple bands.
1193 Combines consistent (i.e. with the same peaks and footprints) catalogs of sources from multiple filter
1194 bands to construct a unified catalog that is suitable for driving forced photometry. Every source is
1195 required to have centroid, shape and flux measurements in each band.
1198 deepCoadd_meas{tract,patch,filter}: SourceCatalog
1200 deepCoadd_ref{tract,patch}: SourceCatalog
1204 MergeMeasurementsTask subclasses \ref MergeSourcesTask_ "MergeSourcesTask".
1206 \section pipe_tasks_multiBand_MergeMeasurementsTask_Initialize Task initialization
1208 \copydoc \_\_init\_\_
1210 \section pipe_tasks_multiBand_MergeMeasurementsTask_Run Invoking the Task
1214 \section pipe_tasks_multiBand_MergeMeasurementsTask_Config Configuration parameters
1216 See \ref MergeMeasurementsConfig_
1218 \section pipe_tasks_multiBand_MergeMeasurementsTask_Debug Debug variables
1220 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
1221 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
1224 MergeMeasurementsTask has no debug variables.
1226 \section pipe_tasks_multiband_MergeMeasurementsTask_Example A complete example of using MergeMeasurementsTask
1228 MergeMeasurementsTask is meant to be run after deblending & measuring sources in every band.
1229 The purpose of the task is to generate a catalog of sources suitable for driving forced photometry in
1230 coadds and individual exposures.
1231 Command-line usage of MergeMeasurementsTask expects a data reference to the coadds to be processed. A list
1232 of the available optional arguments can be obtained by calling mergeCoaddMeasurements.py with the `--help`
1233 command line argument:
1235 mergeCoaddMeasurements.py --help
1238 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
1239 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
1240 step 7 at \ref pipeTasks_multiBand, one may merge the catalogs generated after deblending and measuring
1243 mergeCoaddMeasurements.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I^HSC-R
1245 This will merge the HSC-I & HSC-R band catalogs. The results are written in
1246 `$CI_HSC_DIR/DATA/deepCoadd-results/`.
1248 _DefaultName =
"mergeCoaddMeasurements"
1249 ConfigClass = MergeMeasurementsConfig
1250 inputDataset =
"meas"
1251 outputDataset =
"ref"
1254 def __init__(self, butler=None, schema=None, **kwargs):
1256 Initialize the task.
1258 Additional keyword arguments (forwarded to MergeSourcesTask.__init__):
1259 \param[in] schema: the schema of the detection catalogs used as input to this one
1260 \param[in] butler: a butler used to read the input schema from disk, if schema is None
1262 The task will set its own self.schema attribute to the schema of the output merged catalog.
1264 MergeSourcesTask.__init__(self, butler=butler, schema=schema, **kwargs)
1267 self.schemaMapper.addMinimalSchema(inputSchema,
True)
1268 self.
fluxKey = inputSchema.find(self.config.snName +
"_flux").getKey()
1269 self.
fluxErrKey = inputSchema.find(self.config.snName +
"_fluxSigma").getKey()
1270 self.
fluxFlagKey = inputSchema.find(self.config.snName +
"_flag").getKey()
1273 for band
in self.config.priorityList:
1275 outputKey = self.schemaMapper.editOutputSchema().addField(
1276 "merge_measurement_%s" % short,
1278 doc=
"Flag field set if the measurements here are from the %s filter" % band
1280 peakKey = inputSchema.find(
"merge_peak_%s" % short).key
1281 footprintKey = inputSchema.find(
"merge_footprint_%s" % short).key
1282 self.
flagKeys[band] = Struct(peak=peakKey, footprint=footprintKey, output=outputKey)
1283 self.
schema = self.schemaMapper.getOutputSchema()
1286 for filt
in self.config.pseudoFilterList:
1288 self.pseudoFilterKeys.append(self.schema.find(
"merge_peak_%s" % filt).getKey())
1290 self.log.warn(
"merge_peak is not set for pseudo-filter %s" % filt)
1293 for flag
in self.config.flags:
1295 self.
badFlags[flag] = self.schema.find(flag).getKey()
1296 except KeyError
as exc:
1297 self.log.warn(
"Can't find flag %s in schema: %s" % (flag, exc,))
1302 Merge measurement catalogs to create a single reference catalog for forced photometry
1304 \param[in] catalogs: the catalogs to be merged
1305 \param[in] patchRef: patch reference for data
1307 For parent sources, we choose the first band in config.priorityList for which the
1308 merge_footprint flag for that band is is True.
1310 For child sources, the logic is the same, except that we use the merge_peak flags.
1313 orderedCatalogs = [catalogs[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
1314 orderedKeys = [self.
flagKeys[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
1317 mergedCatalog.reserve(len(orderedCatalogs[0]))
1319 idKey = orderedCatalogs[0].table.getIdKey()
1320 for catalog
in orderedCatalogs[1:]:
1321 if numpy.any(orderedCatalogs[0].get(idKey) != catalog.get(idKey)):
1322 raise ValueError(
"Error in inputs to MergeCoaddMeasurements: source IDs do not match")
1326 for orderedRecords
in zip(*orderedCatalogs):
1329 maxSNFlagKeys =
None
1331 priorityRecord =
None
1332 priorityFlagKeys =
None
1334 hasPseudoFilter =
False
1338 for inputRecord, flagKeys
in zip(orderedRecords, orderedKeys):
1339 parent = (inputRecord.getParent() == 0
and inputRecord.get(flagKeys.footprint))
1340 child = (inputRecord.getParent() != 0
and inputRecord.get(flagKeys.peak))
1342 if not (parent
or child):
1344 if inputRecord.get(pseudoFilterKey):
1345 hasPseudoFilter =
True
1346 priorityRecord = inputRecord
1347 priorityFlagKeys = flagKeys
1352 isBad =
any(inputRecord.get(flag)
for flag
in self.
badFlags)
1357 if numpy.isnan(sn)
or sn < 0.:
1359 if (parent
or child)
and priorityRecord
is None:
1360 priorityRecord = inputRecord
1361 priorityFlagKeys = flagKeys
1364 maxSNRecord = inputRecord
1365 maxSNFlagKeys = flagKeys
1378 bestRecord = priorityRecord
1379 bestFlagKeys = priorityFlagKeys
1380 elif (prioritySN < self.config.minSN
and (maxSN - prioritySN) > self.config.minSNDiff
and
1381 maxSNRecord
is not None):
1382 bestRecord = maxSNRecord
1383 bestFlagKeys = maxSNFlagKeys
1384 elif priorityRecord
is not None:
1385 bestRecord = priorityRecord
1386 bestFlagKeys = priorityFlagKeys
1388 if bestRecord
is not None and bestFlagKeys
is not None:
1389 outputRecord = mergedCatalog.addNew()
1391 outputRecord.set(bestFlagKeys.output,
True)
1393 raise ValueError(
"Error in inputs to MergeCoaddMeasurements: no valid reference for %s" %
1394 inputRecord.getId())
1397 for inputCatalog
in orderedCatalogs:
1398 if len(mergedCatalog) != len(inputCatalog):
1399 raise ValueError(
"Mismatch between catalog sizes: %s != %s" %
1400 (len(mergedCatalog), len(orderedCatalogs)))
1402 return mergedCatalog
def writeMetadata
No metadata to write, and not sure how to write it for a list of dataRefs.
def cullPeaks
Attempt to remove garbage peaks (mostly on the outskirts of large blends).
def run
Deblend and measure.
Merge coadd detections from multiple bands.
def __init__
Initialize the task.
def mergeCatalogs
Merge measurement catalogs to create a single reference catalog for forced photometry.
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool left, bool right, bool up, bool down)
Grow a Footprint in at least one of the cardinal directions, returning a new Footprint.
def runDetection
Run detection on an exposure.
Task runner for the MergeSourcesTask. Required because the run method requires a list of dataRefs rat...
def write
Write the source catalog.
def run
Merge coadd sources from multiple bands.
Class for storing ordered metadata with comments.
A mapping between the keys of two Schemas, used to copy data between them.
Configuration parameters for the DetectCoaddSourcesTask.
def run
Run detection on a coadd.
Merge measurements from multiple bands.
Deblend sources from master catalog in each coadd seperately and measure.
def getTargetList
Provide a list of patch references for each patch.
def __init__
Initialize the task.
def readSources
Read input sources.
def __init__
Initialize the task.
bool any(CoordinateExpr< N > const &expr)
Return true if any elements are true.
def scaleVariance
Scale the variance in a maskedImage.
def write
Write the output.
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
Configuration parameters for the MergeMeasurementsTask.
def mergeCatalogs
Merge multiple catalogs.
Configuration parameters for the MergeDetectionsTask.
def _makeGetSchemaCatalogs
Configuration for merging sources.
def mergeCatalogs
Merge multiple catalogs.
Holds an integer identifier for an LSST filter.
BaseCatalog packMatches(std::vector< Match< Record1, Record2 > > const &matches)
Return a table representation of a MatchVector that can be used to persist it.
def makeTask
Provide a butler to the Task constructor.
def readCatalog
Read input catalog.
MaskT setMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
OR bitmask into all the Mask's pixels that are in the Footprint.
A base class for merging source catalogs.
def getSkyInfo
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded...
Configuration parameters for the MeasureMergedCoaddSourcesTask.
def __init__
Initialize the task.
def getSkySourceFootprints
Return a list of Footprints of sky objects which don't overlap with anything in mergedList.
def __init__
Initialize the merge detections task.
def getInputSchema
Obtain the input schema either directly or froma butler reference.
def _makeArgumentParser
Create a suitable ArgumentParser.
Detect sources on a coadd.
def getSchemaCatalogs
Return a dict of empty catalogs for each catalog dataset produced by this task.
def write
Write out results from runDetection.
def writeMatches
Write matches of the sources to the astrometric reference catalog.