1 from __future__
import absolute_import, division, print_function
33 from future.utils
import with_metaclass
35 __all__ = [
"getRefFluxField",
"getRefFluxKeys",
"LoadReferenceObjectsTask",
"LoadReferenceObjectsConfig"]
39 """!Get name of flux field in schema
41 if filterName is specified:
42 return *filterName*_camFlux if present
43 else return *filterName*_flux if present (camera filter name matches reference filter name)
44 else throw RuntimeError
46 return camFlux, if present,
47 else throw RuntimeError
49 @param[in] schema reference catalog schema
50 @param[in] filterName name of camera filter
51 @return flux field name
52 @throw RuntimeError if appropriate field is not found
55 raise RuntimeError(
"schema=%s is not a schema" % (schema,))
57 fluxFieldList = [filterName +
"_camFlux", filterName +
"_flux"]
59 fluxFieldList = [
"camFlux"]
60 for fluxField
in fluxFieldList:
61 if fluxField
in schema:
64 raise RuntimeError(
"Could not find flux field(s) %s" % (
", ".join(fluxFieldList)))
68 """!Return flux and flux error keys
70 @param[in] schema reference catalog schema
71 @param[in] filterName name of camera filter
72 @return a pair of keys:
74 flux error key, if present, else None
75 @throw RuntimeError if flux field not found
78 fluxErrField = fluxField +
"Sigma"
79 fluxKey = schema[fluxField].asKey()
81 fluxErrKey = schema[fluxErrField].asKey()
84 return (fluxKey, fluxErrKey)
88 pixelMargin = pexConfig.RangeField(
89 doc=
"Padding to add to 4 all edges of the bounding box (pixels)",
94 defaultFilter = pexConfig.Field(
95 doc=
"Default reference catalog filter to use if filter not specified in exposure; " +
96 "if blank then filter must be specified in exposure",
100 filterMap = pexConfig.DictField(
101 doc=
"Mapping of camera filter name: reference catalog filter name; " +
102 "each reference filter must exist",
118 """!Abstract base class to load objects from reference catalogs
120 @anchor LoadReferenceObjectsTask_
122 @section meas_algorithms_loadReferenceObjects_Contents Contents
124 - @ref meas_algorithms_loadReferenceObjects_Purpose
125 - @ref meas_algorithms_loadReferenceObjects_Initialize
126 - @ref meas_algorithms_loadReferenceObjects_IO
127 - @ref meas_algorithms_loadReferenceObjects_Schema
128 - @ref meas_algorithms_loadReferenceObjects_Config
130 @section meas_algorithms_loadReferenceObjects_Purpose Description
132 Abstract base class for tasks that load objects from a reference catalog
133 in a particular region of the sky.
135 Implementations must subclass this class, override the loadSkyCircle method,
136 and will typically override the value of ConfigClass with a task-specific config class.
138 @section meas_algorithms_loadReferenceObjects_Initialize Task initialisation
140 @copydoc \_\_init\_\_
142 @section meas_algorithms_loadReferenceObjects_IO Invoking the Task
144 @copydoc loadObjectsInBBox
146 @section meas_algorithms_loadReferenceObjects_Schema Schema of the reference object catalog
148 Reference object catalogs are instances of lsst.afw.table.SimpleCatalog with the following schema
149 (other fields may also be present):
150 - coord: position of star on sky (an lsst.afw.coord.IcrsCoord)
151 - centroid: position of star on an exposure, if relevant (an lsst.afw.Point2D)
152 - hasCentroid: is centroid usable?
153 - *referenceFilterName*_flux: brightness in the specified reference catalog filter (Jy)
154 Note: the function lsst.afw.image.abMagFromFlux will convert flux in Jy to AB Magnitude.
155 - *referenceFilterName*_fluxSigma (optional): brightness standard deviation (Jy);
156 omitted if no data is available; possibly nan if data is available for some objects but not others
157 - camFlux: brightness in default camera filter (Jy); omitted if defaultFilter not specified
158 - camFluxSigma: brightness standard deviation for default camera filter;
159 omitted if defaultFilter not specified or standard deviation not available that filter
160 - *cameraFilterName*_camFlux: brightness in specified camera filter (Jy)
161 - *cameraFilterName*_camFluxSigma (optional): brightness standard deviation
162 in specified camera filter (Jy); omitted if no data is available;
163 possibly nan if data is available for some objects but not others
164 - photometric (optional): is the object usable for photometric calibration?
165 - resolved (optional): is the object spatially resolved?
166 - variable (optional): does the object have variable brightness?
168 @section meas_algorithms_loadReferenceObjects_Config Configuration parameters
170 See @ref LoadReferenceObjectsConfig for a base set of configuration parameters.
171 Most subclasses will add configuration variables.
173 ConfigClass = LoadReferenceObjectsConfig
174 _DefaultName =
"LoadReferenceObjects"
177 """!Construct a LoadReferenceObjectsTask
179 @param[in] butler A daf.persistence.Butler object. This allows subclasses to use the butler to
180 access reference catalog files using the stack I/O abstraction scheme.
182 pipeBase.Task.__init__(self, *args, **kwargs)
187 """!Load reference objects that overlap a pixel-based rectangular region
189 The search algorithm works by searching in a region in sky coordinates whose center is the center
190 of the bbox and radius is large enough to just include all 4 corners of the bbox.
191 Stars that lie outside the bbox are then trimmed from the list.
193 @param[in] bbox bounding box for pixels (an lsst.afw.geom.Box2I or Box2D)
194 @param[in] wcs WCS (an lsst.afw.image.Wcs)
195 @param[in] filterName name of camera filter, or None or blank for the default filter
196 @param[in] calib calibration, or None if unknown
198 @return an lsst.pipe.base.Struct containing:
199 - refCat a catalog of reference objects with the
200 \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
201 as documented in LoadReferenceObjects, including photometric, resolved and variable;
202 hasCentroid is False for all objects.
203 - fluxField = name of flux field for specified filterName
207 bbox.grow(self.config.pixelMargin)
208 ctrCoord = wcs.pixelToSky(bbox.getCenter())
209 maxRadius = max(ctrCoord.angularSeparation(wcs.pixelToSky(pp))
for pp
in bbox.getCorners())
212 self.log.info(
"Loading reference objects using center %s pix = %s sky and radius %s deg" %
213 (bbox.getCenter(), ctrCoord, maxRadius.asDegrees()))
214 loadRes = self.
loadSkyCircle(ctrCoord, maxRadius, filterName)
215 refCat = loadRes.refCat
216 numFound = len(refCat)
219 refCat = self.
_trimToBBox(refCat=refCat, bbox=bbox, wcs=wcs)
220 numTrimmed = numFound - len(refCat)
221 self.log.debug(
"trimmed %d out-of-bbox objects, leaving %d", numTrimmed, len(refCat))
222 self.log.info(
"Loaded %d reference objects", len(refCat))
224 loadRes.refCat = refCat
229 """!Load reference objects that overlap a circular sky region
231 @param[in] ctrCoord center of search region (an lsst.afw.geom.Coord)
232 @param[in] radius radius of search region (an lsst.afw.geom.Angle)
233 @param[in] filterName name of filter, or None for the default filter;
234 used for flux values in case we have flux limits (which are not yet implemented)
236 @return an lsst.pipe.base.Struct containing:
237 - refCat a catalog of reference objects with the
238 \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
239 as documented in LoadReferenceObjects, including photometric, resolved and variable;
240 hasCentroid is False for all objects.
241 - fluxField = name of flux field for specified filterName
247 """!Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields
249 @param[in] refCat a catalog of objects (an lsst.afw.table.SimpleCatalog,
250 or other table type that supports getCoord() on records)
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
257 hasCentroidKey = refCat.schema[
"hasCentroid"].asKey()
258 retStarCat = type(refCat)(refCat.table)
260 point = wcs.skyToPixel(star.getCoord())
261 if bbox.contains(point):
262 star.set(centroidKey, point)
263 star.set(hasCentroidKey,
True)
264 retStarCat.append(star)
268 """Add aliases for camera filter fluxes to the schema
270 If self.config.defaultFilter then adds these aliases:
271 camFlux: <defaultFilter>_flux
272 camFluxSigma: <defaultFilter>_fluxSigma, if the latter exists
274 For each camFilter: refFilter in self.config.filterMap adds these aliases:
275 <camFilter>_camFlux: <refFilter>_flux
276 <camFilter>_camFluxSigma: <refFilter>_fluxSigma, if the latter exists
278 @throw RuntimeError if any reference flux field is missing from the schema
280 aliasMap = schema.getAliasMap()
282 def addAliasesForOneFilter(filterName, refFilterName):
283 """Add aliases for a single filter
285 @param[in] filterName camera filter name, or ""
286 the name is <filterName>_camFlux or camFlux if filterName is None
287 @param[in] refFilterName reference filter name; <refFilterName>_flux must exist
289 camFluxName = filterName +
"_camFlux" if filterName
is not None else "camFlux"
290 refFluxName = refFilterName +
"_flux"
291 if refFluxName
not in schema:
292 raise RuntimeError(
"Unknown reference filter %s" % (refFluxName,))
293 aliasMap.set(camFluxName, refFluxName)
294 refFluxErrName = refFluxName +
"Sigma"
295 if refFluxErrName
in schema:
296 camFluxErrName = camFluxName +
"Sigma"
297 aliasMap.set(camFluxErrName, refFluxErrName)
299 if self.config.defaultFilter:
300 addAliasesForOneFilter(
None, self.config.defaultFilter)
302 for filterName, refFilterName
in self.config.filterMap.items():
303 addAliasesForOneFilter(filterName, refFilterName)
307 addIsPhotometric=
False, addIsResolved=
False, addIsVariable=
False):
308 """!Make the standard schema for reference object catalogs
310 @param[in] filterNameList list of filter names; used to create *filterName*_flux fields
311 @param[in] addFluxSigma if True then include flux sigma fields
312 @param[in] addIsPhotometric if True add field "photometric"
313 @param[in] addIsResolved if True add field "resolved"
314 @param[in] addIsVariable if True add field "variable"
316 schema = afwTable.SimpleTable.makeMinimalSchema()
317 afwTable.Point2DKey.addFields(
320 "centroid on an exposure, if relevant",
326 doc=
"is position known?",
328 for filterName
in filterNameList:
330 field=
"%s_flux" % (filterName,),
332 doc=
"flux in filter %s" % (filterName,),
336 for filterName
in filterNameList:
338 field=
"%s_fluxSigma" % (filterName,),
340 doc=
"flux uncertainty in filter %s" % (filterName,),
347 doc=
"set if the object can be used for photometric calibration",
353 doc=
"set if the object is spatially resolved",
359 doc=
"set if the object has variable brightness",
364 """!Relink an unpersisted match list to sources and reference objects
366 A match list is persisted and unpersisted as a catalog of IDs produced by
367 afw.table.packMatches(), with match metadata (as returned by the astrometry tasks)
368 in the catalog's metadata attribute. This method converts such a match catalog
369 into a match list (an lsst.afw.table.ReferenceMatchVector) with links to source
370 records and reference object records.
372 @param[in] matchCat Unperisted packed match list (an lsst.afw.table.BaseCatalog).
373 matchCat.table.getMetadata() must contain match metadata,
374 as returned by the astrometry tasks.
375 @param[in,out] sourceCat Source catalog (an lsst.afw.table.SourceCatalog).
376 As a side effect, the catalog will be sorted by ID.
378 @return the match list (an lsst.afw.table.ReferenceMatchVector)
380 matchmeta = matchCat.table.getMetadata()
381 version = matchmeta.getInt(
'SMATCHV')
383 raise ValueError(
'SourceMatchVector version number is %i, not 1.' % version)
384 filterName = matchmeta.getString(
'FILTER').strip()
386 matchmeta.getDouble(
'RA') * afwGeom.degrees,
387 matchmeta.getDouble(
'DEC') * afwGeom.degrees,
389 rad = matchmeta.getDouble(
'RADIUS') * afwGeom.degrees
390 refCat = self.
loadSkyCircle(ctrCoord, rad, filterName).refCat
Defines the fields and offsets for a table.
def getRefFluxKeys
Return flux and flux error keys.
def _trimToBBox
Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields.
def loadPixelBox
Load reference objects that overlap a pixel-based rectangular region.
def loadSkyCircle
Load reference objects that overlap a circular sky region.
def __init__
Construct a LoadReferenceObjectsTask.
Abstract base class to load objects from reference catalogs.
def getRefFluxField
Get name of flux field in schema.
A floating-point coordinate rectangle geometry.
A class to handle Icrs coordinates (inherits from Coord)
std::vector< Match< typename Cat1::Record, typename Cat2::Record > > unpackMatches(BaseCatalog const &matches, Cat1 const &cat1, Cat2 const &cat2)
Reconstruct a MatchVector from a BaseCatalog representation of the matches and a pair of catalogs...
def joinMatchListWithCatalog
Relink an unpersisted match list to sources and reference objects.
def makeMinimalSchema
Make the standard schema for reference object catalogs.