diff --git a/astroquery/vamdc/__init__.py b/astroquery/vamdc/__init__.py new file mode 100644 index 0000000000..3931496608 --- /dev/null +++ b/astroquery/vamdc/__init__.py @@ -0,0 +1,25 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +""" +VAMDC molecular line database +""" +from astropy import config as _config +from astropy.config import paths +import os + + +class Conf(_config.ConfigNamespace): + """ + Configuration parameters for `astroquery.vamdc`. + """ + + timeout = _config.ConfigItem(60, "Timeout in seconds") + + cache_location = os.path.join(paths.get_cache_dir(), 'astroquery/vamdc',) + +conf = Conf() + +from .core import Vamdc, VamdcClass + +__all__ = ['Vamdc', 'VamdcClass', + 'Conf', 'conf', + ] diff --git a/astroquery/vamdc/core.py b/astroquery/vamdc/core.py new file mode 100644 index 0000000000..c97e1ff201 --- /dev/null +++ b/astroquery/vamdc/core.py @@ -0,0 +1,124 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +from __future__ import print_function +import time +import os.path +import getpass +import keyring +import numpy as np +import re +import tarfile +import string +import requests +import sys +from pkg_resources import resource_filename +from bs4 import BeautifulSoup + +from astropy.extern.six.moves.urllib_parse import urljoin, urlparse +from astropy.extern.six import iteritems +from astropy.extern import six +from astropy.table import Table, Column +from astropy import log +from astropy.utils.console import ProgressBar +from astropy import units as u +import astropy.io.votable as votable + +from ..exceptions import (RemoteServiceError, TableParseError, + InvalidQueryError) +from ..utils import commons, system_tools +from ..utils.process_asyncs import async_to_sync +from ..query import BaseQuery +from . import conf +from . load_species_table import species_lookuptable + +__doctest_skip__ = ['VamdcClass.*'] + + +@async_to_sync +class VamdcClass(BaseQuery): + + TIMEOUT = conf.timeout + CACHE_LOCATION = conf.cache_location + + def __init__(self): + super(VamdcClass, self).__init__() + + from vamdclib import nodes as vnodes + from vamdclib import request as vrequest + from vamdclib import specmodel + + self._vnodes = vnodes + self._vrequest = vrequest + + self._nl = vnodes.Nodelist() + self._cdms = self._nl.findnode('cdms') + + self.specmodel = specmodel + + @property + def species_lookuptable(self, cache=True): + """ + As a property, you can't turn off caching.... + """ + if not hasattr(self, '_lut'): + self._lut = species_lookuptable(cache=cache) + + return self._lut + + def query_molecule(self, molecule_name, chem_re_flags=0, cache=True): + """ + Query for the VAMDC data for a specific molecule + + Parameters + ---------- + molecule_name: str + The common name (including unicode characters) or the ordinary + molecular formula (e.g., CH3OH for Methanol) of the molecule. + chem_re_flags: int + The re (regular expression) flags for comparison of the molecule + name with the lookuptable keys + cache: bool + Use the astroquery cache to store/recover the result + + Returns + ------- + result: `vamdclib.request.Result` + A vamdclib Result object that has a data attribute. The result + object has dictionary-like entries but has more functionality built + on top of that + """ + + myhash = "{0}_re{1}".format(molecule_name, chem_re_flags) + myhashpath = os.path.join(self.CACHE_LOCATION, + myhash) + if os.path.exists(myhashpath) and cache: + with open(myhashpath, 'r') as fh: + xml = fh.read() + result = self._vrequest.Result() + result.Xml = xml + result.populate_model() + else: + species_id_dict = self.species_lookuptable.find(molecule_name, + flags=chem_re_flags) + if len(species_id_dict) == 1: + species_id = list(species_id_dict.values())[0] + else: + raise ValueError("Too many species matched: {0}" + .format(species_id_dict)) + + request = self._vrequest.Request(node=self._cdms) + query_string = "SELECT ALL WHERE VAMDCSpeciesID='%s'" % species_id + request.setquery(query_string) + result = request.dorequest() + + if cache: + with open(myhashpath, 'w') as fh: + xml = fh.write(result.Xml) + + return result + + # example use of specmodel; return to this later... + #Q = self.specmodel.calculate_partitionfunction(result.data['States'], + # temperature=tex)[species_id] + + +Vamdc = VamdcClass() diff --git a/astroquery/vamdc/load_species_table.py b/astroquery/vamdc/load_species_table.py index 673d9d4a0d..6d88aa919d 100644 --- a/astroquery/vamdc/load_species_table.py +++ b/astroquery/vamdc/load_species_table.py @@ -1,29 +1,49 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst from astropy import log +import os +import json from ..splatalogue.load_species_table import SpeciesLookuptable - - -def species_lookuptable(): - - log.info("Loading molecular line ID database") - - from vamdclib import nodes - from vamdclib import request as r - - nl = nodes.Nodelist() - nl.findnode('cdms') - cdms = nl.findnode('cdms') - - request = r.Request(node=cdms) - - # Retrieve all species from CDMS - result = request.getspecies() - molecules = result.data['Molecules'] - - lutdict = {"{0} {1}".format(molecules[key].ChemicalName, - molecules[key].OrdinaryStructuralFormula): - molecules[key].VAMDCSpeciesID - for key in molecules} - lookuptable = SpeciesLookuptable(lutdict) +from . import Conf + +def species_lookuptable(cache=True): + """ + Get a lookuptable from chemical name + OrdinaryStructuralFormula to VAMDC + id + """ + + if not os.path.exists(Conf.cache_location): + os.makedirs(Conf.cache_location) + + lut_path = os.path.join(Conf.cache_location, + 'species_lookuptable.json') + if os.path.exists(lut_path) and cache: + log.info("Loading cached molecular line ID database") + with open(lut_path, 'r') as fh: + lutdict = json.load(fh) + lookuptable = SpeciesLookuptable(lutdict) + else: + log.info("Loading molecular line ID database") + + from vamdclib import nodes as vnodes + from vamdclib import request as vrequest + + nl = vnodes.Nodelist() + nl.findnode('cdms') + cdms = nl.findnode('cdms') + + request = vrequest.Request(node=cdms) + + # Retrieve all species from CDMS + result = request.getspecies() + molecules = result.data['Molecules'] + + lutdict = {"{0} {1}".format(molecules[key].ChemicalName, + molecules[key].OrdinaryStructuralFormula): + molecules[key].VAMDCSpeciesID + for key in molecules} + lookuptable = SpeciesLookuptable(lutdict) + if cache: + with open(lut_path, 'w') as fh: + json.dump(lookuptable, fh) return lookuptable