24 __all__ = [
"getRefFluxField",
"getRefFluxKeys",
"LoadReferenceObjectsTask",
"LoadReferenceObjectsConfig"]
38 """!Get name of flux field in schema 40 if filterName is specified: 41 return *filterName*_camFlux if present 42 else return *filterName*_flux if present (camera filter name matches reference filter name) 43 else throw RuntimeError 45 return camFlux, if present, 46 else throw RuntimeError 48 @param[in] schema reference catalog schema 49 @param[in] filterName name of camera filter 50 @return flux field name 51 @throw RuntimeError if appropriate field is not found 53 if not isinstance(schema, afwTable.Schema):
54 raise RuntimeError(
"schema=%s is not a schema" % (schema,))
56 fluxFieldList = [filterName +
"_camFlux", filterName +
"_flux"]
58 fluxFieldList = [
"camFlux"]
59 for fluxField
in fluxFieldList:
60 if fluxField
in schema:
63 raise RuntimeError(
"Could not find flux field(s) %s" % (
", ".join(fluxFieldList)))
67 """!Return flux and flux error keys 69 @param[in] schema reference catalog schema 70 @param[in] filterName name of camera filter 71 @return a pair of keys: 73 flux error key, if present, else None 74 @throw RuntimeError if flux field not found 77 fluxErrField = fluxField +
"Sigma" 78 fluxKey = schema[fluxField].asKey()
80 fluxErrKey = schema[fluxErrField].asKey()
83 return (fluxKey, fluxErrKey)
87 pixelMargin = pexConfig.RangeField(
88 doc=
"Padding to add to 4 all edges of the bounding box (pixels)",
93 defaultFilter = pexConfig.Field(
94 doc=
"Default reference catalog filter to use if filter not specified in exposure; " +
95 "if blank then filter must be specified in exposure",
99 filterMap = pexConfig.DictField(
100 doc=
"Mapping of camera filter name: reference catalog filter name; " +
101 "each reference filter must exist",
117 """!Abstract base class to load objects from reference catalogs 119 @anchor LoadReferenceObjectsTask_ 121 @section meas_algorithms_loadReferenceObjects_Contents Contents 123 - @ref meas_algorithms_loadReferenceObjects_Purpose 124 - @ref meas_algorithms_loadReferenceObjects_Initialize 125 - @ref meas_algorithms_loadReferenceObjects_IO 126 - @ref meas_algorithms_loadReferenceObjects_Schema 127 - @ref meas_algorithms_loadReferenceObjects_Config 129 @section meas_algorithms_loadReferenceObjects_Purpose Description 131 Abstract base class for tasks that load objects from a reference catalog 132 in a particular region of the sky. 134 Implementations must subclass this class, override the loadSkyCircle method, 135 and will typically override the value of ConfigClass with a task-specific config class. 137 @section meas_algorithms_loadReferenceObjects_Initialize Task initialisation 139 @copydoc \_\_init\_\_ 141 @section meas_algorithms_loadReferenceObjects_IO Invoking the Task 143 @copydoc loadPixelBox 145 @section meas_algorithms_loadReferenceObjects_Schema Schema of the reference object catalog 147 Reference object catalogs are instances of lsst.afw.table.SimpleCatalog with the following schema 148 (other fields may also be present): 149 - coord: ICRS position of star on sky (an lsst.afw.geom.SpherePoint) 150 - centroid: position of star on an exposure, if relevant (an lsst.afw.Point2D) 151 - hasCentroid: is centroid usable? 152 - *referenceFilterName*_flux: brightness in the specified reference catalog filter (Jy) 153 Note: the function lsst.afw.image.abMagFromFlux will convert flux in Jy to AB Magnitude. 154 - *referenceFilterName*_fluxSigma (optional): brightness standard deviation (Jy); 155 omitted if no data is available; possibly nan if data is available for some objects but not others 156 - camFlux: brightness in default camera filter (Jy); omitted if defaultFilter not specified 157 - camFluxSigma: brightness standard deviation for default camera filter; 158 omitted if defaultFilter not specified or standard deviation not available that filter 159 - *cameraFilterName*_camFlux: brightness in specified camera filter (Jy) 160 - *cameraFilterName*_camFluxSigma (optional): brightness standard deviation 161 in specified camera filter (Jy); omitted if no data is available; 162 possibly nan if data is available for some objects but not others 163 - photometric (optional): is the object usable for photometric calibration? 164 - resolved (optional): is the object spatially resolved? 165 - variable (optional): does the object have variable brightness? 167 @section meas_algorithms_loadReferenceObjects_Config Configuration parameters 169 See @ref LoadReferenceObjectsConfig for a base set of configuration parameters. 170 Most subclasses will add configuration variables. 172 ConfigClass = LoadReferenceObjectsConfig
173 _DefaultName =
"LoadReferenceObjects" 176 """!Construct a LoadReferenceObjectsTask 178 @param[in] butler A daf.persistence.Butler object. This allows subclasses to use the butler to 179 access reference catalog files using the stack I/O abstraction scheme. 181 pipeBase.Task.__init__(self, *args, **kwargs)
186 """!Load reference objects that overlap a pixel-based rectangular region 188 The search algorithm works by searching in a region in sky coordinates whose center is the center 189 of the bbox and radius is large enough to just include all 4 corners of the bbox. 190 Stars that lie outside the bbox are then trimmed from the list. 192 @param[in] bbox bounding box for pixels (an lsst.afw.geom.Box2I or Box2D) 193 @param[in] wcs WCS (an lsst.afw.geom.SkyWcs) 194 @param[in] filterName name of camera filter, or None or blank for the default filter 195 @param[in] calib calibration, or None if unknown 197 @return an lsst.pipe.base.Struct containing: 198 - refCat a catalog of reference objects with the 199 @link meas_algorithms_loadReferenceObjects_Schema standard schema @endlink 200 as documented in LoadReferenceObjects, including photometric, resolved and variable; 201 hasCentroid is False for all objects. 202 - fluxField = name of flux field for specified filterName 207 self.log.info(
"Loading reference objects using center %s and radius %s deg" %
208 (circle.coord, circle.radius.asDegrees()))
209 loadRes = self.
loadSkyCircle(circle.coord, circle.radius, filterName)
210 refCat = loadRes.refCat
211 numFound = len(refCat)
214 refCat = self.
_trimToBBox(refCat=refCat, bbox=circle.bbox, wcs=wcs)
215 numTrimmed = numFound - len(refCat)
216 self.log.debug(
"trimmed %d out-of-bbox objects, leaving %d", numTrimmed, len(refCat))
217 self.log.info(
"Loaded %d reference objects", len(refCat))
219 loadRes.refCat = refCat
224 """!Load reference objects that overlap a circular sky region 226 @param[in] ctrCoord ICRS center of search region (an lsst.afw.geom.SpherePoint) 227 @param[in] radius radius of search region (an lsst.afw.geom.Angle) 228 @param[in] filterName name of filter, or None for the default filter; 229 used for flux values in case we have flux limits (which are not yet implemented) 231 @return an lsst.pipe.base.Struct containing: 232 - refCat a catalog of reference objects with the 233 @link meas_algorithms_loadReferenceObjects_Schema standard schema @endlink 234 as documented in LoadReferenceObjects, including photometric, resolved and variable; 235 hasCentroid is False for all objects. 236 - fluxField = name of flux field for specified filterName 241 def _trimToBBox(refCat, bbox, wcs):
242 """!Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields 244 @param[in,out] refCat a catalog of objects (an lsst.afw.table.SimpleCatalog, 245 or other table type that has fields "coord", "centroid" and "hasCentroid"). 246 The "coord" field is read. 247 The "centroid" and "hasCentroid" fields are set. 248 @param[in] bbox pixel region (an afwImage.Box2D) 249 @param[in] wcs WCS used to convert sky position to pixel position (an lsst.afw.math.WCS) 251 @return a catalog of reference objects in bbox, with centroid and hasCentroid fields set 253 afwTable.updateRefCentroids(wcs, refCat)
254 centroidKey = afwTable.Point2DKey(refCat.schema[
"centroid"])
255 retStarCat = type(refCat)(refCat.table)
257 point = star.get(centroidKey)
258 if bbox.contains(point):
259 retStarCat.append(star)
262 def _addFluxAliases(self, schema):
263 """Add aliases for camera filter fluxes to the schema 265 If self.config.defaultFilter then adds these aliases: 266 camFlux: <defaultFilter>_flux 267 camFluxSigma: <defaultFilter>_fluxSigma, if the latter exists 269 For each camFilter: refFilter in self.config.filterMap adds these aliases: 270 <camFilter>_camFlux: <refFilter>_flux 271 <camFilter>_camFluxSigma: <refFilter>_fluxSigma, if the latter exists 273 @throw RuntimeError if any reference flux field is missing from the schema 275 aliasMap = schema.getAliasMap()
277 def addAliasesForOneFilter(filterName, refFilterName):
278 """Add aliases for a single filter 280 @param[in] filterName camera filter name, or "" 281 the name is <filterName>_camFlux or camFlux if filterName is None 282 @param[in] refFilterName reference filter name; <refFilterName>_flux must exist 284 camFluxName = filterName +
"_camFlux" if filterName
is not None else "camFlux" 285 refFluxName = refFilterName +
"_flux" 286 if refFluxName
not in schema:
287 raise RuntimeError(
"Unknown reference filter %s" % (refFluxName,))
288 aliasMap.set(camFluxName, refFluxName)
289 refFluxErrName = refFluxName +
"Sigma" 290 if refFluxErrName
in schema:
291 camFluxErrName = camFluxName +
"Sigma" 292 aliasMap.set(camFluxErrName, refFluxErrName)
294 if self.config.defaultFilter:
295 addAliasesForOneFilter(
None, self.config.defaultFilter)
297 for filterName, refFilterName
in self.config.filterMap.items():
298 addAliasesForOneFilter(filterName, refFilterName)
302 addIsPhotometric=False, addIsResolved=False, addIsVariable=False):
303 """!Make the standard schema for reference object catalogs 305 @param[in] filterNameList list of filter names; used to create *filterName*_flux fields 306 @param[in] addFluxSigma if True then include flux sigma fields 307 @param[in] addIsPhotometric if True add field "photometric" 308 @param[in] addIsResolved if True add field "resolved" 309 @param[in] addIsVariable if True add field "variable" 311 schema = afwTable.SimpleTable.makeMinimalSchema()
312 afwTable.Point2DKey.addFields(
315 "centroid on an exposure, if relevant",
321 doc=
"is position known?",
323 for filterName
in filterNameList:
325 field=
"%s_flux" % (filterName,),
327 doc=
"flux in filter %s" % (filterName,),
331 for filterName
in filterNameList:
333 field=
"%s_fluxSigma" % (filterName,),
335 doc=
"flux uncertainty in filter %s" % (filterName,),
342 doc=
"set if the object can be used for photometric calibration",
348 doc=
"set if the object is spatially resolved",
354 doc=
"set if the object has variable brightness",
358 def _calculateCircle(self, bbox, wcs):
359 """!Compute on-sky center and radius of search region 361 @param[in] bbox bounding box for pixels (an lsst.afw.geom.Box2I or Box2D) 362 @param[in] wcs WCS (an lsst.afw.geom.SkyWcs) 363 @return an lsst.pipe.base.Struct containing: 364 - coord: ICRS center of the search region (lsst.afw.geom.SpherePoint) 365 - radius: the radius of the search region (lsst.afw.geom.Angle) 366 - bbox: the bounding box used to compute the circle (lsst.afw.geom.Box2D) 369 bbox.grow(self.config.pixelMargin)
370 coord = wcs.pixelToSky(bbox.getCenter())
371 radius = max(coord.separation(wcs.pixelToSky(pp))
for pp
in bbox.getCorners())
372 return pipeBase.Struct(coord=coord, radius=radius, bbox=bbox)
375 """!Return metadata about the load 377 This metadata is used for reloading the catalog (e.g., for 378 reconstituting a normalised match list. 380 @param[in] bbox bounding box for pixels (an lsst.afw.geom.Box2I or Box2D) 381 @param[in] wcs WCS (an lsst.afw.geom.SkyWcs) 382 @param[in] filterName name of camera filter, or None or blank for the default filter 383 @param[in] calib calibration, or None if unknown 384 @return metadata (lsst.daf.base.PropertyList) 390 """!Return metadata about the load 392 This metadata is used for reloading the catalog (e.g., for 393 reconstituting a normalised match list. 395 @param[in] coord ICRS centr of circle (lsst.afw.geom.SpherePoint) 396 @param[in] radius radius of circle (lsst.afw.geom.Angle) 397 @param[in] filterName name of camera filter, or None or blank for the default filter 398 @param[in] calib calibration, or None if unknown 399 @return metadata (lsst.daf.base.PropertyList) 402 md.add(
'RA', coord.getRa().asDegrees(),
'field center in degrees')
403 md.add(
'DEC', coord.getDec().asDegrees(),
'field center in degrees')
404 md.add(
'RADIUS', radius.asDegrees(),
'field radius in degrees, minimum')
405 md.add(
'SMATCHV', 1,
'SourceMatchVector version number')
406 filterName =
"UNKNOWN" if filterName
is None else str(filterName)
407 md.add(
'FILTER', filterName,
'filter name for photometric data')
411 """!Relink an unpersisted match list to sources and reference objects 413 A match list is persisted and unpersisted as a catalog of IDs produced by 414 afw.table.packMatches(), with match metadata (as returned by the astrometry tasks) 415 in the catalog's metadata attribute. This method converts such a match catalog 416 into a match list (an lsst.afw.table.ReferenceMatchVector) with links to source 417 records and reference object records. 419 @param[in] matchCat Unperisted packed match list (an lsst.afw.table.BaseCatalog). 420 matchCat.table.getMetadata() must contain match metadata, 421 as returned by the astrometry tasks. 422 @param[in,out] sourceCat Source catalog (an lsst.afw.table.SourceCatalog). 423 As a side effect, the catalog will be sorted by ID. 425 @return the match list (an lsst.afw.table.ReferenceMatchVector) 427 matchmeta = matchCat.table.getMetadata()
428 version = matchmeta.getInt(
'SMATCHV')
430 raise ValueError(
'SourceMatchVector version number is %i, not 1.' % version)
431 filterName = matchmeta.getString(
'FILTER').strip()
433 matchmeta.getDouble(
'DEC'), afwGeom.degrees)
434 rad = matchmeta.getDouble(
'RADIUS') * afwGeom.degrees
435 refCat = self.
loadSkyCircle(ctrCoord, rad, filterName).refCat
438 return afwTable.unpackMatches(matchCat, refCat, sourceCat)
def joinMatchListWithCatalog(self, matchCat, sourceCat)
Relink an unpersisted match list to sources and reference objects.
def __init__(self, butler=None, args, kwargs)
Construct a LoadReferenceObjectsTask.
def _trimToBBox(refCat, bbox, wcs)
Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields.
def loadPixelBox(self, bbox, wcs, filterName=None, calib=None)
Load reference objects that overlap a pixel-based rectangular region.
def getRefFluxField(schema, filterName=None)
Get name of flux field in schema.
def getMetadataCircle(self, coord, radius, filterName, calib=None)
Return metadata about the load.
def getRefFluxKeys(schema, filterName=None)
Return flux and flux error keys.
def makeMinimalSchema(filterNameList, addFluxSigma=False, addIsPhotometric=False, addIsResolved=False, addIsVariable=False)
Make the standard schema for reference object catalogs.
Abstract base class to load objects from reference catalogs.
def loadSkyCircle(self, ctrCoord, radius, filterName=None)
Load reference objects that overlap a circular sky region.
def _calculateCircle(self, bbox, wcs)
Compute on-sky center and radius of search region.
def getMetadataBox(self, bbox, wcs, filterName=None, calib=None)
Return metadata about the load.