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.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.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))
220 if not refCat.isContiguous():
221 loadRes.refCat = refCat.copy(deep=
True)
227 """!Load reference objects that overlap a circular sky region 229 @param[in] ctrCoord ICRS center of search region (an lsst.geom.SpherePoint) 230 @param[in] radius radius of search region (an lsst.geom.Angle) 231 @param[in] filterName name of filter, or None for the default filter; 232 used for flux values in case we have flux limits (which are not yet implemented) 234 @return an lsst.pipe.base.Struct containing: 235 - refCat a catalog of reference objects with the 236 @link meas_algorithms_loadReferenceObjects_Schema standard schema @endlink 237 as documented in LoadReferenceObjects, including photometric, resolved and variable; 238 hasCentroid is False for all objects. 239 - fluxField = name of flux field for specified filterName 244 def _trimToBBox(refCat, bbox, wcs):
245 """!Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields 247 @param[in,out] refCat a catalog of objects (an lsst.afw.table.SimpleCatalog, 248 or other table type that has fields "coord", "centroid" and "hasCentroid"). 249 The "coord" field is read. 250 The "centroid" and "hasCentroid" fields are set. 251 @param[in] bbox pixel region (an afwImage.Box2D) 252 @param[in] wcs WCS used to convert sky position to pixel position (an lsst.afw.math.WCS) 254 @return a catalog of reference objects in bbox, with centroid and hasCentroid fields set 256 afwTable.updateRefCentroids(wcs, refCat)
257 centroidKey = afwTable.Point2DKey(refCat.schema[
"centroid"])
258 retStarCat = type(refCat)(refCat.table)
260 point = star.get(centroidKey)
261 if bbox.contains(point):
262 retStarCat.append(star)
265 def _addFluxAliases(self, schema):
266 """Add aliases for camera filter fluxes to the schema 268 If self.config.defaultFilter then adds these aliases: 269 camFlux: <defaultFilter>_flux 270 camFluxSigma: <defaultFilter>_fluxSigma, if the latter exists 272 For each camFilter: refFilter in self.config.filterMap adds these aliases: 273 <camFilter>_camFlux: <refFilter>_flux 274 <camFilter>_camFluxSigma: <refFilter>_fluxSigma, if the latter exists 276 @throw RuntimeError if any reference flux field is missing from the schema 278 aliasMap = schema.getAliasMap()
280 def addAliasesForOneFilter(filterName, refFilterName):
281 """Add aliases for a single filter 283 @param[in] filterName camera filter name, or "" 284 the name is <filterName>_camFlux or camFlux if filterName is None 285 @param[in] refFilterName reference filter name; <refFilterName>_flux must exist 287 camFluxName = filterName +
"_camFlux" if filterName
is not None else "camFlux" 288 refFluxName = refFilterName +
"_flux" 289 if refFluxName
not in schema:
290 raise RuntimeError(
"Unknown reference filter %s" % (refFluxName,))
291 aliasMap.set(camFluxName, refFluxName)
292 refFluxErrName = refFluxName +
"Sigma" 293 if refFluxErrName
in schema:
294 camFluxErrName = camFluxName +
"Sigma" 295 aliasMap.set(camFluxErrName, refFluxErrName)
297 if self.config.defaultFilter:
298 addAliasesForOneFilter(
None, self.config.defaultFilter)
300 for filterName, refFilterName
in self.config.filterMap.items():
301 addAliasesForOneFilter(filterName, refFilterName)
305 addIsPhotometric=False, addIsResolved=False, addIsVariable=False):
306 """!Make the standard schema for reference object catalogs 308 @param[in] filterNameList list of filter names; used to create *filterName*_flux fields 309 @param[in] addFluxSigma if True then include flux sigma fields 310 @param[in] addIsPhotometric if True add field "photometric" 311 @param[in] addIsResolved if True add field "resolved" 312 @param[in] addIsVariable if True add field "variable" 314 schema = afwTable.SimpleTable.makeMinimalSchema()
315 afwTable.Point2DKey.addFields(
318 "centroid on an exposure, if relevant",
324 doc=
"is position known?",
326 for filterName
in filterNameList:
328 field=
"%s_flux" % (filterName,),
330 doc=
"flux in filter %s" % (filterName,),
334 for filterName
in filterNameList:
336 field=
"%s_fluxSigma" % (filterName,),
338 doc=
"flux uncertainty in filter %s" % (filterName,),
345 doc=
"set if the object can be used for photometric calibration",
351 doc=
"set if the object is spatially resolved",
357 doc=
"set if the object has variable brightness",
361 def _calculateCircle(self, bbox, wcs):
362 """!Compute on-sky center and radius of search region 364 @param[in] bbox bounding box for pixels (an lsst.geom.Box2I or Box2D) 365 @param[in] wcs WCS (an lsst.afw.geom.SkyWcs) 366 @return an lsst.pipe.base.Struct containing: 367 - coord: ICRS center of the search region (lsst.geom.SpherePoint) 368 - radius: the radius of the search region (lsst.geom.Angle) 369 - bbox: the bounding box used to compute the circle (lsst.geom.Box2D) 372 bbox.grow(self.config.pixelMargin)
373 coord = wcs.pixelToSky(bbox.getCenter())
374 radius = max(coord.separation(wcs.pixelToSky(pp))
for pp
in bbox.getCorners())
375 return pipeBase.Struct(coord=coord, radius=radius, bbox=bbox)
378 """!Return metadata about the load 380 This metadata is used for reloading the catalog (e.g., for 381 reconstituting a normalised match list. 383 @param[in] bbox bounding box for pixels (an lsst.geom.Box2I or Box2D) 384 @param[in] wcs WCS (an lsst.afw.geom.SkyWcs) 385 @param[in] filterName name of camera filter, or None or blank for the default filter 386 @param[in] calib calibration, or None if unknown 387 @return metadata (lsst.daf.base.PropertyList) 393 """!Return metadata about the load 395 This metadata is used for reloading the catalog (e.g., for 396 reconstituting a normalised match list. 398 @param[in] coord ICRS centr of circle (lsst.geom.SpherePoint) 399 @param[in] radius radius of circle (lsst.geom.Angle) 400 @param[in] filterName name of camera filter, or None or blank for the default filter 401 @param[in] calib calibration, or None if unknown 402 @return metadata (lsst.daf.base.PropertyList) 405 md.add(
'RA', coord.getRa().asDegrees(),
'field center in degrees')
406 md.add(
'DEC', coord.getDec().asDegrees(),
'field center in degrees')
407 md.add(
'RADIUS', radius.asDegrees(),
'field radius in degrees, minimum')
408 md.add(
'SMATCHV', 1,
'SourceMatchVector version number')
409 filterName =
"UNKNOWN" if filterName
is None else str(filterName)
410 md.add(
'FILTER', filterName,
'filter name for photometric data')
414 """!Relink an unpersisted match list to sources and reference objects 416 A match list is persisted and unpersisted as a catalog of IDs produced by 417 afw.table.packMatches(), with match metadata (as returned by the astrometry tasks) 418 in the catalog's metadata attribute. This method converts such a match catalog 419 into a match list (an lsst.afw.table.ReferenceMatchVector) with links to source 420 records and reference object records. 422 @param[in] matchCat Unperisted packed match list (an lsst.afw.table.BaseCatalog). 423 matchCat.table.getMetadata() must contain match metadata, 424 as returned by the astrometry tasks. 425 @param[in,out] sourceCat Source catalog (an lsst.afw.table.SourceCatalog). 426 As a side effect, the catalog will be sorted by ID. 428 @return the match list (an lsst.afw.table.ReferenceMatchVector) 430 matchmeta = matchCat.table.getMetadata()
431 version = matchmeta.getInt(
'SMATCHV')
433 raise ValueError(
'SourceMatchVector version number is %i, not 1.' % version)
434 filterName = matchmeta.getString(
'FILTER').strip()
436 matchmeta.getDouble(
'DEC'), lsst.geom.degrees)
437 rad = matchmeta.getDouble(
'RADIUS') * lsst.geom.degrees
438 refCat = self.
loadSkyCircle(ctrCoord, rad, filterName).refCat
441 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.