LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
loadAstrometryNetObjects.py
Go to the documentation of this file.
1 from __future__ import absolute_import, division, print_function
2 from builtins import object
3 
4 import lsst.pipe.base as pipeBase
5 from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField
6 from . import astrometry_net as astromNet
7 from .multiindex import AstrometryNetCatalog, getConfigFromEnvironment
8 
9 __all__ = ["LoadAstrometryNetObjectsTask", "LoadAstrometryNetObjectsConfig"]
10 
11 LoadAstrometryNetObjectsConfig = LoadReferenceObjectsTask.ConfigClass
12 
13 # The following block adds links to this task from the Task Documentation page.
14 ## \addtogroup LSST_task_documentation
15 ## \{
16 ## \page measAstrom_loadAstrometryNetObjectsTask
17 ## \ref LoadAstrometryNetObjectsTask "LoadAstrometryNetObjectsTask"
18 ## Load reference objects from astrometry.net index files
19 ## \}
20 
21 
22 class LoadAstrometryNetObjectsTask(LoadReferenceObjectsTask):
23  """!Load reference objects from astrometry.net index files
24 
25  @anchor LoadAstrometryNetObjectsTask_
26 
27  @section meas_astrom_loadAstrometryNetObjects_Contents Contents
28 
29  - @ref meas_astrom_loadAstrometryNetObjects_Purpose
30  - @ref meas_astrom_loadAstrometryNetObjects_Initialize
31  - @ref meas_astrom_loadAstrometryNetObjects_IO
32  - @ref meas_algorithms_loadReferenceObjects_Schema
33  - @ref meas_astrom_loadAstrometryNetObjects_Config
34  - @ref meas_astrom_loadAstrometryNetObjects_Example
35  - @ref meas_astrom_loadAstrometryNetObjects_Debug
36 
37  @section meas_astrom_loadAstrometryNetObjects_Purpose Description
38 
39  Load reference objects from astrometry.net index files.
40 
41  @section meas_astrom_loadAstrometryNetObjects_Initialize Task initialisation
42 
43  @copydoc \_\_init\_\_
44 
45  @section meas_astrom_loadAstrometryNetObjects_IO Invoking the Task
46 
47  @copydoc loadObjectsInBBox
48 
49  @section meas_astrom_loadAstrometryNetObjects_Config Configuration parameters
50 
51  See @ref LoadAstrometryNetObjectsConfig
52 
53  @section meas_astrom_loadAstrometryNetObjects_Example A complete example of using
54  LoadAstrometryNetObjectsTask
55 
56  LoadAstrometryNetObjectsTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
57  See \ref meas_photocal_photocal_Example.
58 
59  @section meas_astrom_loadAstrometryNetObjects_Debug Debug variables
60 
61  LoadAstrometryNetObjectsTask does not support any debug variables.
62  """
63  ConfigClass = LoadAstrometryNetObjectsConfig
64 
65  def __init__(self, config=None, andConfig=None, **kwargs):
66  """!Create a LoadAstrometryNetObjectsTask
67 
68  @param[in] config configuration (an instance of self.ConfigClass); if None use self.ConfigClass()
69  @param[in] andConfig astrometry.net data config (an instance of AstromNetDataConfig, or None);
70  if None then use andConfig.py in the astrometry_net_data product (which must be setup)
71  @param[in] kwargs additional keyword arguments for pipe_base Task.\_\_init\_\_
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.debug("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.debug("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.debug("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 
186  def __init__(self, multiInds):
187  self.multiInds = multiInds
188 
189  def __enter__(self):
190  for mi in self.multiInds:
191  mi.reload()
192  return self.multiInds
193 
194  def __exit__(self, typ, val, trace):
195  for mi in self.multiInds:
196  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.