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#!/usr/local/bin/python 

2# encoding: utf-8 

3""" 

4*perform a conesearch on a **single** sherlock crossmatch catalogue table* 

5 

6:Author: 

7 David Young 

8 

9:noindex: 

10""" 

11from builtins import zip 

12from builtins import object 

13import sys 

14import os 

15os.environ['TERM'] = 'vt100' 

16from fundamentals import tools 

17from astrocalc.coords import unit_conversion 

18from HMpTy.mysql import conesearch as hmptyConesearch 

19import copy 

20 

21 

22class catalogue_conesearch(object): 

23 """ 

24 *The worker class for the conesearch module* 

25 

26 **Key Arguments** 

27 

28 - ``dbConn`` -- mysql database connection to the catalogues database 

29 - ``log`` -- logger 

30 - ``ra`` -- ra of transient location (sexegesimal or decimal degrees, J2000, single location or list of locations) 

31 - ``dec`` -- dec of transient location (sexegesimal or decimal degrees, J2000, single location or list of locations) 

32 - ``tableName`` -- the name of the database table to perform the conesearch on 

33 - ``radius`` -- radius of the conesearch to perform (arcsec) 

34 - ``colMaps`` -- maps of the important column names for each table/view in the crossmatch-catalogues database 

35 - ``nearestOnly`` -- return only the nearest object. Default *False* 

36 - ``physicalSearch`` -- is this a physical search, so only return matches with distance information. Default *False* 

37 - ``upperMagnitudeLimit`` -- the upper magnitude limit if a magnitude cut is requird with the conesearch. Default *False* 

38 

39 

40 - ``lowerMagnitudeLimit`` -- the lower magnitude limit if a magnitude cut is requird with the conesearch. Default *False* 

41 - ``magnitudeLimitFilter`` -- the filter to use for the magnitude limit if requird. Default *False*, ("_u"|"_g"|"_r"|"_i"|"_z"|"_y"|"U"|"B"|"V"|"R"|"I"|"Z"|"J"|"H"|"K"|"G") 

42 

43 **Usage** 

44 

45 To setup your logger, settings and database connections, please use the ``fundamentals`` package (`see tutorial here <http://fundamentals.readthedocs.io/en/latest/#tutorial>`_).  

46 

47 .. todo:: 

48 

49 - update the package tutorial if needed 

50 

51 The following examples assume you've connected to the various databases and generated the catalogue column maps in the following menner: 

52 

53 ```python 

54 # SETUP ALL DATABASE CONNECTIONS 

55 from sherlock import database 

56 db = database( 

57 log=log, 

58 settings=settings 

59 ) 

60 dbConns, dbVersions = db.connect() 

61 transientsDbConn = dbConns["transients"] 

62 cataloguesDbConn = dbConns["catalogues"] 

63 

64 # GET THE COLUMN MAPS FROM THE CATALOGUE DATABASE 

65 from sherlock.commonutils import get_crossmatch_catalogues_column_map 

66 colMaps = get_crossmatch_catalogues_column_map( 

67 log=log, 

68 dbConn=cataloguesDbConn 

69 ) 

70 ``` 

71 

72 To perform a single location conesearch on a catalogue in the database, for example the milliquas AGN catalogue: 

73 

74 ```python 

75 from sherlock import catalogue_conesearch 

76 cs = catalogue_conesearch( 

77 log=log, 

78 ra="23:01:07.99", 

79 dec="-01:58:04.5", 

80 radiusArcsec=60., 

81 colMaps=colMaps, 

82 tableName="tcs_view_agn_milliquas_v4_5", 

83 dbConn=cataloguesDbConn, 

84 nearestOnly=False, 

85 physicalSearch=False 

86 ) 

87 # catalogueMatches ARE ORDERED BY ANGULAR SEPARATION 

88 indices, catalogueMatches = cs.search() 

89 

90 print(catalogueMatches) 

91 ``` 

92 

93 The output of this search is: 

94 

95 ```text 

96 [{'R': 20.1, 'cmSepArcsec': 0.28015184686564643, 'ra': 345.2832267, 'catalogue_object_subtype': u'QR', 'z': 0.777, 'dec': -1.9679629, 'catalogue_object_id': u'PKS 2258-022'}]  

97 ``` 

98 

99 Note ``catalogue_conesearch`` can accept coordinates in sexegesimal or decimal degrees (J200). It can also accept lists of corrdinates: 

100 

101 ```python 

102 from sherlock import catalogue_conesearch 

103 cs = catalogue_conesearch( 

104 log=log, 

105 ra=["23:01:07.99", 45.36722, 13.875250], 

106 dec=["-01:58:04.5", 30.45671, -25.26721], 

107 radiusArcsec=60., 

108 

109 

110 colMaps=colMaps, 

111 tableName="tcs_view_agn_milliquas_v4_5", 

112 dbConn=cataloguesDbConn, 

113 nearestOnly=False, 

114 physicalSearch=False 

115 ) 

116 ``` 

117 

118 When passing a list of transient coordinates the returned ``indices`` value becomes important as this list identifies which transient is matched with which crossmatch results (and possibly multiple crossmatch results) 

119 

120 ```python 

121 indices, catalogueMatches = cs.search() 

122 for i, c in zip(indices, catalogueMatches): 

123 print(i, c) 

124 ``` 

125 

126 The output of this search is: 

127 

128 ```text 

129 0 {'R': 20.1, 'cmSepArcsec': 0.28015184686564643, 'ra': 345.2832267, 'catalogue_object_subtype': u'QR', 'z': 0.777, 'dec': -1.9679629, 'catalogue_object_id': u'PKS 2258-022'} 

130 2 {'R': 19.2, 'cmSepArcsec': 0.81509715903447644, 'ra': 13.875, 'catalogue_object_subtype': u'Q', 'z': 2.7, 'dec': -25.2672223, 'catalogue_object_id': u'Q 0053-2532'} 

131 ``` 

132 

133 .. todo :: 

134 

135 - update key arguments values and definitions with defaults 

136 - update return values and definitions 

137 - update usage examples and text 

138 - update docstring text 

139 - check sublime snippet exists 

140 - clip any useful text to docs mindmap 

141 - regenerate the docs and check redendering of this docstring 

142 """ 

143 # Initialisation 

144 

145 def __init__( 

146 self, 

147 log, 

148 ra, 

149 dec, 

150 tableName, 

151 radiusArcsec, 

152 colMaps, 

153 dbConn=False, 

154 nearestOnly=False, 

155 physicalSearch=False, 

156 upperMagnitudeLimit=False, 

157 lowerMagnitudeLimit=False, 

158 magnitudeLimitFilter=False 

159 ): 

160 self.log = log 

161 log.debug("instansiating a new 'conesearcher' object") 

162 self.dbConn = dbConn 

163 self.radius = radiusArcsec 

164 self.tableName = tableName 

165 self.nearestOnly = nearestOnly 

166 self.colMaps = colMaps 

167 self.physicalSearch = physicalSearch 

168 self.upperMagnitudeLimit = upperMagnitudeLimit 

169 self.lowerMagnitudeLimit = lowerMagnitudeLimit 

170 self.magnitudeLimitFilter = magnitudeLimitFilter 

171 # xt-self-arg-tmpx 

172 

173 # CONVERT RA AND DEC TO DEGREES 

174 if not isinstance(ra, list): 

175 ra = [ra] 

176 dec = [dec] 

177 

178 self.ra = [] 

179 self.dec = [] 

180 

181 converter = unit_conversion( 

182 log=self.log 

183 ) 

184 

185 try: 

186 float(ra[0]) 

187 convert = False 

188 except: 

189 convert = True 

190 

191 if convert == True: 

192 

193 for r, d in zip(ra, dec): 

194 self.ra.append(converter.ra_sexegesimal_to_decimal( 

195 ra=r 

196 )) 

197 self.dec.append(converter.dec_sexegesimal_to_decimal( 

198 dec=d 

199 )) 

200 else: 

201 self.ra = ra 

202 self.dec = dec 

203 

204 return None 

205 

206 def search(self): 

207 """ 

208 *trigger the conesearch* 

209 

210 **Return** 

211 

212 - ``matchIndies`` -- the indicies of the input transient sources (syncs with ``uniqueMatchDicts``) 

213 - ``uniqueMatchDicts`` -- the crossmatch results 

214 

215 

216 **Usage** 

217 

218 See class docstring for usage examples 

219 

220 

221 .. todo :: 

222 

223 - update key arguments values and definitions with defaults 

224 - update return values and definitions 

225 - update usage examples and text 

226 - update docstring text 

227 - check sublime snippet exists 

228 - clip any useful text to docs mindmap 

229 - regenerate the docs and check redendering of this docstring 

230 """ 

231 self.log.debug('starting the ``search`` method') 

232 

233 # ACCOUNT FOR TYPE OF SEARCH 

234 sqlWhere = False 

235 magnitudeLimitFilter = self.magnitudeLimitFilter 

236 disCols = ["zColName", 

237 "distanceColName", "semiMajorColName"] 

238 sqlWhere = "" 

239 

240 if self.physicalSearch == True: 

241 for d in disCols: 

242 colName = self.colMaps[self.tableName][d] 

243 if colName: 

244 sqlWhere += " or `%(colName)s` is not null" % locals() 

245 if len(sqlWhere): 

246 sqlWhere = " and (" + sqlWhere[4:] + ")" 

247 

248 if self.upperMagnitudeLimit != False and self.upperMagnitudeLimit and not self.lowerMagnitudeLimit: 

249 mag = self.upperMagnitudeLimit 

250 sqlWhere += " and `%(magnitudeLimitFilter)s` > %(mag)s" % locals() 

251 if self.lowerMagnitudeLimit != False and self.lowerMagnitudeLimit and not self.upperMagnitudeLimit: 

252 mag = self.lowerMagnitudeLimit 

253 sqlWhere += " and `%(magnitudeLimitFilter)s` < %(mag)s" % locals() 

254 # THE GENERAL (INBETWEEN) CASE 

255 if self.lowerMagnitudeLimit != False and self.lowerMagnitudeLimit and self.upperMagnitudeLimit != False and self.upperMagnitudeLimit: 

256 upperMagnitudeLimit = self.upperMagnitudeLimit 

257 lowerMagnitudeLimit = self.lowerMagnitudeLimit 

258 sqlWhere += " and ((`%(magnitudeLimitFilter)s` > %(upperMagnitudeLimit)s and `%(magnitudeLimitFilter)s` < %(lowerMagnitudeLimit)s))" % locals() 

259 

260 if sqlWhere and " and" == sqlWhere[0:4]: 

261 sqlWhere = sqlWhere[5:] 

262 

263 # THE COLUMN MAP LIFTED FROM ``tcs_helper_catalogue_tables_info` TABLE 

264 # IN CATALOGUE DATABASE (COLUMN NAMES ENDDING WITH 'ColName') 

265 columns = {} 

266 for k, v in list(self.colMaps[self.tableName].items()): 

267 name = k.replace("ColName", "") 

268 if "colname" in k.lower() and v: 

269 columns[k] = "`%(v)s` as `%(name)s`" % locals() 

270 columns = ", ".join(list(columns.values())) 

271 

272 cs = hmptyConesearch( 

273 log=self.log, 

274 dbConn=self.dbConn, 

275 tableName=self.tableName, 

276 columns=columns, 

277 ra=self.ra, 

278 dec=self.dec, 

279 radiusArcsec=self.radius, 

280 separations=True, 

281 distinct=False, 

282 sqlWhere=sqlWhere, 

283 closest=self.nearestOnly, 

284 raCol="ra", 

285 decCol="dec" 

286 ) 

287 matchIndies, matches = cs.search() 

288 

289 # MATCH ARE NOT NECESSARILY UNIQUE IF MANY TRANSIENT MATCH ONE SOURCE 

290 uniqueMatchDicts = [] 

291 uniqueMatchDicts[:] = [copy.copy(d) for d in matches.list] 

292 

293 self.log.debug('completed the ``search`` method') 

294 return matchIndies, uniqueMatchDicts 

295 

296 # xt-class-method