Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

from __future__ import absolute_import, division, print_function 

 

__all__ = ["LoadAstrometryNetObjectsTask", "LoadAstrometryNetObjectsConfig"] 

 

from builtins import object 

 

import lsst.pipe.base as pipeBase 

from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField 

from . import astrometry_net 

from .multiindex import AstrometryNetCatalog, getConfigFromEnvironment 

 

LoadAstrometryNetObjectsConfig = LoadReferenceObjectsTask.ConfigClass 

 

# The following block adds links to this task from the Task Documentation page. 

## \addtogroup LSST_task_documentation 

## \{ 

## \page measAstrom_loadAstrometryNetObjectsTask 

## \ref LoadAstrometryNetObjectsTask "LoadAstrometryNetObjectsTask" 

## Load reference objects from astrometry.net index files 

## \} 

 

 

class LoadAstrometryNetObjectsTask(LoadReferenceObjectsTask): 

"""!Load reference objects from astrometry.net index files 

 

@anchor LoadAstrometryNetObjectsTask_ 

 

@section meas_astrom_loadAstrometryNetObjects_Contents Contents 

 

- @ref meas_astrom_loadAstrometryNetObjects_Purpose 

- @ref meas_astrom_loadAstrometryNetObjects_Initialize 

- @ref meas_astrom_loadAstrometryNetObjects_IO 

- @ref meas_algorithms_loadReferenceObjects_Schema 

- @ref meas_astrom_loadAstrometryNetObjects_Config 

- @ref meas_astrom_loadAstrometryNetObjects_Example 

- @ref meas_astrom_loadAstrometryNetObjects_Debug 

 

@section meas_astrom_loadAstrometryNetObjects_Purpose Description 

 

Load reference objects from astrometry.net index files. 

 

@section meas_astrom_loadAstrometryNetObjects_Initialize Task initialisation 

 

@copydoc \_\_init\_\_ 

 

@section meas_astrom_loadAstrometryNetObjects_IO Invoking the Task 

 

@copydoc loadObjectsInBBox 

 

@section meas_astrom_loadAstrometryNetObjects_Config Configuration parameters 

 

See @ref LoadAstrometryNetObjectsConfig 

 

@section meas_astrom_loadAstrometryNetObjects_Example A complete example of using 

LoadAstrometryNetObjectsTask 

 

LoadAstrometryNetObjectsTask is a subtask of AstrometryTask, which is called by PhotoCalTask. 

See \ref pipe_tasks_photocal_Example. 

 

@section meas_astrom_loadAstrometryNetObjects_Debug Debug variables 

 

LoadAstrometryNetObjectsTask does not support any debug variables. 

""" 

ConfigClass = LoadAstrometryNetObjectsConfig 

 

def __init__(self, config=None, andConfig=None, **kwargs): 

"""!Create a LoadAstrometryNetObjectsTask 

 

@param[in] config configuration (an instance of self.ConfigClass); if None use self.ConfigClass() 

@param[in] andConfig astrometry.net data config (an instance of AstromNetDataConfig, or None); 

if None then use andConfig.py in the astrometry_net_data product (which must be setup) 

@param[in] kwargs additional keyword arguments for pipe_base Task.\_\_init\_\_ 

 

@throw RuntimeError if andConfig is None and the configuration cannot be found, 

either because astrometry_net_data is not setup in eups 

or because the setup version does not include the file "andConfig.py" 

""" 

LoadReferenceObjectsTask.__init__(self, config=config, **kwargs) 

self.andConfig = andConfig 

self.haveIndexFiles = False # defer reading index files until we know they are needed 

# because astrometry may not be used, in which case it may not be properly configured 

 

@pipeBase.timeMethod 

def loadSkyCircle(self, ctrCoord, radius, filterName=None, epoch=None): 

"""!Load reference objects that overlap a circular sky region 

 

@param[in] ctrCoord center of search region (an afwGeom.Coord) 

@param[in] radius radius of search region (an afwGeom.Angle) 

@param[in] filterName name of filter, or None for the default filter; 

used for flux values in case we have flux limits (which are not yet implemented) 

@param[in] epoch Epoch for proper motion and parallax correction 

(an astropy.time.Time), or None 

 

No proper motion correction is made, since our astrometry.net catalogs 

typically don't support that, and even if they do they format is uncertain. 

Users interested in proper motion corrections should use the 

lsst.meas.algorithms.LoadIndexedReferenceObjectsTask or they will need to 

subclass and define how the proper motion correction is to be done. 

 

@return an lsst.pipe.base.Struct containing: 

- refCat a catalog of reference objects with the 

\link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink 

as documented in LoadReferenceObjects, including photometric, resolved and variable; 

hasCentroid is False for all objects. 

- fluxField = name of flux field for specified filterName 

""" 

self._readIndexFiles() 

 

names = [] 

mcols = [] 

ecols = [] 

for col, mcol in self.andConfig.magColumnMap.items(): 

names.append(col) 

mcols.append(mcol) 

ecols.append(self.andConfig.magErrorColumnMap.get(col, '')) 

margs = (names, mcols, ecols) 

 

solver = self._getSolver() 

 

# Find multi-index files within range 

multiInds = self._getMIndexesWithinRange(ctrCoord, radius) 

 

# compute solver.getCatalog arguments that follow the list of star kd-trees: 

# - center equatorial angle (e.g. RA) in deg 

# - center polar angle (e.g. Dec) in deg 

# - radius, in deg 

# - idColumn 

# - (margs) 

# - star-galaxy column 

# - variability column 

fixedArgTuple = ( 

ctrCoord, 

radius, 

self.andConfig.idColumn, 

) + margs + ( 

self.andConfig.starGalaxyColumn, 

self.andConfig.variableColumn, 

True, # eliminate duplicate IDs 

) 

 

self.log.debug("search for objects at %s with radius %s deg", ctrCoord, radius.asDegrees()) 

with LoadMultiIndexes(multiInds): 

# We just want to pass the star kd-trees, so just pass the 

# first element of each multi-index. 

inds = tuple(mi[0] for mi in multiInds) 

refCat = solver.getCatalog(inds, *fixedArgTuple) 

 

self._addFluxAliases(schema=refCat.schema) 

 

fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName) 

 

# NOTE: sourceSelectors require contiguous catalogs, so ensure 

# contiguity now, so views are preserved from here on. 

if not refCat.isContiguous(): 

refCat = refCat.copy(deep=True) 

 

self.log.debug("found %d objects", len(refCat)) 

return pipeBase.Struct( 

refCat=refCat, 

fluxField=fluxField, 

) 

 

@pipeBase.timeMethod 

def _readIndexFiles(self): 

"""!Read all astrometry.net index files, if not already read 

""" 

if self.haveIndexFiles: 

return 

 

self.log.debug("read index files") 

self.haveIndexFiles = True # just try once 

 

if self.andConfig is None: 

self.andConfig = getConfigFromEnvironment() 

 

self.multiInds = AstrometryNetCatalog(self.andConfig) 

 

def _getMIndexesWithinRange(self, ctrCoord, radius): 

"""!Get list of muti-index objects within range 

 

@param[in] ctrCoord center of search region (an afwGeom.Coord) 

@param[in] radius radius of search region (an afwGeom.Angle) 

 

@return list of multiindex objects 

""" 

return [mi for mi in self.multiInds if mi.isWithinRange(ctrCoord, radius)] 

 

def _getSolver(self): 

solver = astrometry_net.Solver() 

# HACK, set huge default pixel scale range. 

lo, hi = 0.01, 3600. 

solver.setPixelScaleRange(lo, hi) 

return solver 

 

 

class LoadMultiIndexes(object): 

"""Context manager for loading and unloading astrometry.net multi-index files 

""" 

 

def __init__(self, multiInds): 

self.multiInds = multiInds 

 

def __enter__(self): 

for mi in self.multiInds: 

mi.reload() 

return self.multiInds 

 

def __exit__(self, typ, val, trace): 

for mi in self.multiInds: 

mi.unload()