Skip to content

Commit b9c6ae6

Browse files
committed
Merge pull request #499 from vilhelmp/master
Search provider - NASA ADS
2 parents ca460a2 + 2aae04f commit b9c6ae6

File tree

8 files changed

+257
-1
lines changed

8 files changed

+257
-1
lines changed

astroquery/nasa_ads/__init__.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2+
"""
3+
SAO/NASA ADS Query Tool
4+
-----------------------------------
5+
6+
:Author: Magnus Vilhelm Persson ([email protected])
7+
8+
"""
9+
10+
from astropy import config as _config
11+
12+
13+
class Conf(_config.ConfigNamespace):
14+
"""
15+
Configuration parameters for `astroquery.nasa_ads`.
16+
"""
17+
18+
server = _config.ConfigItem(
19+
'http://adswww.harvard.edu',
20+
'SAO/NASA ADS main server.'
21+
)
22+
mirrors = _config.ConfigItem(
23+
['http://cdsads.u-strasbg.fr',
24+
'http://ukads.nottingham.ac.uk',
25+
'http://esoads.eso.org',
26+
'http://ads.ari.uni-heidelberg.de',
27+
'http://ads.inasan.ru',
28+
'http://ads.mao.kiev.ua',
29+
'http://ads.astro.puc.cl',
30+
'http://ads.nao.ac.jp',
31+
'http://ads.bao.ac.cn',
32+
'http://ads.iucaa.ernet.in',
33+
'http://ads.arsip.lipi.go.id',
34+
'http://saaoads.chpc.ac.za',
35+
'http://ads.on.br'],
36+
'SAO/NASA ADS mirrors around the world'
37+
)
38+
advanced_path = _config.ConfigItem(
39+
'/cgi-bin/nph-abs_connect',
40+
'Path for advanced query (unconfirmed)'
41+
)
42+
simple_path = _config.ConfigItem(
43+
'/cgi-bin/basic_connect',
44+
'Path for simple query (return XML)'
45+
)
46+
timeout = _config.ConfigItem(
47+
120,
48+
'Time limit for connecting to ADS server'
49+
)
50+
51+
conf = Conf()
52+
53+
54+
conf.adsfields = ['bibcode', 'title', 'author', 'affiliation',
55+
'journal', 'volume', 'pubdate', 'page', 'lastpage', 'keywords', 'keyword',
56+
'origin', 'copyright', 'link', 'name', 'url', 'count', 'score', 'citations',
57+
'abstract', 'doi', 'eprintid']
58+
59+
from .core import ADSClass, ADS
60+
61+
__all__ = ['ADSClass', 'ADS',
62+
'Conf', 'conf']

astroquery/nasa_ads/core.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2+
"""
3+
Module to search the SAO/NASA Astrophysics Data System
4+
5+
:author: Magnus Persson <[email protected]>
6+
7+
"""
8+
9+
import warnings
10+
from ..query import BaseQuery
11+
from ..utils import commons, async_to_sync
12+
from . import conf
13+
from astropy.table import Table, Column
14+
15+
from ..utils.class_or_instance import class_or_instance
16+
from ..utils import commons, async_to_sync
17+
from .utils import *
18+
19+
from xml.dom import minidom
20+
21+
__all__ = ['ADS', 'ADSClass']
22+
23+
@async_to_sync
24+
class ADSClass(BaseQuery):
25+
26+
SERVER = conf.server
27+
QUERY_ADVANCED_PATH = conf.advanced_path
28+
QUERY_SIMPLE_PATH = conf.simple_path
29+
TIMEOUT = conf.timeout
30+
31+
QUERY_SIMPLE_URL = SERVER + QUERY_SIMPLE_PATH
32+
QUERY_ADVANCED_URL = SERVER + QUERY_ADVANCED_PATH
33+
34+
def __init__(self, *args):
35+
""" set some parameters """
36+
pass
37+
38+
@class_or_instance
39+
def query_simple(self, query_string, get_query_payload=False, get_raw_response=False):
40+
self.query_string = query_string
41+
request_payload = self._args_to_payload(query_string)
42+
43+
response = commons.send_request(self.QUERY_SIMPLE_URL, request_payload, self.TIMEOUT)
44+
45+
# primarily for debug purposes, but also useful if you want to send
46+
# someone a URL linking directly to the data
47+
if get_query_payload:
48+
return request_payload
49+
if get_raw_response:
50+
return response
51+
# parse the XML response into AstroPy Table
52+
resulttable = self._parse_response(response.encode(results.encoding).decode('utf-8'))
53+
54+
return resulttable
55+
56+
def _parse_response(self, response):
57+
xmlrepr = minidom.parseString(response.text)
58+
# Check if there are any results!
59+
60+
# get the list of hits
61+
hitlist = xmlrepr.childNodes[0].childNodes
62+
hitlist = hitlist[1::2] # every second hit is a "line break"
63+
64+
# Grab the various fields
65+
titles = _get_data_from_xml(hitlist, 'title')
66+
bibcode = _get_data_from_xml(hitlist, 'bibcode')
67+
journal = _get_data_from_xml(hitlist, 'journal')
68+
volume = _get_data_from_xml(hitlist, 'volume')
69+
pubdate = _get_data_from_xml(hitlist, 'pubdate')
70+
page = _get_data_from_xml(hitlist, 'page')
71+
score = _get_data_from_xml(hitlist, 'score')
72+
citations = _get_data_from_xml(hitlist, 'citations')
73+
abstract = _get_data_from_xml(hitlist, 'abstract')
74+
doi = _get_data_from_xml(hitlist, 'DOI')
75+
eprintid = _get_data_from_xml(hitlist, 'eprintid')
76+
authors = _get_data_from_xml(hitlist, 'author')
77+
# put into AstroPy Table
78+
t = Table()
79+
t['title'] = titles
80+
t['bibcode'] = bibcode
81+
t['journal'] = journal
82+
t['volume'] = volume
83+
t['pubdate'] = pubdate
84+
t['page'] = page
85+
t['score'] = score
86+
t['citations'] = citations
87+
t['abstract'] = abstract
88+
t['doi'] = doi
89+
t['eprintid'] = eprintid
90+
t['authors'] = authors
91+
92+
return t
93+
94+
def _args_to_payload(self, query_string):
95+
# convert arguments to a valid requests payload
96+
# i.e. a dictionary
97+
return {'qsearch' : query_string, 'data_type' : 'XML'}
98+
99+
100+
101+
ADS = ADSClass()
102+

astroquery/nasa_ads/tests/__init__.py

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from ... import nasa_ads
2+
from astropy.tests.helper import remote_data
3+
4+
@remote_data
5+
def test_simple():
6+
x = nasa_ads.ADS.query_simple('^Persson Origin of water around deeply embedded low-mass protostars')
7+
assert x[-1]['authors'][0] == 'Persson, M. V.'

astroquery/nasa_ads/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
3+
def _get_data_from_xml(doclist, fieldname, nohitreturn=None):
4+
"""Get the fieldname (i.e. author, title etc)
5+
from minidom.parseString().childNodes[0].childNodes list
6+
"""
7+
result = []
8+
for element in doclist:
9+
fieldlist = element.getElementsByTagName(fieldname)
10+
try:
11+
tmp = fieldlist[0]
12+
except IndexError:
13+
fields = [nohitreturn]
14+
fields = []
15+
for field in fieldlist: # this is useful for e.g. author field
16+
fields.append(field.childNodes[0].data)
17+
result.append(fields)
18+
return result

docs/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ Directory Structure::
171171
if get_query_payload:
172172
return request_payload
173173
174-
return result
174+
return response
175175
176176
@class_or_instance
177177
def get_images_async(self, *args):

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ The following modules have been completed using a common API:
132132
atomic/atomic.rst
133133
alma/alma.rst
134134
skyview/skyview.rst
135+
nasa_ads/nasa_ads.rst
135136

136137
These others are functional, but do not follow a common & consistent API:
137138

@@ -225,6 +226,7 @@ above categories.
225226
lamda/lamda.rst
226227
nist/nist.rst
227228
splatalogue/splatalogue.rst
229+
nasa_ads/nasa_ads.rst
228230

229231

230232
Developer documentation

docs/nasa_ads/nasa_ads.rst

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
.. doctest-skip-all
2+
3+
.. _astroquery.nasa_ads:
4+
5+
****************************************
6+
NASA ADS Queries (`astroquery.nasa_ads`)
7+
****************************************
8+
9+
Getting Started
10+
===============
11+
12+
This module provides an interface to the online `SAO/NASA Astrophysics Data System`_.
13+
At the moment only the "simple search", i.e. omni-box search is available, and only
14+
a subset of the results are accessible.
15+
16+
Examples
17+
========
18+
19+
Search works by specific identifier
20+
-----------------------------------
21+
.. code-block:: python
22+
23+
from astroquery import nasa_ads as na
24+
# the "^" makes ADS to return only papers where Persson
25+
# is first author
26+
results = na.ADS.query_simple('^Persson Origin of water\
27+
around deeply embedded low-mass protostars') results[0].title
28+
29+
# to sort after publication date
30+
results.sort(['pubdate'])
31+
32+
# get the title of the last hit
33+
title = results[-1]['title'][0]
34+
35+
# printout the authors of the last hit
36+
print results[-1]['authors']
37+
38+
39+
Get links
40+
---------
41+
Not yet implemented.
42+
43+
Download publisher/ArXiv PDF
44+
----------------------------
45+
Not yet implemented.
46+
47+
Get Bibtex
48+
----------
49+
Not yet implemented.
50+
51+
52+
53+
54+
55+
56+
Reference/API
57+
=============
58+
59+
#.. automodapi:: astroquery.nasa_ads:no-inheritance-diagram:
60+
61+
.. _nasa_ads: http://adsabs.harvard.edu/
62+
.. _SAO/NASA Astrophysics Data System: http://adsabs.harvard.edu/
63+
64+
65+

0 commit comments

Comments
 (0)