Coverage for sloancone/sdss_square_search.py : 73%

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*
6:Author:
7 David Young
9:Date Created:
10 December 2, 2014
12.. todo::
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
34###################################################################
35# CLASSES #
36###################################################################
39class sdss_square_search(object):
41 """
42 *The worker class for the sdss_square_search module*
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
50 .. todo::
52 """
53 # Initialisation
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
71 # Variable Data Atrributes
72 self.sdssUrl = 'http://skyserver.sdss3.org/public/en/tools/search/x_sql.aspx'
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 ))
86 self._calculate_search_limits()
87 self._build_sql_query()
89 return None
91 def close(self):
92 del self
93 return None
95 # Method Attributes
96 def get(self):
97 """
98 *get the results from the the sdss square search*
100 **Return:**
101 - ``sdss_square_search``
103 .. todo::
105 """
106 self.log.debug('starting the ``get`` method')
108 self._execute_sql_query()
109 self._append_separations_to_results()
110 self._generate_sdss_object_name()
112 self.log.debug('completed the ``get`` method')
113 return self.results
115 def _calculate_search_limits(
116 self):
117 """
118 *calculate search limits for the square search*
120 **Key Arguments:**
121 # -
123 **Return:**
124 - None
126 .. todo::
128 """
129 self.log.debug('starting the ``_calculate_search_limits`` method')
131 # TRANSLATE COORDINATES ACROSS SKY
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()
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()
149 self.log.debug('completed the ``_calculate_search_limits`` method')
150 return
152 def _build_sql_query(
153 self):
154 """
155 *build sql query for the sdss square search*
157 **Key Arguments:**
158 # -
160 **Return:**
161 - None
163 .. todo::
165 """
166 self.log.debug('starting the ``_build_sql_query`` method')
168 ra1, ra2, dec1, dec2 = self.ra1, self.ra2, self.dec1, self.dec2
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()
199 self.sqlQuery = self.sqlQuery.strip()
201 self.log.debug('completed the ``_build_sql_query`` method')
202 return None
204 def _execute_sql_query(
205 self):
206 """
207 *execute sql query using the sdss API*
209 **Key Arguments:**
210 # -
212 **Return:**
213 - None
215 .. todo::
217 """
218 self.log.debug('starting the ``_execute_sql_query`` method')
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)
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)
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"]
249 self.log.debug('completed the ``_execute_sql_query`` method')
250 return
252 def _append_separations_to_results(
253 self):
254 """
255 *append angular separations to results*
257 **Key Arguments:**
258 # -
260 **Return:**
261 - None
263 .. todo::
265 """
266 self.log.debug(
267 'starting the ``_append_separations_to_results`` method')
269 for row in self.results:
270 if "ra" not in row:
271 print(row)
272 exit(0)
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()
284 row["separation_arcsec"] = angularSeparation
285 row["separation_north_arcsec"] = northSep
286 row["separation_east_arcsec"] = eastSep
288 self.log.debug(
289 'completed the ``_append_separations_to_results`` method')
290 return None
292 def _generate_sdss_object_name(
293 self):
294 """
295 *generate sdss object names for the results*
297 **Key Arguments:**
298 # -
300 **Return:**
301 - None
303 .. todo::
305 """
306 self.log.debug('starting the ``_generate_sdss_object_name`` method')
308 converter = unit_conversion(
309 log=self.log
310 )
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:
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
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"]]
334 self.log.debug('completed the ``_generate_sdss_object_name`` method')
335 return None
337 # use the tab-trigger below for new method
338 # xt-class-method
341if __name__ == '__main__':
342 main()