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