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*A first pass square search of SDSS using the conesearch radius as the diameter of the (on sky) square* 

5 

6:Author: 

7 David Young 

8 

9:Date Created: 

10 December 2, 2014 

11 

12.. todo:: 

13  

14""" 

15from __future__ import print_function 

16################# GLOBAL IMPORTS #################### 

17from future import standard_library 

18standard_library.install_aliases() 

19from builtins import object 

20import sys 

21import os 

22import re 

23import readline 

24import glob 

25import urllib.request 

26import urllib.parse 

27import urllib.error 

28import string 

29import json 

30from docopt import docopt 

31from fundamentals import tools, times 

32from astrocalc.coords import unit_conversion, separations, translate 

33 

34################################################################### 

35# CLASSES # 

36################################################################### 

37 

38 

39class sdss_square_search(object): 

40 

41 """ 

42 *The worker class for the sdss_square_search module* 

43 

44 **Key Arguments:** 

45 ``log`` -- logger 

46 - ``ra`` -- ra in sexigesimal or decimal degrees 

47 - ``dec`` -- dec in sexigesimal or decimal degrees 

48 - ``searchRadius`` -- search radius in arcsecs 

49 

50 .. todo:: 

51 

52 """ 

53 # Initialisation 

54 

55 def __init__( 

56 self, 

57 log, 

58 ra, 

59 dec, 

60 searchRadius, 

61 galaxyType=False 

62 ): 

63 self.log = log 

64 log.debug("instansiating a new 'sdss_square_search' object") 

65 self.ra = ra 

66 self.dec = dec 

67 self.searchRadius = searchRadius 

68 self.galaxyType = galaxyType 

69 # xt-self-arg-tmpx 

70 

71 # Variable Data Atrributes 

72 self.sdssUrl = 'http://skyserver.sdss3.org/public/en/tools/search/x_sql.aspx' 

73 

74 # Initial Actions 

75 # convert ra and dec to decimal degrees (if required) 

76 converter = unit_conversion( 

77 log=log 

78 ) 

79 self.ra = float(converter.ra_sexegesimal_to_decimal( 

80 ra=self.ra 

81 )) 

82 self.dec = float(converter.dec_sexegesimal_to_decimal( 

83 dec=self.dec 

84 )) 

85 

86 self._calculate_search_limits() 

87 self._build_sql_query() 

88 

89 return None 

90 

91 def close(self): 

92 del self 

93 return None 

94 

95 # Method Attributes 

96 def get(self): 

97 """ 

98 *get the results from the the sdss square search* 

99 

100 **Return:** 

101 - ``sdss_square_search`` 

102 

103 .. todo:: 

104 

105 """ 

106 self.log.debug('starting the ``get`` method') 

107 

108 self._execute_sql_query() 

109 self._append_separations_to_results() 

110 self._generate_sdss_object_name() 

111 

112 self.log.debug('completed the ``get`` method') 

113 return self.results 

114 

115 def _calculate_search_limits( 

116 self): 

117 """ 

118 *calculate search limits for the square search* 

119 

120 **Key Arguments:** 

121 # - 

122 

123 **Return:** 

124 - None 

125 

126 .. todo:: 

127 

128 """ 

129 self.log.debug('starting the ``_calculate_search_limits`` method') 

130 

131 # TRANSLATE COORDINATES ACROSS SKY 

132 

133 self.ra1, self.dec1 = translate( 

134 log=self.log, 

135 ra=self.ra, 

136 dec=self.dec, 

137 northArcsec=-self.searchRadius, 

138 eastArcsec=-self.searchRadius 

139 ).get() 

140 

141 self.ra2, self.dec2 = translate( 

142 log=self.log, 

143 ra=self.ra, 

144 dec=self.dec, 

145 northArcsec=self.searchRadius, 

146 eastArcsec=self.searchRadius 

147 ).get() 

148 

149 self.log.debug('completed the ``_calculate_search_limits`` method') 

150 return 

151 

152 def _build_sql_query( 

153 self): 

154 """ 

155 *build sql query for the sdss square search* 

156 

157 **Key Arguments:** 

158 # - 

159 

160 **Return:** 

161 - None 

162 

163 .. todo:: 

164 

165 """ 

166 self.log.debug('starting the ``_build_sql_query`` method') 

167 

168 ra1, ra2, dec1, dec2 = self.ra1, self.ra2, self.dec1, self.dec2 

169 

170 if self.galaxyType == "all": 

171 self.sqlQuery = u""" 

172 SELECT p.objiD, p.ra, p.dec, s.z as specz, s.zerr as specz_err, z.z as photoz, z.zerr as photoz_err, p.type 

173 FROM PhotoObjAll p 

174 LEFT JOIN SpecObjAll AS s ON s.bestobjid = p.objid 

175 LEFT JOIN Photoz AS z ON z.objid = p.objid  

176 WHERE (p.ra between %(ra1)s and %(ra2)s) and (p.dec between %(dec1)s and %(dec2)s) and p.clean = 1 and p.type = 3 

177 """ % locals() 

178 elif self.galaxyType == "specz": 

179 self.sqlQuery = u""" 

180 SELECT p.objiD, p.ra, p.dec, s.z as specz, s.zerr as specz_err, p.type 

181 FROM PhotoObjAll p, SpecObjAll s 

182 WHERE (s.bestobjid = p.objid) and (p.ra between %(ra1)s and %(ra2)s) and (p.dec between %(dec1)s and %(dec2)s) and p.type = 3 

183 """ % locals() 

184 elif self.galaxyType == "photoz": 

185 self.sqlQuery = u""" 

186 SELECT p.objiD, p.ra, p.dec, z.z as photoz, z.zerr as photoz_err, p.type 

187 FROM PhotoObjAll p, Photoz z 

188 WHERE (z.objid = p.objid) and (p.ra between %(ra1)s and %(ra2)s) and (p.dec between %(dec1)s and %(dec2)s) and p.clean = 1 and p.type = 3 

189 """ % locals() 

190 elif self.galaxyType == False or not self.galaxyType: 

191 self.sqlQuery = u""" 

192 SELECT p.objiD, p.ra, p.dec, s.z as specz, s.zerr as specz_err, z.z as photoz, z.zerr as photoz_err, p.type 

193 FROM PhotoObjAll p 

194 LEFT JOIN SpecObjAll AS s ON s.bestobjid = p.objid 

195 LEFT JOIN Photoz AS z ON z.objid = p.objid  

196 WHERE (p.ra between %(ra1)s and %(ra2)s) and (p.dec between %(dec1)s and %(dec2)s) and p.clean = 1 and (p.type = 3 or p.type = 6) 

197 """ % locals() 

198 

199 self.sqlQuery = self.sqlQuery.strip() 

200 

201 self.log.debug('completed the ``_build_sql_query`` method') 

202 return None 

203 

204 def _execute_sql_query( 

205 self): 

206 """ 

207 *execute sql query using the sdss API* 

208 

209 **Key Arguments:** 

210 # - 

211 

212 **Return:** 

213 - None 

214 

215 .. todo:: 

216 

217 """ 

218 self.log.debug('starting the ``_execute_sql_query`` method') 

219 

220 # generate the api call url 

221 params = urllib.parse.urlencode( 

222 {'cmd': self.sqlQuery, 'format': "json"}) 

223 # grab the results 

224 results = urllib.request.urlopen(self.sdssUrl + '?%s' % params) 

225 

226 # report any errors 

227 ofp = sys.stdout 

228 results = results.read() 

229 if str(results).startswith("ERROR"): # SQL Statement Error -> stderr 

230 ofp = sys.stderr 

231 ofp.write(string.rstrip(line) + os.linesep) 

232 

233 # clean up the json response so it can be parsed 

234 try: 

235 # PYTHON 3 

236 # parse the json results 

237 results = json.loads(results)[0] 

238 except: 

239 # PYTHON 2 

240 results = results.replace( 

241 ": ,", ': "NULL",') 

242 regex = re.compile(r'"photoz_err"\:\s*(\n\s*})') 

243 newString = regex.sub('"photoz_err": "NULL"\g<1>', results) 

244 results = newString 

245 # parse the json results 

246 results = json.loads(results)[0] 

247 self.results = results["Rows"] 

248 

249 self.log.debug('completed the ``_execute_sql_query`` method') 

250 return 

251 

252 def _append_separations_to_results( 

253 self): 

254 """ 

255 *append angular separations to results* 

256 

257 **Key Arguments:** 

258 # - 

259 

260 **Return:** 

261 - None 

262 

263 .. todo:: 

264 

265 """ 

266 self.log.debug( 

267 'starting the ``_append_separations_to_results`` method') 

268 

269 for row in self.results: 

270 if "ra" not in row: 

271 print(row) 

272 exit(0) 

273 

274 # CALCULATE SEPARATION IN ARCSEC 

275 calculator = separations( 

276 log=self.log, 

277 ra1=self.ra, 

278 dec1=self.dec, 

279 ra2=row["ra"], 

280 dec2=row["dec"], 

281 ) 

282 angularSeparation, northSep, eastSep = calculator.get() 

283 

284 row["separation_arcsec"] = angularSeparation 

285 row["separation_north_arcsec"] = northSep 

286 row["separation_east_arcsec"] = eastSep 

287 

288 self.log.debug( 

289 'completed the ``_append_separations_to_results`` method') 

290 return None 

291 

292 def _generate_sdss_object_name( 

293 self): 

294 """ 

295 *generate sdss object names for the results* 

296 

297 **Key Arguments:** 

298 # - 

299 

300 **Return:** 

301 - None 

302 

303 .. todo:: 

304 

305 """ 

306 self.log.debug('starting the ``_generate_sdss_object_name`` method') 

307 

308 converter = unit_conversion( 

309 log=self.log 

310 ) 

311 

312 # Names should be of the format `SDSS JHHMMSS.ss+DDMMSS.s` 

313 # where the coordinates are truncated, not rounded. 

314 for row in self.results: 

315 

316 raSex = converter.ra_decimal_to_sexegesimal( 

317 ra=row["ra"], 

318 delimiter=":" 

319 ) 

320 decSex = converter.dec_decimal_to_sexegesimal( 

321 dec=row["dec"], 

322 delimiter=":" 

323 ) 

324 raSex = raSex.replace(":", "")[:9] 

325 decSex = decSex.replace(":", "")[:9] 

326 sdssName = "SDSS J%(raSex)s%(decSex)s" % locals() 

327 row["sdss_name"] = sdssName 

328 

329 wordType = ["unknown", "cosmic_ray", "defect", "galaxy", 

330 "ghost", "knownobj", "star", "trail", "sky", "notatype", ] 

331 numberType = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

332 row["type"] = wordType[row["type"]] 

333 

334 self.log.debug('completed the ``_generate_sdss_object_name`` method') 

335 return None 

336 

337 # use the tab-trigger below for new method 

338 # xt-class-method 

339 

340 

341if __name__ == '__main__': 

342 main()