65 def run(self, diaSources, idGenerator=None):
66 """Associate DiaSources into a collection of DiaObjects using a
67 brute force matching algorithm.
69 Reproducible is for the same input data is assured by ordering the
70 DiaSource data by ccdVisit ordering.
74 diaSources : `pandas.DataFrame`
75 DiaSources grouped by CcdVisitId to spatially associate into
77 idGenerator : `lsst.meas.base.IdGenerator`, optional
78 Object that generates Object IDs and random number generator seeds.
82 results : `lsst.pipe.base.Struct`
83 Results struct with attributes:
86 Table of DiaSources with updated values for the DiaObjects
87 they are spatially associated to (`pandas.DataFrame`).
89 Table of DiaObjects from matching DiaSources
96 doDropIndex = diaSources.index.names[0]
is None
97 diaSources.reset_index(inplace=
True, drop=doDropIndex)
101 diaSources.set_index([
"ccdVisitId",
"diaSourceId"], inplace=
True)
109 if idGenerator
is None:
110 idGenerator = IdGenerator()
111 idCat = idGenerator.make_source_catalog(afwTable.SourceTable.makeMinimalSchema())
113 for ccdVisit
in diaSources.index.levels[0]:
116 ccdVisitSources = diaSources.loc[ccdVisit]
117 if len(diaObjectCat) == 0:
118 for diaSourceId, diaSrc
in ccdVisitSources.iterrows():
129 usedMatchIndicies = []
131 for diaSourceId, diaSrc
in ccdVisitSources.iterrows():
135 2*self.config.tolerance,
138 dists = matchResult.dists
139 matches = matchResult.matches
152 if np.min(dists) < np.deg2rad(self.config.tolerance/3600):
153 matchDistArg = np.argmin(dists)
154 matchIndex = matches[matchDistArg]
156 if np.isin([matchIndex], usedMatchIndicies).sum() < 1:
165 usedMatchIndicies.append(matchIndex)
190 diaSources.reset_index(inplace=
True)
191 diaSources.set_index(
"diaSourceId", inplace=
True, verify_integrity=
True)
193 objs = diaObjectCat
if diaObjectCat
else np.array([], dtype=[(
'diaObjectId',
'int64'),
196 (
'nDiaSources',
'int64')])
197 diaObjects = pd.DataFrame(data=objs)
199 if "diaObjectId" in diaObjects.columns:
200 diaObjects.set_index(
"diaObjectId", inplace=
True, verify_integrity=
True)
202 return pipeBase.Struct(
203 assocDiaSources=diaSources,
204 diaObjects=diaObjects)
215 """Create a new DiaObject and append its data.
219 diaSrc : `pandas.Series`
220 Full unassociated DiaSource to create a DiaObject from.
221 diaSources : `pandas.DataFrame`
222 DiaSource catalog to update information in. The catalog is
225 Unique identifier of the ccdVisit where ``diaSrc`` was observed.
227 Unique identifier of the DiaSource.
228 diaObjectCat : `list` of `dict`s
229 Catalog of diaObjects to append the new object o.
230 idCat : `lsst.afw.table.SourceCatalog`
231 Catalog with the IdFactory used to generate unique DiaObject
233 diaObjectCoords : `list` of `list`s of `lsst.geom.SpherePoint`s
234 Set of coordinates of DiaSource locations that make up the
235 DiaObject average coordinate.
236 healPixIndices : `list` of `int`s
237 HealPix indices representing the locations of each currently
240 hpIndex = toIndex(self.config.nside,
243 healPixIndices.append(hpIndex)
248 diaObjCoords.append([sphPoint])
250 diaObjId = idCat.addNew().get(
"id")
254 diaSources.loc[(ccdVisit, diaSourceId),
"diaObjectId"] = diaObjId
265 """Update DiaObject and DiaSource values after an association.
270 Array index location of the DiaObject that ``diaSrc`` was
272 diaSrc : `pandas.Series`
273 Full unassociated DiaSource to create a DiaObject from.
274 diaSources : `pandas.DataFrame`
275 DiaSource catalog to update information in. The catalog is
278 Unique identifier of the ccdVisit where ``diaSrc`` was observed.
280 Unique identifier of the DiaSource.
281 diaObjectCat : `list` of `dict`s
282 Catalog of diaObjects to append the new object o.
283 diaObjectCoords : `list` of `list`s of `lsst.geom.SpherePoint`s
284 Set of coordinates of DiaSource locations that make up the
285 DiaObject average coordinate.
286 healPixIndices : `list` of `int`s
287 HealPix indices representing the locations of each currently
294 diaObjCoords[matchIndex].append(sphPoint)
295 aveCoord = geom.averageSpherePoint(diaObjCoords[matchIndex])
296 diaObjCat[matchIndex][
"ra"] = aveCoord.getRa().asDegrees()
297 diaObjCat[matchIndex][
"dec"] = aveCoord.getDec().asDegrees()
298 nSources = diaObjCat[matchIndex][
"nDiaSources"]
299 diaObjCat[matchIndex][
"nDiaSources"] = nSources + 1
300 healPixIndices[matchIndex] = toIndex(self.config.nside,
301 diaObjCat[matchIndex][
"ra"],
302 diaObjCat[matchIndex][
"dec"])
304 diaSources.loc[(ccdVisit, diaSourceId),
"diaObjectId"] = \
305 diaObjCat[matchIndex][
"diaObjectId"]
308 """Search healPixels around DiaSource locations for DiaObjects.
313 DiaSource RA location.
315 DiaSource Dec location.
317 Size of annulus to convert to covering healPixels and search for
319 hpIndices : `list` of `int`s
320 List of heal pix indices containing the DiaObjects in ``diaObjs``.
321 diaObjs : `list` of `dict`s
322 Catalog diaObjects to with full location information for comparing
327 results : `lsst.pipe.base.Struct`
328 Results struct containing
331 Array of distances between the current DiaSource diaObjects.
332 (`numpy.ndarray` or `None`)
334 Array of array indices of diaObjects this DiaSource matches to.
335 (`numpy.ndarray` or `None`)
337 match_indices = query_disc(self.config.nside,
340 np.deg2rad(tol/3600.))
341 matchIndices = np.argwhere(np.isin(hpIndices, match_indices)).flatten()
343 if len(matchIndices) < 1:
344 return pipeBase.Struct(dists=
None, matches=
None)
347 [np.sqrt(np.sum((eq2xyz(src_ra, src_dec)
348 - eq2xyz(diaObjs[match][
"ra"],
349 diaObjs[match][
"dec"]))**2))
350 for match
in matchIndices])
351 return pipeBase.Struct(
353 matches=matchIndices)