23 """Pipeline for running DiaSource association in a DRP context.
33 from .coaddBase
import makeSkyInfo
35 __all__ = [
"DrpAssociationPipeTask",
36 "DrpAssociationPipeConfig",
37 "DrpAssociationPipeConnections"]
41 dimensions=(
"tract",
"patch",
"skymap"),
42 defaultTemplates={
"coaddName":
"deep",
45 diaSourceTables = pipeBase.connectionTypes.Input(
46 doc=
"Set of catalogs of calibrated DiaSources.",
47 name=
"{fakesType}{coaddName}Diff_diaSrcTable",
48 storageClass=
"DataFrame",
49 dimensions=(
"instrument",
"visit",
"detector"),
53 skyMap = pipeBase.connectionTypes.Input(
54 doc=
"Input definition of geometry/bbox and projection/wcs for coadded "
56 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
57 storageClass=
"SkyMap",
58 dimensions=(
"skymap", ),
60 assocDiaSourceTable = pipeBase.connectionTypes.Output(
61 doc=
"Catalog of DiaSources covering the patch and associated with a "
63 name=
"{fakesType}{coaddName}Diff_assocDiaSrcTable",
64 storageClass=
"DataFrame",
65 dimensions=(
"tract",
"patch"),
67 diaObjectTable = pipeBase.connectionTypes.Output(
68 doc=
"Catalog of DiaObjects created from spatially associating "
70 name=
"{fakesType}{coaddName}Diff_diaObjTable",
71 storageClass=
"DataFrame",
72 dimensions=(
"tract",
"patch"),
76 class DrpAssociationPipeConfig(
77 pipeBase.PipelineTaskConfig,
78 pipelineConnections=DrpAssociationPipeConnections):
82 class DrpAssociationPipeTask(pipeBase.PipelineTask):
83 """Driver pipeline for loading DiaSource catalogs in a patch/tract
84 region and associating them.
86 ConfigClass = DrpAssociationPipeConfig
87 _DefaultName =
"drpAssociation"
89 def runQuantum(self, butlerQC, inputRefs, outputRefs):
90 inputs = butlerQC.get(inputRefs)
92 inputs[
"tractId"] = butlerQC.quantum.dataId[
"tract"]
93 inputs[
"patchId"] = butlerQC.quantum.dataId[
"patch"]
95 outputs = self.run(**inputs)
96 butlerQC.put(outputs, outputRefs)
98 def run(self, diaSourceTables, skyMap, tractId, patchId):
99 """Trim DiaSources to the current Patch and run association.
101 Takes in the set of DiaSource catalogs that covers the current patch,
102 trims them to the dimensions of the patch, and [TODO: eventually]
103 runs association on the concatenated DiaSource Catalog.
107 diaSourceTables : `list` of `lst.daf.butler.DeferredDatasetHandle`
108 Set of DiaSource catalogs potentially covering this patch/tract.
109 skyMap : `lsst.skymap.BaseSkyMap`
110 SkyMap defining the patch/tract
112 Id of current tract being processed.
114 Id of current patch being processed
118 output : `lsst.pipe.base.Struct`
119 Results struct with attributes:
121 ``assocDiaSourceTable``
122 Table of DiaSources with updated value for diaObjectId.
125 Table of DiaObjects from matching DiaSources
126 (`pandas.DataFrame`).
128 self.log.info(
"Running DPR Association on patch %i, tract %i..." %
134 innerPatchBox =
geom.Box2D(skyInfo.patchInfo.getInnerBBox())
136 diaSourceHistory = []
137 for catRef
in diaSourceTables:
139 datasetType=self.config.connections.diaSourceTables,
142 isInTractPatch = self._trimToPatch(cat,
146 nDiaSrc = isInTractPatch.sum()
148 "Read DiaSource catalog of length %i from visit %i, "
149 "detector %i. Found %i sources within the patch/tract "
151 (len(cat), catRef.dataId[
"visit"],
152 catRef.dataId[
"detector"], nDiaSrc))
155 diaSourceHistory.append(pd.DataFrame(columns=cat.columns))
158 cutCat = cat[isInTractPatch]
159 diaSourceHistory.append(cutCat)
163 diaSourceHistoryCat = pd.concat(diaSourceHistory)
164 self.log.info(
"Found %i DiaSources overlaping patch %i, tract %i"
165 % (len(diaSourceHistoryCat), patchId, tractId))
167 return pipeBase.Struct(
168 diaObjectTable=pd.DataFrame(columns=[
"diaObjectId",
170 assocDiaSourceTable=diaSourceHistoryCat)
172 def _trimToPatch(self, cat, innerPatchBox, wcs):
173 """Create generator testing if a set of DiaSources are in the
178 cat : `pandas.DataFrame`
179 Catalog of DiaSources to test within patch/tract.
180 innerPatchBox : `lsst.geom.Box2D`
181 Bounding box of the patch.
182 wcs : `lsst.geom.SkyWcs`
187 isInPatch : `numpy.ndarray`, (N,)
188 Booleans representing if the DiaSources are contained within the
189 current patch and tract.
191 isInPatch = np.array([
192 innerPatchBox.contains(
195 for idx, row
in cat.iterrows()])
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)
def makeSkyInfo(skyMap, tractId, patchId)