23 """Pipeline for running DiaSource association in a DRP context.
34 from .coaddBase
import makeSkyInfo
35 from .simpleAssociation
import SimpleAssociationTask
37 __all__ = [
"DrpAssociationPipeTask",
38 "DrpAssociationPipeConfig",
39 "DrpAssociationPipeConnections"]
43 dimensions=(
"tract",
"patch",
"skymap"),
44 defaultTemplates={
"coaddName":
"deep",
47 diaSourceTables = pipeBase.connectionTypes.Input(
48 doc=
"Set of catalogs of calibrated DiaSources.",
49 name=
"{fakesType}{coaddName}Diff_diaSrcTable",
50 storageClass=
"DataFrame",
51 dimensions=(
"instrument",
"visit",
"detector"),
55 skyMap = pipeBase.connectionTypes.Input(
56 doc=
"Input definition of geometry/bbox and projection/wcs for coadded "
58 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
59 storageClass=
"SkyMap",
60 dimensions=(
"skymap", ),
62 assocDiaSourceTable = pipeBase.connectionTypes.Output(
63 doc=
"Catalog of DiaSources covering the patch and associated with a "
65 name=
"{fakesType}{coaddName}Diff_assocDiaSrcTable",
66 storageClass=
"DataFrame",
67 dimensions=(
"tract",
"patch"),
69 diaObjectTable = pipeBase.connectionTypes.Output(
70 doc=
"Catalog of DiaObjects created from spatially associating "
72 name=
"{fakesType}{coaddName}Diff_diaObjTable",
73 storageClass=
"DataFrame",
74 dimensions=(
"tract",
"patch"),
78 class DrpAssociationPipeConfig(
79 pipeBase.PipelineTaskConfig,
80 pipelineConnections=DrpAssociationPipeConnections):
81 associator = pexConfig.ConfigurableField(
82 target=SimpleAssociationTask,
83 doc=
"Task used to associate DiaSources with DiaObjects.",
87 class DrpAssociationPipeTask(pipeBase.PipelineTask):
88 """Driver pipeline for loading DiaSource catalogs in a patch/tract
89 region and associating them.
91 ConfigClass = DrpAssociationPipeConfig
92 _DefaultName =
"drpAssociation"
94 def __init__(self, **kwargs):
95 super().__init__(**kwargs)
96 self.makeSubtask(
'associator')
98 def runQuantum(self, butlerQC, inputRefs, outputRefs):
99 inputs = butlerQC.get(inputRefs)
101 inputs[
"tractId"] = butlerQC.quantum.dataId[
"tract"]
102 inputs[
"patchId"] = butlerQC.quantum.dataId[
"patch"]
103 tractPatchId, skymapBits = butlerQC.quantum.dataId.pack(
106 inputs[
"tractPatchId"] = tractPatchId
107 inputs[
"skymapBits"] = skymapBits
109 outputs = self.run(**inputs)
110 butlerQC.put(outputs, outputRefs)
119 """Trim DiaSources to the current Patch and run association.
121 Takes in the set of DiaSource catalogs that covers the current patch,
122 trims them to the dimensions of the patch, and [TODO: eventually]
123 runs association on the concatenated DiaSource Catalog.
127 diaSourceTables : `list` of `lst.daf.butler.DeferredDatasetHandle`
128 Set of DiaSource catalogs potentially covering this patch/tract.
129 skyMap : `lsst.skymap.BaseSkyMap`
130 SkyMap defining the patch/tract
132 Id of current tract being processed.
134 Id of current patch being processed
138 output : `lsst.pipe.base.Struct`
139 Results struct with attributes:
141 ``assocDiaSourceTable``
142 Table of DiaSources with updated value for diaObjectId.
145 Table of DiaObjects from matching DiaSources
146 (`pandas.DataFrame`).
148 self.log.info(
"Running DPR Association on patch %i, tract %i..." %
154 innerPatchBox =
geom.Box2D(skyInfo.patchInfo.getInnerBBox())
156 diaSourceHistory = []
157 for catRef
in diaSourceTables:
159 datasetType=self.config.connections.diaSourceTables,
162 isInTractPatch = self._trimToPatch(cat,
166 nDiaSrc = isInTractPatch.sum()
168 "Read DiaSource catalog of length %i from visit %i, "
169 "detector %i. Found %i sources within the patch/tract "
171 (len(cat), catRef.dataId[
"visit"],
172 catRef.dataId[
"detector"], nDiaSrc))
175 diaSourceHistory.append(pd.DataFrame(columns=cat.columns))
178 cutCat = cat[isInTractPatch]
179 diaSourceHistory.append(cutCat)
181 diaSourceHistoryCat = pd.concat(diaSourceHistory)
182 self.log.info(
"Found %i DiaSources overlapping patch %i, tract %i"
183 % (len(diaSourceHistoryCat), patchId, tractId))
185 assocResult = self.associator.
run(diaSourceHistoryCat,
189 self.log.info(
"Associated DiaSources into %i DiaObjects" %
190 len(assocResult.diaObjects))
192 return pipeBase.Struct(
193 diaObjectTable=assocResult.diaObjects,
194 assocDiaSourceTable=assocResult.assocDiaSources)
196 def _trimToPatch(self, cat, innerPatchBox, wcs):
197 """Create generator testing if a set of DiaSources are in the
202 cat : `pandas.DataFrame`
203 Catalog of DiaSources to test within patch/tract.
204 innerPatchBox : `lsst.geom.Box2D`
205 Bounding box of the patch.
206 wcs : `lsst.geom.SkyWcs`
211 isInPatch : `numpy.ndarray`, (N,)
212 Booleans representing if the DiaSources are contained within the
213 current patch and tract.
215 isInPatch = np.array([
216 innerPatchBox.contains(
219 for idx, row
in cat.iterrows()])
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)
def makeSkyInfo(skyMap, tractId, patchId)