forked from astropy/astroquery
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.py
More file actions
205 lines (166 loc) · 6.53 KB
/
core.py
File metadata and controls
205 lines (166 loc) · 6.53 KB
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
# Licensed under a 3-clause BSD style license - see LICENSE.rst
import functools
import numpy as np
from astropy.table import Table
from ..query import BaseQuery
from ..utils import commons, async_to_sync
from . import conf
__all__ = ['Ogle', 'OgleClass']
__doctest_skip__ = ['OgleClass.*']
def _validate_params(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
algorithm = kwargs.get('algorithm')
quality = kwargs.get('quality')
coord_sys = kwargs.get('coord_sys')
# if unspecified, the defaults (which are OK) will be used
if algorithm is not None and algorithm not in Ogle.algorithms:
raise ValueError("'algorithm` must be one of \
{!s}".format(Ogle.algorithms))
if quality is not None and quality not in Ogle.quality_codes:
raise ValueError("'quality' must be one of \
{!s}".format(Ogle.quality_codes))
if coord_sys is not None and coord_sys not in Ogle.coord_systems:
raise ValueError("'coord_sys' must be one of \
{!s}".format(Ogle.coord_systems))
return func(*args, **kwargs)
return wrapper
class CoordParseError(ValueError):
def __init__(self, message='Could not parse `coord` argument.', **kwargs):
super().__init__(message, **kwargs)
@async_to_sync
class OgleClass(BaseQuery):
DATA_URL = conf.server
TIMEOUT = conf.timeout
algorithms = ['NG', 'NN']
quality_codes = ['GOOD', 'ALL']
coord_systems = ['RD', 'LB']
@_validate_params
def query_region_async(self, *, coord=None, algorithm='NG', quality='GOOD',
coord_sys='RD', get_query_payload=False):
"""
Query the OGLE-III interstellar extinction calculator.
Parameters
----------
coord : list-like
Pointings to evaluate interstellar extinction. Three forms of
coordinates may be passed::
* single astropy coordinate instance
* list-like object (1 x N) of astropy coordinate instances
algorithm : string
Algorithm to interpolate data for desired coordinate.
Valid options::
* 'NG': nearest grid point
* 'NN': natural neighbor interpolation
quality : string
Quality factor for data. Valid options::
* 'All': all points
* 'GOOD': QF=0 as described in Nataf et al. (2012).
coord_sys : string
Coordinate system if using lists of RA/Decs in ``coord``.
Valid options::
* 'RD': equatorial coordinates
* 'LB': Galactic coordinates.
get_query_payload : bool, optional
If `True` then returns the generated query payload.
Defaults to `False`.
Returns
-------
response : `requests.Response`
The HTTP response returned from the service.
Raises
------
CoordParseError
Exception raised for malformed coordinate input
Examples
--------
Using astropy coordinates:
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> co = SkyCoord(0.0, 3.0, unit=(u.degree, u.degree),
... frame='galactic')
>>> from astroquery.ogle import Ogle
>>> t = Ogle.query_region(coord=co)
>>> t.pprint()
RA/LON Dec/Lat A_I E(V-I) S_E(V-I) R_JKVI mu S_mu
--------- ---------- ----- ------ -------- ------ ------ ----- ...
17.568157 -27.342475 3.126 2.597 0.126 0.3337 14.581 0.212
"""
# Determine the coord object type and generate list of coordinates
lon, lat = self._parse_coords(coord, coord_sys)
# Generate payload
query_header = '# {0} {1} {2}\n'.format(coord_sys, algorithm, quality)
sources = '\n'.join(['{0} {1}'.format(lo, la) for lo, la in
zip(lon, lat)])
file_data = query_header + sources
files = {'file1': file_data}
if get_query_payload:
return files
# Make request
params = {'dnfile': 'submit'}
response = self._request("POST", url=self.DATA_URL, data=params,
timeout=self.TIMEOUT, files=files)
response.raise_for_status()
return response
def _parse_result(self, response, *, verbose=False):
# Header is in first row starting with #, this works with the default
t = Table.read(response.text.split('\n'), format='ascii')
return t
def _parse_coords(self, coord, coord_sys):
"""
Parse single astropy.coordinates instance, list of astropy.coordinate
instances, or 2xN list of coordinate values.
Parameters
----------
coord : list-like
coord_sys : string
Returns
-------
lon : list
Longitude coordinate values
lat : list
Latitude coordinate values
"""
if not isinstance(coord, list):
# single astropy coordinate
try:
ra, dec = commons.coord_to_radec(coord)
lon = [ra]
lat = [dec]
return lon, lat
except ValueError:
raise CoordParseError()
elif isinstance(coord, list):
shape = np.shape(coord)
# list of astropy coordinates
if len(shape) == 1:
try:
radec = [commons.coord_to_radec(co) for co in coord]
lon, lat = list(zip(*radec))
return lon, lat
except ValueError:
raise CoordParseError()
else:
raise CoordParseError()
else:
raise CoordParseError()
def _parse_raw(self, raw_data):
"""
Parse the raw strings returned from the query request and return a list
of lists for each column in string format.
Parameters
----------
raw_data : list
Raw data from the request formatted to as list of strings for each
line
Returns
-------
data : list
List of lists for each column as strings
"""
# Requests returns unicode encoding, return to ascii
data = [line.split() for line in raw_data[1:]]
# Transpose while keeping as list of lists
data = list(map(list, zip(*data)))
return data
Ogle = OgleClass()