1 from builtins
import zip
2 from builtins
import range
28 from lsst.pipe.base import CmdLineTask, Struct, TaskRunner, ArgumentParser, ButlerInitializedTaskRunner
29 from lsst.pex.config import Config, Field, ListField, ConfigurableField, RangeField, ConfigField
31 from lsst.meas.base import SingleFrameMeasurementTask, ApplyApCorrTask, CatalogCalculationTask
46 * deepCoadd_det: detections from what used to be processCoadd (tract, patch, filter)
47 * deepCoadd_mergeDet: merged detections (tract, patch)
48 * deepCoadd_meas: measurements of merged detections (tract, patch, filter)
49 * deepCoadd_ref: reference sources (tract, patch)
50 All of these have associated *_schema catalogs that require no data ID and hold no records.
52 In addition, we have a schema-only dataset, which saves the schema for the PeakRecords in
53 the mergeDet, meas, and ref dataset Footprints:
54 * deepCoadd_peak_schema
59 """Construct a getSchemaCatalogs instance method
61 These are identical for most of the classes here, so we'll consolidate
64 datasetSuffix: Suffix of dataset name, e.g., "src" for "deepCoadd_src"
67 def getSchemaCatalogs(self):
68 """Return a dict of empty catalogs for each catalog dataset produced by this task."""
70 if hasattr(self,
"algMetadata"):
71 src.getTable().setMetadata(self.algMetadata)
72 return {self.config.coaddName +
"Coadd_" + datasetSuffix: src}
73 return getSchemaCatalogs
77 """Construct a makeIdFactory instance method
79 These are identical for all the classes here, so this consolidates
82 datasetName: Dataset name without the coadd name prefix, e.g., "CoaddId" for "deepCoaddId"
85 def makeIdFactory(self, dataRef):
86 """Return an IdFactory for setting the detection identifiers
88 The actual parameters used in the IdFactory are provided by
89 the butler (through the provided data reference.
91 expBits = dataRef.get(self.config.coaddName + datasetName +
"_bits")
92 expId = int(dataRef.get(self.config.coaddName + datasetName))
93 return afwTable.IdFactory.makeSource(expId, 64 - expBits)
98 """Given a longer, camera-specific filter name (e.g. "HSC-I") return its shorthand name ("i").
109 \anchor DetectCoaddSourcesConfig_
111 \brief Configuration parameters for the DetectCoaddSourcesTask
113 doScaleVariance = Field(dtype=bool, default=
True, doc=
"Scale variance plane using empirical noise?")
114 detection = ConfigurableField(target=SourceDetectionTask, doc=
"Source detection")
115 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
116 mask = ListField(dtype=str, default=[
"DETECTED",
"BAD",
"SAT",
"NO_DATA",
"INTRP"],
117 doc=
"Mask planes for pixels to ignore when scaling variance")
120 Config.setDefaults(self)
121 self.detection.thresholdType =
"pixel_stdev"
122 self.detection.isotropicGrow =
True
124 self.detection.background.useApprox =
False
125 self.detection.background.binSize = 4096
126 self.detection.background.undersampleStyle =
'REDUCE_INTERP_ORDER'
138 \anchor DetectCoaddSourcesTask_
140 \brief Detect sources on a coadd
142 \section pipe_tasks_multiBand_Contents Contents
144 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Purpose
145 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Initialize
146 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Run
147 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Config
148 - \ref pipe_tasks_multiBand_DetectCoaddSourcesTask_Debug
149 - \ref pipe_tasks_multiband_DetectCoaddSourcesTask_Example
151 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Purpose Description
153 Command-line task that detects sources on a coadd of exposures obtained with a single filter.
155 Coadding individual visits requires each exposure to be warped. This introduces covariance in the noise
156 properties across pixels. Before detection, we correct the coadd variance by scaling the variance plane
157 in the coadd to match the observed variance. This is an approximate approach -- strictly, we should
158 propagate the full covariance matrix -- but it is simple and works well in practice.
160 After scaling the variance plane, we detect sources and generate footprints by delegating to the \ref
161 SourceDetectionTask_ "detection" subtask.
164 deepCoadd{tract,patch,filter}: ExposureF
166 deepCoadd_det{tract,patch,filter}: SourceCatalog (only parent Footprints)
167 \n deepCoadd_calexp{tract,patch,filter}: Variance scaled, background-subtracted input
169 \n deepCoadd_calexp_background{tract,patch,filter}: BackgroundList
173 DetectCoaddSourcesTask delegates most of its work to the \ref SourceDetectionTask_ "detection" subtask.
174 You can retarget this subtask if you wish.
176 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Initialize Task initialization
178 \copydoc \_\_init\_\_
180 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Run Invoking the Task
184 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Config Configuration parameters
186 See \ref DetectCoaddSourcesConfig_ "DetectSourcesConfig"
188 \section pipe_tasks_multiBand_DetectCoaddSourcesTask_Debug Debug variables
190 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
191 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
194 DetectCoaddSourcesTask has no debug variables of its own because it relegates all the work to
195 \ref SourceDetectionTask_ "SourceDetectionTask"; see the documetation for
196 \ref SourceDetectionTask_ "SourceDetectionTask" for further information.
198 \section pipe_tasks_multiband_DetectCoaddSourcesTask_Example A complete example of using DetectCoaddSourcesTask
200 DetectCoaddSourcesTask is meant to be run after assembling a coadded image in a given band. The purpose of
201 the task is to update the background, detect all sources in a single band and generate a set of parent
202 footprints. Subsequent tasks in the multi-band processing procedure will merge sources across bands and,
203 eventually, perform forced photometry. Command-line usage of DetectCoaddSourcesTask expects a data
204 reference to the coadd to be processed. A list of the available optional arguments can be obtained by
205 calling detectCoaddSources.py with the `--help` command line argument:
207 detectCoaddSources.py --help
210 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
211 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has followed
212 steps 1 - 4 at \ref pipeTasks_multiBand, one may detect all the sources in each coadd as follows:
214 detectCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I
216 that will process the HSC-I band data. The results are written to
217 `$CI_HSC_DIR/DATA/deepCoadd-results/HSC-I`.
219 It is also necessary to run:
221 detectCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-R
223 to generate the sources catalogs for the HSC-R band required by the next step in the multi-band
224 processing procedure: \ref MergeDetectionsTask_ "MergeDetectionsTask".
226 _DefaultName =
"detectCoaddSources"
227 ConfigClass = DetectCoaddSourcesConfig
233 parser = ArgumentParser(name=cls._DefaultName)
234 parser.add_id_argument(
"--id",
"deepCoadd", help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=r",
235 ContainerClass=ExistingCoaddDataIdContainer)
240 \brief Initialize the task. Create the \ref SourceDetectionTask_ "detection" subtask.
242 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
244 \param[in] schema: initial schema for the output catalog, modified-in place to include all
245 fields set by this task. If None, the source minimal schema will be used.
246 \param[in] **kwargs: keyword arguments to be passed to lsst.pipe.base.task.Task.__init__
248 CmdLineTask.__init__(self, **kwargs)
250 schema = afwTable.SourceTable.makeMinimalSchema()
252 self.makeSubtask(
"detection", schema=self.
schema)
256 \brief Run detection on a coadd.
258 Invokes \ref runDetection and then uses \ref write to output the
261 \param[in] patchRef: data reference for patch
263 exposure = patchRef.get(self.config.coaddName +
"Coadd", immediate=
True)
265 self.
write(exposure, results, patchRef)
270 \brief Run detection on an exposure.
272 First scale the variance plane to match the observed variance
273 using \ref scaleVariance. Then invoke the \ref SourceDetectionTask_ "detection" subtask to
276 \param[in] exposure: Exposure on which to detect
277 \param[in] idFactory: IdFactory to set source identifiers
279 \return a pipe.base.Struct with fields
280 - sources: catalog of detections
281 - backgrounds: list of backgrounds
283 if self.config.doScaleVariance:
284 scaleVariance(exposure.getMaskedImage(), self.config.mask, log=self.log)
285 backgrounds = afwMath.BackgroundList()
286 table = afwTable.SourceTable.make(self.
schema, idFactory)
287 detections = self.detection.makeSourceCatalog(table, exposure)
288 sources = detections.sources
289 fpSets = detections.fpSets
290 if fpSets.background:
291 backgrounds.append(fpSets.background)
292 return Struct(sources=sources, backgrounds=backgrounds)
294 def write(self, exposure, results, patchRef):
296 \brief Write out results from runDetection.
298 \param[in] exposure: Exposure to write out
299 \param[in] results: Struct returned from runDetection
300 \param[in] patchRef: data reference for patch
302 coaddName = self.config.coaddName +
"Coadd"
303 patchRef.put(results.backgrounds, coaddName +
"_calexp_background")
304 patchRef.put(results.sources, coaddName +
"_det")
305 patchRef.put(exposure, coaddName +
"_calexp")
312 \anchor MergeSourcesRunner_
314 \brief Task runner for the \ref MergeSourcesTask_ "MergeSourcesTask". Required because the run method
315 requires a list of dataRefs rather than a single dataRef.
320 \brief Provide a butler to the Task constructor.
322 \param[in] parsedCmd the parsed command
323 \param[in] args tuple of a list of data references and kwargs (un-used)
324 \throws RuntimeError if both parsedCmd & args are None
326 if parsedCmd
is not None:
327 butler = parsedCmd.butler
328 elif args
is not None:
329 dataRefList, kwargs = args
330 butler = dataRefList[0].getButler()
332 raise RuntimeError(
"Neither parsedCmd or args specified")
333 return self.TaskClass(config=self.config, log=self.log, butler=butler)
338 \brief Provide a list of patch references for each patch.
340 The patch references within the list will have different filters.
342 \param[in] parsedCmd the parsed command
343 \param **kwargs key word arguments (unused)
344 \throws RuntimeError if multiple references are provided for the same combination of tract, patch and
348 for ref
in parsedCmd.id.refList:
349 tract = ref.dataId[
"tract"]
350 patch = ref.dataId[
"patch"]
351 filter = ref.dataId[
"filter"]
352 if not tract
in refList:
354 if not patch
in refList[tract]:
355 refList[tract][patch] = {}
356 if filter
in refList[tract][patch]:
357 raise RuntimeError(
"Multiple versions of %s" % (ref.dataId,))
358 refList[tract][patch][filter] = ref
359 return [(list(p.values()), kwargs)
for t
in refList.values()
for p
in t.values()]
364 \anchor MergeSourcesConfig_
366 \brief Configuration for merging sources.
368 priorityList = ListField(dtype=str, default=[],
369 doc=
"Priority-ordered list of bands for the merge.")
370 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
373 Config.validate(self)
375 raise RuntimeError(
"No priority list provided")
380 \anchor MergeSourcesTask_
382 \brief A base class for merging source catalogs.
384 Merging detections (MergeDetectionsTask) and merging measurements (MergeMeasurementsTask) are
385 so similar that it makes sense to re-use the code, in the form of this abstract base class.
387 NB: Do not use this class directly. Instead use one of the child classes that inherit from
388 MergeSourcesTask such as \ref MergeDetectionsTask_ "MergeDetectionsTask" or \ref MergeMeasurementsTask_
389 "MergeMeasurementsTask"
391 Sub-classes should set the following class variables:
392 * `_DefaultName`: name of Task
393 * `inputDataset`: name of dataset to read
394 * `outputDataset`: name of dataset to write
395 * `getSchemaCatalogs` to the result of `_makeGetSchemaCatalogs(outputDataset)`
397 In addition, sub-classes must implement the mergeCatalogs method.
400 ConfigClass = MergeSourcesConfig
401 RunnerClass = MergeSourcesRunner
404 getSchemaCatalogs =
None
409 \brief Create a suitable ArgumentParser.
411 We will use the ArgumentParser to get a provide a list of data
412 references for patches; the RunnerClass will sort them into lists
413 of data references for the same patch
415 parser = ArgumentParser(name=cls._DefaultName)
416 parser.add_id_argument(
"--id",
"deepCoadd_" + cls.inputDataset,
417 ContainerClass=ExistingCoaddDataIdContainer,
418 help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=g^r^i")
423 \brief Obtain the input schema either directly or froma butler reference.
425 \param[in] butler butler reference to obtain the input schema from
426 \param[in] schema the input schema
429 assert butler
is not None,
"Neither butler nor schema specified"
430 schema = butler.get(self.config.coaddName +
"Coadd_" + self.
inputDataset +
"_schema",
431 immediate=
True).schema
434 def __init__(self, butler=None, schema=None, **kwargs):
436 \brief Initialize the task.
438 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
439 \param[in] schema the schema of the detection catalogs used as input to this one
440 \param[in] butler a butler used to read the input schema from disk, if schema is None
442 Derived classes should use the getInputSchema() method to handle the additional
443 arguments and retreive the actual input schema.
445 CmdLineTask.__init__(self, **kwargs)
447 def run(self, patchRefList):
449 \brief Merge coadd sources from multiple bands. Calls \ref mergeCatalogs which must be defined in
450 subclasses that inherit from MergeSourcesTask.
452 \param[in] patchRefList list of data references for each filter
454 catalogs = dict(self.
readCatalog(patchRef)
for patchRef
in patchRefList)
455 mergedCatalog = self.
mergeCatalogs(catalogs, patchRefList[0])
456 self.
write(patchRefList[0], mergedCatalog)
460 \brief Read input catalog.
462 We read the input dataset provided by the 'inputDataset'
465 \param[in] patchRef data reference for patch
466 \return tuple consisting of the filter name and the catalog
468 filterName = patchRef.dataId[
"filter"]
469 catalog = patchRef.get(self.config.coaddName +
"Coadd_" + self.
inputDataset, immediate=
True)
470 self.log.info(
"Read %d sources for filter %s: %s" % (len(catalog), filterName, patchRef.dataId))
471 return filterName, catalog
475 \brief Merge multiple catalogs. This function must be defined in all subclasses that inherit from
478 \param[in] catalogs dict mapping filter name to source catalog
480 \return merged catalog
482 raise NotImplementedError()
486 \brief Write the output.
488 \param[in] patchRef data reference for patch
489 \param[in] catalog catalog
491 We write as the dataset provided by the 'outputDataset'
494 patchRef.put(catalog, self.config.coaddName +
"Coadd_" + self.
outputDataset)
497 mergeDataId = patchRef.dataId.copy()
498 del mergeDataId[
"filter"]
499 self.log.info(
"Wrote merged catalog: %s" % (mergeDataId,))
503 \brief No metadata to write, and not sure how to write it for a list of dataRefs.
508 class CullPeaksConfig(Config):
510 \anchor CullPeaksConfig_
512 \brief Configuration for culling garbage peaks after merging footprints.
514 Peaks may also be culled after detection or during deblending; this configuration object
515 only deals with culling after merging Footprints.
517 These cuts are based on three quantities:
518 - nBands: the number of bands in which the peak was detected
519 - peakRank: the position of the peak within its family, sorted from brightest to faintest.
520 - peakRankNormalized: the peak rank divided by the total number of peaks in the family.
522 The formula that identifie peaks to cull is:
524 nBands < nBandsSufficient
525 AND (rank >= rankSufficient)
526 AND (rank >= rankConsider OR rank >= rankNormalizedConsider)
528 To disable peak culling, simply set nBandsSafe=1.
531 nBandsSufficient = RangeField(dtype=int, default=2, min=1,
532 doc=
"Always keep peaks detected in this many bands")
533 rankSufficient = RangeField(dtype=int, default=20, min=1,
534 doc=
"Always keep this many peaks in each family")
535 rankConsidered = RangeField(dtype=int, default=30, min=1,
536 doc=(
"Keep peaks with less than this rank that also match the "
537 "rankNormalizedConsidered condition."))
538 rankNormalizedConsidered = RangeField(dtype=float, default=0.7, min=0.0,
539 doc=(
"Keep peaks with less than this normalized rank that"
540 " also match the rankConsidered condition."))
545 \anchor MergeDetectionsConfig_
547 \brief Configuration parameters for the MergeDetectionsTask.
549 minNewPeak = Field(dtype=float, default=1,
550 doc=
"Minimum distance from closest peak to create a new one (in arcsec).")
552 maxSamePeak = Field(dtype=float, default=0.3,
553 doc=
"When adding new catalogs to the merge, all peaks less than this distance "
554 " (in arcsec) to an existing peak will be flagged as detected in that catalog.")
555 cullPeaks = ConfigField(dtype=CullPeaksConfig, doc=
"Configuration for how to cull peaks.")
557 skyFilterName = Field(dtype=str, default=
"sky",
558 doc=
"Name of `filter' used to label sky objects (e.g. flag merge_peak_sky is set)\n"
559 "(N.b. should be in MergeMeasurementsConfig.pseudoFilterList)")
560 skySourceRadius = Field(dtype=float, default=8,
561 doc=
"Radius, in pixels, of sky objects")
562 skyGrowDetectedFootprints = Field(dtype=int, default=0,
563 doc=
"Number of pixels to grow the detected footprint mask "
564 "when adding sky objects")
565 nSkySourcesPerPatch = Field(dtype=int, default=100,
566 doc=
"Try to add this many sky objects to the mergeDet list, which will\n"
567 "then be measured along with the detected objects in sourceMeasurementTask")
568 nTrialSkySourcesPerPatch = Field(dtype=int, default=
None, optional=
True,
569 doc=
"Maximum number of trial sky object positions\n"
570 "(default: nSkySourcesPerPatch*nTrialSkySourcesPerPatchMultiplier)")
571 nTrialSkySourcesPerPatchMultiplier = Field(dtype=int, default=5,
572 doc=
"Set nTrialSkySourcesPerPatch to\n"
573 " nSkySourcesPerPatch*nTrialSkySourcesPerPatchMultiplier\n"
574 "if nTrialSkySourcesPerPatch is None")
586 \anchor MergeDetectionsTask_
588 \brief Merge coadd detections from multiple bands.
590 \section pipe_tasks_multiBand_Contents Contents
592 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Purpose
593 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Init
594 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Run
595 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Config
596 - \ref pipe_tasks_multiBand_MergeDetectionsTask_Debug
597 - \ref pipe_tasks_multiband_MergeDetectionsTask_Example
599 \section pipe_tasks_multiBand_MergeDetectionsTask_Purpose Description
601 Command-line task that merges sources detected in coadds of exposures obtained with different filters.
603 To perform photometry consistently across coadds in multiple filter bands, we create a master catalog of
604 sources from all bands by merging the sources (peaks & footprints) detected in each coadd, while keeping
605 track of which band each source originates in.
607 The catalog merge is performed by \ref getMergedSourceCatalog. Spurious peaks detected around bright
608 objects are culled as described in \ref CullPeaksConfig_.
611 deepCoadd_det{tract,patch,filter}: SourceCatalog (only parent Footprints)
613 deepCoadd_mergeDet{tract,patch}: SourceCatalog (only parent Footprints)
617 MergeDetectionsTask subclasses \ref MergeSourcesTask_ "MergeSourcesTask".
619 \section pipe_tasks_multiBand_MergeDetectionsTask_Init Task initialisation
621 \copydoc \_\_init\_\_
623 \section pipe_tasks_multiBand_MergeDetectionsTask_Run Invoking the Task
627 \section pipe_tasks_multiBand_MergeDetectionsTask_Config Configuration parameters
629 See \ref MergeDetectionsConfig_
631 \section pipe_tasks_multiBand_MergeDetectionsTask_Debug Debug variables
633 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a flag \c -d
634 to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py files.
636 MergeDetectionsTask has no debug variables.
638 \section pipe_tasks_multiband_MergeDetectionsTask_Example A complete example of using MergeDetectionsTask
640 MergeDetectionsTask is meant to be run after detecting sources in coadds generated for the chosen subset
641 of the available bands.
642 The purpose of the task is to merge sources (peaks & footprints) detected in the coadds generated from the
643 chosen subset of filters.
644 Subsequent tasks in the multi-band processing procedure will deblend the generated master list of sources
645 and, eventually, perform forced photometry.
646 Command-line usage of MergeDetectionsTask expects data references for all the coadds to be processed.
647 A list of the available optional arguments can be obtained by calling mergeCoaddDetections.py with the
648 `--help` command line argument:
650 mergeCoaddDetections.py --help
653 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
654 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
655 step 5 at \ref pipeTasks_multiBand, one may merge the catalogs of sources from each coadd as follows:
657 mergeCoaddDetections.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I^HSC-R
659 This will merge the HSC-I & -R band parent source catalogs and write the results to
660 `$CI_HSC_DIR/DATA/deepCoadd-results/merged/0/5,4/mergeDet-0-5,4.fits`.
662 The next step in the multi-band processing procedure is
663 \ref MeasureMergedCoaddSourcesTask_ "MeasureMergedCoaddSourcesTask"
665 ConfigClass = MergeDetectionsConfig
666 _DefaultName =
"mergeCoaddDetections"
668 outputDataset =
"mergeDet"
671 def __init__(self, butler=None, schema=None, **kwargs):
673 \brief Initialize the merge detections task.
675 A \ref FootprintMergeList_ "FootprintMergeList" will be used to
676 merge the source catalogs.
678 Additional keyword arguments (forwarded to MergeSourcesTask.__init__):
679 \param[in] schema the schema of the detection catalogs used as input to this one
680 \param[in] butler a butler used to read the input schema from disk, if schema is None
681 \param[in] **kwargs keyword arguments to be passed to MergeSourcesTask.__init__
683 The task will set its own self.schema attribute to the schema of the output merged catalog.
685 MergeSourcesTask.__init__(self, butler=butler, schema=schema, **kwargs)
689 if self.config.nSkySourcesPerPatch > 0:
690 filterNames += [self.config.skyFilterName]
695 \brief Merge multiple catalogs.
697 After ordering the catalogs and filters in priority order,
698 \ref getMergedSourceCatalog of the \ref FootprintMergeList_ "FootprintMergeList" created by
699 \ref \_\_init\_\_ is used to perform the actual merging. Finally, \ref cullPeaks is used to remove
700 garbage peaks detected around bright objects.
704 \param[out] mergedList
708 skyInfo =
getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
709 tractWcs = skyInfo.wcs
710 peakDistance = self.config.minNewPeak / tractWcs.pixelScale().asArcseconds()
711 samePeakDistance = self.config.maxSamePeak / tractWcs.pixelScale().asArcseconds()
714 orderedCatalogs = [catalogs[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
716 if band
in catalogs.keys()]
718 mergedList = self.merged.getMergedSourceCatalog(orderedCatalogs, orderedBands, peakDistance,
726 mergedList, skyInfo, self.config.skyGrowDetectedFootprints)
727 if skySourceFootprints:
728 key = mergedList.schema.find(
"merge_footprint_%s" % self.config.skyFilterName).key
730 for foot
in skySourceFootprints:
731 s = mergedList.addNew()
735 self.log.info(
"Added %d sky sources (%.0f%% of requested)",
736 len(skySourceFootprints),
737 100*len(skySourceFootprints)/float(self.config.nSkySourcesPerPatch))
740 for record
in mergedList:
741 record.getFootprint().sortPeaks()
742 self.log.info(
"Merged to %d sources" % len(mergedList))
749 \brief Attempt to remove garbage peaks (mostly on the outskirts of large blends).
751 \param[in] catalog Source catalog
753 keys = [item.key
for item
in self.merged.getPeakSchema().extract(
"merge.peak.*").values()]
756 for parentSource
in catalog:
759 keptPeaks = parentSource.getFootprint().getPeaks()
760 oldPeaks = list(keptPeaks)
762 familySize = len(oldPeaks)
763 totalPeaks += familySize
764 for rank, peak
in enumerate(oldPeaks):
765 if ((rank < self.config.cullPeaks.rankSufficient)
or
766 (self.config.cullPeaks.nBandsSufficient > 1
and
767 sum([peak.get(k)
for k
in keys]) >= self.config.cullPeaks.nBandsSufficient)
or
768 (rank < self.config.cullPeaks.rankConsidered
and
769 rank < self.config.cullPeaks.rankNormalizedConsidered * familySize)):
770 keptPeaks.append(peak)
773 self.log.info(
"Culled %d of %d peaks" % (culledPeaks, totalPeaks))
777 Return a dict of empty catalogs for each catalog dataset produced by this task.
779 \param[out] dictionary of empty catalogs
783 return {self.config.coaddName +
"Coadd_mergeDet": mergeDet,
784 self.config.coaddName +
"Coadd_peak": peak}
788 \brief Return a list of Footprints of sky objects which don't overlap with anything in mergedList
790 \param mergedList The merged Footprints from all the input bands
791 \param skyInfo A description of the patch
792 \param growDetectedFootprints The number of pixels to grow the detected footprints
795 if self.config.nSkySourcesPerPatch <= 0:
798 skySourceRadius = self.config.skySourceRadius
799 nSkySourcesPerPatch = self.config.nSkySourcesPerPatch
800 nTrialSkySourcesPerPatch = self.config.nTrialSkySourcesPerPatch
801 if nTrialSkySourcesPerPatch
is None:
802 nTrialSkySourcesPerPatch = self.config.nTrialSkySourcesPerPatchMultiplier*nSkySourcesPerPatch
808 patchBBox = skyInfo.patchInfo.getOuterBBox()
809 mask = afwImage.MaskU(patchBBox)
810 detectedMask = mask.getPlaneBitMask(
"DETECTED")
812 foot = s.getFootprint()
813 if growDetectedFootprints > 0:
817 xmin, ymin = patchBBox.getMin()
818 xmax, ymax = patchBBox.getMax()
820 xmin += skySourceRadius + 1
821 ymin += skySourceRadius + 1
822 xmax -= skySourceRadius + 1
823 ymax -= skySourceRadius + 1
825 skySourceFootprints = []
826 for i
in range(nTrialSkySourcesPerPatch):
827 if len(skySourceFootprints) == nSkySourcesPerPatch:
830 x = int(numpy.random.uniform(xmin, xmax))
831 y = int(numpy.random.uniform(ymin, ymax))
833 foot.setPeakSchema(self.merged.getPeakSchema())
835 if not foot.overlapsMask(mask):
836 foot.addPeak(x, y, 0)
837 foot.getPeaks()[0].set(
"merge_peak_%s" % self.config.skyFilterName,
True)
838 skySourceFootprints.append(foot)
840 return skySourceFootprints
845 \anchor MeasureMergedCoaddSourcesConfig_
847 \brief Configuration parameters for the MeasureMergedCoaddSourcesTask
849 doDeblend = Field(dtype=bool, default=
True, doc=
"Deblend sources?")
850 deblend = ConfigurableField(target=SourceDeblendTask, doc=
"Deblend sources")
851 measurement = ConfigurableField(target=SingleFrameMeasurementTask, doc=
"Source measurement")
852 setPrimaryFlags = ConfigurableField(target=SetPrimaryFlagsTask, doc=
"Set flags for primary tract/patch")
853 doPropagateFlags = Field(
854 dtype=bool, default=
True,
855 doc=
"Whether to match sources to CCD catalogs to propagate flags (to e.g. identify PSF stars)"
857 propagateFlags = ConfigurableField(target=PropagateVisitFlagsTask, doc=
"Propagate visit flags to coadd")
858 doMatchSources = Field(dtype=bool, default=
True, doc=
"Match sources to reference catalog?")
859 match = ConfigurableField(target=DirectMatchTask, doc=
"Matching to reference catalog")
860 coaddName = Field(dtype=str, default=
"deep", doc=
"Name of coadd")
861 checkUnitsParseStrict = Field(
862 doc=
"Strictness of Astropy unit compatibility check, can be 'raise', 'warn' or 'silent'",
869 doc=
"Apply aperture corrections"
871 applyApCorr = ConfigurableField(
872 target=ApplyApCorrTask,
873 doc=
"Subtask to apply aperture corrections"
875 doRunCatalogCalculation = Field(
878 doc=
'Run catalogCalculation task'
880 catalogCalculation = ConfigurableField(
881 target=CatalogCalculationTask,
882 doc=
"Subtask to run catalogCalculation plugins on catalog"
886 Config.setDefaults(self)
887 self.deblend.propagateAllPeaks =
True
888 self.measurement.plugins.names |= [
'base_InputCount']
891 self.measurement.plugins[
'base_PixelFlags'].masksFpAnywhere = [
'CLIPPED']
903 \anchor MeasureMergedCoaddSourcesTask_
905 \brief Deblend sources from master catalog in each coadd seperately and measure.
907 \section pipe_tasks_multiBand_Contents Contents
909 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Purpose
910 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Initialize
911 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Run
912 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Config
913 - \ref pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Debug
914 - \ref pipe_tasks_multiband_MeasureMergedCoaddSourcesTask_Example
916 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Purpose Description
918 Command-line task that uses peaks and footprints from a master catalog to perform deblending and
919 measurement in each coadd.
921 Given a master input catalog of sources (peaks and footprints), deblend and measure each source on the
922 coadd. Repeating this procedure with the same master catalog across multiple coadds will generate a
923 consistent set of child sources.
925 The deblender retains all peaks and deblends any missing peaks (dropouts in that band) as PSFs. Source
926 properties are measured and the \c is-primary flag (indicating sources with no children) is set. Visit
927 flags are propagated to the coadd sources.
929 Optionally, we can match the coadd sources to an external reference catalog.
932 deepCoadd_mergeDet{tract,patch}: SourceCatalog
933 \n deepCoadd_calexp{tract,patch,filter}: ExposureF
935 deepCoadd_meas{tract,patch,filter}: SourceCatalog
939 MeasureMergedCoaddSourcesTask delegates most of its work to a set of sub-tasks:
942 <DT> \ref SourceDeblendTask_ "deblend"
943 <DD> Deblend all the sources from the master catalog.</DD>
944 <DT> \ref SingleFrameMeasurementTask_ "measurement"
945 <DD> Measure source properties of deblended sources.</DD>
946 <DT> \ref SetPrimaryFlagsTask_ "setPrimaryFlags"
947 <DD> Set flag 'is-primary' as well as related flags on sources. 'is-primary' is set for sources that are
948 not at the edge of the field and that have either not been deblended or are the children of deblended
950 <DT> \ref PropagateVisitFlagsTask_ "propagateFlags"
951 <DD> Propagate flags set in individual visits to the coadd.</DD>
952 <DT> \ref DirectMatchTask_ "match"
953 <DD> Match input sources to a reference catalog (optional).
956 These subtasks may be retargeted as required.
958 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Initialize Task initialization
960 \copydoc \_\_init\_\_
962 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Run Invoking the Task
966 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Config Configuration parameters
968 See \ref MeasureMergedCoaddSourcesConfig_
970 \section pipe_tasks_multiBand_MeasureMergedCoaddSourcesTask_Debug Debug variables
972 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
973 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
976 MeasureMergedCoaddSourcesTask has no debug variables of its own because it delegates all the work to
977 the various sub-tasks. See the documetation for individual sub-tasks for more information.
979 \section pipe_tasks_multiband_MeasureMergedCoaddSourcesTask_Example A complete example of using MeasureMergedCoaddSourcesTask
981 After MeasureMergedCoaddSourcesTask has been run on multiple coadds, we have a set of per-band catalogs.
982 The next stage in the multi-band processing procedure will merge these measurements into a suitable
983 catalog for driving forced photometry.
985 Command-line usage of MeasureMergedCoaddSourcesTask expects a data reference to the coadds to be processed.
986 A list of the available optional arguments can be obtained by calling measureCoaddSources.py with the
987 `--help` command line argument:
989 measureCoaddSources.py --help
992 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
993 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
994 step 6 at \ref pipeTasks_multiBand, one may perform deblending and measure sources in the HSC-I band
997 measureCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I
999 This will process the HSC-I band data. The results are written in
1000 `$CI_HSC_DIR/DATA/deepCoadd-results/HSC-I/0/5,4/meas-HSC-I-0-5,4.fits
1002 It is also necessary to run
1004 measureCoaddSources.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-R
1006 to generate the sources catalogs for the HSC-R band required by the next step in the multi-band
1007 procedure: \ref MergeMeasurementsTask_ "MergeMeasurementsTask".
1009 _DefaultName =
"measureCoaddSources"
1010 ConfigClass = MeasureMergedCoaddSourcesConfig
1011 RunnerClass = ButlerInitializedTaskRunner
1017 parser = ArgumentParser(name=cls._DefaultName)
1018 parser.add_id_argument(
"--id",
"deepCoadd_calexp",
1019 help=
"data ID, e.g. --id tract=12345 patch=1,2 filter=r",
1020 ContainerClass=ExistingCoaddDataIdContainer)
1023 def __init__(self, butler=None, schema=None, peakSchema=None, refObjLoader=None, **kwargs):
1025 \brief Initialize the task.
1027 Keyword arguments (in addition to those forwarded to CmdLineTask.__init__):
1028 \param[in] schema: the schema of the merged detection catalog used as input to this one
1029 \param[in] peakSchema: the schema of the PeakRecords in the Footprints in the merged detection catalog
1030 \param[in] refObjLoader: an instance of LoadReferenceObjectsTasks that supplies an external reference
1031 catalog. May be None if the loader can be constructed from the butler argument or all steps
1032 requiring a reference catalog are disabled.
1033 \param[in] butler: a butler used to read the input schemas from disk or construct the reference
1034 catalog loader, if schema or peakSchema or refObjLoader is None
1036 The task will set its own self.schema attribute to the schema of the output measurement catalog.
1037 This will include all fields from the input schema, as well as additional fields for all the
1040 CmdLineTask.__init__(self, **kwargs)
1042 assert butler
is not None,
"Neither butler nor schema is defined"
1043 schema = butler.get(self.config.coaddName +
"Coadd_mergeDet_schema", immediate=
True).schema
1045 self.schemaMapper.addMinimalSchema(schema)
1046 self.
schema = self.schemaMapper.getOutputSchema()
1048 if self.config.doDeblend:
1049 if peakSchema
is None:
1050 assert butler
is not None,
"Neither butler nor peakSchema is defined"
1051 peakSchema = butler.get(self.config.coaddName +
"Coadd_peak_schema", immediate=
True).schema
1052 self.makeSubtask(
"deblend", schema=self.
schema, peakSchema=peakSchema)
1053 self.makeSubtask(
"measurement", schema=self.
schema, algMetadata=self.
algMetadata)
1054 self.makeSubtask(
"setPrimaryFlags", schema=self.
schema)
1055 if self.config.doMatchSources:
1056 if refObjLoader
is None:
1057 assert butler
is not None,
"Neither butler nor refObjLoader is defined"
1058 self.makeSubtask(
"match", butler=butler, refObjLoader=refObjLoader)
1059 if self.config.doPropagateFlags:
1060 self.makeSubtask(
"propagateFlags", schema=self.
schema)
1061 self.schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
1062 if self.config.doApCorr:
1063 self.makeSubtask(
"applyApCorr", schema=self.
schema)
1064 if self.config.doRunCatalogCalculation:
1065 self.makeSubtask(
"catalogCalculation", schema=self.
schema)
1069 \brief Deblend and measure.
1071 \param[in] patchRef: Patch reference.
1073 Deblend each source in every coadd and measure. Set 'is-primary' and related flags. Propagate flags
1074 from individual visits. Optionally match the sources to a reference catalog and write the matches.
1075 Finally, write the deblended sources and measurements out.
1077 exposure = patchRef.get(self.config.coaddName +
"Coadd_calexp", immediate=
True)
1079 if self.config.doDeblend:
1080 self.deblend.run(exposure, sources)
1082 bigKey = sources.schema[
"deblend_parentTooBig"].asKey()
1084 numBig = sum((s.get(bigKey)
for s
in sources))
1086 self.log.warn(
"Patch %s contains %d large footprints that were not deblended" %
1087 (patchRef.dataId, numBig))
1089 table = sources.getTable()
1092 self.measurement.run(sources, exposure, exposureId=self.
getExposureId(patchRef))
1094 if self.config.doApCorr:
1095 self.applyApCorr.run(
1097 apCorrMap=exposure.getInfo().getApCorrMap()
1100 if self.config.doRunCatalogCalculation:
1101 self.catalogCalculation.run(sources)
1103 skyInfo =
getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
1104 self.setPrimaryFlags.run(sources, skyInfo.skyMap, skyInfo.tractInfo, skyInfo.patchInfo,
1105 includeDeblend=self.config.doDeblend)
1106 if self.config.doPropagateFlags:
1107 self.propagateFlags.run(patchRef.getButler(), sources, self.propagateFlags.getCcdInputs(exposure),
1109 if self.config.doMatchSources:
1111 self.
write(patchRef, sources)
1115 \brief Read input sources.
1117 \param[in] dataRef: Data reference for catalog of merged detections
1118 \return List of sources in merged catalog
1120 We also need to add columns to hold the measurements we're about to make
1121 so we can measure in-place.
1123 merged = dataRef.get(self.config.coaddName +
"Coadd_mergeDet", immediate=
True)
1124 self.log.info(
"Read %d detections: %s" % (len(merged), dataRef.dataId))
1127 idFactory.notify(s.getId())
1128 table = afwTable.SourceTable.make(self.
schema, idFactory)
1135 \brief Write matches of the sources to the astrometric reference catalog.
1137 We use the Wcs in the exposure to match sources.
1139 \param[in] dataRef: data reference
1140 \param[in] exposure: exposure with Wcs
1141 \param[in] sources: source catalog
1143 result = self.match.run(sources, exposure.getInfo().getFilter().getName())
1146 matches.table.setMetadata(result.matchMeta)
1147 dataRef.put(matches, self.config.coaddName +
"Coadd_srcMatch")
1151 \brief Write the source catalog.
1153 \param[in] dataRef: data reference
1154 \param[in] sources: source catalog
1156 dataRef.put(sources, self.config.coaddName +
"Coadd_meas")
1157 self.log.info(
"Wrote %d sources: %s" % (len(sources), dataRef.dataId))
1160 return int(dataRef.get(self.config.coaddName +
"CoaddId"))
1167 \anchor MergeMeasurementsConfig_
1169 \brief Configuration parameters for the MergeMeasurementsTask
1171 pseudoFilterList = ListField(dtype=str, default=[
"sky"],
1172 doc=
"Names of filters which may have no associated detection\n"
1173 "(N.b. should include MergeDetectionsConfig.skyFilterName)")
1174 snName = Field(dtype=str, default=
"base_PsfFlux",
1175 doc=
"Name of flux measurement for calculating the S/N when choosing the reference band.")
1176 minSN = Field(dtype=float, default=10.,
1177 doc=
"If the S/N from the priority band is below this value (and the S/N "
1178 "is larger than minSNDiff compared to the priority band), use the band with "
1179 "the largest S/N as the reference band.")
1180 minSNDiff = Field(dtype=float, default=3.,
1181 doc=
"If the difference in S/N between another band and the priority band is larger "
1182 "than this value (and the S/N in the priority band is less than minSN) "
1183 "use the band with the largest S/N as the reference band")
1184 flags = ListField(dtype=str, doc=
"Require that these flags, if available, are not set",
1185 default=[
"base_PixelFlags_flag_interpolatedCenter",
"base_PsfFlux_flag",
1186 "ext_photometryKron_KronFlux_flag",
"modelfit_CModel_flag", ])
1198 \anchor MergeMeasurementsTask_
1200 \brief Merge measurements from multiple bands
1202 \section pipe_tasks_multiBand_Contents Contents
1204 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Purpose
1205 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Initialize
1206 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Run
1207 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Config
1208 - \ref pipe_tasks_multiBand_MergeMeasurementsTask_Debug
1209 - \ref pipe_tasks_multiband_MergeMeasurementsTask_Example
1211 \section pipe_tasks_multiBand_MergeMeasurementsTask_Purpose Description
1213 Command-line task that merges measurements from multiple bands.
1215 Combines consistent (i.e. with the same peaks and footprints) catalogs of sources from multiple filter
1216 bands to construct a unified catalog that is suitable for driving forced photometry. Every source is
1217 required to have centroid, shape and flux measurements in each band.
1220 deepCoadd_meas{tract,patch,filter}: SourceCatalog
1222 deepCoadd_ref{tract,patch}: SourceCatalog
1226 MergeMeasurementsTask subclasses \ref MergeSourcesTask_ "MergeSourcesTask".
1228 \section pipe_tasks_multiBand_MergeMeasurementsTask_Initialize Task initialization
1230 \copydoc \_\_init\_\_
1232 \section pipe_tasks_multiBand_MergeMeasurementsTask_Run Invoking the Task
1236 \section pipe_tasks_multiBand_MergeMeasurementsTask_Config Configuration parameters
1238 See \ref MergeMeasurementsConfig_
1240 \section pipe_tasks_multiBand_MergeMeasurementsTask_Debug Debug variables
1242 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
1243 flag \c -d to import \b debug.py from your \c PYTHONPATH; see \ref baseDebug for more about \b debug.py
1246 MergeMeasurementsTask has no debug variables.
1248 \section pipe_tasks_multiband_MergeMeasurementsTask_Example A complete example of using MergeMeasurementsTask
1250 MergeMeasurementsTask is meant to be run after deblending & measuring sources in every band.
1251 The purpose of the task is to generate a catalog of sources suitable for driving forced photometry in
1252 coadds and individual exposures.
1253 Command-line usage of MergeMeasurementsTask expects a data reference to the coadds to be processed. A list
1254 of the available optional arguments can be obtained by calling mergeCoaddMeasurements.py with the `--help`
1255 command line argument:
1257 mergeCoaddMeasurements.py --help
1260 To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we
1261 will process HSC data in the [ci_hsc](https://github.com/lsst/ci_hsc) package. Assuming one has finished
1262 step 7 at \ref pipeTasks_multiBand, one may merge the catalogs generated after deblending and measuring
1265 mergeCoaddMeasurements.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I^HSC-R
1267 This will merge the HSC-I & HSC-R band catalogs. The results are written in
1268 `$CI_HSC_DIR/DATA/deepCoadd-results/`.
1270 _DefaultName =
"mergeCoaddMeasurements"
1271 ConfigClass = MergeMeasurementsConfig
1272 inputDataset =
"meas"
1273 outputDataset =
"ref"
1276 def __init__(self, butler=None, schema=None, **kwargs):
1278 Initialize the task.
1280 Additional keyword arguments (forwarded to MergeSourcesTask.__init__):
1281 \param[in] schema: the schema of the detection catalogs used as input to this one
1282 \param[in] butler: a butler used to read the input schema from disk, if schema is None
1284 The task will set its own self.schema attribute to the schema of the output merged catalog.
1286 MergeSourcesTask.__init__(self, butler=butler, schema=schema, **kwargs)
1289 self.schemaMapper.addMinimalSchema(inputSchema,
True)
1290 self.
fluxKey = inputSchema.find(self.config.snName +
"_flux").getKey()
1291 self.
fluxErrKey = inputSchema.find(self.config.snName +
"_fluxSigma").getKey()
1292 self.
fluxFlagKey = inputSchema.find(self.config.snName +
"_flag").getKey()
1295 for band
in self.config.priorityList:
1297 outputKey = self.schemaMapper.editOutputSchema().addField(
1298 "merge_measurement_%s" % short,
1300 doc=
"Flag field set if the measurements here are from the %s filter" % band
1302 peakKey = inputSchema.find(
"merge_peak_%s" % short).key
1303 footprintKey = inputSchema.find(
"merge_footprint_%s" % short).key
1304 self.
flagKeys[band] = Struct(peak=peakKey, footprint=footprintKey, output=outputKey)
1305 self.
schema = self.schemaMapper.getOutputSchema()
1308 for filt
in self.config.pseudoFilterList:
1310 self.pseudoFilterKeys.append(self.schema.find(
"merge_peak_%s" % filt).getKey())
1312 self.log.warn(
"merge_peak is not set for pseudo-filter %s" % filt)
1315 for flag
in self.config.flags:
1317 self.
badFlags[flag] = self.schema.find(flag).getKey()
1318 except KeyError
as exc:
1319 self.log.warn(
"Can't find flag %s in schema: %s" % (flag, exc,))
1323 Merge measurement catalogs to create a single reference catalog for forced photometry
1325 \param[in] catalogs: the catalogs to be merged
1326 \param[in] patchRef: patch reference for data
1328 For parent sources, we choose the first band in config.priorityList for which the
1329 merge_footprint flag for that band is is True.
1331 For child sources, the logic is the same, except that we use the merge_peak flags.
1334 orderedCatalogs = [catalogs[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
1335 orderedKeys = [self.
flagKeys[band]
for band
in self.config.priorityList
if band
in catalogs.keys()]
1338 mergedCatalog.reserve(len(orderedCatalogs[0]))
1340 idKey = orderedCatalogs[0].table.getIdKey()
1341 for catalog
in orderedCatalogs[1:]:
1342 if numpy.any(orderedCatalogs[0].get(idKey) != catalog.get(idKey)):
1343 raise ValueError(
"Error in inputs to MergeCoaddMeasurements: source IDs do not match")
1347 for orderedRecords
in zip(*orderedCatalogs):
1350 maxSNFlagKeys =
None
1352 priorityRecord =
None
1353 priorityFlagKeys =
None
1355 hasPseudoFilter =
False
1359 for inputRecord, flagKeys
in zip(orderedRecords, orderedKeys):
1360 parent = (inputRecord.getParent() == 0
and inputRecord.get(flagKeys.footprint))
1361 child = (inputRecord.getParent() != 0
and inputRecord.get(flagKeys.peak))
1363 if not (parent
or child):
1365 if inputRecord.get(pseudoFilterKey):
1366 hasPseudoFilter =
True
1367 priorityRecord = inputRecord
1368 priorityFlagKeys = flagKeys
1373 isBad =
any(inputRecord.get(flag)
for flag
in self.
badFlags)
1378 if numpy.isnan(sn)
or sn < 0.:
1380 if (parent
or child)
and priorityRecord
is None:
1381 priorityRecord = inputRecord
1382 priorityFlagKeys = flagKeys
1385 maxSNRecord = inputRecord
1386 maxSNFlagKeys = flagKeys
1399 bestRecord = priorityRecord
1400 bestFlagKeys = priorityFlagKeys
1401 elif (prioritySN < self.config.minSN
and (maxSN - prioritySN) > self.config.minSNDiff
and
1402 maxSNRecord
is not None):
1403 bestRecord = maxSNRecord
1404 bestFlagKeys = maxSNFlagKeys
1405 elif priorityRecord
is not None:
1406 bestRecord = priorityRecord
1407 bestFlagKeys = priorityFlagKeys
1409 if bestRecord
is not None and bestFlagKeys
is not None:
1410 outputRecord = mergedCatalog.addNew()
1412 outputRecord.set(bestFlagKeys.output,
True)
1414 raise ValueError(
"Error in inputs to MergeCoaddMeasurements: no valid reference for %s" %
1415 inputRecord.getId())
1418 for inputCatalog
in orderedCatalogs:
1419 if len(mergedCatalog) != len(inputCatalog):
1420 raise ValueError(
"Mismatch between catalog sizes: %s != %s" %
1421 (len(mergedCatalog), len(orderedCatalogs)))
1423 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.
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
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.