65 def run(self, diaSources, idGenerator=None):
66 """Associate DiaSources into a collection of DiaObjects using a
67 brute force matching algorithm.
68
69 Reproducible is for the same input data is assured by ordering the
70 DiaSource data by ccdVisit ordering.
71
72 Parameters
73 ----------
74 diaSources : `pandas.DataFrame`
75 DiaSources grouped by CcdVisitId to spatially associate into
76 DiaObjects.
77 idGenerator : `lsst.meas.base.IdGenerator`, optional
78 Object that generates Object IDs and random number generator seeds.
79
80 Returns
81 -------
82 results : `lsst.pipe.base.Struct`
83 Results struct with attributes:
84
85 ``assocDiaSources``
86 Table of DiaSources with updated values for the DiaObjects
87 they are spatially associated to (`pandas.DataFrame`).
88 ``diaObjects``
89 Table of DiaObjects from matching DiaSources
90 (`pandas.DataFrame`).
91
92 """
93
94
95
96 doDropIndex = diaSources.index.names[0] is None
97 diaSources.reset_index(inplace=True, drop=doDropIndex)
98
99
100
101 diaSources.set_index(["ccdVisitId", "diaSourceId"], inplace=True)
102
103
104 diaObjectCat = []
105 diaObjectCoords = []
106 healPixIndices = []
107
108
109 if idGenerator is None:
110 idGenerator = IdGenerator()
111 idCat = idGenerator.make_source_catalog(afwTable.SourceTable.makeMinimalSchema())
112
113 for ccdVisit in diaSources.index.levels[0]:
114
115
116 ccdVisitSources = diaSources.loc[ccdVisit]
117 if len(diaObjectCat) == 0:
118 for diaSourceId, diaSrc in ccdVisitSources.iterrows():
119 self.addNewDiaObject(diaSrc,
120 diaSources,
121 ccdVisit,
122 diaSourceId,
123 diaObjectCat,
124 idCat,
125 diaObjectCoords,
126 healPixIndices)
127 continue
128
129 usedMatchIndicies = []
130
131 for diaSourceId, diaSrc in ccdVisitSources.iterrows():
132
133 matchResult = self.findMatches(diaSrc["ra"],
134 diaSrc["dec"],
135 2*self.config.tolerance,
136 healPixIndices,
137 diaObjectCat)
138 dists = matchResult.dists
139 matches = matchResult.matches
140
141 if dists is None:
142 self.addNewDiaObject(diaSrc,
143 diaSources,
144 ccdVisit,
145 diaSourceId,
146 diaObjectCat,
147 idCat,
148 diaObjectCoords,
149 healPixIndices)
150 continue
151
152 if np.min(dists) < np.deg2rad(self.config.tolerance/3600):
153 matchDistArg = np.argmin(dists)
154 matchIndex = matches[matchDistArg]
155
156 if np.isin([matchIndex], usedMatchIndicies).sum() < 1:
157 self.updateCatalogs(matchIndex,
158 diaSrc,
159 diaSources,
160 ccdVisit,
161 diaSourceId,
162 diaObjectCat,
163 diaObjectCoords,
164 healPixIndices)
165 usedMatchIndicies.append(matchIndex)
166
167
168 else:
169 self.addNewDiaObject(diaSrc,
170 diaSources,
171 ccdVisit,
172 diaSourceId,
173 diaObjectCat,
174 idCat,
175 diaObjectCoords,
176 healPixIndices)
177
178
179 else:
180 self.addNewDiaObject(diaSrc,
181 diaSources,
182 ccdVisit,
183 diaSourceId,
184 diaObjectCat,
185 idCat,
186 diaObjectCoords,
187 healPixIndices)
188
189
190 diaSources.reset_index(inplace=True)
191 diaSources.set_index("diaSourceId", inplace=True, verify_integrity=True)
192
193 objs = diaObjectCat if diaObjectCat else np.array([], dtype=[('diaObjectId', 'int64'),
194 ('ra', 'float64'),
195 ('dec', 'float64'),
196 ('nDiaSources', 'int64')])
197 diaObjects = pd.DataFrame(data=objs)
198
199 if "diaObjectId" in diaObjects.columns:
200 diaObjects.set_index("diaObjectId", inplace=True, verify_integrity=True)
201
202 return pipeBase.Struct(
203 assocDiaSources=diaSources,
204 diaObjects=diaObjects)
205