LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
loadReferenceObjects.py
Go to the documentation of this file.
1 from __future__ import absolute_import, division, print_function
2 
3 import abc
4 
5 import numpy
6 
7 import lsst.afw.table as afwTable
8 import lsst.afw.geom as afwGeom
9 import lsst.pex.config as pexConfig
10 import lsst.pipe.base as pipeBase
11 
12 __all__ = ["getRefFluxField", "getRefFluxKeys", "LoadReferenceObjectsTask", "LoadReferenceObjectsConfig"]
13 
14 def getRefFluxField(schema, filterName=None):
15  """!Get name of flux field in schema
16 
17  if filterName is specified:
18  return <filterName>_camFlux if present
19  else return <filterName>_flux if present (camera filter name matches reference filter name)
20  else throw RuntimeError
21  else:
22  return camFlux, if present,
23  else throw RuntimeError
24 
25  @param[in] schema reference catalog schema
26  @param[in] filterName name of camera filter
27  @return flux field name
28  @throw RuntimeError if appropriate field is not found
29  """
30  if not isinstance(schema, afwTable.Schema):
31  raise RuntimeError("schema=%s is not a schema" % (schema,))
32  if filterName:
33  fluxFieldList = [filterName + "_camFlux", filterName + "_flux"]
34  else:
35  fluxFieldList = ["camFlux"]
36  for fluxField in fluxFieldList:
37  if fluxField in schema:
38  return fluxField
39 
40  raise RuntimeError("Could not find flux field(s) %s" % (", ".join(fluxFieldList)))
41 
42 def getRefFluxKeys(schema, filterName=None):
43  """!Return flux and flux error keys
44 
45  @param[in] schema reference catalog schema
46  @param[in] filterName name of camera filter
47  @return a pair of keys:
48  flux key
49  flux error key, if present, else None
50  @throw RuntimeError if flux field not found
51  """
52  fluxField = getRefFluxField(schema, filterName)
53  fluxErrField = fluxField + "Sigma"
54  fluxKey = schema[fluxField].asKey()
55  try:
56  fluxErrKey = schema[fluxErrField].asKey()
57  except Exception:
58  fluxErrKey = None
59  return (fluxKey, fluxErrKey)
60 
61 class LoadReferenceObjectsConfig(pexConfig.Config):
62  pixelMargin = pexConfig.RangeField(
63  doc = "Padding to add to 4 all edges of the bounding box (pixels)",
64  dtype = int,
65  default = 50,
66  min = 0,
67  )
68  defaultFilter = pexConfig.Field(
69  doc = "Default reference catalog filter to use if filter not specified in exposure; " + \
70  "if blank then filter must be specified in exposure",
71  dtype = str,
72  default = "",
73  )
74  filterMap = pexConfig.DictField(
75  doc = "Mapping of camera filter name: reference catalog filter name; " + \
76  "each reference filter must exist",
77  keytype = str,
78  itemtype = str,
79  default = {},
80  )
81 
82 class LoadReferenceObjectsTask(pipeBase.Task):
83  """!Abstract base class to load objects from reference catalogs
84 
85  @anchor LoadReferenceObjectsTask_
86 
87  @section meas_algorithms_loadReferenceObjects_Contents Contents
88 
89  - @ref meas_algorithms_loadReferenceObjects_Purpose
90  - @ref meas_algorithms_loadReferenceObjects_Initialize
91  - @ref meas_algorithms_loadReferenceObjects_IO
92  - @ref meas_algorithms_loadReferenceObjects_Schema
93  - @ref meas_algorithms_loadReferenceObjects_Config
94 
95  @section meas_algorithms_loadReferenceObjects_Purpose Description
96 
97  Abstract base class for tasks that load objects from a reference catalog
98  in a particular region of the sky.
99 
100  Implementations must subclass this class, override the loadSkyCircle method,
101  and will typically override the value of ConfigClass with a task-specific config class.
102 
103  @section meas_algorithms_loadReferenceObjects_Initialize Task initialisation
104 
105  @copydoc \_\_init\_\_
106 
107  @section meas_algorithms_loadReferenceObjects_IO Invoking the Task
108 
109  @copydoc loadObjectsInBBox
110 
111  @section meas_algorithms_loadReferenceObjects_Schema Schema of the reference object catalog
112 
113  Reference object catalogs are instances of lsst.afw.table.SimpleCatalog with the following schema
114  (other fields may also be present):
115  - coord: position of star on sky (an lsst.afw.coord.IcrsCoord)
116  - centroid: position of star on an exposure, if relevant (an lsst.afw.Point2D)
117  - hasCentroid: is centroid usable?
118  - *referenceFilterName*_flux: brightness in the specified reference catalog filter: 10^(-0.4*mag)
119  - *referenceFilterName*_fluxSigma (optional): brightness standard deviation;
120  omitted if no data is available; possibly nan if data is available for some objects but not others
121  - *cameraFilterName*_camera_flux: brightness in specified camera filter (magnitude)
122  - *cameraFilterName*_camera_fluxSigma (optional): brightness standard deviation
123  in specified camera filter (magnitude); omitted if no data is available;
124  possibly nan if data is available for some objects but not others
125  - default_flux (optional): brightness to use if no camera filter is available (magnitude);
126  omitted unless defaultFilter is specified in the config
127  - default_fluxSigma (optional): brightness standard deviation to use if no camera filter is available
128  (magnitude); omitted unless defaultFilter is specified in the config and the corresponding
129  fluxSigma field exists
130  - photometric (optional): is the object usable for photometric calibration?
131  - resolved (optional): is the object spatially resolved?
132  - variable (optional): does the object have variable brightness?
133 
134  @section meas_algorithms_loadReferenceObjects_Config Configuration parameters
135 
136  See @ref LoadReferenceObjectsConfig for a base set of configuration parameters.
137  Most subclasses will add configuration variables.
138  """
139  __metaclass__ = abc.ABCMeta
140  ConfigClass = LoadReferenceObjectsConfig
141  _DefaultName = "LoadReferenceObjects"
142 
143  @pipeBase.timeMethod
144  def loadPixelBox(self, bbox, wcs, filterName=None, calib=None):
145  """!Load reference objects that overlap a pixel-based rectangular region
146 
147  The search algorith works by searching in a region in sky coordinates whose center is the center
148  of the bbox and radius is large enough to just include all 4 corners of the bbox.
149  Stars that lie outside the bbox are then trimmed from the list.
150 
151  @param[in] bbox bounding box for pixels (an lsst.afw.geom.Box2I or Box2D)
152  @param[in] wcs WCS (an lsst.afw.image.Wcs)
153  @param[in] filterName name of camera filter, or None or blank for the default filter
154  @param[in] calib calibration, or None if unknown
155 
156  @return a catalog of reference objects using the standard schema (see the class doc string)
157  """
158  # compute on-sky center and radius of search region, for loadSkyCircle
159  bbox = afwGeom.Box2D(bbox) # make sure bbox is double and that we have a copy
160  bbox.grow(self.config.pixelMargin)
161  ctrCoord = wcs.pixelToSky(bbox.getCenter())
162  maxRadius = afwGeom.Angle(0)
163  for pixPt in bbox.getCorners():
164  coord = wcs.pixelToSky(pixPt)
165  rad = ctrCoord.angularSeparation(coord)
166  maxRadius = max(rad, maxRadius)
167  del rad
168 
169  # find objects in circle
170  self.log.info("getting reference objects using center %s pix = %s sky and radius %s" %
171  (bbox.getCenter(), ctrCoord, maxRadius))
172  loadRes = self.loadSkyCircle(ctrCoord, maxRadius, filterName)
173  refCat = loadRes.refCat
174  numFound = len(refCat)
175 
176  # trim objects outside bbox
177  refCat = self._trimToBBox(refCat=refCat, bbox=bbox, wcs=wcs)
178  numTrimmed = numFound - len(refCat)
179  self.log.info("trimmed %d out-of-bbox objects, leaving %d" % (numTrimmed, len(refCat)))
180 
181  loadRes.refCat = refCat # should be a no-op, but just in case
182  return loadRes
183 
184  @abc.abstractmethod
185  def loadSkyCircle(self, ctrCoord, radius, filterName=None):
186  """!Load reference objects that overlap a circular sky region
187 
188  @param[in] ctrCoord center of search region (an lsst.afw.geom.Coord)
189  @param[in] radius radius of search region (an lsst.afw.geom.Angle)
190  @param[in] filterName name of filter, or None for the default filter;
191  used for flux values in case we have flux limits (which are not yet implemented)
192 
193  @return an lsst.pipe.base.Struct containing:
194  - refCat a catalog of reference objects with the
195  \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
196  as documented in LoadReferenceObjects, including photometric, resolved and variable;
197  hasCentroid is False for all objects.
198  - fluxField = name of flux field for specified filterName
199  """
200  return
201 
202  @staticmethod
203  def _trimToBBox(refCat, bbox, wcs):
204  """!Remove objects outside a given pixel-based bbox and set centroid and hasCentroid fields
205 
206  @param[in] refCat a catalog of objects (an lsst.afw.table.SimpleCatalog,
207  or other table type that supports getCoord() on records)
208  @param[in] bbox pixel region (an afwImage.Box2D)
209  @param[in] wcs WCS used to convert sky position to pixel position (an lsst.afw.math.WCS)
210 
211  @return a catalog of reference objects in bbox, with centroid and hasCentroid fields set
212  """
213  retStarCat = type(refCat)(refCat.table)
214  for star in refCat:
215  point = wcs.skyToPixel(star.getCoord())
216  if bbox.contains(point):
217  star.set("centroid", point)
218  star.set("hasCentroid", True)
219  retStarCat.append(star)
220  return retStarCat
221 
222  def _addFluxAliases(self, schema):
223  """Add aliases for camera filter fluxes to the schema
224 
225  If self.config.defaultFilter then adds these aliases:
226  camFlux: <defaultFilter>_flux
227  camFluxSigma: <defaultFilter>_fluxSigma, if the latter exists
228 
229  For each camFilter: refFilter in self.config.filterMap adds these aliases:
230  <camFilter>_camFlux: <refFilter>_flux
231  <camFilter>_camFluxSigma: <refFilter>_fluxSigma, if the latter exists
232 
233  @throw RuntimeError if any reference flux field is missing from the schema
234  """
235  aliasMap = schema.getAliasMap()
236 
237  def addAliasesForOneFilter(filterName, refFilterName):
238  """Add aliases for a single filter
239 
240  @param[in] filterName camera filter name, or ""
241  the name is <filterName>_camFlux or camFlux if filterName is None
242  @param[in] refFilterName reference filter name; <refFilterName>_flux must exist
243  """
244  camFluxName = filterName + "_camFlux" if filterName is not None else "camFlux"
245  refFluxName = refFilterName + "_flux"
246  if refFluxName not in schema:
247  raise RuntimeError("Unknown reference filter %s" % (refFluxName,))
248  aliasMap.set(camFluxName, refFluxName)
249  refFluxErrName = refFluxName + "Sigma"
250  if refFluxErrName in schema:
251  camFluxErrName = camFluxName + "Sigma"
252  aliasMap.set(camFluxErrName, refFluxErrName)
253 
254  if self.config.defaultFilter:
255  addAliasesForOneFilter(None, self.config.defaultFilter)
256 
257  for filterName, refFilterName in self.config.filterMap.iteritems():
258  addAliasesForOneFilter(filterName, refFilterName)
259 
260  @staticmethod
261  def makeMinimalSchema(filterNameList, addFluxSigma=False,
262  addIsPhotometric=False, addIsResolved=False, addIsVariable=False):
263  """!Make the standard schema for reference object catalogs
264 
265  @param[in] filterNameList list of filter names; used to create <filterName>_flux fields
266  @param[in] addFluxSigma if True then include flux sigma fields
267  @param[in] addIsPhotometric if True add field "photometric"
268  @param[in] addIsResolved if True add field "resolved"
269  """
270  schema = afwTable.SimpleTable.makeMinimalSchema()
271  schema.addField(
272  field = "centroid",
273  type = "PointD",
274  doc = "centroid on an exposure, if relevant",
275  units = "pixels",
276  )
277  schema.addField(
278  field = "hasCentroid",
279  type = "Flag",
280  doc = "is position known?",
281  )
282  for filterName in filterNameList:
283  schema.addField(
284  field = "%s_flux" % (filterName,),
285  type = numpy.float64,
286  doc = "flux in filter %s" % (filterName,),
287  units = "?",
288  )
289  if addFluxSigma:
290  for filterName in filterNameList:
291  schema.addField(
292  field = "%s_fluxSigma" % (filterName,),
293  type = numpy.float64,
294  doc = "flux uncertainty in filter %s" % (filterName,),
295  units = "?",
296  )
297  if addIsPhotometric:
298  schema.addField(
299  field = "photometric",
300  type = "Flag",
301  doc = "set if the object can be used for photometric calibration",
302  )
303  if addIsResolved:
304  schema.addField(
305  field = "resolved",
306  type = "Flag",
307  doc = "set if the object is spatially resolved",
308  )
309  if addIsVariable:
310  schema.addField(
311  field = "variable",
312  type = "Flag",
313  doc = "set if the object has variable brightness",
314  )
315  return schema
Defines the fields and offsets for a table.
Definition: Schema.h:46
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.
double max
Definition: attributes.cc:218
Abstract base class to load objects from reference catalogs.
def getRefFluxField
Get name of flux field in schema.
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
def makeMinimalSchema
Make the standard schema for reference object catalogs.