-
-
Save gregreen/20291d238bc398d9df84 to your computer and use it in GitHub Desktop.
;+ | |
; NAME: | |
; query_argonaut | |
; | |
; PURPOSE: | |
; Query the Argonaut server for 3D dust information or SFD | |
; | |
; CALLING SEQUENCE: | |
; qresult = query_argonaut(/struct, /debug, _extra=coords) | |
; | |
; INPUTS: | |
; ra, dec : numeric scalars or arrays [deg] | |
; OR | |
; l, b : numeric scalars or arrays [deg] | |
; mode : 'full', 'lite', or 'sfd'. Default to 'full' | |
; structure : set this keyword to return structure instead of hash | |
; debug : set to return timing information | |
; | |
; OUTPUTS: | |
; qresult : a hash (or structure, if /structure set) containing | |
; 'distmod': The distance moduli that define the distance bins. | |
; 'best': The best-fit (maximum probability density) | |
; line-of-sight reddening, in units of SFD-equivalent | |
; E(B-V), to each distance modulus in 'distmod.' See | |
; Schlafly & Finkbeiner (2011) for a definition of the | |
; reddening vector (use R_V = 3.1). | |
; 'samples': Samples of the line-of-sight reddening, drawn from | |
; the probability density on reddening profiles. | |
; 'success': 1 if the query succeeded, and 0 otherwise. | |
; 'converged': 1 if the line-of-sight reddening fit converged, and | |
; 0 otherwise. | |
; 'n_stars': # of stars used to fit the line-of-sight reddening. | |
; 'DM_reliable_min': Minimum reliable distance modulus in pixel. | |
; 'DM_reliable_max': Maximum reliable distance modulus in pixel. | |
; | |
; EXAMPLES: | |
; IDL> qresult = query_argonaut(l=90, b=10) | |
; IDL> help,qresult | |
; QRESULT HASH <ID=1685 NELEMENTS=13> | |
; IDL> qresult = query_argonaut(l=90, b=10, /struct) | |
; IDL> help,qresult | |
; ** Structure <d76608>, 13 tags, length=5776, data length=5776, refs=1: | |
; GR DOUBLE Array[31] | |
; SUCCESS LONG64 1 | |
; N_STARS LONG64 750 | |
; DEC DOUBLE 54.568690 | |
; DM_RELIABLE_MAX DOUBLE 15.189000 | |
; CONVERGED LONG64 1 | |
; DISTMOD DOUBLE Array[31] | |
; L DOUBLE 90.000000 | |
; B DOUBLE 10.000000 | |
; RA DOUBLE -54.585789 | |
; BEST DOUBLE Array[31] | |
; DM_RELIABLE_MIN DOUBLE 6.7850000 | |
; SAMPLES DOUBLE Array[20, 31] | |
; | |
; COMMENTS: | |
; - Any keywords other than "struct" or "debug" go into the | |
; coords structure. | |
; - Must call either with ra=, dec= or l=, b=. | |
; - Angles are in degrees and can be arrays. | |
; - JSON support introduced in IDL 8.2 (Jan, 2013) is required. | |
; | |
; - THIS CODE RETURNS SFD-EQUIVALENT E(B-V)! | |
; See Schlafly & Finkbeiner 2011) for conversion factors. | |
; E(B-V)_Landolt is approximately 0.86*E(B-V)_SFD. | |
; | |
; REVISION HISTORY: | |
; 2015-Feb-26 - Written by Douglas Finkbeiner, CfA | |
; | |
;---------------------------------------------------------------------- | |
function argo_json_serialize, struc | |
ntags = n_tags(struc) | |
key = tag_names(struc) | |
val = strarr(ntags) | |
for i=0L, ntags-1 do begin | |
if size(struc.(i), /tname) EQ 'STRING' then $ | |
val[i] = '"'+key[i]+'":"'+struc.(i)+'"' $ | |
else begin | |
arr = string(struc.(i), format='(F12.7)')+',' | |
arr[0]='['+arr[0] | |
arr[-1] = repstr(arr[-1], ',', '')+']' | |
val[i] = '"'+key[i]+'":'+strjoin(arr) | |
endelse | |
endfor | |
; -------- put it together | |
for i=0L, ntags-2 do val[i]=val[i]+',' | |
string='{'+strjoin(val)+'}' | |
return, string | |
end | |
function query_argonaut, struct=struct, debug=debug, _extra=coords | |
; -------- Check IDL version | |
if !version.release lt 8.2 then begin | |
message, 'IDL '+!version.release+' may lack JSON support', /info | |
return, 0 | |
endif | |
t0=systime(1) | |
; -------- Check inputs | |
verb = keyword_set(debug) | |
if n_tags(coords) GE 2 then tags = tag_names(coords) else tags=['', ''] | |
if ~((total((tags eq 'RA')+(tags eq 'DEC')) eq 2) or $ | |
(total((tags eq 'L') +(tags eq 'B')) eq 2)) then begin | |
print, 'Must call with coordinates, e.g.' | |
print, 'qresult = query_argonaut(ra=3.25, dec=4.5) or ' | |
print, 'qresult = query_argonaut(l=90, b=10)' | |
return, 0 | |
endif | |
ncoords = n_elements(coords.(0)) > n_elements(coords.(1)) | |
; -------- Convert input parameters to lower case JSON string | |
data = strlowcase(argo_json_serialize(coords)) | |
if verb then print, 'JSON serialize :', systime(1)-t0, ' sec', format='(A,F8.3,A)' | |
; -------- Specify URL | |
url = 'http://argonaut.rc.fas.harvard.edu/gal-lb-query-light' | |
; -------- Create a new url object and set header | |
oUrl = OBJ_NEW('IDLnetUrl') | |
oUrl.SetProperty, HEADER = 'Content-Type: application/json' | |
oUrl.SetProperty, encode=2 ; request gzipped response | |
; -------- Query Argonaut, send output to tmpfile | |
tmpfile = filepath('argo-'+string(randomu(iseed,/double)*1D9,$ | |
format='(I9.9)'), /tmp) | |
out = oUrl.Put(data, url=url, /buffer, /post, filename=tmpfile) | |
if verb then print, 'Server query time:', systime(1)-t0, ' sec', format='(A,F8.3,A)' | |
; -------- Parse output to hash or structure | |
result = keyword_set(struct) ? json_parse(out, /tostruct, /toarray) : $ | |
json_parse(out) | |
if verb then print, 'Total time: ', systime(1)-t0, ' sec', format='(A,F8.3,A)' | |
; -------- Clean up | |
obj_destroy, oUrl | |
file_delete, out | |
return, result | |
end |
import json, requests | |
def query(lon, lat, coordsys='gal', mode='full'): | |
''' | |
Send a line-of-sight reddening query to the Argonaut web server. | |
Inputs: | |
lon, lat: longitude and latitude, in degrees. | |
coordsys: 'gal' for Galactic, 'equ' for Equatorial (J2000). | |
mode: 'full', 'lite' or 'sfd' | |
In 'full' mode, outputs a dictionary containing, among other things: | |
'distmod': The distance moduli that define the distance bins. | |
'best': The best-fit (maximum proability density) | |
line-of-sight reddening, in units of SFD-equivalent | |
E(B-V), to each distance modulus in 'distmod.' See | |
Schlafly & Finkbeiner (2011) for a definition of the | |
reddening vector (use R_V = 3.1). | |
'samples': Samples of the line-of-sight reddening, drawn from | |
the probability density on reddening profiles. | |
'success': 1 if the query succeeded, and 0 otherwise. | |
'converged': 1 if the line-of-sight reddening fit converged, and | |
0 otherwise. | |
'n_stars': # of stars used to fit the line-of-sight reddening. | |
'DM_reliable_min': Minimum reliable distance modulus in pixel. | |
'DM_reliable_max': Maximum reliable distance modulus in pixel. | |
Less information is returned in 'lite' mode, while in 'sfd' mode, | |
the Schlegel, Finkbeiner & Davis (1998) E(B-V) is returned. | |
''' | |
url = 'http://argonaut.skymaps.info/gal-lb-query-light' | |
payload = {'mode': mode} | |
if coordsys.lower() in ['gal', 'g']: | |
payload['l'] = lon | |
payload['b'] = lat | |
elif coordsys.lower() in ['equ', 'e']: | |
payload['ra'] = lon | |
payload['dec'] = lat | |
else: | |
raise ValueError("coordsys '{0}' not understood.".format(coordsys)) | |
headers = {'content-type': 'application/json'} | |
r = requests.post(url, data=json.dumps(payload), headers=headers) | |
try: | |
r.raise_for_status() | |
except requests.exceptions.HTTPError as e: | |
print('Response received from Argonaut:') | |
print(r.text) | |
raise e | |
return json.loads(r.text) |
@eteq, I'm wary of introducing astropy as a dependency in the query code. Right now, the only two dependencies, json
and requests
, are very lightweight.
Maybe one way of leveraging astropy is to write a different version of the query function that accepts SkyCoord
as an input. It would have to translate from SkyCoord
to l
and b
, or to RA
and Dec
(J2000).
The other way going about things is to modify the code that underlies argonaut.skymaps.info/gal-lb-query-light
, so that it accepts named objects (the user would send JSON with a name
field, and the server would use SkyCoord.from_name
to find the coordinates) or SkyCoord
specifications (the user sends **kwargs
needed by SkyCoord
as JSON
fields, and the server constructs the SkyCoord
object).
What do you think would be most useful?
@gregreen - how would you feel about supporting astropy's coordinates framework on the python version? I.e. allowing a user to do things like: