Skip to content

Commit b3584b1

Browse files
committed
Update HITRAN module to use class-based query API
fixes #824
1 parent 4042ea9 commit b3584b1

File tree

7 files changed

+450
-339
lines changed

7 files changed

+450
-339
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
0.3.7 (unreleased)
22
------------------
33

4+
- HITRAN: use class-based API [#824]
45
- IRSA Dust: fix units in extinction by band table. [#1016]
56
- NRAO: Allow multiple configurations, telescopes in queries [#1020]
67
- New tool: Exoplanet Orbit Catalog, NASA Exoplanet Archive [#771]

astroquery/hitran/__init__.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,25 @@
55
66
:Author: Adam Ginsburg (adam.g.ginsburg@gmail.com)
77
"""
8-
from .reader import download_hitran, read_hitran_file, cache_location
8+
import os
9+
from astropy import config as _config
10+
11+
12+
class Conf(_config.ConfigNamespace):
13+
"""
14+
Configuration parameters for `astroquery.hitran`.
15+
"""
16+
query_url = _config.ConfigItem('http://hitran.org/lbl/api',
17+
'HITRAN web interface URL.')
18+
timeout = _config.ConfigItem(60,
19+
'Time limit for connecting to HITRAN server.')
20+
data_dir = os.path.join(os.path.dirname(__file__), 'data')
21+
formatfile = _config.ConfigItem(os.path.join(data_dir, 'readme.txt'),
22+
'Format file.')
23+
24+
25+
conf = Conf()
26+
27+
from .core import Hitran, HitranClass
28+
29+
__all__ = ['Hitran', 'HitranClass', 'conf']

astroquery/hitran/core.py

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
from astropy.table import Table
2+
from astropy import units as u
3+
4+
from ..query import BaseQuery
5+
from ..utils import async_to_sync, prepend_docstr_nosections
6+
from . import conf
7+
from .utils import parse_readme
8+
9+
__all__ = ['Hitran', 'HitranClass']
10+
11+
12+
@async_to_sync
13+
class HitranClass(BaseQuery):
14+
15+
QUERY_URL = conf.query_url
16+
TIMEOUT = conf.timeout
17+
FORMATFILE = conf.formatfile
18+
ISO_INDEX = {'id': 0, 'iso_name': 1, 'abundance': 2, 'mass': 3,
19+
'mol_name': 4}
20+
21+
# Copied from the hapi.py code (Academic Free License)
22+
# http://hitran.org/static/hapi/hapi.py
23+
# M I id iso_name abundance mass mol_name
24+
ISO = {
25+
(1, 1): [1, 'H2(16O)', 0.997317, 18.010565, 'H2O'],
26+
(1, 2): [2, 'H2(18O)', 0.00199983, 20.014811, 'H2O'],
27+
(1, 3): [3, 'H2(17O)', 0.000372, 19.01478, 'H2O'],
28+
(1, 4): [4, 'HD(16O)', 0.00031069, 19.01674, 'H2O'],
29+
(1, 5): [5, 'HD(18O)', 0.000000623, 21.020985, 'H2O'],
30+
(1, 6): [6, 'HD(17O)', 0.000000116, 20.020956, 'H2O'],
31+
(2, 1): [7, '(12C)(16O)2', 0.9842, 43.98983, 'CO2'],
32+
(2, 2): [8, '(13C)(16O)2', 0.01106, 44.993185, 'CO2'],
33+
(2, 3): [9, '(16O)(12C)(18O)', 0.0039471, 45.994076, 'CO2'],
34+
(2, 4): [10, '(16O)(12C)(17O)', 0.000734, 44.994045, 'CO2'],
35+
(2, 5): [11, '(16O)(13C)(18O)', 0.00004434, 46.997431, 'CO2'],
36+
(2, 6): [12, '(16O)(13C)(17O)', 0.00000825, 45.9974, 'CO2'],
37+
(2, 7): [13, '(12C)(18O)2', 0.0000039573, 47.998322, 'CO2'],
38+
(2, 8): [14, '(17O)(12C)(18O)', 0.00000147, 46.998291, 'CO2'],
39+
(2, 0): [15, '(13C)(18O)2', 0.000000044967, 49.001675, 'CO2'],
40+
(2, 11): [120, '(18O)(13C)(17O)', 0.00000001654, 48.00165, 'CO2'],
41+
(2, 9): [121, '(12C)(17O)2', 0.0000001368, 45.998262, 'CO2'],
42+
(3, 1): [16, '(16O)3', 0.992901, 47.984745, 'O3'],
43+
(3, 2): [17, '(16O)(16O)(18O)', 0.00398194, 49.988991, 'O3'],
44+
(3, 3): [18, '(16O)(18O)(16O)', 0.00199097, 49.988991, 'O3'],
45+
(3, 4): [19, '(16O)(16O)(17O)', 0.00074, 48.98896, 'O3'],
46+
(3, 5): [20, '(16O)(17O)(16O)', 0.00037, 48.98896, 'O3'],
47+
(4, 1): [21, '(14N)2(16O)', 0.990333, 44.001062, 'N2O'],
48+
(4, 2): [22, '(14N)(15N)(16O)', 0.0036409, 44.998096, 'N2O'],
49+
(4, 3): [23, '(15N)(14N)(16O)', 0.0036409, 44.998096, 'N2O'],
50+
(4, 4): [24, '(14N)2(18O)', 0.00198582, 46.005308, 'N2O'],
51+
(4, 5): [25, '(14N)2(17O)', 0.000369, 45.005278, 'N2O'],
52+
(5, 1): [26, '(12C)(16O)', 0.98654, 27.994915, 'CO'],
53+
(5, 2): [27, '(13C)(16O)', 0.01108, 28.99827, 'CO'],
54+
(5, 3): [28, '(12C)(18O)', 0.0019782, 29.999161, 'CO'],
55+
(5, 4): [29, '(12C)(17O)', 0.000368, 28.99913, 'CO'],
56+
(5, 5): [30, '(13C)(18O)', 0.00002222, 31.002516, 'CO'],
57+
(5, 6): [31, '(13C)(17O)', 0.00000413, 30.002485, 'CO'],
58+
(6, 1): [32, '(12C)H4', 0.98827, 16.0313, 'CH4'],
59+
(6, 2): [33, '(13C)H4', 0.0111, 17.034655, 'CH4'],
60+
(6, 3): [34, '(12C)H3D', 0.00061575, 17.037475, 'CH4'],
61+
(6, 4): [35, '(13C)H3D', 0.0000049203, 18.04083, 'CH4'],
62+
(7, 1): [36, '(16O)2', 0.995262, 31.98983, 'O2'],
63+
(7, 2): [37, '(16O)(18O)', 0.00399141, 33.994076, 'O2'],
64+
(7, 3): [38, '(16O)(17O)', 0.000742, 32.994045, 'O2'],
65+
(8, 1): [39, '(14N)(16O)', 0.993974, 29.997989, 'NO'],
66+
(8, 2): [40, '(15N)(16O)', 0.0036543, 30.995023, 'NO'],
67+
(8, 3): [41, '(14N)(18O)', 0.00199312, 32.002234, 'NO'],
68+
(9, 1): [42, '(32S)(16O)2', 0.94568, 63.961901, 'SO2'],
69+
(9, 2): [43, '(34S)(16O)2', 0.04195, 65.957695, 'SO2'],
70+
(10, 1): [44, '(14N)(16O)2', 0.991616, 45.992904, 'NO2'],
71+
(11, 1): [45, '(14N)H3', 0.9958715, 17.026549, 'NH3'],
72+
(11, 2): [46, '(15N)H3', 0.0036613, 18.023583, 'NH3'],
73+
(12, 1): [47, 'H(14N)(16O)3', 0.98911, 62.995644, 'HNO3'],
74+
(12, 2): [117, 'H(15N)(16O)3', 0.003636, 63.99268, 'HNO3'],
75+
(13, 1): [48, '(16O)H', 0.997473, 17.00274, 'OH'],
76+
(13, 2): [49, '(18O)H', 0.00200014, 19.006986, 'OH'],
77+
(13, 3): [50, '(16O)D', 0.00015537, 18.008915, 'OH'],
78+
(14, 1): [51, 'H(19F)', 0.99984425, 20.006229, 'HF'],
79+
(14, 2): [110, 'D(19F)', 0.000115, 21.0125049978, 'HF'],
80+
(15, 1): [52, 'H(35Cl)', 0.757587, 35.976678, 'HCl'],
81+
(15, 2): [53, 'H(37Cl)', 0.242257, 37.973729, 'HCl'],
82+
(15, 3): [107, 'D(35Cl)', 0.000118005, 36.9829544578, 'HCl'],
83+
(15, 4): [108, 'D(37Cl)', 0.000037735, 38.9800043678, 'HCl'],
84+
(16, 1): [54, 'H(79Br)', 0.50678, 79.92616, 'HBr'],
85+
(16, 2): [55, 'H(81Br)', 0.49306, 81.924115, 'HBr'],
86+
(16, 3): [111, 'D(79Br)', 0.0000582935, 80.9324388778, 'HBr'],
87+
(16, 4): [112, 'D(81Br)', 0.0000567065, 82.9303923778, 'HBr'],
88+
(17, 1): [56, 'H(127I)', 0.99984425, 127.912297, 'HI'],
89+
(17, 2): [113, 'D(127I)', 0.000115, 128.918574778, 'HI'],
90+
(18, 1): [57, '(35Cl)(16O)', 0.75591, 50.963768, 'ClO'],
91+
(18, 2): [58, '(37Cl)(16O)', 0.24172, 52.960819, 'ClO'],
92+
(19, 1): [59, '(16O)(12C)(32S)', 0.93739, 59.966986, 'OCS'],
93+
(19, 2): [60, '(16O)(12C)(34S)', 0.04158, 61.96278, 'OCS'],
94+
(19, 3): [61, '(16O)(13C)(32S)', 0.01053, 60.970341, 'OCS'],
95+
(19, 4): [62, '(16O)(12C)(33S)', 0.01053, 60.966371, 'OCS'],
96+
(19, 5): [63, '(18O)(12C)(32S)', 0.00188, 61.971231, 'OCS'],
97+
(20, 1): [64, 'H2(12C)(16O)', 0.98624, 30.010565, 'H2CO'],
98+
(20, 2): [65, 'H2(13C)(16O)', 0.01108, 31.01392, 'H2CO'],
99+
(20, 3): [66, 'H2(12C)(18O)', 0.0019776, 32.014811, 'H2CO'],
100+
(21, 1): [67, 'H(16O)(35Cl)', 0.75579, 51.971593, 'HOCl'],
101+
(21, 2): [68, 'H(16O)(37Cl)', 0.24168, 53.968644, 'HOCl'],
102+
(22, 1): [69, '(14N)2', 0.9926874, 28.006147, 'N2'],
103+
(22, 2): [118, '(14N)(15N)', 0.0072535, 29.997989, 'N2'],
104+
(23, 1): [70, 'H(12C)(14N)', 0.98511, 27.010899, 'HCN'],
105+
(23, 2): [71, 'H(13C)(14N)', 0.01107, 28.014254, 'HCN'],
106+
(23, 3): [72, 'H(12C)(15N)', 0.0036217, 28.007933, 'HCN'],
107+
(24, 1): [73, '(12C)H3(35Cl)', 0.74894, 49.992328, 'CH3Cl'],
108+
(24, 2): [74, '(12C)H3(37Cl)', 0.23949, 51.989379, 'CH3Cl'],
109+
(25, 1): [75, 'H2(16O)2', 0.994952, 34.00548, 'H2O2'],
110+
(26, 1): [76, '(12C)2H2', 0.9776, 26.01565, 'C2H2'],
111+
(26, 2): [77, '(12C)(13C)H2', 0.02197, 27.019005, 'C2H2'],
112+
(26, 3): [105, '(12C)2HD', 0.00030455, 27.021825, 'C2H2'],
113+
(27, 1): [78, '(12C)2H6', 0.97699, 30.04695, 'C2H6'],
114+
(27, 2): [106, '(12C)H3(13C)H3', 0.021952611, 31.050305, 'C2H6'],
115+
(28, 1): [79, '(31P)H3', 0.99953283, 33.997238, 'PH3'],
116+
(29, 1): [80, '(12C)(16O)(19F)2', 0.98654, 65.991722, 'COF2'],
117+
(29, 2): [119, '(13C)(16O)(19F)2', 0.0110834, 66.995083, 'COF2'],
118+
(31, 1): [81, 'H2(32S)', 0.94988, 33.987721, 'H2S'],
119+
(31, 2): [82, 'H2(34S)', 0.04214, 35.983515, 'H2S'],
120+
(31, 3): [83, 'H2(33S)', 0.007498, 34.987105, 'H2S'],
121+
(32, 1): [84, 'H(12C)(16O)(16O)H', 0.983898, 46.00548, 'HCOOH'],
122+
(33, 1): [85, 'H(16O)2', 0.995107, 32.997655, 'HO2'],
123+
(34, 1): [86, '(16O)', 0.997628, 15.994915, 'O'],
124+
(36, 1): [87, '(14N)(16O)+', 0.993974, 29.997989, 'NOp'],
125+
(37, 1): [88, 'H(16O)(79Br)', 0.5056, 95.921076, 'HOBr'],
126+
(37, 2): [89, 'H(16O)(81Br)', 0.4919, 97.919027, 'HOBr'],
127+
(38, 1): [90, '(12C)2H4', 0.9773, 28.0313, 'C2H4'],
128+
(38, 2): [91, '(12C)H2(13C)H2', 0.02196, 29.034655, 'C2H4'],
129+
(39, 1): [92, '(12C)H3(16O)H', 0.98593, 32.026215, 'CH3OH'],
130+
(40, 1): [93, '(12C)H3(79Br)', 0.5013, 93.941811, 'CH3Br'],
131+
(40, 2): [94, '(12C)H3(81Br)', 0.48766, 95.939764, 'CH3Br'],
132+
(41, 1): [95, '(12C)H3(12C)(14N)', 0.97482, 41.026549, 'CH3CN'],
133+
(42, 1): [96, '(12C)(19F)4', 0.9893, 87.993616, 'CF4'],
134+
(43, 1): [116, '(12C)4H2', 0.955998, 50.01565, 'C4H2'],
135+
(44, 1): [109, 'H(12C)3(14N)', 0.9646069, 51.01089903687, 'HC3N'],
136+
(45, 1): [103, 'H2', 0.999688, 2.01565, 'H2'],
137+
(45, 2): [115, 'HD', 0.00022997, 3.021825, 'H2'],
138+
(46, 1): [97, '(12C)(32S)', 0.939624, 43.971036, 'CS'],
139+
(46, 2): [98, '(12C)(34S)', 0.0416817, 45.966787, 'CS'],
140+
(46, 3): [99, '(13C)(32S)', 0.0105565, 44.974368, 'CS'],
141+
(46, 4): [100, '(12C)(33S)', 0.00741668, 44.970399, 'CS'],
142+
(47, 1): [114, '(32S)(16O)3', 0.9423964, 79.95682, 'SO3'],
143+
(1001, 1): [101, 'H', None, None, 'H'],
144+
(1002, 1): [102, 'He', None, None, 'He'],
145+
(1018, 1): [104, 'Ar', None, None, 'Ar'],
146+
}
147+
148+
def __init__(self, **kwargs):
149+
"""
150+
Initialize a Hitran query class.
151+
"""
152+
super(HitranClass, self).__init__()
153+
154+
def _args_to_payload(self, molecule_number=1, isotopologue_number=1,
155+
min_frequency=None, max_frequency=None):
156+
"""
157+
Code to parse input and construct the payload dicttionary.
158+
159+
Parameters
160+
----------
161+
molecule_number : int
162+
HITRAN molecule number
163+
isotopologue_number : int
164+
HITRAN isotopologue number
165+
min_frequency : `astropy.units`
166+
Minimum frequency (or any spectral() equivalent)
167+
max_frequency : `astropy.units`
168+
Maximum frequency (or any spectral() equivalent)
169+
170+
Returns
171+
-------
172+
payload : dict
173+
Dictionary of the parameters to send to the SPLAT page
174+
175+
"""
176+
177+
payload = dict()
178+
179+
iso_id = str(self.ISO[(molecule_number,
180+
isotopologue_number)][self.ISO_INDEX['id']])
181+
# mol_name = self.ISO[(molecule_number,
182+
# isotopologue_number)][self.ISO_INDEX['mol_name']]
183+
184+
payload['iso_ids_list'] = iso_id
185+
186+
if min_frequency is not None:
187+
min_frequency = min_frequency.to(u.cm**-1, u.spectral())
188+
189+
if max_frequency is not None:
190+
max_frequency = max_frequency.to(u.cm**-1, u.spectral())
191+
192+
if min_frequency is not None and max_frequency is not None:
193+
if min_frequency > max_frequency:
194+
min_frequency, max_frequency = max_frequency, min_frequency
195+
196+
payload['numin'] = min_frequency.value
197+
payload['numax'] = max_frequency.value
198+
199+
return payload
200+
201+
@prepend_docstr_nosections("\n" + _args_to_payload.__doc__)
202+
def query_lines_async(self, get_query_payload=False, cache=True, **kwargs):
203+
"""
204+
Queries Hitran class for a particular molecule with default arguments
205+
set. Based on fetch function from hapi.py.
206+
207+
Returns
208+
-------
209+
response : `requests.Response`
210+
The response of the HTTP request.
211+
"""
212+
213+
params = self._args_to_payload(**kwargs)
214+
215+
if get_query_payload:
216+
return params
217+
218+
response = self._request(method='GET',
219+
url=self.QUERY_URL,
220+
params=params,
221+
timeout=self.TIMEOUT,
222+
cache=cache)
223+
224+
return response
225+
226+
def _parse_result(self, response, verbose=False):
227+
"""
228+
Parse a response into an `~astropy.table.Table`
229+
"""
230+
formats = parse_readme(self.FORMATFILE)
231+
232+
dtypes = [entry['dtype'] for entry in formats.values()]
233+
234+
rows = []
235+
for line in response.text.split('\n'):
236+
if line.strip():
237+
row = []
238+
start = 0
239+
for key, entry in formats.items():
240+
formatter = entry['formatter']
241+
length = entry['length']
242+
value = formatter(line[start:start+length])
243+
row.append(value)
244+
start = start + length
245+
rows.append(row)
246+
247+
result = Table(rows=rows, names=formats.keys(), dtype=dtypes)
248+
249+
return result
250+
251+
252+
Hitran = HitranClass()

0 commit comments

Comments
 (0)