LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
loadAstrometryNetObjects.py
Go to the documentation of this file.
1 from __future__ import absolute_import, division, print_function
2 
3 import lsst.pipe.base as pipeBase
4 from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField
5 from . import astrometry_net as astromNet
6 from .multiindex import AstrometryNetCatalog, getConfigFromEnvironment
7 
8 __all__ = ["LoadAstrometryNetObjectsTask", "LoadAstrometryNetObjectsConfig"]
9 
10 LoadAstrometryNetObjectsConfig = LoadReferenceObjectsTask.ConfigClass
11 
12 # The following block adds links to this task from the Task Documentation page.
13 ## \addtogroup LSST_task_documentation
14 ## \{
15 ## \page measAstrom_loadAstrometryNetObjectsTask
16 ## \ref LoadAstrometryNetObjectsTask "LoadAstrometryNetObjectsTask"
17 ## Load reference objects from astrometry.net index files
18 ## \}
19 
20 class LoadAstrometryNetObjectsTask(LoadReferenceObjectsTask):
21  """!Load reference objects from astrometry.net index files
22 
23  @anchor LoadAstrometryNetObjectsTask_
24 
25  @section meas_astrom_loadAstrometryNetObjects_Contents Contents
26 
27  - @ref meas_astrom_loadAstrometryNetObjects_Purpose
28  - @ref meas_astrom_loadAstrometryNetObjects_Initialize
29  - @ref meas_astrom_loadAstrometryNetObjects_IO
30  - @ref meas_algorithms_loadReferenceObjects_Schema
31  - @ref meas_astrom_loadAstrometryNetObjects_Config
32  - @ref meas_astrom_loadAstrometryNetObjects_Example
33  - @ref meas_astrom_loadAstrometryNetObjects_Debug
34 
35  @section meas_astrom_loadAstrometryNetObjects_Purpose Description
36 
37  Load reference objects from astrometry.net index files.
38 
39  @section meas_astrom_loadAstrometryNetObjects_Initialize Task initialisation
40 
41  @copydoc \_\_init\_\_
42 
43  @section meas_astrom_loadAstrometryNetObjects_IO Invoking the Task
44 
45  @copydoc loadObjectsInBBox
46 
47  @section meas_astrom_loadAstrometryNetObjects_Config Configuration parameters
48 
49  See @ref LoadAstrometryNetObjectsConfig
50 
51  @section meas_astrom_loadAstrometryNetObjects_Example A complete example of using LoadAstrometryNetObjectsTask
52 
53  LoadAstrometryNetObjectsTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
54  See \ref meas_photocal_photocal_Example.
55 
56  @section meas_astrom_loadAstrometryNetObjects_Debug Debug variables
57 
58  LoadAstrometryNetObjectsTask does not support any debug variables.
59  """
60  ConfigClass = LoadAstrometryNetObjectsConfig
61 
62  def __init__(self, config, andConfig=None, **kwargs):
63  """!Create a LoadAstrometryNetObjectsTask
64 
65  @param[in] config configuration (an instance of self.ConfigClass)
66  @param[in] andConfig astrometry.net data config (an instance of AstromNetDataConfig, or None);
67  if None then use andConfig.py in the astrometry_net_data product (which must be setup)
68  @param[in] kwargs additional keyword arguments for pipe_base Task.\_\_init\_\_
69 
70  @throw RuntimeError if andConfig is None and the configuration cannot be found,
71  either because astrometry_net_data is not setup in eups
72  or because the setup version does not include the file "andConfig.py"
73  """
74  LoadReferenceObjectsTask.__init__(self, config=config, **kwargs)
75  self.andConfig = andConfig
76  self.haveIndexFiles = False # defer reading index files until we know they are needed
77  # because astrometry may not be used, in which case it may not be properly configured
78 
79  @pipeBase.timeMethod
80  def loadSkyCircle(self, ctrCoord, radius, filterName=None):
81  """!Load reference objects that overlap a circular sky region
82 
83  @param[in] ctrCoord center of search region (an afwGeom.Coord)
84  @param[in] radius radius of search region (an afwGeom.Angle)
85  @param[in] filterName name of filter, or None for the default filter;
86  used for flux values in case we have flux limits (which are not yet implemented)
87 
88  @return an lsst.pipe.base.Struct containing:
89  - refCat a catalog of reference objects with the
90  \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
91  as documented in LoadReferenceObjects, including photometric, resolved and variable;
92  hasCentroid is False for all objects.
93  - fluxField = name of flux field for specified filterName
94  """
95  self._readIndexFiles()
96 
97  names = []
98  mcols = []
99  ecols = []
100  for col, mcol in self.andConfig.magColumnMap.items():
101  names.append(col)
102  mcols.append(mcol)
103  ecols.append(self.andConfig.magErrorColumnMap.get(col, ''))
104  margs = (names, mcols, ecols)
105 
106  solver = self._getSolver()
107 
108  # Find multi-index files within range
109  multiInds = self._getMIndexesWithinRange(ctrCoord, radius)
110 
111  # compute solver.getCatalog arguments that follow the list of star kd-trees:
112  # - center equatorial angle (e.g. RA) in deg
113  # - center polar angle (e.g. Dec) in deg
114  # - radius, in deg
115  # - idColumn
116  # - (margs)
117  # - star-galaxy column
118  # - variability column
119  fixedArgTuple = (
120  ctrCoord,
121  radius,
122  self.andConfig.idColumn,
123  ) + margs + (
124  self.andConfig.starGalaxyColumn,
125  self.andConfig.variableColumn,
126  True, # eliminate duplicate IDs
127  )
128 
129  self.log.logdebug("search for objects at %s with radius %s deg" % (ctrCoord, radius.asDegrees()))
130  with LoadMultiIndexes(multiInds):
131  # We just want to pass the star kd-trees, so just pass the
132  # first element of each multi-index.
133  inds = tuple(mi[0] for mi in multiInds)
134  refCat = solver.getCatalog(inds, *fixedArgTuple)
135 
136  self._addFluxAliases(schema=refCat.schema)
137 
138  fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
139 
140  self.log.logdebug("found %d objects" % (len(refCat),))
141  return pipeBase.Struct(
142  refCat = refCat,
143  fluxField = fluxField,
144  )
145 
146  @pipeBase.timeMethod
147  def _readIndexFiles(self):
148  """!Read all astrometry.net index files, if not already read
149  """
150  if self.haveIndexFiles:
151  return
152 
153  self.log.logdebug("read index files")
154  self.haveIndexFiles = True # just try once
155 
156  if self.andConfig is None:
158 
159  self.multiInds = AstrometryNetCatalog(self.andConfig)
160 
161  def _getMIndexesWithinRange(self, ctrCoord, radius):
162  """!Get list of muti-index objects within range
163 
164  @param[in] ctrCoord center of search region (an afwGeom.Coord)
165  @param[in] radius radius of search region (an afwGeom.Angle)
166 
167  @return list of multiindex objects
168  """
169  return [mi for mi in self.multiInds if mi.isWithinRange(ctrCoord, radius)]
170 
171  def _getSolver(self):
172  solver = astromNet.solver_new()
173  # HACK, set huge default pixel scale range.
174  lo,hi = 0.01, 3600.
175  solver.setPixelScaleRange(lo, hi)
176  return solver
177 
178 
179 class LoadMultiIndexes(object):
180  """Context manager for loading and unloading astrometry.net multi-index files
181  """
182  def __init__(self, multiInds):
183  self.multiInds = multiInds
184  def __enter__(self):
185  for mi in self.multiInds:
186  mi.reload()
187  return self.multiInds
188  def __exit__(self, typ, val, trace):
189  for mi in self.multiInds:
190  mi.unload()
def _getMIndexesWithinRange
Get list of muti-index objects within range.
def getRefFluxField
Get name of flux field in schema.
Load reference objects from astrometry.net index files.
def _readIndexFiles
Read all astrometry.net index files, if not already read.
def loadSkyCircle
Load reference objects that overlap a circular sky region.