LSSTApplications  17.0+103,17.0+11,17.0+61,18.0.0+13,18.0.0+25,18.0.0+5,18.0.0+52,18.0.0-4-g68ffd23,18.1.0-1-g0001055+8,18.1.0-1-g03d53ef+1,18.1.0-1-g1349e88+28,18.1.0-1-g2505f39+22,18.1.0-1-g380d4d4+27,18.1.0-1-g5315e5e+1,18.1.0-1-g5e4b7ea+10,18.1.0-1-g7e8fceb+1,18.1.0-1-g85f8cd4+23,18.1.0-1-g9a6769a+13,18.1.0-1-ga1a4c1a+22,18.1.0-1-gd55f500+17,18.1.0-12-g42eabe8e+10,18.1.0-14-gd04256d+15,18.1.0-16-g430f6a53+1,18.1.0-17-gd2166b6e4,18.1.0-18-gb5d19ff+1,18.1.0-2-gfbf3545+7,18.1.0-2-gfefb8b5+16,18.1.0-3-g52aa583+13,18.1.0-3-g62b5e86+14,18.1.0-3-g8f4a2b1+17,18.1.0-3-g9bc06b8+7,18.1.0-3-gb69f684+9,18.1.0-4-g1ee41a7+1,18.1.0-5-g6dbcb01+13,18.1.0-5-gc286bb7+3,18.1.0-6-g48bdcd3+2,18.1.0-6-gd05e160+9,18.1.0-7-gc4d902b+2,18.1.0-7-gebc0338+8,18.1.0-9-gae7190a+10,w.2019.38
LSSTDataManagementBasePackage
loadAstrometryNetObjects.py
Go to the documentation of this file.
1 __all__ = ["LoadAstrometryNetObjectsTask", "LoadAstrometryNetObjectsConfig"]
2 
3 import lsst.pipe.base as pipeBase
4 from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField
5 from lsst.meas.algorithms.loadReferenceObjects import convertToNanojansky
6 from . import astrometry_net
7 from .multiindex import AstrometryNetCatalog, getConfigFromEnvironment
8 
9 LoadAstrometryNetObjectsConfig = LoadReferenceObjectsTask.ConfigClass
10 
11 # The following block adds links to this task from the Task Documentation page.
12 
18 
19 
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
52  LoadAstrometryNetObjectsTask
53 
54  LoadAstrometryNetObjectsTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
55  See \ref pipe_tasks_photocal_Example.
56 
57  @section meas_astrom_loadAstrometryNetObjects_Debug Debug variables
58 
59  LoadAstrometryNetObjectsTask does not support any debug variables.
60  """
61  ConfigClass = LoadAstrometryNetObjectsConfig
62 
63  def __init__(self, config=None, andConfig=None, **kwargs):
64  """!Create a LoadAstrometryNetObjectsTask
65 
66  @param[in] config configuration (an instance of self.ConfigClass); if None use self.ConfigClass()
67  @param[in] andConfig astrometry.net data config (an instance of AstromNetDataConfig, or None);
68  if None then use andConfig.py in the astrometry_net_data product (which must be setup)
69  @param[in] kwargs additional keyword arguments for pipe_base Task.\_\_init\_\_
70 
71  @throw RuntimeError if andConfig is None and the configuration cannot be found,
72  either because astrometry_net_data is not setup in eups
73  or because the setup version does not include the file "andConfig.py"
74  """
75  LoadReferenceObjectsTask.__init__(self, config=config, **kwargs)
76  self.andConfig = andConfig
77  self.haveIndexFiles = False # defer reading index files until we know they are needed
78  # because astrometry may not be used, in which case it may not be properly configured
79 
80  @pipeBase.timeMethod
81  def loadSkyCircle(self, ctrCoord, radius, filterName=None, epoch=None, centroids=True):
82  """!Load reference objects that overlap a circular sky region
83 
84  @param[in] ctrCoord center of search region (an afwGeom.Coord)
85  @param[in] radius radius of search region (an geom.Angle)
86  @param[in] filterName name of filter, or None for the default filter;
87  used for flux values in case we have flux limits (which are not yet implemented)
88  @param[in] epoch Epoch for proper motion and parallax correction
89  (an astropy.time.Time), or None
90  centroids : `bool` (optional)
91  Ignored: a.net refcats always have centroid fields.
92 
93  No proper motion correction is made, since our astrometry.net catalogs
94  typically don't support that, and even if they do they format is uncertain.
95  Users interested in proper motion corrections should use the
96  lsst.meas.algorithms.LoadIndexedReferenceObjectsTask or they will need to
97  subclass and define how the proper motion correction is to be done.
98 
99  @return an lsst.pipe.base.Struct containing:
100  - refCat a catalog of reference objects with the
101  \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
102  as documented in LoadReferenceObjects, including photometric, resolved and variable;
103  hasCentroid is False for all objects.
104  - fluxField = name of flux field for specified filterName
105  """
106  self._readIndexFiles()
107 
108  names = []
109  mcols = []
110  ecols = []
111  for col, mcol in self.andConfig.magColumnMap.items():
112  names.append(col)
113  mcols.append(mcol)
114  ecols.append(self.andConfig.magErrorColumnMap.get(col, ''))
115  margs = (names, mcols, ecols)
116 
117  solver = self._getSolver()
118 
119  # Find multi-index files within range
120  multiInds = self._getMIndexesWithinRange(ctrCoord, radius)
121 
122  # compute solver.getCatalog arguments that follow the list of star kd-trees:
123  # - center equatorial angle (e.g. RA) in deg
124  # - center polar angle (e.g. Dec) in deg
125  # - radius, in deg
126  # - idColumn
127  # - (margs)
128  # - star-galaxy column
129  # - variability column
130  fixedArgTuple = (
131  ctrCoord,
132  radius,
133  self.andConfig.idColumn,
134  ) + margs + (
135  self.andConfig.starGalaxyColumn,
136  self.andConfig.variableColumn,
137  True, # eliminate duplicate IDs
138  )
139 
140  self.log.debug("search for objects at %s with radius %s deg", ctrCoord, radius.asDegrees())
141  with LoadMultiIndexes(multiInds):
142  # We just want to pass the star kd-trees, so just pass the
143  # first element of each multi-index.
144  inds = tuple(mi[0] for mi in multiInds)
145  refCat = solver.getCatalog(inds, *fixedArgTuple)
146 
147  self._addFluxAliases(schema=refCat.schema)
148 
149  fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
150 
151  # NOTE: sourceSelectors require contiguous catalogs, so ensure
152  # contiguity now, so views are preserved from here on.
153  if not refCat.isContiguous():
154  refCat = refCat.copy(deep=True)
155 
156  # Update flux fields to be nJy. a.net catalogs do not have a conversion script.
157  self.log.warn("Loading A.net reference catalog with old style units in schema.")
158  self.log.warn("A.net reference catalogs will not be supported in the future.")
159  self.log.warn("See RFC-562 and RFC-575 for more details.")
160  refCat = convertToNanojansky(refCat, self.log)
161 
162  self.log.debug("found %d objects", len(refCat))
163  return pipeBase.Struct(
164  refCat=refCat,
165  fluxField=fluxField,
166  )
167 
168  @pipeBase.timeMethod
169  def _readIndexFiles(self):
170  """!Read all astrometry.net index files, if not already read
171  """
172  if self.haveIndexFiles:
173  return
174 
175  self.log.debug("read index files")
176  self.haveIndexFiles = True # just try once
177 
178  if self.andConfig is None:
180 
182 
183  def _getMIndexesWithinRange(self, ctrCoord, radius):
184  """!Get list of muti-index objects within range
185 
186  @param[in] ctrCoord center of search region (an afwGeom.Coord)
187  @param[in] radius radius of search region (an geom.Angle)
188 
189  @return list of multiindex objects
190  """
191  return [mi for mi in self.multiInds if mi.isWithinRange(ctrCoord, radius)]
192 
193  def _getSolver(self):
194  solver = astrometry_net.Solver()
195  # HACK, set huge default pixel scale range.
196  lo, hi = 0.01, 3600.
197  solver.setPixelScaleRange(lo, hi)
198  return solver
199 
200 
202  """Context manager for loading and unloading astrometry.net multi-index files
203  """
204 
205  def __init__(self, multiInds):
206  self.multiInds = multiInds
207 
208  def __enter__(self):
209  for mi in self.multiInds:
210  mi.reload()
211  return self.multiInds
212 
213  def __exit__(self, typ, val, trace):
214  for mi in self.multiInds:
215  mi.unload()
def _readIndexFiles(self)
Read all astrometry.net index files, if not already read.
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
def convertToNanojansky(catalog, log, doConvert=True)
def _getMIndexesWithinRange(self, ctrCoord, radius)
Get list of muti-index objects within range.
Abstract base class to load objects from reference catalogs.
def loadSkyCircle(self, ctrCoord, radius, filterName=None, epoch=None, centroids=True)
Load reference objects that overlap a circular sky region.
def __init__(self, config=None, andConfig=None, kwargs)
Create a LoadAstrometryNetObjectsTask.