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